atom.io 0.6.7 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +241 -263
- package/dist/index.d.ts +241 -263
- package/dist/index.js +28 -1911
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -1871
- package/dist/index.mjs.map +1 -1
- package/introspection/dist/index.d.mts +121 -176
- package/introspection/dist/index.d.ts +121 -176
- package/introspection/dist/index.js +6 -346
- package/introspection/dist/index.js.map +1 -1
- package/introspection/dist/index.mjs +5 -324
- package/introspection/dist/index.mjs.map +1 -1
- package/json/dist/index.d.mts +37 -8
- package/json/dist/index.d.ts +37 -8
- package/json/dist/index.js +31 -48
- package/json/dist/index.js.map +1 -1
- package/json/dist/index.mjs +6 -14
- package/json/dist/index.mjs.map +1 -1
- package/package.json +30 -14
- package/react/dist/index.js +34 -83
- package/react/dist/index.js.map +1 -1
- package/react/dist/index.mjs +7 -43
- package/react/dist/index.mjs.map +1 -1
- package/react-devtools/dist/index.css +1 -42
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +128 -193
- package/react-devtools/dist/index.d.ts +128 -193
- package/react-devtools/dist/index.js +56 -4154
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +19 -4117
- package/react-devtools/dist/index.mjs.map +1 -1
- package/realtime/dist/index.d.mts +7 -11
- package/realtime/dist/index.d.ts +7 -11
- package/realtime/dist/index.js +26 -185
- package/realtime/dist/index.js.map +1 -1
- package/realtime/dist/index.mjs +4 -149
- package/realtime/dist/index.mjs.map +1 -1
- package/realtime-react/dist/index.d.mts +12 -16
- package/realtime-react/dist/index.d.ts +12 -16
- package/realtime-react/dist/index.js +41 -214
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/dist/index.mjs +9 -169
- package/realtime-react/dist/index.mjs.map +1 -1
- package/src/atom.ts +7 -6
- package/src/index.ts +12 -9
- package/src/logger.ts +5 -5
- package/src/selector.ts +16 -14
- package/src/silo.ts +36 -39
- package/src/subscribe.ts +25 -20
- package/src/timeline.ts +9 -4
- package/src/transaction.ts +3 -4
- package/src/internal/atom-internal.ts +0 -54
- package/src/internal/families-internal.ts +0 -141
- package/src/internal/get.ts +0 -129
- package/src/internal/index.ts +0 -15
- package/src/internal/is-default.ts +0 -35
- package/src/internal/operation.ts +0 -139
- package/src/internal/selector/create-read-write-selector.ts +0 -66
- package/src/internal/selector/create-readonly-selector.ts +0 -46
- package/src/internal/selector/index.ts +0 -4
- package/src/internal/selector/lookup-selector-sources.ts +0 -16
- package/src/internal/selector/register-selector.ts +0 -57
- package/src/internal/selector/trace-selector-atoms.ts +0 -43
- package/src/internal/selector/update-selector-atoms.ts +0 -33
- package/src/internal/selector-internal.ts +0 -58
- package/src/internal/set.ts +0 -99
- package/src/internal/store.ts +0 -151
- package/src/internal/subject.ts +0 -24
- package/src/internal/subscribe-internal.ts +0 -88
- package/src/internal/time-travel-internal.ts +0 -91
- package/src/internal/timeline/add-atom-to-timeline.ts +0 -168
- package/src/internal/timeline/index.ts +0 -1
- package/src/internal/timeline-internal.ts +0 -107
- package/src/internal/transaction/abort-transaction.ts +0 -12
- package/src/internal/transaction/apply-transaction.ts +0 -57
- package/src/internal/transaction/build-transaction.ts +0 -33
- package/src/internal/transaction/index.ts +0 -25
- package/src/internal/transaction/redo-transaction.ts +0 -23
- package/src/internal/transaction/undo-transaction.ts +0 -23
- package/src/internal/transaction-internal.ts +0 -61
- package/src/introspection/attach-atom-index.ts +0 -73
- package/src/introspection/attach-introspection-states.ts +0 -42
- package/src/introspection/attach-selector-index.ts +0 -77
- package/src/introspection/attach-timeline-family.ts +0 -59
- package/src/introspection/attach-timeline-index.ts +0 -36
- package/src/introspection/attach-transaction-index.ts +0 -38
- package/src/introspection/attach-transaction-logs.ts +0 -40
- package/src/introspection/index.ts +0 -20
- package/src/json/index.ts +0 -1
- package/src/json/select-json.ts +0 -18
- package/src/react/index.ts +0 -2
- package/src/react/store-context.tsx +0 -13
- package/src/react/store-hooks.ts +0 -47
- package/src/react-devtools/AtomIODevtools.tsx +0 -107
- package/src/react-devtools/Button.tsx +0 -24
- package/src/react-devtools/StateEditor.tsx +0 -70
- package/src/react-devtools/StateIndex.tsx +0 -153
- package/src/react-devtools/TimelineIndex.tsx +0 -92
- package/src/react-devtools/TransactionIndex.tsx +0 -70
- package/src/react-devtools/Updates.tsx +0 -145
- package/src/react-devtools/devtools.scss +0 -311
- package/src/react-devtools/index.ts +0 -72
- package/src/react-explorer/AtomIOExplorer.tsx +0 -218
- package/src/react-explorer/explorer-effects.ts +0 -20
- package/src/react-explorer/explorer-states.ts +0 -217
- package/src/react-explorer/index.ts +0 -23
- package/src/react-explorer/space-states.ts +0 -72
- package/src/react-explorer/view-states.ts +0 -41
- package/src/realtime/README.md +0 -33
- package/src/realtime/hook-composition/expose-family.ts +0 -101
- package/src/realtime/hook-composition/expose-single.ts +0 -38
- package/src/realtime/hook-composition/expose-timeline.ts +0 -60
- package/src/realtime/hook-composition/index.ts +0 -12
- package/src/realtime/hook-composition/receive-state.ts +0 -29
- package/src/realtime/hook-composition/receive-transaction.ts +0 -18
- package/src/realtime/index.ts +0 -1
- package/src/realtime-react/index.ts +0 -3
- package/src/realtime-react/realtime-context.tsx +0 -30
- package/src/realtime-react/realtime-hooks.ts +0 -39
- package/src/realtime-react/realtime-state.ts +0 -10
- package/src/realtime-react/use-pull-family-member.ts +0 -26
- package/src/realtime-react/use-pull-family.ts +0 -24
- package/src/realtime-react/use-pull.ts +0 -22
- package/src/realtime-react/use-push.ts +0 -25
- package/src/realtime-react/use-server-action.ts +0 -33
- package/src/realtime-testing/index.ts +0 -1
- package/src/realtime-testing/setup-realtime-test.tsx +0 -159
- package/src/web-effects/index.ts +0 -1
- package/src/web-effects/storage.ts +0 -30
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { Json } from "anvl/json"
|
|
2
|
-
import { parseJson } from "anvl/json"
|
|
3
|
-
import * as AtomIO from "atom.io"
|
|
4
|
-
|
|
5
|
-
import type { ServerConfig } from ".."
|
|
6
|
-
|
|
7
|
-
const subscribeToTokenCreation = <T>(
|
|
8
|
-
family: AtomIO.AtomFamily<T> | AtomIO.SelectorFamily<T>,
|
|
9
|
-
handleTokenCreation: (token: AtomIO.StateToken<T>) => void,
|
|
10
|
-
): (() => void) => {
|
|
11
|
-
const subscription =
|
|
12
|
-
family.type === `atom_family`
|
|
13
|
-
? family.subject.subscribe(handleTokenCreation)
|
|
14
|
-
: family.subject.subscribe(handleTokenCreation)
|
|
15
|
-
return () => subscription.unsubscribe()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
19
|
-
export const useExposeFamily = ({ socket, store }: ServerConfig) => {
|
|
20
|
-
return function exposeFamily<J extends Json>(
|
|
21
|
-
family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
|
|
22
|
-
index: AtomIO.StateToken<Set<string>>,
|
|
23
|
-
): () => void {
|
|
24
|
-
const unsubSingleCallbacksByKey = new Map<string, () => void>()
|
|
25
|
-
const unsubFamilyCallbacksByKey = new Map<string, () => void>()
|
|
26
|
-
|
|
27
|
-
const fillFamilyUnsubRequest = () => {
|
|
28
|
-
unsubFamilyCallbacksByKey.forEach((unsub) => unsub())
|
|
29
|
-
unsubFamilyCallbacksByKey.clear()
|
|
30
|
-
socket.off(`unsub:${family.key}`, fillFamilyUnsubRequest)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const fillSingleUnsubRequest = (key: string) => {
|
|
34
|
-
socket.off(`unsub:${key}`, fillSingleUnsubRequest)
|
|
35
|
-
const unsub = unsubSingleCallbacksByKey.get(key)
|
|
36
|
-
if (unsub) {
|
|
37
|
-
unsub()
|
|
38
|
-
unsubSingleCallbacksByKey.delete(key)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const fillSubRequest = (subKey?: AtomIO.Serializable) => {
|
|
43
|
-
if (subKey === undefined) {
|
|
44
|
-
const keys = AtomIO.getState(index, store)
|
|
45
|
-
keys.forEach((key) => {
|
|
46
|
-
const token = family(key)
|
|
47
|
-
socket.emit(
|
|
48
|
-
`serve:${family.key}`,
|
|
49
|
-
parseJson(token.family?.subKey || `null`),
|
|
50
|
-
AtomIO.getState(token, store),
|
|
51
|
-
)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const unsubscribeFromTokenCreation = subscribeToTokenCreation(
|
|
55
|
-
family,
|
|
56
|
-
(token) => {
|
|
57
|
-
const unsub = AtomIO.subscribe(
|
|
58
|
-
token,
|
|
59
|
-
({ newValue }) => {
|
|
60
|
-
socket.emit(
|
|
61
|
-
`serve:${family.key}`,
|
|
62
|
-
parseJson(token.family?.subKey || `null`),
|
|
63
|
-
newValue,
|
|
64
|
-
)
|
|
65
|
-
},
|
|
66
|
-
store,
|
|
67
|
-
)
|
|
68
|
-
unsubFamilyCallbacksByKey.set(token.key, unsub)
|
|
69
|
-
},
|
|
70
|
-
)
|
|
71
|
-
unsubFamilyCallbacksByKey.set(family.key, unsubscribeFromTokenCreation)
|
|
72
|
-
|
|
73
|
-
socket.on(`unsub:${family.key}`, fillFamilyUnsubRequest)
|
|
74
|
-
} else {
|
|
75
|
-
const token = family(subKey)
|
|
76
|
-
socket.emit(`serve:${token.key}`, AtomIO.getState(token, store))
|
|
77
|
-
const unsubscribe = AtomIO.subscribe(
|
|
78
|
-
token,
|
|
79
|
-
({ newValue }) => {
|
|
80
|
-
socket.emit(`serve:${token.key}`, newValue)
|
|
81
|
-
},
|
|
82
|
-
store,
|
|
83
|
-
)
|
|
84
|
-
unsubSingleCallbacksByKey.set(token.key, unsubscribe)
|
|
85
|
-
socket.on(`unsub:${token.key}`, () => {
|
|
86
|
-
fillSingleUnsubRequest(token.key)
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
socket.on(`sub:${family.key}`, fillSubRequest)
|
|
92
|
-
|
|
93
|
-
return () => {
|
|
94
|
-
socket.off(`sub:${family.key}`, fillSubRequest)
|
|
95
|
-
unsubFamilyCallbacksByKey.forEach((unsub) => unsub())
|
|
96
|
-
unsubSingleCallbacksByKey.forEach((unsub) => unsub())
|
|
97
|
-
unsubFamilyCallbacksByKey.clear()
|
|
98
|
-
unsubSingleCallbacksByKey.clear()
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Json } from "anvl/json"
|
|
2
|
-
import * as AtomIO from "atom.io"
|
|
3
|
-
|
|
4
|
-
import type { ServerConfig } from ".."
|
|
5
|
-
|
|
6
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
7
|
-
export const useExposeSingle = ({ socket, store }: ServerConfig) => {
|
|
8
|
-
return function exposeSingle<J extends Json>(
|
|
9
|
-
token: AtomIO.StateToken<J>,
|
|
10
|
-
): () => void {
|
|
11
|
-
let unsubscribeFromStateUpdates: (() => void) | null = null
|
|
12
|
-
|
|
13
|
-
const fillUnsubRequest = () => {
|
|
14
|
-
socket.off(`unsub:${token.key}`, fillUnsubRequest)
|
|
15
|
-
unsubscribeFromStateUpdates?.()
|
|
16
|
-
unsubscribeFromStateUpdates = null
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const fillSubRequest = () => {
|
|
20
|
-
socket.emit(`serve:${token.key}`, AtomIO.getState(token, store))
|
|
21
|
-
unsubscribeFromStateUpdates = AtomIO.subscribe(
|
|
22
|
-
token,
|
|
23
|
-
({ newValue }) => {
|
|
24
|
-
socket.emit(`serve:${token.key}`, newValue)
|
|
25
|
-
},
|
|
26
|
-
store,
|
|
27
|
-
)
|
|
28
|
-
socket.on(`unsub:${token.key}`, fillUnsubRequest)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
socket.on(`sub:${token.key}`, fillSubRequest)
|
|
32
|
-
|
|
33
|
-
return () => {
|
|
34
|
-
socket.off(`sub:${token.key}`, fillSubRequest)
|
|
35
|
-
unsubscribeFromStateUpdates?.()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
|
|
3
|
-
import { Join } from "~/packages/anvl/src/join"
|
|
4
|
-
|
|
5
|
-
import type { ServerConfig } from "."
|
|
6
|
-
import type { TimelineTransactionUpdate } from "../../internal"
|
|
7
|
-
|
|
8
|
-
export type TransactionRequest = {
|
|
9
|
-
key: string
|
|
10
|
-
params: unknown[]
|
|
11
|
-
transactionId: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const useExposeTimeline__UNSTABLE = ({
|
|
15
|
-
socket,
|
|
16
|
-
store,
|
|
17
|
-
}: ServerConfig): ((tl: AtomIO.TimelineToken) => () => void) => {
|
|
18
|
-
const timestampsOfTransactionsState = AtomIO.__INTERNAL__.atom__INTERNAL(
|
|
19
|
-
{
|
|
20
|
-
key: `timestampsOfTransactions`,
|
|
21
|
-
default: new Join<null, `transactionId`, `timestamp`>({
|
|
22
|
-
relationType: `1:1`,
|
|
23
|
-
})
|
|
24
|
-
.from(`transactionId`)
|
|
25
|
-
.to(`timestamp`),
|
|
26
|
-
},
|
|
27
|
-
undefined,
|
|
28
|
-
store,
|
|
29
|
-
)
|
|
30
|
-
return function exposeTimeline(tl: AtomIO.TimelineToken): () => void {
|
|
31
|
-
const handleTransactionRequest = (update: TransactionRequest) => {
|
|
32
|
-
AtomIO.runTransaction(
|
|
33
|
-
{ key: update.key, type: `transaction` },
|
|
34
|
-
store,
|
|
35
|
-
)(...update.params)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
socket.on(`txr:${tl.key}`, handleTransactionRequest)
|
|
39
|
-
|
|
40
|
-
const unsubscribeFromTimeline = AtomIO.subscribeToTimeline(
|
|
41
|
-
tl,
|
|
42
|
-
(update: TimelineTransactionUpdate) => {
|
|
43
|
-
// const timestamp = update.timestamp.toString()
|
|
44
|
-
// AtomIO.setState(
|
|
45
|
-
// timestampsOfTransactionsState,
|
|
46
|
-
// (j) => j.set(update),
|
|
47
|
-
// store
|
|
48
|
-
// )
|
|
49
|
-
if (update.type === `transaction_update`) {
|
|
50
|
-
socket.emit(`tl:${tl.key}`, update)
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
return () => {
|
|
56
|
-
socket.off(`tlu:${tl.key}`, handleTransactionRequest)
|
|
57
|
-
unsubscribeFromTimeline()
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type * as AtomIO from "atom.io"
|
|
2
|
-
import type * as SocketIO from "socket.io"
|
|
3
|
-
|
|
4
|
-
export * from "./expose-single"
|
|
5
|
-
export * from "./expose-family"
|
|
6
|
-
export * from "./receive-transaction"
|
|
7
|
-
export * from "./receive-state"
|
|
8
|
-
|
|
9
|
-
export type ServerConfig = {
|
|
10
|
-
socket: SocketIO.Socket
|
|
11
|
-
store?: AtomIO.__INTERNAL__.Store
|
|
12
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { Json } from "anvl/json"
|
|
2
|
-
import * as AtomIO from "atom.io"
|
|
3
|
-
|
|
4
|
-
import type { ServerConfig } from ".."
|
|
5
|
-
|
|
6
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
7
|
-
export const useReceiveState = ({ socket, store }: ServerConfig) => {
|
|
8
|
-
return function receiveState<J extends Json>(
|
|
9
|
-
token: AtomIO.StateToken<J>,
|
|
10
|
-
): () => void {
|
|
11
|
-
const publish = (newValue: J) => AtomIO.setState(token, newValue, store)
|
|
12
|
-
|
|
13
|
-
const fillPubUnclaim = () => {
|
|
14
|
-
socket.off(`pub:${token.key}`, publish)
|
|
15
|
-
socket.off(`unclaim:${token.key}`, fillPubUnclaim)
|
|
16
|
-
}
|
|
17
|
-
const fillPubClaim = () => {
|
|
18
|
-
socket.on(`pub:${token.key}`, publish)
|
|
19
|
-
socket.on(`unclaim:${token.key}`, fillPubUnclaim)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
socket.on(`claim:${token.key}`, fillPubClaim)
|
|
23
|
-
|
|
24
|
-
return () => {
|
|
25
|
-
socket.off(`claim:${token.key}`, fillPubClaim)
|
|
26
|
-
socket.off(`pub:${token.key}`, publish)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
|
|
3
|
-
import type { ƒn } from "~/packages/anvl/src/function"
|
|
4
|
-
|
|
5
|
-
import type { ServerConfig } from "."
|
|
6
|
-
|
|
7
|
-
export const useReceiveTransaction = ({ socket, store }: ServerConfig) => {
|
|
8
|
-
return function receiveTransaction<ƒ extends ƒn>(
|
|
9
|
-
tx: AtomIO.TransactionToken<ƒ>,
|
|
10
|
-
): () => void {
|
|
11
|
-
const fillTransactionRequest = (update: AtomIO.TransactionUpdate<ƒ>) =>
|
|
12
|
-
AtomIO.runTransaction<ƒ>(tx, store)(...update.params)
|
|
13
|
-
|
|
14
|
-
socket.on(`tx:${tx.key}`, fillTransactionRequest)
|
|
15
|
-
|
|
16
|
-
return () => socket.off(`tx:${tx.key}`, fillTransactionRequest)
|
|
17
|
-
}
|
|
18
|
-
}
|
package/src/realtime/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./hook-composition"
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as AR from "atom.io/react"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
import type { Socket } from "socket.io-client"
|
|
4
|
-
import { io } from "socket.io-client"
|
|
5
|
-
|
|
6
|
-
import { myIdState__INTERNAL } from "./realtime-state"
|
|
7
|
-
|
|
8
|
-
export const RealtimeContext = React.createContext<{ socket: Socket }>({
|
|
9
|
-
socket: io(),
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
export const RealtimeProvider: React.FC<{
|
|
13
|
-
children: React.ReactNode
|
|
14
|
-
socket: Socket
|
|
15
|
-
}> = ({ children, socket }) => {
|
|
16
|
-
const setMyId = AR.useI(myIdState__INTERNAL)
|
|
17
|
-
React.useEffect(() => {
|
|
18
|
-
socket.on(`connect`, () => {
|
|
19
|
-
setMyId(socket.id)
|
|
20
|
-
})
|
|
21
|
-
socket.on(`disconnect`, () => {
|
|
22
|
-
setMyId(null)
|
|
23
|
-
})
|
|
24
|
-
}, [socket, setMyId])
|
|
25
|
-
return (
|
|
26
|
-
<RealtimeContext.Provider value={{ socket }}>
|
|
27
|
-
{children}
|
|
28
|
-
</RealtimeContext.Provider>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type * as AtomIO from "atom.io"
|
|
2
|
-
|
|
3
|
-
import type { ƒn } from "~/packages/anvl/src/function"
|
|
4
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
5
|
-
|
|
6
|
-
import { usePull } from "./use-pull"
|
|
7
|
-
import { usePullFamily } from "./use-pull-family"
|
|
8
|
-
import { usePullFamilyMember } from "./use-pull-family-member"
|
|
9
|
-
import { usePush } from "./use-push"
|
|
10
|
-
import { useServerAction } from "./use-server-action"
|
|
11
|
-
|
|
12
|
-
export type RealtimeHooks = {
|
|
13
|
-
usePull: <J extends Json>(token: AtomIO.StateToken<J>) => void
|
|
14
|
-
usePullFamily: <J extends Json>(
|
|
15
|
-
family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
|
|
16
|
-
) => void
|
|
17
|
-
usePullFamilyMember: <J extends Json>(
|
|
18
|
-
family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
|
|
19
|
-
subKey: string,
|
|
20
|
-
) => void
|
|
21
|
-
usePush: <J extends Json>(token: AtomIO.StateToken<J>) => void
|
|
22
|
-
useServerAction: <ƒ extends ƒn>(
|
|
23
|
-
token: AtomIO.TransactionToken<ƒ>,
|
|
24
|
-
) => (...parameters: Parameters<ƒ>) => ReturnType<ƒ>
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const realtimeHooks: RealtimeHooks = {
|
|
28
|
-
usePull,
|
|
29
|
-
usePullFamily,
|
|
30
|
-
usePullFamilyMember,
|
|
31
|
-
usePush,
|
|
32
|
-
useServerAction,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export * from "./use-pull"
|
|
36
|
-
export * from "./use-pull-family"
|
|
37
|
-
export * from "./use-pull-family-member"
|
|
38
|
-
export * from "./use-push"
|
|
39
|
-
export * from "./use-server-action"
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
|
|
3
|
-
export const myIdState__INTERNAL = AtomIO.atom<string | null>({
|
|
4
|
-
key: `myId__INTERNAL`,
|
|
5
|
-
default: null,
|
|
6
|
-
})
|
|
7
|
-
export const myIdState = AtomIO.selector<string | null>({
|
|
8
|
-
key: `myId`,
|
|
9
|
-
get: ({ get }) => get(myIdState__INTERNAL),
|
|
10
|
-
})
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
|
|
4
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
5
|
-
|
|
6
|
-
import { RealtimeContext } from "./realtime-context"
|
|
7
|
-
import { StoreContext } from "../react"
|
|
8
|
-
|
|
9
|
-
export function usePullFamilyMember<J extends Json>(
|
|
10
|
-
family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
|
|
11
|
-
subKey: AtomIO.Serializable,
|
|
12
|
-
): void {
|
|
13
|
-
const token = family(subKey)
|
|
14
|
-
const { socket } = React.useContext(RealtimeContext)
|
|
15
|
-
const store = React.useContext(StoreContext)
|
|
16
|
-
React.useEffect(() => {
|
|
17
|
-
socket?.on(`serve:${token.key}`, (data: J) => {
|
|
18
|
-
AtomIO.setState(family(subKey), data, store)
|
|
19
|
-
})
|
|
20
|
-
socket?.emit(`sub:${family.key}`, subKey)
|
|
21
|
-
return () => {
|
|
22
|
-
socket?.off(`serve:${token.key}`)
|
|
23
|
-
socket?.emit(`unsub:${token.key}`)
|
|
24
|
-
}
|
|
25
|
-
}, [family.key])
|
|
26
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
|
|
4
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
5
|
-
|
|
6
|
-
import { RealtimeContext } from "./realtime-context"
|
|
7
|
-
import { StoreContext } from "../react"
|
|
8
|
-
|
|
9
|
-
export function usePullFamily<J extends Json>(
|
|
10
|
-
family: AtomIO.AtomFamily<J> | AtomIO.SelectorFamily<J>,
|
|
11
|
-
): void {
|
|
12
|
-
const { socket } = React.useContext(RealtimeContext)
|
|
13
|
-
const store = React.useContext(StoreContext)
|
|
14
|
-
React.useEffect(() => {
|
|
15
|
-
socket.on(`serve:${family.key}`, (key: Json, data: J) => {
|
|
16
|
-
AtomIO.setState(family(key), data, store)
|
|
17
|
-
})
|
|
18
|
-
socket?.emit(`sub:${family.key}`)
|
|
19
|
-
return () => {
|
|
20
|
-
socket?.off(`serve:${family.key}`)
|
|
21
|
-
socket?.emit(`unsub:${family.key}`)
|
|
22
|
-
}
|
|
23
|
-
}, [family.key])
|
|
24
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
|
|
4
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
5
|
-
|
|
6
|
-
import { RealtimeContext } from "./realtime-context"
|
|
7
|
-
import { StoreContext } from "../react"
|
|
8
|
-
|
|
9
|
-
export function usePull<J extends Json>(token: AtomIO.StateToken<J>): void {
|
|
10
|
-
const { socket } = React.useContext(RealtimeContext)
|
|
11
|
-
const store = React.useContext(StoreContext)
|
|
12
|
-
React.useEffect(() => {
|
|
13
|
-
socket.on(`serve:${token.key}`, (data: J) => {
|
|
14
|
-
AtomIO.setState(token, data, store)
|
|
15
|
-
})
|
|
16
|
-
socket.emit(`sub:${token.key}`)
|
|
17
|
-
return () => {
|
|
18
|
-
socket.off(`serve:${token.key}`)
|
|
19
|
-
socket.emit(`unsub:${token.key}`)
|
|
20
|
-
}
|
|
21
|
-
}, [token.key])
|
|
22
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
import * as React from "react"
|
|
3
|
-
|
|
4
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
5
|
-
|
|
6
|
-
import { RealtimeContext } from "./realtime-context"
|
|
7
|
-
import { StoreContext } from "../react"
|
|
8
|
-
|
|
9
|
-
export function usePush<J extends Json>(token: AtomIO.StateToken<J>): void {
|
|
10
|
-
const { socket } = React.useContext(RealtimeContext)
|
|
11
|
-
const store = React.useContext(StoreContext)
|
|
12
|
-
React.useEffect(() => {
|
|
13
|
-
socket.emit(`claim:${token.key}`)
|
|
14
|
-
AtomIO.subscribe(
|
|
15
|
-
token,
|
|
16
|
-
({ newValue }) => {
|
|
17
|
-
socket.emit(`pub:${token.key}`, newValue)
|
|
18
|
-
},
|
|
19
|
-
store,
|
|
20
|
-
)
|
|
21
|
-
return () => {
|
|
22
|
-
socket.emit(`unclaim:${token.key}`)
|
|
23
|
-
}
|
|
24
|
-
}, [token.key])
|
|
25
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import * as AtomIO from "atom.io"
|
|
2
|
-
import { StoreContext } from "atom.io/react"
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
|
|
5
|
-
import type { ƒn } from "~/packages/anvl/src/function"
|
|
6
|
-
|
|
7
|
-
import { RealtimeContext } from "./realtime-context"
|
|
8
|
-
|
|
9
|
-
const TX_SUBS = new Map<string, number>()
|
|
10
|
-
export function useServerAction<ƒ extends ƒn>(
|
|
11
|
-
token: AtomIO.TransactionToken<ƒ>,
|
|
12
|
-
): (...parameters: Parameters<ƒ>) => ReturnType<ƒ> {
|
|
13
|
-
const store = React.useContext(StoreContext)
|
|
14
|
-
const { socket } = React.useContext(RealtimeContext)
|
|
15
|
-
React.useEffect(() => {
|
|
16
|
-
const count = TX_SUBS.get(token.key) ?? 0
|
|
17
|
-
TX_SUBS.set(token.key, count + 1)
|
|
18
|
-
const unsubscribe =
|
|
19
|
-
count === 0
|
|
20
|
-
? AtomIO.subscribeToTransaction(
|
|
21
|
-
token,
|
|
22
|
-
(update) => socket.emit(`tx:${token.key}`, update),
|
|
23
|
-
store,
|
|
24
|
-
)
|
|
25
|
-
: () => null
|
|
26
|
-
return () => {
|
|
27
|
-
const newCount = TX_SUBS.get(token.key) ?? 0
|
|
28
|
-
TX_SUBS.set(token.key, newCount - 1)
|
|
29
|
-
unsubscribe()
|
|
30
|
-
}
|
|
31
|
-
}, [token.key])
|
|
32
|
-
return AtomIO.runTransaction(token, store)
|
|
33
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./setup-realtime-test"
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import * as http from "http"
|
|
2
|
-
|
|
3
|
-
import { prettyDOM, render, type RenderResult } from "@testing-library/react"
|
|
4
|
-
import * as AtomIO from "atom.io"
|
|
5
|
-
import * as AR from "atom.io/react"
|
|
6
|
-
import * as RTC from "atom.io/realtime-react"
|
|
7
|
-
import * as RR from "fp-ts/ReadonlyRecord"
|
|
8
|
-
import * as Happy from "happy-dom"
|
|
9
|
-
import * as React from "react"
|
|
10
|
-
import * as SocketIO from "socket.io"
|
|
11
|
-
import type { Socket as ClientSocket } from "socket.io-client"
|
|
12
|
-
import { io } from "socket.io-client"
|
|
13
|
-
|
|
14
|
-
export type TestSetupOptions = {
|
|
15
|
-
server: (tools: { socket: SocketIO.Socket; silo: AtomIO.Silo }) => void
|
|
16
|
-
}
|
|
17
|
-
export type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
18
|
-
client: React.FC
|
|
19
|
-
}
|
|
20
|
-
export type TestSetupOptions__MultiClient<ClientNames extends string> =
|
|
21
|
-
TestSetupOptions & {
|
|
22
|
-
clients: {
|
|
23
|
-
[K in ClientNames]: React.FC
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type RealtimeTestTools = {
|
|
28
|
-
name: string
|
|
29
|
-
silo: AtomIO.Silo
|
|
30
|
-
dispose: () => void
|
|
31
|
-
}
|
|
32
|
-
export type RealtimeTestClient = RealtimeTestTools & {
|
|
33
|
-
renderResult: RenderResult
|
|
34
|
-
prettyPrint: () => void
|
|
35
|
-
reconnect: () => void
|
|
36
|
-
disconnect: () => void
|
|
37
|
-
}
|
|
38
|
-
export type RealtimeTestServer = RealtimeTestTools & {
|
|
39
|
-
port: number
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export type RealtimeTestAPI = {
|
|
43
|
-
server: RealtimeTestServer
|
|
44
|
-
teardown: () => void
|
|
45
|
-
}
|
|
46
|
-
export type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {
|
|
47
|
-
client: RealtimeTestClient
|
|
48
|
-
}
|
|
49
|
-
export type RealtimeTestAPI__MultiClient<ClientNames extends string> =
|
|
50
|
-
RealtimeTestAPI & {
|
|
51
|
-
clients: Record<ClientNames, RealtimeTestClient>
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const setupRealtimeTestServer = (
|
|
55
|
-
options: TestSetupOptions,
|
|
56
|
-
): RealtimeTestServer => {
|
|
57
|
-
const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
|
|
58
|
-
const address = httpServer.listen().address()
|
|
59
|
-
const port =
|
|
60
|
-
typeof address === `string` ? 80 : address === null ? null : address.port
|
|
61
|
-
if (port === null) throw new Error(`Could not determine port for test server`)
|
|
62
|
-
const server = new SocketIO.Server(httpServer)
|
|
63
|
-
const silo = AtomIO.silo(`SERVER`, AtomIO.__INTERNAL__.IMPLICIT.STORE)
|
|
64
|
-
|
|
65
|
-
server.on(`connection`, (socket: SocketIO.Socket) => {
|
|
66
|
-
options.server({ socket, silo })
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
const dispose = () => {
|
|
70
|
-
server.close()
|
|
71
|
-
AtomIO.__INTERNAL__.clearStore(silo.store)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
name: `SERVER`,
|
|
76
|
-
silo,
|
|
77
|
-
dispose,
|
|
78
|
-
port,
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export const setupRealtimeTestClient = (
|
|
82
|
-
options: TestSetupOptions__SingleClient,
|
|
83
|
-
name: string,
|
|
84
|
-
port: number,
|
|
85
|
-
): RealtimeTestClient => {
|
|
86
|
-
const socket: ClientSocket = io(`http://localhost:${port}/`)
|
|
87
|
-
const silo = AtomIO.silo(name, AtomIO.__INTERNAL__.IMPLICIT.STORE)
|
|
88
|
-
|
|
89
|
-
const { document } = new Happy.Window()
|
|
90
|
-
document.body.innerHTML = `<div id="app"></div>`
|
|
91
|
-
const renderResult = render(
|
|
92
|
-
<AR.StoreProvider store={silo.store}>
|
|
93
|
-
<RTC.RealtimeProvider socket={socket}>
|
|
94
|
-
<options.client />
|
|
95
|
-
</RTC.RealtimeProvider>
|
|
96
|
-
</AR.StoreProvider>,
|
|
97
|
-
{
|
|
98
|
-
container: document.querySelector(`#app`) as unknown as HTMLElement,
|
|
99
|
-
},
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
const prettyPrint = () => console.log(prettyDOM(renderResult.container))
|
|
103
|
-
|
|
104
|
-
const disconnect = () => socket.disconnect()
|
|
105
|
-
const reconnect = () => socket.connect()
|
|
106
|
-
|
|
107
|
-
const dispose = () => {
|
|
108
|
-
socket.disconnect()
|
|
109
|
-
AtomIO.__INTERNAL__.clearStore(silo.store)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
name,
|
|
114
|
-
silo,
|
|
115
|
-
renderResult,
|
|
116
|
-
prettyPrint,
|
|
117
|
-
disconnect,
|
|
118
|
-
reconnect,
|
|
119
|
-
dispose,
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export const singleClient = (
|
|
124
|
-
options: TestSetupOptions__SingleClient,
|
|
125
|
-
): RealtimeTestAPI__SingleClient => {
|
|
126
|
-
const server = setupRealtimeTestServer(options)
|
|
127
|
-
const client = setupRealtimeTestClient(options, `CLIENT`, server.port)
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
client,
|
|
131
|
-
server,
|
|
132
|
-
teardown: () => {
|
|
133
|
-
client.dispose()
|
|
134
|
-
server.dispose()
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export const multiClient = <ClientNames extends string>(
|
|
140
|
-
options: TestSetupOptions__MultiClient<ClientNames>,
|
|
141
|
-
): RealtimeTestAPI__MultiClient<ClientNames> => {
|
|
142
|
-
const server = setupRealtimeTestServer(options)
|
|
143
|
-
const clients = RR.toEntries(options.clients).reduce(
|
|
144
|
-
(clients, [name, client]) => ({
|
|
145
|
-
...clients,
|
|
146
|
-
[name]: setupRealtimeTestClient({ ...options, client }, name, server.port),
|
|
147
|
-
}),
|
|
148
|
-
{} as Record<ClientNames, RealtimeTestClient>,
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
clients,
|
|
153
|
-
server,
|
|
154
|
-
teardown: () => {
|
|
155
|
-
RR.toEntries(clients).forEach(([, client]) => client.dispose())
|
|
156
|
-
server.dispose()
|
|
157
|
-
},
|
|
158
|
-
}
|
|
159
|
-
}
|
package/src/web-effects/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./storage"
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { Json } from "~/packages/anvl/src/json"
|
|
2
|
-
|
|
3
|
-
import type { AtomEffect } from "../index"
|
|
4
|
-
|
|
5
|
-
export type StringInterface<T> = {
|
|
6
|
-
stringify: (t: T) => string
|
|
7
|
-
parse: (s: string) => T
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const persistAtom =
|
|
11
|
-
<T>(storage: Storage) =>
|
|
12
|
-
({ stringify, parse }: StringInterface<T>) =>
|
|
13
|
-
(key: string): AtomEffect<T> =>
|
|
14
|
-
({ setSelf, onSet }) => {
|
|
15
|
-
const savedValue = storage.getItem(key)
|
|
16
|
-
|
|
17
|
-
if (savedValue != null) setSelf(parse(savedValue))
|
|
18
|
-
|
|
19
|
-
onSet(({ newValue }) => {
|
|
20
|
-
if (newValue == null) {
|
|
21
|
-
storage.removeItem(key)
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
storage.setItem(key, stringify(newValue))
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const lazyLocalStorageEffect: <J extends Json>(
|
|
29
|
-
key: string,
|
|
30
|
-
) => AtomEffect<J> = persistAtom(localStorage)(JSON)
|