Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V0.1.0 #2

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
af3286b
upgrade to hyperapp 2.0.1 pre-release
diontools Aug 15, 2019
973a69b
v0.1.0-beta.0
diontools Aug 17, 2019
7cccf15
update readme
diontools Aug 17, 2019
380a0cc
rename action params to payload
diontools Aug 17, 2019
a0823f9
add default payload for EffectAction
diontools Aug 18, 2019
e841f99
invalid dispatch warning
diontools Aug 18, 2019
5c60e09
remove ref on Html.d.ts
diontools Aug 21, 2019
0c39b52
Html.d.ts: any to unknown on BaseSyntheticEvent
diontools Aug 21, 2019
a211dcf
Html.d.ts: clean up comment
diontools Aug 21, 2019
85a3117
Html.d.ts: use native event type instead of SyntheticEvent
diontools Aug 21, 2019
0a4bc92
Add referrerPolicy to iframe attrs
diontools Aug 21, 2019
ce50df1
add template to IntrinsicElements
diontools Aug 21, 2019
4e80930
Support <a ping> attribute
diontools Aug 21, 2019
583e9c6
Add `value` attribute to `data` element
diontools Aug 21, 2019
90aed00
Add Valign attributes
diontools Aug 21, 2019
f111e77
0.1.0-beta.1
diontools Aug 21, 2019
dfcea15
simplize type arguments of actionCreator
diontools Aug 21, 2019
15e8295
improve comments
diontools Aug 22, 2019
2c1944e
fix actionCreator
diontools Aug 22, 2019
3b51395
Html.d.ts: key props
diontools Aug 22, 2019
f0c1fea
allow number key
diontools Aug 22, 2019
9e47013
list sample
diontools Aug 22, 2019
b9024ef
Html.d.ts: rename namespace TyperApp to Typerapp
diontools Aug 22, 2019
ea5b8f8
0.1.0-beta.2
diontools Aug 22, 2019
8f28e92
conditional subscription type
diontools Aug 22, 2019
f1efd53
change default props type of Effect/Subs
diontools Aug 22, 2019
0a8b7cd
add CHANGELOG
diontools Aug 23, 2019
5ee0d10
fix README
diontools Aug 23, 2019
b78eb26
0.1.0-beta.3
diontools Aug 23, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Changelog

## v0.1.0

Upgraded to Hyperapp 2.0.1 base.

### Breaking Changes

* Changed Signature of Effect / Subscription.

```tsx
// new: dispatch moved to first argument. And, props default type is undefined.
type Effect<S, P = undefined> = [(dispatch: Dispatch<S>, props: P) => void, P]
type Subscription<S, P = undefined> = [(dispatch: Dispatch<S>, props: P) => () => void, P]

// old
type Effect<S, P = Empty> = [(props: P, dispatch: Dispatch<S>) => void, P]
type Subscription<S, P = Empty> = [(props: P, dispatch: Dispatch<S>) => () => void, P]
```

* Renamed `container` to `node`.

```tsx
// new
app({
node: document.getElementById('app')
})

// old
app({
container: document.getElementById('app')
})
```

* Renamed `render` to `view` of `Lazy`.

```tsx
// new
<Lazy view={lazyView} />

// old
<Lazy render={lazyView} />
```

* Use native event type instead of React specific SyntheticEvent on Html.d.ts.

### Obsoleted

* Deleted `ActionParamOf`. Payload Creator instead.
* Deleted `mergedAction`. Payload Creator instead.

### New API

* Payload Creator

```tsx
import { httpText } from 'typerapp/fx'

const Act: Action<State, { value: string }> = (state, payload) => ({ ...state, value: payload.value })

// create payload { value: string } from result by httpText.
httpText([Act, result => ({ value: result.text })], '/')
```

* Allow number of `key`.

```tsx
<div key={1} />
```

* Add `middleware` function.

```tsx
app({
middleware: dispatch => (action: any, props?: any) => {
console.log('dispatch', action, props);
dispatch(action, props);
}
})
```

## v0.0.1

Initial Release

85 changes: 16 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

