Skip to content

Commit 6862b70

Browse files
committed
separate fx from subs for time and websocket
1 parent acaccaf commit 6862b70

File tree

16 files changed

+454
-266
lines changed

16 files changed

+454
-266
lines changed

api.md

Lines changed: 111 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* [.exports.ReadFromStorage(props)](#module_fx.exports.ReadFromStorage)
2525
* [.exports.RemoveFromStorage(props)](#module_fx.exports.RemoveFromStorage)
2626
* [.exports.Throttle(props)](#module_fx.exports.Throttle)
27+
* [.exports.Now(props)](#module_fx.exports.Now)
28+
* [.exports.Delay(props)](#module_fx.exports.Delay)
2729

2830
<a name="module_fx.exports.BatchFx"></a>
2931

@@ -115,7 +117,7 @@ Describes an effect that will add an entry to the browsers navigation [`history`
115117

116118
**Example**
117119
```js
118-
import { Console } from "hyperapp-fx"
120+
import { HistoryPush } from "hyperapp-fx"
119121

120122
export const UpdateHistory = state => [
121123
state,
@@ -142,7 +144,7 @@ Describes an effect that will replace the browsers current [`history`](https://d
142144

143145
**Example**
144146
```js
145-
import { Console } from "hyperapp-fx"
147+
import { HistoryReplace } from "hyperapp-fx"
146148

147149
export const InitialiseHistory = state => [
148150
state,
@@ -355,17 +357,100 @@ const ThrottledAction = state => [
355357
})
356358
]
357359
```
360+
<a name="module_fx.exports.Now"></a>
361+
362+
### fx.exports.Now(props)
363+
Describes an effect that provides the current timestamp (using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) or current date (using [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax)). The timestamp/date will be provided as the action `data`.
364+
365+
**Kind**: static method of [<code>fx</code>](#module_fx)
366+
367+
| Param | Type | Description |
368+
| --- | --- | --- |
369+
| props | <code>object</code> | |
370+
| props.asDate | <code>boolean</code> | use a Date object instead of a timestamp |
371+
| props.action | <code>\*</code> | action to call with the timestamp/date |
372+
373+
**Example**
374+
```js
375+
import { Now } from "hyperapp-fx"
376+
377+
const NowAction = state => [
378+
state,
379+
Now({
380+
asDate: true,
381+
action(currentDate) {
382+
}
383+
})
384+
]
385+
```
386+
<a name="module_fx.exports.Delay"></a>
387+
388+
### fx.exports.Delay(props)
389+
Describes an effect that provides a timestamp (using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) or date (using [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax)) after a delay. The timestamp/date will be provided as the action `data`.
390+
391+
**Kind**: static method of [<code>fx</code>](#module_fx)
392+
393+
| Param | Type | Description |
394+
| --- | --- | --- |
395+
| props | <code>object</code> | |
396+
| props.wait | <code>number</code> | delay to wait before calling action |
397+
| props.asDate | <code>boolean</code> | use a Date object instead of a timestamp |
398+
| props.action | <code>\*</code> | action to call with the timestamp/date |
399+
400+
**Example**
401+
```js
402+
import { Delay } from "hyperapp-fx"
403+
404+
const DelayedAction = state => [
405+
state,
406+
Delay({
407+
wait: 500,
408+
action() {
409+
// This action will run after a 500ms delay
410+
}
411+
})
412+
]
413+
```
358414
<a name="module_subs"></a>
359415

360416
## subs
361417

362418
* [subs](#module_subs)
419+
* [.exports.WebSocketSend(props)](#module_subs.exports.WebSocketSend)
363420
* [.exports.Animation(action)](#module_subs.exports.Animation)
364421
* [.exports.HistoryPop(action)](#module_subs.exports.HistoryPop)
365422
* [.exports.Keyboard(props)](#module_subs.exports.Keyboard)
366-
* [.exports.Time(props)](#module_subs.exports.Time)
367-
* [.exports.WebSocketClient(props)](#module_subs.exports.WebSocketClient)
423+
* [.exports.Interval(props)](#module_subs.exports.Interval)
424+
* [.exports.WebSocketListen(props)](#module_subs.exports.WebSocketListen)
368425

426+
<a name="module_subs.exports.WebSocketSend"></a>
427+
428+
### subs.exports.WebSocketSend(props)
429+
Describes an effect that will open a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) connection for a given URL (and optional protocols) and send a message reusing existing connections.
430+
431+
**Kind**: static method of [<code>subs</code>](#module_subs)
432+
433+
| Param | Type | Description |
434+
| --- | --- | --- |
435+
| props | <code>object</code> | |
436+
| props.url | <code>string</code> | The URL to which to connect; this should be the URL to which the WebSocket server will respond |
437+
| props.protocols | <code>string</code> \| <code>Array.&lt;string&gt;</code> | Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols, so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified `protocol`). If you don't specify a protocol string, an empty string is assumed. |
438+
| props.data | <code>\*</code> | data to send once connected |
439+
440+
**Example**
441+
```js
442+
import { WebSocketSend } from "hyperapp-fx"
443+
444+
const SendAction = state => [
445+
state,
446+
WebSocketSend({
447+
url: "wss://example.com",
448+
data: JSON.stringify({
449+
sendThisData: "on connecting"
450+
})
451+
})
452+
]
453+
```
369454
<a name="module_subs.exports.Animation"></a>
370455

371456
### subs.exports.Animation(action)
@@ -421,13 +506,16 @@ Describes an effect that will call an action whenever a user navigates through t
421506

422507
**Example**
423508
```js
509+
import { h, app } from "hyperapp"
424510
import { HistoryPop } from "hyperapp-fx"
425511

426512
app({
427-
init: { page: 1 },
428-
view: state => <App page={state.page} />,
429-
container: document.body,
430-
subscriptions: state => [HistoryPop({ action: (state, event) => event.state || state })]
513+
init: { page: 1 },
514+
view: state => <App page={state.page} />,
515+
container: document.body,
516+
subscriptions: state => [
517+
HistoryPop({ action: (state, event) => event.state || state })
518+
]
431519
})
432520
```
433521
<a name="module_subs.exports.Keyboard"></a>
@@ -458,26 +546,24 @@ const KeySub = Keyboard({
458546
}
459547
})
460548
```
461-
<a name="module_subs.exports.Time"></a>
549+
<a name="module_subs.exports.Interval"></a>
462550

463-
### subs.exports.Time(props)
464-
Describes an effect that can provide timestamps to actions using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) or dates using the [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax) API. The action can be fired now, after a delay, or at a regular interval. The timestamp/date will be provided as the action `data`.
551+
### subs.exports.Interval(props)
552+
Describes an effect that provides a timestamp (using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) or date (using [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax)) at a regular interval. The timestamp/date will be provided as the action `data`.
465553

466554
**Kind**: static method of [<code>subs</code>](#module_subs)
467555

468556
| Param | Type | Description |
469557
| --- | --- | --- |
470558
| props | <code>object</code> | |
471-
| props.now | <code>boolean</code> | get the current time immediately |
472-
| props.after | <code>number</code> | get the time after a delay |
473-
| props.every | <code>number</code> | get the time repeatedly after waiting a set interval |
474559
| props.asDate | <code>boolean</code> | use a Date object instead of a timestamp |
475-
| props.action | <code>\*</code> | action to call with the time |
560+
| props.every | <code>number</code> | get the time repeatedly after waiting a set interval |
561+
| props.action | <code>\*</code> | action to call with the timestamp/date |
476562

477563
**Example**
478564
```js
479565
import { h, app } from "hyperapp"
480-
import { Time } from "hyperapp-fx"
566+
import { Now, Interval } from "hyperapp-fx"
481567

482568
const UpdateDate = (_, date) =>
483569
date.toLocaleString("uk", {
@@ -486,13 +572,12 @@ const UpdateDate = (_, date) =>
486572
second: "numeric"
487573
})
488574

489-
const InitialTime = Time({
490-
now: true,
575+
const InitialTime = Now({
491576
asDate: true,
492577
action: UpdateDate
493578
})
494579

495-
const TimeSub = Time({
580+
const TimeSub = Interval({
496581
every: 100,
497582
asDate: true,
498583
action: UpdateDate
@@ -505,10 +590,10 @@ app({
505590
subscriptions: () => [TimeSub]
506591
})
507592
```
508-
<a name="module_subs.exports.WebSocketClient"></a>
593+
<a name="module_subs.exports.WebSocketListen"></a>
509594

510-
### subs.exports.WebSocketClient(props)
511-
Describes an effect that will open a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) connection for a given URL and optional protocols. A message may be sent to the server on connection and messages to the client may be listened for. Connections will remain open until the last subscription for that URL are cancelled.
595+
### subs.exports.WebSocketListen(props)
596+
Describes an effect that will open a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) connection for a given URL and optional protocols. Connections will remain open until the last subscription for that URL are cancelled.
512597

513598
**Kind**: static method of [<code>subs</code>](#module_subs)
514599

@@ -517,19 +602,15 @@ Describes an effect that will open a [`WebSocket`](https://developer.mozilla.org
517602
| props | <code>object</code> | |
518603
| props.url | <code>string</code> | The URL to which to connect; this should be the URL to which the WebSocket server will respond |
519604
| props.protocols | <code>string</code> \| <code>Array.&lt;string&gt;</code> | Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols, so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified `protocol`). If you don't specify a protocol string, an empty string is assumed. |
520-
| props.send | <code>\*</code> | data to send once connected |
521-
| props.listen | <code>\*</code> | action to call with new incoming messages |
605+
| props.action | <code>\*</code> | action to call with new incoming messages |
522606
| props.error | <code>\*</code> | action to call if an error occurs |
523607

524608
**Example**
525609
```js
526-
import { WebSocketClient } from "hyperapp-fx"
610+
import { WebSocketListen } from "hyperapp-fx"
527611

528-
const WebSocketSub = WebSocketClient({
612+
const WebSocketSub = WebSocketListen({
529613
url: "wss://example.com",
530-
send: JSON.stringify({
531-
sendThisData: "on connecting"
532-
}),
533-
listen: ReceivedMessageAction
614+
action: ReceivedMessageAction
534615
})
535616
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hyperapp-fx",
3-
"version": "2.0.0-alpha.3",
3+
"version": "2.0.0-alpha.4",
44
"description": "Effects for use with Hyperapp",
55
"main": "dist/hyperappFx.js",
66
"module": "src/index.js",

src/fx/History.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function historyReplaceEffect(props) {
2121
* @param {string} props.url - url to add to browser history
2222
* @param {string} props.title - title to set document to
2323
* @example
24-
* import { Console } from "hyperapp-fx"
24+
* import { HistoryPush } from "hyperapp-fx"
2525
*
2626
* export const UpdateHistory = state => [
2727
* state,
@@ -46,7 +46,7 @@ export function HistoryPush(props) {
4646
* @param {string} props.url - url to add to browser history
4747
* @param {string} props.title - title to set document to
4848
* @example
49-
* import { Console } from "hyperapp-fx"
49+
* import { HistoryReplace } from "hyperapp-fx"
5050
*
5151
* export const InitialiseHistory = state => [
5252
* state,

src/fx/Time.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { makeDispatchTime } from "../utils"
2+
3+
function nowEffect(props, dispatch) {
4+
makeDispatchTime(props, dispatch)()
5+
}
6+
7+
function delayEffect(props, dispatch) {
8+
setTimeout(makeDispatchTime(props, dispatch), props.wait)
9+
}
10+
11+
/**
12+
* Describes an effect that provides the current timestamp (using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) or current date (using [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax)). The timestamp/date will be provided as the action `data`.
13+
*
14+
* @memberof module:fx
15+
* @param {object} props
16+
* @param {boolean} props.asDate - use a Date object instead of a timestamp
17+
* @param {*} props.action - action to call with the timestamp/date
18+
* @example
19+
* import { Now } from "hyperapp-fx"
20+
*
21+
* const NowAction = state => [
22+
* state,
23+
* Now({
24+
* asDate: true,
25+
* action(currentDate) {
26+
* }
27+
* })
28+
* ]
29+
*/
30+
export function Now(props) {
31+
return [nowEffect, props]
32+
}
33+
34+
/**
35+
* Describes an effect that provides a timestamp (using [`performance.now`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)) or date (using [`new Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax)) after a delay. The timestamp/date will be provided as the action `data`.
36+
*
37+
* @memberof module:fx
38+
* @param {object} props
39+
* @param {number} props.wait - delay to wait before calling action
40+
* @param {boolean} props.asDate - use a Date object instead of a timestamp
41+
* @param {*} props.action - action to call with the timestamp/date
42+
* @example
43+
* import { Delay } from "hyperapp-fx"
44+
*
45+
* const DelayedAction = state => [
46+
* state,
47+
* Delay({
48+
* wait: 500,
49+
* action() {
50+
* // This action will run after a 500ms delay
51+
* }
52+
* })
53+
* ]
54+
*/
55+
export function Delay(props) {
56+
return [delayEffect, props]
57+
}

src/fx/WebSocket.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getOpenWebSocket } from "../utils.js"
2+
3+
var CONNECTING = 0
4+
5+
function webSocketSendEffect(props) {
6+
var connection = getOpenWebSocket(props)
7+
function sendMessage() {
8+
connection.socket.send(props.data)
9+
connection.socket.removeEventListener("open", sendMessage)
10+
}
11+
if (connection.socket.readyState === CONNECTING) {
12+
connection.socket.addEventListener("open", sendMessage)
13+
} else {
14+
sendMessage()
15+
}
16+
}
17+
18+
/**
19+
* Describes an effect that will open a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) connection for a given URL (and optional protocols) and send a message reusing existing connections.
20+
*
21+
* @memberof module:subs
22+
* @param {object} props
23+
* @param {string} props.url - The URL to which to connect; this should be the URL to which the WebSocket server will respond
24+
* @param {string | string[]} props.protocols - Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols, so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified `protocol`). If you don't specify a protocol string, an empty string is assumed.
25+
* @param {*} props.data - data to send once connected
26+
* @example
27+
* import { WebSocketSend } from "hyperapp-fx"
28+
*
29+
* const SendAction = state => [
30+
* state,
31+
* WebSocketSend({
32+
* url: "wss://example.com",
33+
* data: JSON.stringify({
34+
* sendThisData: "on connecting"
35+
* })
36+
* })
37+
* ]
38+
*/
39+
export function WebSocketSend(props) {
40+
return [webSocketSendEffect, props]
41+
}

src/fx/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export * from "./Debounce.js"
1111
export * from "./Throttle.js"
1212
export * from "./Storage.js"
1313
export * from "./History.js"
14+
export * from "./Time.js"
15+
export * from "./WebSocket.js"

src/subs/History.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ function historyPopEffect(props, dispatch) {
1010
* @memberof module:subs
1111
* @param {*} action - Action to call
1212
* @example
13+
* import { h, app } from "hyperapp"
1314
* import { HistoryPop } from "hyperapp-fx"
1415
*
1516
* app({
16-
* init: { page: 1 },
17-
* view: state => <App page={state.page} />,
18-
* container: document.body,
19-
* subscriptions: state => [HistoryPop({ action: (state, event) => event.state || state })]
17+
* init: { page: 1 },
18+
* view: state => <App page={state.page} />,
19+
* container: document.body,
20+
* subscriptions: state => [
21+
* HistoryPop({ action: (state, event) => event.state || state })
22+
* ]
2023
* })
21-
*
2224
*/
2325

2426
export function HistoryPop(props) {

0 commit comments

Comments
 (0)