atom.io 0.40.6 → 0.40.8
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/README.md +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +1 -2
- package/dist/data/index.js.map +1 -1
- package/dist/employ-socket-D6wgByWh.js +12 -0
- package/dist/employ-socket-D6wgByWh.js.map +1 -0
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/has-role-CMlaUlaf.js +1133 -0
- package/dist/has-role-CMlaUlaf.js.map +1 -0
- package/dist/internal/index.d.ts +248 -248
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +590 -1803
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +1 -1
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +13 -32
- package/dist/introspection/index.js.map +1 -1
- package/dist/is-fn-DY1wZ-md.js +10 -0
- package/dist/is-fn-DY1wZ-md.js.map +1 -0
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts +33 -33
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +3 -4
- package/dist/main/index.js.map +1 -1
- package/dist/mutex-store-CSvxY9i3.js +11 -0
- package/dist/mutex-store-CSvxY9i3.js.map +1 -0
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.d.ts.map +1 -1
- package/dist/react-devtools/index.js +9 -11
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +7 -15
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +4 -35
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +6 -9
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +96 -88
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +17 -13
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +39 -50
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +83 -84
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +604 -543
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +5 -4
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +35 -22
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/shared-room-store-BfW3nWif.js +31 -0
- package/dist/shared-room-store-BfW3nWif.js.map +1 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +4 -8
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/web/index.d.ts +3 -3
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +4 -3
- package/dist/web/index.js.map +1 -1
- package/package.json +13 -13
- package/src/internal/atom/create-regular-atom.ts +5 -4
- package/src/internal/atom/dispose-atom.ts +7 -2
- package/src/internal/atom/has-role.ts +3 -3
- package/src/internal/caching.ts +4 -2
- package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
- package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
- package/src/internal/families/create-regular-atom-family.ts +2 -1
- package/src/internal/families/create-writable-held-selector-family.ts +2 -1
- package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
- package/src/internal/families/dispose-from-store.ts +4 -4
- package/src/internal/families/find-in-store.ts +10 -10
- package/src/internal/families/get-family-of-token.ts +2 -2
- package/src/internal/families/index.ts +1 -0
- package/src/internal/families/mint-in-store.ts +54 -19
- package/src/internal/families/seek-in-store.ts +1 -1
- package/src/internal/get-state/get-fallback.ts +2 -2
- package/src/internal/get-state/get-from-store.ts +5 -5
- package/src/internal/get-state/read-or-compute-value.ts +1 -1
- package/src/internal/get-state/reduce-reference.ts +8 -6
- package/src/internal/index.ts +2 -220
- package/src/internal/molecule.ts +1 -2
- package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
- package/src/internal/mutable/create-mutable-atom.ts +4 -2
- package/src/internal/mutable/get-json-family.ts +1 -1
- package/src/internal/mutable/get-update-family.ts +1 -1
- package/src/internal/mutable/tracker-family.ts +2 -1
- package/src/internal/mutable/tracker.ts +71 -59
- package/src/internal/safe-compute.ts +1 -1
- package/src/internal/selector/create-readonly-held-selector.ts +2 -1
- package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
- package/src/internal/selector/create-writable-held-selector.ts +2 -1
- package/src/internal/selector/create-writable-pure-selector.ts +2 -1
- package/src/internal/selector/dispose-selector.ts +3 -2
- package/src/internal/selector/register-selector.ts +8 -5
- package/src/internal/selector/trace-selector-atoms.ts +2 -1
- package/src/internal/set-state/dispatch-state-update.ts +3 -2
- package/src/internal/set-state/evict-downstream.ts +1 -1
- package/src/internal/set-state/operate-on-store.ts +16 -22
- package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
- package/src/internal/set-state/reset-in-store.ts +5 -5
- package/src/internal/set-state/set-atom-or-selector.ts +2 -2
- package/src/internal/set-state/set-atom.ts +4 -2
- package/src/internal/set-state/set-into-store.ts +21 -39
- package/src/internal/set-state/set-selector.ts +3 -2
- package/src/internal/state-types.ts +228 -0
- package/src/internal/store/deposit.ts +4 -4
- package/src/internal/store/index.ts +0 -1
- package/src/internal/store/store.ts +9 -9
- package/src/internal/store/withdraw.ts +4 -4
- package/src/internal/subscribe/recall-state.ts +1 -1
- package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
- package/src/internal/subscribe/subscribe-to-state.ts +9 -0
- package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
- package/src/internal/transaction/build-transaction.ts +3 -2
- package/src/internal/transaction/index.ts +1 -23
- package/src/internal/transaction/is-root-store.ts +4 -1
- package/src/internal/transaction/transaction-meta-progress.ts +22 -0
- package/src/main/atom.ts +1 -2
- package/src/main/find-state.ts +5 -5
- package/src/main/get-state.ts +4 -4
- package/src/main/realm.ts +2 -2
- package/src/main/set-state.ts +10 -10
- package/src/react/parse-state-overloads.ts +3 -3
- package/src/react/use-i.ts +6 -4
- package/src/react/use-loadable.ts +4 -10
- package/src/react/use-o.ts +6 -4
- package/src/react-devtools/store.ts +6 -6
- package/src/realtime/index.ts +1 -0
- package/src/realtime/mutex-store.ts +11 -0
- package/src/realtime/realtime-continuity.ts +1 -5
- package/src/realtime-client/index.ts +0 -1
- package/src/realtime-client/pull-atom-family-member.ts +14 -17
- package/src/realtime-client/pull-atom.ts +1 -1
- package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
- package/src/realtime-client/pull-selector-family-member.ts +8 -35
- package/src/realtime-client/pull-selector-roots.ts +90 -0
- package/src/realtime-client/pull-selector.ts +2 -27
- package/src/realtime-client/push-state.ts +33 -5
- package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
- package/src/realtime-react/index.ts +2 -2
- package/src/realtime-react/realtime-context.tsx +9 -5
- package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
- package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
- package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
- package/src/realtime-react/use-push.ts +7 -3
- package/src/realtime-react/use-realtime-service.ts +11 -11
- package/src/realtime-react/use-single-effect.ts +11 -14
- package/src/realtime-server/{realtime-server-stores/server-sync-store.ts → continuity/continuity-store.ts} +2 -27
- package/src/realtime-server/continuity/provide-continuity.ts +50 -0
- package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +15 -13
- package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +10 -8
- package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +6 -4
- package/src/realtime-server/continuity/receive-action-requests.ts +68 -0
- package/src/realtime-server/continuity/track-acknowledgements.ts +46 -0
- package/src/realtime-server/employ-socket.ts +14 -0
- package/src/realtime-server/index.ts +3 -22
- package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
- package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
- package/src/realtime-server/ipc-sockets/parent-socket.ts +98 -69
- package/src/realtime-server/realtime-family-provider.ts +78 -29
- package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
- package/src/realtime-server/realtime-mutable-provider.ts +30 -22
- package/src/realtime-server/realtime-server-stores/index.ts +0 -2
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
- package/src/realtime-server/realtime-state-provider.ts +30 -29
- package/src/realtime-server/realtime-state-receiver.ts +62 -16
- package/src/realtime-server/server-config.ts +8 -0
- package/src/realtime-server/socket-interface.ts +14 -0
- package/src/realtime-testing/setup-realtime-test.tsx +70 -31
- package/src/web/index.ts +1 -1
- package/src/web/{persist-sync.ts → storage-sync.ts} +5 -2
- package/src/internal/store/mint-or-counterfeit.ts +0 -108
- package/src/realtime-client/server-action.ts +0 -23
- package/src/realtime-react/on-mount.ts +0 -5
- package/src/realtime-react/use-server-action.ts +0 -19
- package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
- package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
- package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +0 -41
- package/src/realtime-server/realtime-action-receiver.ts +0 -40
- package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +0 -79
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { AtomToken, SelectorToken } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { getFamilyOfToken, subscribeToState } from "atom.io/internal"
|
|
4
|
+
import { parseJson } from "atom.io/json"
|
|
5
|
+
import type { Socket } from "socket.io-client"
|
|
6
|
+
|
|
7
|
+
import { pullAtom } from "./pull-atom"
|
|
8
|
+
import { pullAtomFamilyMember } from "./pull-atom-family-member"
|
|
9
|
+
import { pullMutableAtom } from "./pull-mutable-atom"
|
|
10
|
+
import { pullMutableAtomFamilyMember } from "./pull-mutable-atom-family-member"
|
|
11
|
+
|
|
12
|
+
export function pullSelectorRoots(
|
|
13
|
+
store: Store,
|
|
14
|
+
socket: Socket,
|
|
15
|
+
selectorToken: SelectorToken<any>,
|
|
16
|
+
): () => void {
|
|
17
|
+
const atomSubscriptions = new Map<string, () => void>()
|
|
18
|
+
const clearAtomSubscriptions = () => {
|
|
19
|
+
for (const [, unsub] of atomSubscriptions) unsub()
|
|
20
|
+
atomSubscriptions.clear()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const start = () => {
|
|
24
|
+
const atomKeys = store.selectorAtoms.getRelatedKeys(selectorToken.key)
|
|
25
|
+
if (atomKeys) {
|
|
26
|
+
for (const [atomKey, unsub] of atomSubscriptions) {
|
|
27
|
+
if (!atomKeys.has(atomKey)) {
|
|
28
|
+
unsub()
|
|
29
|
+
atomSubscriptions.delete(atomKey)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const atomKey of atomKeys) {
|
|
34
|
+
if (atomSubscriptions.has(atomKey)) {
|
|
35
|
+
continue
|
|
36
|
+
}
|
|
37
|
+
const atom = store.atoms.get(atomKey) as AtomToken<any, any>
|
|
38
|
+
switch (atom.type) {
|
|
39
|
+
case `atom`: {
|
|
40
|
+
if (atom.family) {
|
|
41
|
+
const { subKey: serializedSubKey } = atom.family
|
|
42
|
+
const subKey = parseJson(serializedSubKey)
|
|
43
|
+
const family = getFamilyOfToken(store, atom)
|
|
44
|
+
atomSubscriptions.set(
|
|
45
|
+
atomKey,
|
|
46
|
+
pullAtomFamilyMember(store, socket, family, subKey),
|
|
47
|
+
)
|
|
48
|
+
} else {
|
|
49
|
+
atomSubscriptions.set(atomKey, pullAtom(store, socket, atom))
|
|
50
|
+
}
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
case `mutable_atom`: {
|
|
54
|
+
if (atom.family) {
|
|
55
|
+
const { subKey: serializedSubKey } = atom.family
|
|
56
|
+
const subKey = parseJson(serializedSubKey)
|
|
57
|
+
const family = getFamilyOfToken(store, atom)
|
|
58
|
+
atomSubscriptions.set(
|
|
59
|
+
atomKey,
|
|
60
|
+
pullMutableAtomFamilyMember(store, socket, family, subKey),
|
|
61
|
+
)
|
|
62
|
+
} else {
|
|
63
|
+
atomSubscriptions.set(
|
|
64
|
+
atomKey,
|
|
65
|
+
pullMutableAtom(store, socket, atom),
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
break
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const unsubFromSelector = subscribeToState(
|
|
76
|
+
store,
|
|
77
|
+
selectorToken,
|
|
78
|
+
`pull-watches-dependencies`,
|
|
79
|
+
() => {
|
|
80
|
+
start()
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
start()
|
|
85
|
+
|
|
86
|
+
return () => {
|
|
87
|
+
clearAtomSubscriptions()
|
|
88
|
+
unsubFromSelector()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -2,37 +2,12 @@ import type * as AtomIO from "atom.io"
|
|
|
2
2
|
import type { Store } from "atom.io/internal"
|
|
3
3
|
import type { Socket } from "socket.io-client"
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { pullMutableAtom } from "./pull-mutable-atom"
|
|
5
|
+
import { pullSelectorRoots } from "./pull-selector-roots"
|
|
7
6
|
|
|
8
7
|
export function pullSelector<T>(
|
|
9
8
|
store: Store,
|
|
10
9
|
socket: Socket,
|
|
11
10
|
token: AtomIO.SelectorToken<T>,
|
|
12
11
|
): () => void {
|
|
13
|
-
|
|
14
|
-
const unsubscribes: Array<() => void> = []
|
|
15
|
-
if (atomKeys) {
|
|
16
|
-
for (const atomKey of atomKeys) {
|
|
17
|
-
const atom = store.atoms.get(atomKey)
|
|
18
|
-
if (!atom) {
|
|
19
|
-
continue
|
|
20
|
-
}
|
|
21
|
-
switch (atom.type) {
|
|
22
|
-
case `atom`: {
|
|
23
|
-
unsubscribes.push(pullAtom(store, socket, atom))
|
|
24
|
-
break
|
|
25
|
-
}
|
|
26
|
-
case `mutable_atom`: {
|
|
27
|
-
unsubscribes.push(pullMutableAtom(store, socket, atom))
|
|
28
|
-
break
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return () => {
|
|
34
|
-
for (const unsubscribe of unsubscribes) {
|
|
35
|
-
unsubscribe()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
12
|
+
return pullSelectorRoots(store, socket, token)
|
|
38
13
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { WritableToken } from "atom.io"
|
|
2
2
|
import type { Store } from "atom.io/internal"
|
|
3
|
-
import { subscribeToState } from "atom.io/internal"
|
|
3
|
+
import { setIntoStore, subscribeToState } from "atom.io/internal"
|
|
4
4
|
import type { Json } from "atom.io/json"
|
|
5
|
+
import { mutexAtoms } from "atom.io/realtime/mutex-store"
|
|
6
|
+
import { employSocket } from "atom.io/realtime-server/employ-socket"
|
|
5
7
|
import type { Socket } from "socket.io-client"
|
|
6
8
|
|
|
7
9
|
export function pushState<J extends Json.Serializable>(
|
|
@@ -9,12 +11,38 @@ export function pushState<J extends Json.Serializable>(
|
|
|
9
11
|
socket: Socket,
|
|
10
12
|
token: WritableToken<J>,
|
|
11
13
|
): () => void {
|
|
12
|
-
|
|
13
|
-
subscribeToState(store, token, `push`, ({ newValue }) => {
|
|
14
|
+
const publish = (newValue: J) => {
|
|
14
15
|
socket.emit(`pub:${token.key}`, newValue)
|
|
15
|
-
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const subscriptions = new Set<() => void>()
|
|
19
|
+
const clearSubscriptions = () => {
|
|
20
|
+
for (const unsub of subscriptions) unsub()
|
|
21
|
+
subscriptions.clear()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const init = () => {
|
|
25
|
+
subscriptions.add(
|
|
26
|
+
employSocket(socket, `claim-result:${token.key}`, (success: boolean) => {
|
|
27
|
+
if (!success) return
|
|
28
|
+
|
|
29
|
+
clearSubscriptions()
|
|
30
|
+
setIntoStore(store, mutexAtoms, token.key, true)
|
|
31
|
+
subscriptions.add(
|
|
32
|
+
subscribeToState(store, token, `push`, ({ newValue }) => {
|
|
33
|
+
publish(newValue)
|
|
34
|
+
}),
|
|
35
|
+
)
|
|
36
|
+
}),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
socket.emit(`claim:${token.key}`)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
init()
|
|
43
|
+
|
|
16
44
|
return () => {
|
|
17
|
-
|
|
45
|
+
clearSubscriptions()
|
|
18
46
|
socket.emit(`unclaim:${token.key}`)
|
|
19
47
|
}
|
|
20
48
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as AtomIO from "atom.io"
|
|
2
|
-
import {
|
|
2
|
+
import { storageSync } from "atom.io/web"
|
|
3
3
|
|
|
4
4
|
export const myIdState__INTERNAL: AtomIO.RegularAtomToken<string | undefined> =
|
|
5
5
|
AtomIO.atom<string | undefined>({
|
|
@@ -16,8 +16,5 @@ export const myUsernameState: AtomIO.RegularAtomToken<string | null> =
|
|
|
16
16
|
AtomIO.atom<string | null>({
|
|
17
17
|
key: `myName`,
|
|
18
18
|
default: null,
|
|
19
|
-
effects:
|
|
20
|
-
typeof window === `undefined`
|
|
21
|
-
? []
|
|
22
|
-
: [persistSync(window.localStorage, JSON, `myUsername`)],
|
|
19
|
+
effects: [storageSync(globalThis.localStorage, JSON, `myUsername`)],
|
|
23
20
|
})
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export * from "./on-mount"
|
|
2
1
|
export * from "./realtime-context"
|
|
3
2
|
export * from "./use-pull-atom"
|
|
4
3
|
export * from "./use-pull-atom-family-member"
|
|
@@ -7,5 +6,6 @@ export * from "./use-pull-mutable-family-member"
|
|
|
7
6
|
export * from "./use-pull-selector"
|
|
8
7
|
export * from "./use-pull-selector-family-member"
|
|
9
8
|
export * from "./use-push"
|
|
10
|
-
export * from "./use-
|
|
9
|
+
export * from "./use-realtime-service"
|
|
10
|
+
export * from "./use-single-effect"
|
|
11
11
|
export * from "./use-sync-continuity"
|
|
@@ -3,12 +3,14 @@ import * as RTC from "atom.io/realtime-client"
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import type { Socket } from "socket.io-client"
|
|
5
5
|
|
|
6
|
+
export type RealtimeServiceCounter = {
|
|
7
|
+
consumerCount: number
|
|
8
|
+
dispose: () => void
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
export type RealtimeReactStore = {
|
|
7
12
|
socket: Socket | null
|
|
8
|
-
services: Map<
|
|
9
|
-
string,
|
|
10
|
-
[consumerCount: number, dispose: (() => void) | undefined]
|
|
11
|
-
> | null
|
|
13
|
+
services: Map<string, RealtimeServiceCounter> | null
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export const RealtimeContext: React.Context<RealtimeReactStore> =
|
|
@@ -21,7 +23,9 @@ export const RealtimeProvider: React.FC<{
|
|
|
21
23
|
children: React.ReactNode
|
|
22
24
|
socket: Socket | null
|
|
23
25
|
}> = ({ children, socket }) => {
|
|
24
|
-
const services = React.useRef(
|
|
26
|
+
const services = React.useRef(
|
|
27
|
+
new Map<string, RealtimeServiceCounter>(),
|
|
28
|
+
).current
|
|
25
29
|
const setMyId = useI(RTC.myIdState__INTERNAL)
|
|
26
30
|
React.useEffect(() => {
|
|
27
31
|
setMyId(socket?.id)
|
|
@@ -10,12 +10,11 @@ import { useRealtimeService } from "./use-realtime-service"
|
|
|
10
10
|
export function usePullAtomFamilyMember<
|
|
11
11
|
J extends Json.Serializable,
|
|
12
12
|
K extends Canonical,
|
|
13
|
-
|
|
14
|
-
>(family: AtomIO.RegularAtomFamilyToken<J, K>, subKey: Key): J {
|
|
13
|
+
>(family: AtomIO.RegularAtomFamilyToken<J, K>, subKey: NoInfer<K>): J {
|
|
15
14
|
const store = React.useContext(StoreContext)
|
|
16
15
|
const token = findInStore(store, family, subKey)
|
|
17
16
|
useRealtimeService(`pull:${token.key}`, (socket) =>
|
|
18
|
-
RTC.pullAtomFamilyMember(store, socket,
|
|
17
|
+
RTC.pullAtomFamilyMember(store, socket, family, subKey),
|
|
19
18
|
)
|
|
20
19
|
return useO(token)
|
|
21
20
|
}
|
|
@@ -11,12 +11,11 @@ import { useRealtimeService } from "./use-realtime-service"
|
|
|
11
11
|
export function usePullMutableAtomFamilyMember<
|
|
12
12
|
T extends Transceiver<any, any, any>,
|
|
13
13
|
K extends Canonical,
|
|
14
|
-
|
|
15
|
-
>(familyToken: AtomIO.MutableAtomFamilyToken<T, K>, key: Key): T {
|
|
14
|
+
>(familyToken: AtomIO.MutableAtomFamilyToken<T, K>, key: NoInfer<K>): T {
|
|
16
15
|
const store = React.useContext(StoreContext)
|
|
17
16
|
const token = findInStore(store, familyToken, key)
|
|
18
17
|
useRealtimeService(`pull:${token.key}`, (socket) =>
|
|
19
|
-
RTC.pullMutableAtomFamilyMember(store, socket,
|
|
18
|
+
RTC.pullMutableAtomFamilyMember(store, socket, familyToken, key),
|
|
20
19
|
)
|
|
21
20
|
return useO(token)
|
|
22
21
|
}
|
|
@@ -7,15 +7,14 @@ import * as React from "react"
|
|
|
7
7
|
|
|
8
8
|
import { useRealtimeService } from "./use-realtime-service"
|
|
9
9
|
|
|
10
|
-
export function usePullSelectorFamilyMember<
|
|
11
|
-
T,
|
|
12
|
-
K
|
|
13
|
-
|
|
14
|
-
>(familyToken: AtomIO.SelectorFamilyToken<T, K>, key: Key): T {
|
|
10
|
+
export function usePullSelectorFamilyMember<T, K extends Canonical>(
|
|
11
|
+
familyToken: AtomIO.SelectorFamilyToken<T, K>,
|
|
12
|
+
key: NoInfer<K>,
|
|
13
|
+
): T {
|
|
15
14
|
const store = React.useContext(StoreContext)
|
|
16
15
|
const token = findInStore(store, familyToken, key)
|
|
17
16
|
useRealtimeService(`pull:${token.key}`, (socket) =>
|
|
18
|
-
RTC.pullSelectorFamilyMember(store, socket,
|
|
17
|
+
RTC.pullSelectorFamilyMember(store, socket, familyToken, key),
|
|
19
18
|
)
|
|
20
19
|
|
|
21
20
|
return useO(token)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type * as AtomIO from "atom.io"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
|
-
import { StoreContext, useI } from "atom.io/react"
|
|
3
|
+
import { StoreContext, useI, useO } from "atom.io/react"
|
|
4
|
+
import * as RT from "atom.io/realtime"
|
|
4
5
|
import * as RTC from "atom.io/realtime-client"
|
|
5
6
|
import * as React from "react"
|
|
6
7
|
|
|
@@ -8,10 +9,13 @@ import { useRealtimeService } from "./use-realtime-service"
|
|
|
8
9
|
|
|
9
10
|
export function usePush<J extends Json.Serializable>(
|
|
10
11
|
token: AtomIO.WritableToken<J>,
|
|
11
|
-
): <New extends J>(next: New | ((old: J) => New)) => void {
|
|
12
|
+
): (<New extends J>(next: New | ((old: J) => New)) => void) | null {
|
|
12
13
|
const store = React.useContext(StoreContext)
|
|
13
14
|
useRealtimeService(`push:${token.key}`, (socket) =>
|
|
14
15
|
RTC.pushState(store, socket, token),
|
|
15
16
|
)
|
|
16
|
-
|
|
17
|
+
const mutex = useO(RT.mutexAtoms, token.key)
|
|
18
|
+
const setter = useI(token)
|
|
19
|
+
|
|
20
|
+
return mutex ? setter : null
|
|
17
21
|
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import type { Socket } from "socket.io-client"
|
|
3
3
|
|
|
4
|
-
import { onMount } from "./on-mount"
|
|
5
4
|
import { RealtimeContext } from "./realtime-context"
|
|
5
|
+
import { useSingleEffect } from "./use-single-effect"
|
|
6
6
|
|
|
7
7
|
export function useRealtimeService(
|
|
8
8
|
key: string,
|
|
9
|
-
create: (socket: Socket) => (
|
|
9
|
+
create: (socket: Socket) => () => void,
|
|
10
10
|
): void {
|
|
11
11
|
const { socket, services } = React.useContext(RealtimeContext)
|
|
12
|
-
|
|
12
|
+
useSingleEffect(() => {
|
|
13
13
|
let service = services?.get(key)
|
|
14
14
|
if (service) {
|
|
15
|
-
service
|
|
16
|
-
} else {
|
|
17
|
-
const dispose =
|
|
18
|
-
service =
|
|
15
|
+
++service.consumerCount
|
|
16
|
+
} else if (socket) {
|
|
17
|
+
const dispose = create(socket)
|
|
18
|
+
service = { consumerCount: 1, dispose }
|
|
19
19
|
services?.set(key, service)
|
|
20
20
|
}
|
|
21
21
|
return () => {
|
|
22
22
|
if (service) {
|
|
23
|
-
service
|
|
24
|
-
if (service
|
|
25
|
-
service
|
|
23
|
+
--service.consumerCount
|
|
24
|
+
if (service.consumerCount === 0) {
|
|
25
|
+
service.dispose?.()
|
|
26
26
|
services?.delete(key)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
})
|
|
30
|
+
}, [socket, key])
|
|
31
31
|
}
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
/** biome-ignore-all lint/correctness/useHookAtTopLevel: intentional */
|
|
2
2
|
|
|
3
|
+
import { isFn } from "atom.io/internal/is-fn"
|
|
3
4
|
import * as React from "react"
|
|
4
5
|
|
|
5
|
-
// @ts-expect-error this is a safe way to check a property on the global object
|
|
6
|
-
const { NODE_ENV } = globalThis[`env`] ?? {}
|
|
7
|
-
const IN_DEV = NODE_ENV === `development`
|
|
8
|
-
|
|
9
|
-
function noop() {}
|
|
10
|
-
|
|
11
6
|
export function useSingleEffect(
|
|
12
7
|
effect: () => (() => void) | undefined | void,
|
|
13
8
|
deps: unknown[],
|
|
14
9
|
): void {
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
const globalEnv = (globalThis as unknown as { env: any })[`env`]
|
|
11
|
+
const isInDev = globalEnv?.NODE_ENV === `development`
|
|
12
|
+
if (isInDev) {
|
|
13
|
+
const cleanupRef = React.useRef<boolean | (() => void)>(false)
|
|
17
14
|
React.useEffect(() => {
|
|
18
|
-
let
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
let cleanupFn = cleanupRef.current
|
|
16
|
+
if (cleanupFn === false) {
|
|
17
|
+
cleanupFn = effect() ?? true
|
|
18
|
+
cleanupRef.current = cleanupFn
|
|
22
19
|
} else {
|
|
23
20
|
return () => {
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
if (isFn(cleanupFn)) cleanupFn()
|
|
22
|
+
cleanupRef.current = false
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
25
|
}, deps)
|
|
@@ -5,15 +5,7 @@ import type {
|
|
|
5
5
|
} from "atom.io"
|
|
6
6
|
import { atomFamily } from "atom.io"
|
|
7
7
|
|
|
8
|
-
import type { UserKey } from "
|
|
9
|
-
|
|
10
|
-
// export const completeUpdateAtoms = atomFamily<
|
|
11
|
-
// TransactionUpdate<any> | null,
|
|
12
|
-
// string
|
|
13
|
-
// >({
|
|
14
|
-
// key: `completeUpdate`,
|
|
15
|
-
// default: null,
|
|
16
|
-
// })
|
|
8
|
+
import type { UserKey } from "../realtime-server-stores/server-user-store"
|
|
17
9
|
|
|
18
10
|
export function redactTransactionUpdateContent(
|
|
19
11
|
visibleStateKeys: string[],
|
|
@@ -67,29 +59,12 @@ export const redactorAtoms: RegularAtomFamilyToken<
|
|
|
67
59
|
key: `redactor`,
|
|
68
60
|
default: { occlude: (updates) => updates },
|
|
69
61
|
})
|
|
70
|
-
// export const redactedUpdateSelectors = selectorFamily<
|
|
71
|
-
// TransactionUpdate<any> | null,
|
|
72
|
-
// [transactionKey: string, updateId: string]
|
|
73
|
-
// >({
|
|
74
|
-
// key: `redactedUpdate`,
|
|
75
|
-
// get:
|
|
76
|
-
// ([transactionKey, updateId]) =>
|
|
77
|
-
// ({ get, find }) => {
|
|
78
|
-
// const update = get(find(completeUpdateAtoms, updateId))
|
|
79
|
-
// const { filter } = get(find(transactionRedactorAtoms, transactionKey))
|
|
80
|
-
|
|
81
|
-
// if (update && filter) {
|
|
82
|
-
// return { ...update, updates: filter(update.updates) }
|
|
83
|
-
// }
|
|
84
|
-
// return null
|
|
85
|
-
// },
|
|
86
|
-
// })
|
|
87
62
|
|
|
88
63
|
export type ContinuitySyncTransactionUpdate = Pick<
|
|
89
64
|
TransactionOutcomeEvent<any>,
|
|
90
65
|
`epoch` | `id` | `output` | `subEvents` | `token`
|
|
91
66
|
>
|
|
92
|
-
export const
|
|
67
|
+
export const unacknowledgedUpdatesAtoms: RegularAtomFamilyToken<
|
|
93
68
|
ContinuitySyncTransactionUpdate[],
|
|
94
69
|
UserKey
|
|
95
70
|
> = atomFamily<ContinuitySyncTransactionUpdate[], UserKey>({
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getFromStore, IMPLICIT } from "atom.io/internal"
|
|
2
|
+
import type { Json } from "atom.io/json"
|
|
3
|
+
import type { ContinuityToken } from "atom.io/realtime"
|
|
4
|
+
|
|
5
|
+
import type { ServerConfig, UserKey } from ".."
|
|
6
|
+
import { unacknowledgedUpdatesAtoms } from "./continuity-store"
|
|
7
|
+
import { provideOutcomes } from "./provide-outcomes"
|
|
8
|
+
import { providePerspectives } from "./provide-perspectives"
|
|
9
|
+
import { provideStartupPayloads } from "./provide-startup-payloads"
|
|
10
|
+
import { receiveActionRequests } from "./receive-action-requests"
|
|
11
|
+
import { trackAcknowledgements } from "./track-acknowledgements"
|
|
12
|
+
|
|
13
|
+
export type ProvideContinuity = (
|
|
14
|
+
continuity: ContinuityToken,
|
|
15
|
+
userKey: UserKey,
|
|
16
|
+
) => () => void
|
|
17
|
+
export function prepareToProvideContinuity({
|
|
18
|
+
socket,
|
|
19
|
+
store = IMPLICIT.STORE,
|
|
20
|
+
}: ServerConfig): ProvideContinuity {
|
|
21
|
+
return function syncRealtimeContinuity(continuity, userKey) {
|
|
22
|
+
const continuityKey = continuity.key
|
|
23
|
+
|
|
24
|
+
const unacknowledgedUpdates = getFromStore(
|
|
25
|
+
store,
|
|
26
|
+
unacknowledgedUpdatesAtoms,
|
|
27
|
+
userKey,
|
|
28
|
+
)
|
|
29
|
+
for (const unacknowledgedUpdate of unacknowledgedUpdates) {
|
|
30
|
+
socket.emit(
|
|
31
|
+
`tx-new:${continuityKey}`,
|
|
32
|
+
unacknowledgedUpdate as Json.Serializable,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const subscriptions = new Set<() => void>()
|
|
37
|
+
const clearSubscriptions = () => {
|
|
38
|
+
for (const unsubscribe of subscriptions) unsubscribe()
|
|
39
|
+
subscriptions.clear()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
subscriptions.add(providePerspectives(store, socket, continuity, userKey))
|
|
43
|
+
subscriptions.add(provideOutcomes(store, socket, continuity, userKey))
|
|
44
|
+
subscriptions.add(provideStartupPayloads(store, socket, continuity, userKey))
|
|
45
|
+
subscriptions.add(receiveActionRequests(store, socket, continuity, userKey))
|
|
46
|
+
subscriptions.add(trackAcknowledgements(store, socket, continuity, userKey))
|
|
47
|
+
|
|
48
|
+
return clearSubscriptions
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts}
RENAMED
|
@@ -12,24 +12,24 @@ import type { ContinuityToken } from "atom.io/realtime"
|
|
|
12
12
|
import type { Socket, UserKey } from ".."
|
|
13
13
|
import {
|
|
14
14
|
redactTransactionUpdateContent,
|
|
15
|
-
|
|
16
|
-
} from "
|
|
15
|
+
unacknowledgedUpdatesAtoms,
|
|
16
|
+
} from "./continuity-store"
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function provideOutcomes(
|
|
19
19
|
store: Store,
|
|
20
|
+
socket: Socket,
|
|
20
21
|
continuity: ContinuityToken,
|
|
21
22
|
userKey: UserKey,
|
|
22
|
-
|
|
23
|
-
): (() => void)[] {
|
|
23
|
+
): () => void {
|
|
24
24
|
const continuityKey = continuity.key
|
|
25
|
-
const unsubscribeFunctions
|
|
25
|
+
const unsubscribeFunctions = new Set<() => void>()
|
|
26
26
|
|
|
27
27
|
for (const transaction of continuity.actions) {
|
|
28
28
|
const unsubscribeFromTransaction = subscribeToTransaction(
|
|
29
29
|
store,
|
|
30
30
|
transaction,
|
|
31
31
|
`sync-continuity:${continuityKey}:${userKey}`,
|
|
32
|
-
(
|
|
32
|
+
(outcomes) => {
|
|
33
33
|
try {
|
|
34
34
|
const visibleKeys = continuity.globals
|
|
35
35
|
.map((atom) => {
|
|
@@ -59,13 +59,13 @@ export function subscribeToContinuityActions(
|
|
|
59
59
|
)
|
|
60
60
|
const redactedUpdates = redactTransactionUpdateContent(
|
|
61
61
|
visibleKeys,
|
|
62
|
-
|
|
62
|
+
outcomes.subEvents,
|
|
63
63
|
)
|
|
64
64
|
const redactedUpdate = {
|
|
65
|
-
...
|
|
65
|
+
...outcomes,
|
|
66
66
|
updates: redactedUpdates,
|
|
67
67
|
}
|
|
68
|
-
setIntoStore(store,
|
|
68
|
+
setIntoStore(store, unacknowledgedUpdatesAtoms, userKey, (updates) => {
|
|
69
69
|
if (redactedUpdate) {
|
|
70
70
|
updates.push(redactedUpdate)
|
|
71
71
|
updates.sort((a, b) => a.epoch - b.epoch)
|
|
@@ -81,7 +81,7 @@ export function subscribeToContinuityActions(
|
|
|
81
81
|
return updates
|
|
82
82
|
})
|
|
83
83
|
|
|
84
|
-
socket
|
|
84
|
+
socket.emit(
|
|
85
85
|
`tx-new:${continuityKey}`,
|
|
86
86
|
redactedUpdate as Json.Serializable,
|
|
87
87
|
)
|
|
@@ -98,7 +98,9 @@ export function subscribeToContinuityActions(
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
)
|
|
101
|
-
unsubscribeFunctions.
|
|
101
|
+
unsubscribeFunctions.add(unsubscribeFromTransaction)
|
|
102
|
+
}
|
|
103
|
+
return () => {
|
|
104
|
+
for (const unsubscribe of unsubscribeFunctions) unsubscribe()
|
|
102
105
|
}
|
|
103
|
-
return unsubscribeFunctions
|
|
104
106
|
}
|
|
@@ -10,14 +10,14 @@ import type { ContinuityToken } from "atom.io/realtime"
|
|
|
10
10
|
import type { Socket } from ".."
|
|
11
11
|
import type { UserKey } from "../realtime-server-stores"
|
|
12
12
|
|
|
13
|
-
export function
|
|
13
|
+
export function providePerspectives(
|
|
14
14
|
store: Store,
|
|
15
|
+
socket: Socket,
|
|
15
16
|
continuity: ContinuityToken,
|
|
16
17
|
userKey: UserKey,
|
|
17
|
-
|
|
18
|
-
): (() => void)[] {
|
|
18
|
+
): () => void {
|
|
19
19
|
const continuityKey = continuity.key
|
|
20
|
-
const unsubFns
|
|
20
|
+
const unsubFns = new Set<() => void>()
|
|
21
21
|
for (const perspective of continuity.perspectives) {
|
|
22
22
|
const { viewAtoms } = perspective
|
|
23
23
|
const userViewState = findInStore(store, viewAtoms, userKey)
|
|
@@ -47,14 +47,16 @@ export function subscribeToContinuityPerspectives(
|
|
|
47
47
|
{ oldKeys, newKeys, revealed, concealed },
|
|
48
48
|
)
|
|
49
49
|
if (revealed.length > 0) {
|
|
50
|
-
socket
|
|
50
|
+
socket.emit(`reveal:${continuityKey}`, revealed)
|
|
51
51
|
}
|
|
52
52
|
if (concealed && concealed.length > 0) {
|
|
53
|
-
socket
|
|
53
|
+
socket.emit(`conceal:${continuityKey}`, concealed)
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
)
|
|
57
|
-
unsubFns.
|
|
57
|
+
unsubFns.add(unsubscribeFromUserView)
|
|
58
|
+
}
|
|
59
|
+
return () => {
|
|
60
|
+
for (const unsubscribe of unsubFns) unsubscribe()
|
|
58
61
|
}
|
|
59
|
-
return unsubFns
|
|
60
62
|
}
|
|
@@ -9,15 +9,16 @@ import type { Json } from "atom.io/json"
|
|
|
9
9
|
import type { ContinuityToken } from "atom.io/realtime"
|
|
10
10
|
|
|
11
11
|
import type { Socket, UserKey } from ".."
|
|
12
|
+
import { employSocket } from "../employ-socket"
|
|
12
13
|
|
|
13
|
-
export function
|
|
14
|
+
export function provideStartupPayloads(
|
|
14
15
|
store: Store,
|
|
16
|
+
socket: Socket,
|
|
15
17
|
continuity: ContinuityToken,
|
|
16
18
|
userKey: UserKey,
|
|
17
|
-
socket: Socket | null,
|
|
18
19
|
): () => void {
|
|
19
20
|
const continuityKey = continuity.key
|
|
20
|
-
|
|
21
|
+
function sendInitialPayload(): void {
|
|
21
22
|
const initialPayload: Json.Serializable[] = []
|
|
22
23
|
for (const atom of continuity.globals) {
|
|
23
24
|
const resourceToken =
|
|
@@ -49,6 +50,7 @@ export function prepareToSendInitialPayload(
|
|
|
49
50
|
? (store.transactionMeta.epoch.get(continuityKey) ?? null)
|
|
50
51
|
: null
|
|
51
52
|
|
|
52
|
-
socket
|
|
53
|
+
socket.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)
|
|
53
54
|
}
|
|
55
|
+
return employSocket(socket, `get:${continuityKey}`, sendInitialPayload)
|
|
54
56
|
}
|