Typerapp is type-safe [Hyperapp V2](https://github.com/jorgebucaran/hyperapp) + α. It's written in TypeScript.

Sample: [![Edit typerapp-sample](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/diontools/typerapp-sample/tree/master/?fontsize=14&module=%2Fsrc%2Findex.tsx)
Sample: [![Edit typerapp-sample](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/diontools/typerapp-sample/tree/v0.1.0/typerapp-sample/?fontsize=14&module=%2Fsrc%2Findex.tsx)

Minimum sample: [![Edit typerapp-minimum-sample](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/diontools/typerapp-minimum-sample/tree/master/?fontsize=14&module=%2Fsrc%2Findex.tsx)
Minimum sample: [![Edit typerapp-minimum-sample](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/diontools/typerapp-sample/tree/v0.1.0/typerapp-minimum-sample/?fontsize=14&module=%2Fsrc%2Findex.tsx)

## Install

Expand All @@ -21,25 +21,8 @@ npm install typerapp

## Modified points from Hyperapp

1. Remove `data` argument from Action
2. Add `dispatch` to `view` arguments
3. Pure DOM Events

### Remove `data` argument from Action

Typerapp Action has only two arguments.

Hyperapp:

```js
const Act = (state, { value }, data) => ({...})
```

Typerapp:

```typescript
const Act: Action<State, { value: number }> = (state, params) => ({...})
```
1. Add `dispatch` to `view` arguments
1. Pure DOM Events

### Add `dispatch` to `view` arguments

Expand Down Expand Up @@ -104,8 +87,8 @@ Type-safe Actions, Effects, Subscriptions, HTML Elements, and more...
Type:

```typescript
export type ActionResult<S> = S | [S, ...Effect<any, any>[]]
export type Action<S, P = Empty> = (state: S, params: P) => ActionResult<S>
export type ActionResult<S> = S | [S, ...Effect<S, any>[]]
export type Action<S, P = Empty> = (state: S, payload: P) => ActionResult<S>
```

Use:
Expand All @@ -115,9 +98,9 @@ Use:
const Increment: Action<State> = state => ({ ...state, value: state.value + 1 })

// with parameter
const Add: Action<State, { amount: number }> = (state, params) => ({
const Add: Action<State, { amount: number }> = (state, payload) => ({
...state,
value: state.value + params.amount
value: state.value + payload.amount
})
```

Expand All @@ -126,7 +109,7 @@ const Add: Action<State, { amount: number }> = (state, params) => ({
Type:

```typescript
export type Effect<S, P = Empty> = [(props: P, dispatch: Dispatch<S>) => void, P]
export type Effect<S, P = undefined> = [(dispatch: Dispatch<S>, props: P) => void, P]
```

Define Effect:
Expand All @@ -139,7 +122,7 @@ export type DelayProps<S, P> = {
}

// Delay Effect Runner
const DelayRunner = <S, P>(props: DelayProps<S, P>, dispatch: Dispatch<S>) => {
const DelayRunner = <S, P>(dispatch: Dispatch<S>, props: DelayProps<S, P>) => {
setTimeout(() => dispatch(props.action), props.duration)
}

Expand Down Expand Up @@ -170,7 +153,7 @@ const DelayAdd: Action<State, { amount: number }> = (state, params) => [
Type:

```typescript
export type Subscription<S, P = Empty> = [(props: P, dispatch: Dispatch<S>) => () => void, P]
export type Subscription<S, P = undefined> = [(dispatch: Dispatch<S>, props: P) => () => void, P]
```

Define Subscription:
Expand All @@ -183,7 +166,7 @@ export type TimerProps<S, P> = {
}

// Timer Subscription Runner
const timerRunner = <S, P>(props: TimerProps<S, P>, dispatch: Dispatch<S>) => {
const timerRunner = <S, P>(dispatch: Dispatch<S>, props: TimerProps<S, P>) => {
const id = setInterval(() => dispatch(props.action), props.interval)
return () => clearInterval(id)
}
Expand Down Expand Up @@ -222,7 +205,7 @@ const Act: Action<State> = state => ({
Workaround:

```typescript
// type alias for Action/ActionResult
// type alias for Action/ActionResult (for writing short)
type MyAction<P = Empty> = Action<State, P>
type MyResult = ActionResult<State>

Expand Down Expand Up @@ -266,23 +249,6 @@ export const view: View<State> = ({ part: state }, dispatch) => <div>
</div>
```

### ActionParamOf

`ActionParamOf` type gets parameter type of Action from Effect/Subscription Constructor.

```typescript
import { ActionParamOf } from 'typerapp'
import { httpJson } from 'typerapp/fx'

// { json: unknown }
type ParamType = ActionParamOf<typeof httpJson>

const JsonReceived: Action<State, ParamType> = (state, params) => ({
...state,
text: JSON.stringify(params.json)
})
```

### Helmet

`Helmet` renders to the head element of DOM.
Expand All @@ -308,7 +274,7 @@ const renderHead = (props: { title: string }) => <Helmet>

app<State>({
view: (state, dispatch) => <div>
<Lazy key="head" render={renderHead} title={state.title} />
<Lazy key="head" view={renderHead} title={state.title} />
</div>
})
```
Expand Down Expand Up @@ -422,26 +388,7 @@ import "typerapp/main/svg-alias"
</svg>
```

### mergeAction

In Typerapp, if your Effect/Subscription returns a value by Action, you must merge a return value into Action parameter, because Typerapp has not `data` of Action.

In that case, you can use `mergeAction` function.
## Changelog

```typescript
import { EffectAction, Dispatch, Effect } from "typerapp"
import { mergeAction } from 'typerapp/fx/utils'

export type RunnerProps<S, P> = {
action: EffectAction<S, P, { returnValue: number }>
}

const effectRunner = <S, P>(props: RunnerProps<S, P>, dispatch: Dispatch<S>) => {
dispatch(mergeAction(props.action, { returnValue: 1234 }))
}

export function effect<S, P>(action: RunnerProps<S, P>["action"]): Effect<S, RunnerProps<S, P>> {
return [effectRunner, { action }]
}
```
[See CHANGELOG.md](CHANGELOG.md)

2 changes: 1 addition & 1 deletion fx/effects/Delay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type DelayProps<S, P> = {
duration: number
}

const DelayRunner = <S, P>(props: DelayProps<S, P>, dispatch: Dispatch<S>) => {
const DelayRunner = <S, P>(dispatch: Dispatch<S>, props: DelayProps<S, P>) => {
setTimeout(() => dispatch(props.action), props.duration)
}

Expand Down
2 changes: 1 addition & 1 deletion fx/effects/Execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Dispatch, Effect } from "typerapp"

type Callback<S> = (dispatch: Dispatch<S>) => void

const ExecuteRunner = <S>(callback: Callback<S>, dispatch: Dispatch<S>) => callback(dispatch)
const ExecuteRunner = <S>(dispatch: Dispatch<S>, callback: Callback<S>) => callback(dispatch)

export function execute<S>(exec: Callback<S>): Effect<S, Callback<S>> {
return [ExecuteRunner, exec]
Expand Down
17 changes: 8 additions & 9 deletions fx/effects/Http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { EffectAction, Dispatch, Effect } from 'typerapp'
import { mergeAction } from '../utils'

export type HttpProps = string | [string, RequestInit]

export type HttpRunnerPropsBase<S, P, R> = {
action: EffectAction<S, P, R>
export type HttpRunnerPropsBase<S, P, EP> = {
action: EffectAction<S, P, EP>
req: HttpProps
}

Expand All @@ -14,11 +13,11 @@ const request = (req: HttpProps) => Array.isArray(req) ? fetch(req[0], req[1]) :

export type HttpRunnerProps<S, P> = HttpRunnerPropsBase<S, P, { response: Response }>

const httpRunner = <S, P>(props: HttpRunnerProps<S, P>, dispatch: Dispatch<S>) => {
const httpRunner = <S, P>(dispatch: Dispatch<S>, props: HttpRunnerProps<S, P>) => {
request(props.req)
.then(response => {
if (!response.ok) throw response
dispatch(mergeAction(props.action, { response }))
dispatch(props.action, { response })
})
.catch(error => { throw error })
}
Expand All @@ -30,13 +29,13 @@ export function http<S, P>(action: HttpRunnerProps<S, P>['action'], req: HttpPro

export type HttpTextRunnerProps<S, P> = HttpRunnerPropsBase<S, P, { text: string }>

const httpTextRunner = <S, P>(props: HttpTextRunnerProps<S, P>, dispatch: Dispatch<S>) => {
const httpTextRunner = <S, P>(dispatch: Dispatch<S>, props: HttpTextRunnerProps<S, P>) => {
request(props.req)
.then(response => {
if (!response.ok) throw response
return response.text()
})
.then(text => dispatch(mergeAction(props.action, { text })))
.then(text => dispatch(props.action, { text }))
.catch(error => { throw error })
}

Expand All @@ -47,13 +46,13 @@ export function httpText<S, P>(action: HttpTextRunnerProps<S, P>['action'], req:

export type HttpJsonRunnerProps<S, P> = HttpRunnerPropsBase<S, P, { json: unknown }>

const httpJsonRunner = <S, P>(props: HttpJsonRunnerProps<S, P>, dispatch: Dispatch<S>) => {
const httpJsonRunner = <S, P>(dispatch: Dispatch<S>, props: HttpJsonRunnerProps<S, P>) => {
request(props.req)
.then(response => {
if (!response.ok) throw response
return response.json()
})
.then((json: unknown) => dispatch(mergeAction(props.action, { json })))
.then((json: unknown) => dispatch(props.action, { json }))
.catch(error => { throw error })
}

Expand Down
2 changes: 1 addition & 1 deletion fx/subs/Timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type TimerProps<S, P> = {
interval: number
}

const timerRunner = <S, P>(props: TimerProps<S, P>, dispatch: Dispatch<S>) => {
const timerRunner = <S, P>(dispatch: Dispatch<S>, props: TimerProps<S, P>) => {
const id = setInterval(() => dispatch(props.action), props.interval)
return () => clearInterval(id)
}
Expand Down
5 changes: 0 additions & 5 deletions fx/utils.ts

This file was deleted.

Loading