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
|
@@ -1,48 +1,89 @@
|
|
|
1
1
|
import type { ChildProcessWithoutNullStreams } from "node:child_process"
|
|
2
2
|
import { spawn } from "node:child_process"
|
|
3
3
|
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "atom.io"
|
|
9
|
-
import { atomFamily, selectorFamily } from "atom.io"
|
|
4
|
+
import type { TransactionIO, TransactionToken } from "atom.io"
|
|
5
|
+
import { transaction } from "atom.io"
|
|
6
|
+
import { editRelationsInStore } from "atom.io/internal"
|
|
7
|
+
import type { UserInRoomMeta } from "atom.io/realtime/shared-room-store"
|
|
8
|
+
import { roomIndex, usersInRooms } from "atom.io/realtime/shared-room-store"
|
|
10
9
|
|
|
11
10
|
import { ChildSocket } from "../ipc-sockets"
|
|
11
|
+
import type { RoomKey } from "./server-user-store"
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
export const ROOMS: Map<
|
|
14
|
+
string,
|
|
15
|
+
ChildSocket<any, any, ChildProcessWithoutNullStreams>
|
|
16
|
+
> = new Map()
|
|
16
17
|
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export async function spawnRoom(
|
|
19
|
+
roomId: string,
|
|
20
|
+
script: string,
|
|
21
|
+
options: string[],
|
|
22
|
+
): Promise<ChildSocket<any, any>> {
|
|
23
|
+
const child = await new Promise<ChildProcessWithoutNullStreams>((resolve) => {
|
|
24
|
+
const room = spawn(script, options, { env: process.env })
|
|
25
|
+
const resolver = (data: Buffer) => {
|
|
26
|
+
if (data.toString() === `ALIVE`) {
|
|
27
|
+
room.stdout.off(`data`, resolver)
|
|
28
|
+
resolve(room)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
room.stdout.on(`data`, resolver)
|
|
21
32
|
})
|
|
33
|
+
ROOMS.set(roomId, new ChildSocket(child, roomId))
|
|
34
|
+
return new ChildSocket(child, roomId)
|
|
35
|
+
}
|
|
22
36
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
export const joinRoomTX: TransactionToken<
|
|
38
|
+
(roomId: string, userId: string, enteredAtEpoch: number) => UserInRoomMeta
|
|
39
|
+
> = transaction({
|
|
40
|
+
key: `joinRoom`,
|
|
41
|
+
do: (tools, roomId, userId, enteredAtEpoch) => {
|
|
42
|
+
const meta = { enteredAtEpoch }
|
|
43
|
+
editRelationsInStore(
|
|
44
|
+
usersInRooms,
|
|
45
|
+
(relations) => {
|
|
46
|
+
relations.set({ room: roomId, user: userId }, meta)
|
|
47
|
+
},
|
|
48
|
+
tools.env().store,
|
|
49
|
+
)
|
|
50
|
+
return meta
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
export type JoinRoomIO = TransactionIO<typeof joinRoomTX>
|
|
54
|
+
|
|
55
|
+
export const leaveRoomTX: TransactionToken<
|
|
56
|
+
(roomId: string, userId: string) => void
|
|
57
|
+
> = transaction({
|
|
58
|
+
key: `leaveRoom`,
|
|
59
|
+
do: ({ env }, roomId, userId) => {
|
|
60
|
+
editRelationsInStore(
|
|
61
|
+
usersInRooms,
|
|
62
|
+
(relations) => {
|
|
63
|
+
relations.delete({ room: roomId, user: userId })
|
|
64
|
+
},
|
|
65
|
+
env().store,
|
|
66
|
+
)
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
export type LeaveRoomIO = TransactionIO<typeof leaveRoomTX>
|
|
70
|
+
|
|
71
|
+
export const destroyRoomTX: TransactionToken<(roomKey: RoomKey) => void> =
|
|
72
|
+
transaction({
|
|
73
|
+
key: `destroyRoom`,
|
|
74
|
+
do: ({ set, env }, roomId) => {
|
|
75
|
+
editRelationsInStore(
|
|
76
|
+
usersInRooms,
|
|
77
|
+
(relations) => {
|
|
78
|
+
relations.delete({ room: roomId })
|
|
44
79
|
},
|
|
80
|
+
env().store,
|
|
45
81
|
)
|
|
46
|
-
|
|
82
|
+
set(roomIndex, (s) => (s.delete(roomId), s))
|
|
83
|
+
const room = ROOMS.get(roomId)
|
|
84
|
+
if (room) {
|
|
85
|
+
room.emit(`exit`)
|
|
86
|
+
ROOMS.delete(roomId)
|
|
87
|
+
}
|
|
47
88
|
},
|
|
48
|
-
})
|
|
89
|
+
})
|
|
@@ -2,9 +2,10 @@ import type {
|
|
|
2
2
|
Hierarchy,
|
|
3
3
|
JoinToken,
|
|
4
4
|
MutableAtomToken,
|
|
5
|
+
PureSelectorFamilyToken,
|
|
5
6
|
RegularAtomFamilyToken,
|
|
6
7
|
} from "atom.io"
|
|
7
|
-
import { atomFamily, join, mutableAtom } from "atom.io"
|
|
8
|
+
import { atomFamily, join, mutableAtom, selectorFamily } from "atom.io"
|
|
8
9
|
import { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
9
10
|
|
|
10
11
|
import type { Socket } from ".."
|
|
@@ -53,3 +54,13 @@ export const usersOfSockets: JoinToken<
|
|
|
53
54
|
isAType: (s): s is UserKey => s.startsWith(`user::`),
|
|
54
55
|
isBType: (s): s is SocketKey => s.startsWith(`socket::`),
|
|
55
56
|
})
|
|
57
|
+
|
|
58
|
+
export const userMutualSituationalAwarenessIndexes: PureSelectorFamilyToken<
|
|
59
|
+
UserKey[],
|
|
60
|
+
UserKey
|
|
61
|
+
> = selectorFamily<UserKey[], UserKey>({
|
|
62
|
+
key: `userMutualSituationalAwarenessIndexes`,
|
|
63
|
+
get: (userId) => () => {
|
|
64
|
+
return [userId]
|
|
65
|
+
},
|
|
66
|
+
})
|
|
@@ -3,6 +3,7 @@ import { getFromStore, IMPLICIT, subscribeToState } from "atom.io/internal"
|
|
|
3
3
|
import type { Json } from "atom.io/json"
|
|
4
4
|
|
|
5
5
|
import type { ServerConfig } from "."
|
|
6
|
+
import { employSocket } from "./employ-socket"
|
|
6
7
|
|
|
7
8
|
export type StateProvider = ReturnType<typeof realtimeStateProvider>
|
|
8
9
|
export function realtimeStateProvider({
|
|
@@ -12,39 +13,39 @@ export function realtimeStateProvider({
|
|
|
12
13
|
return function stateProvider<J extends Json.Serializable>(
|
|
13
14
|
token: AtomIO.WritableToken<J>,
|
|
14
15
|
): () => void {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const subscriptions = new Set<() => void>()
|
|
17
|
+
const clearSubscriptions = () => {
|
|
18
|
+
for (const unsub of subscriptions) unsub()
|
|
19
|
+
subscriptions.clear()
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
token
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const start = () => {
|
|
23
|
+
subscriptions.add(
|
|
24
|
+
employSocket(socket, `sub:${token.key}`, () => {
|
|
25
|
+
clearSubscriptions()
|
|
26
|
+
socket.emit(`serve:${token.key}`, getFromStore(store, token))
|
|
27
|
+
subscriptions.add(
|
|
28
|
+
subscribeToState(
|
|
29
|
+
store,
|
|
30
|
+
token,
|
|
31
|
+
`expose-single:${socket.id}`,
|
|
32
|
+
({ newValue }) => {
|
|
33
|
+
socket.emit(`serve:${token.key}`, newValue)
|
|
34
|
+
},
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
subscriptions.add(
|
|
38
|
+
employSocket(socket, `unsub:${token.key}`, () => {
|
|
39
|
+
clearSubscriptions()
|
|
40
|
+
start()
|
|
41
|
+
}),
|
|
42
|
+
)
|
|
43
|
+
}),
|
|
27
44
|
)
|
|
28
|
-
|
|
29
|
-
const fillUnsubRequest = () => {
|
|
30
|
-
socket.off(`unsub:${token.key}`, fillUnsubRequest)
|
|
31
|
-
if (unsubscribeFromStateUpdates) {
|
|
32
|
-
unsubscribeFromStateUpdates()
|
|
33
|
-
unsubscribeFromStateUpdates = undefined
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
socket.on(`unsub:${token.key}`, fillUnsubRequest)
|
|
38
45
|
}
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
start()
|
|
41
48
|
|
|
42
|
-
return
|
|
43
|
-
socket.off(`sub:${token.key}`, fillSubRequest)
|
|
44
|
-
if (unsubscribeFromStateUpdates) {
|
|
45
|
-
unsubscribeFromStateUpdates()
|
|
46
|
-
unsubscribeFromStateUpdates = undefined
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
+
return clearSubscriptions
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -1,35 +1,81 @@
|
|
|
1
1
|
import type { WritableToken } from "atom.io"
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
findInStore,
|
|
4
|
+
getFromStore,
|
|
5
|
+
IMPLICIT,
|
|
6
|
+
setIntoStore,
|
|
7
|
+
subscribeToState,
|
|
8
|
+
} from "atom.io/internal"
|
|
9
|
+
import {
|
|
10
|
+
operateOnStore,
|
|
11
|
+
OWN_OP,
|
|
12
|
+
} from "atom.io/internal/set-state/operate-on-store"
|
|
3
13
|
import type { Json } from "atom.io/json"
|
|
14
|
+
import { mutexAtoms } from "atom.io/realtime/mutex-store"
|
|
4
15
|
|
|
5
16
|
import type { ServerConfig } from "."
|
|
17
|
+
import { employSocket } from "./employ-socket"
|
|
6
18
|
|
|
7
19
|
export type StateReceiver = ReturnType<typeof realtimeStateReceiver>
|
|
8
20
|
export function realtimeStateReceiver({
|
|
9
21
|
socket,
|
|
10
22
|
store = IMPLICIT.STORE,
|
|
11
23
|
}: ServerConfig) {
|
|
12
|
-
return function stateReceiver<
|
|
13
|
-
|
|
24
|
+
return function stateReceiver<S extends Json.Serializable, C extends S>(
|
|
25
|
+
clientToken: WritableToken<C>,
|
|
26
|
+
serverToken: WritableToken<S> = clientToken,
|
|
14
27
|
): () => void {
|
|
15
|
-
const
|
|
16
|
-
|
|
28
|
+
const mutexAtom = findInStore(store, mutexAtoms, serverToken.key)
|
|
29
|
+
|
|
30
|
+
const subscriptions = new Set<() => void>()
|
|
31
|
+
const clearSubscriptions = () => {
|
|
32
|
+
for (const unsub of subscriptions) unsub()
|
|
33
|
+
subscriptions.clear()
|
|
17
34
|
}
|
|
18
35
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
36
|
+
const permitPublish = () => {
|
|
37
|
+
clearSubscriptions()
|
|
38
|
+
subscriptions.add(
|
|
39
|
+
employSocket(socket, `pub:${clientToken.key}`, (newValue) => {
|
|
40
|
+
setIntoStore(store, serverToken, newValue as C)
|
|
41
|
+
}),
|
|
42
|
+
)
|
|
43
|
+
subscriptions.add(
|
|
44
|
+
employSocket(socket, `unclaim:${clientToken.key}`, () => {
|
|
45
|
+
setIntoStore(store, mutexAtom, false)
|
|
46
|
+
clearSubscriptions()
|
|
47
|
+
start()
|
|
48
|
+
}),
|
|
49
|
+
)
|
|
22
50
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
51
|
+
|
|
52
|
+
const start = () => {
|
|
53
|
+
subscriptions.add(
|
|
54
|
+
employSocket(socket, `claim:${clientToken.key}`, () => {
|
|
55
|
+
if (getFromStore(store, mutexAtom)) {
|
|
56
|
+
clearSubscriptions()
|
|
57
|
+
subscriptions.add(
|
|
58
|
+
subscribeToState(store, mutexAtom, socket.id!, () => {
|
|
59
|
+
const currentValue = getFromStore(store, mutexAtom)
|
|
60
|
+
if (currentValue === false) {
|
|
61
|
+
operateOnStore(OWN_OP, store, mutexAtom, true)
|
|
62
|
+
permitPublish()
|
|
63
|
+
socket.emit(`claim-result:${clientToken.key}`, true)
|
|
64
|
+
}
|
|
65
|
+
}),
|
|
66
|
+
)
|
|
67
|
+
socket.emit(`claim-result:${clientToken.key}`, false)
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
setIntoStore(store, mutexAtom, true)
|
|
71
|
+
permitPublish()
|
|
72
|
+
socket.emit(`claim-result:${clientToken.key}`, true)
|
|
73
|
+
}),
|
|
74
|
+
)
|
|
26
75
|
}
|
|
27
76
|
|
|
28
|
-
|
|
77
|
+
start()
|
|
29
78
|
|
|
30
|
-
return
|
|
31
|
-
socket.off(`claim:${token.key}`, fillPubClaim)
|
|
32
|
-
socket.off(`pub:${token.key}`, publish)
|
|
33
|
-
}
|
|
79
|
+
return clearSubscriptions
|
|
34
80
|
}
|
|
35
81
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Json } from "atom.io/json"
|
|
2
|
+
|
|
3
|
+
export type Socket = {
|
|
4
|
+
id: string | undefined
|
|
5
|
+
on: (event: string, listener: (...args: Json.Serializable[]) => void) => void
|
|
6
|
+
onAny: (
|
|
7
|
+
listener: (event: string, ...args: Json.Serializable[]) => void,
|
|
8
|
+
) => void
|
|
9
|
+
off: (event: string, listener: (...args: Json.Serializable[]) => void) => void
|
|
10
|
+
offAny: (
|
|
11
|
+
listener: (event: string, ...args: Json.Serializable[]) => void,
|
|
12
|
+
) => void
|
|
13
|
+
emit: (event: string, ...args: Json.Serializable[]) => void
|
|
14
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ChildProcess } from "node:child_process"
|
|
1
2
|
import * as http from "node:http"
|
|
2
3
|
|
|
3
4
|
import type { RenderResult } from "@testing-library/react"
|
|
@@ -15,10 +16,10 @@ import {
|
|
|
15
16
|
} from "atom.io/internal"
|
|
16
17
|
import { toEntries } from "atom.io/json"
|
|
17
18
|
import * as AR from "atom.io/react"
|
|
18
|
-
import * as RT from "atom.io/realtime"
|
|
19
19
|
import * as RTC from "atom.io/realtime-client"
|
|
20
20
|
import * as RTR from "atom.io/realtime-react"
|
|
21
21
|
import * as RTS from "atom.io/realtime-server"
|
|
22
|
+
import { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
22
23
|
import * as Happy from "happy-dom"
|
|
23
24
|
import * as React from "react"
|
|
24
25
|
import * as SocketIO from "socket.io"
|
|
@@ -30,27 +31,50 @@ let testNumber = 0
|
|
|
30
31
|
/* eslint-disable no-console */
|
|
31
32
|
|
|
32
33
|
function prefixLogger(store: Store, prefix: string) {
|
|
33
|
-
store.loggers[0] = new AtomIO.AtomIOLogger(
|
|
34
|
-
info
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
store.loggers[0] = new AtomIO.AtomIOLogger(
|
|
35
|
+
`info`,
|
|
36
|
+
(...params) => {
|
|
37
|
+
let idx = 0
|
|
38
|
+
for (const param of params) {
|
|
39
|
+
if (param instanceof SocketIO.Socket) {
|
|
40
|
+
params[idx] = `Socket:${param.id}`
|
|
41
|
+
}
|
|
42
|
+
if (param instanceof RTS.ChildSocket) {
|
|
43
|
+
params[idx] = `ChildSocket:${param.id}`
|
|
44
|
+
}
|
|
45
|
+
if (param instanceof ChildProcess) {
|
|
46
|
+
params[idx] = `ChildProcess:${param.pid}`
|
|
47
|
+
}
|
|
48
|
+
if (param instanceof SetRTX) {
|
|
49
|
+
params[idx] =
|
|
50
|
+
`SetRTX(${param.size}) {${[...param].join(`, `)}} at ${param.cacheIdx}`
|
|
51
|
+
}
|
|
52
|
+
idx++
|
|
53
|
+
}
|
|
54
|
+
return params
|
|
39
55
|
},
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
{
|
|
57
|
+
info: (...params) => {
|
|
58
|
+
console.info(prefix, ...params)
|
|
59
|
+
},
|
|
60
|
+
warn: (...params) => {
|
|
61
|
+
console.warn(prefix, ...params)
|
|
62
|
+
},
|
|
63
|
+
error: (...params) => {
|
|
64
|
+
console.error(prefix, ...params)
|
|
65
|
+
},
|
|
42
66
|
},
|
|
43
|
-
|
|
67
|
+
)
|
|
44
68
|
}
|
|
45
69
|
|
|
46
70
|
export type TestSetupOptions = {
|
|
47
|
-
port: number
|
|
48
71
|
immortal?: { server?: boolean }
|
|
49
72
|
server: (tools: {
|
|
50
73
|
socket: SocketIO.Socket
|
|
51
74
|
silo: AtomIO.Silo
|
|
75
|
+
userKey: RTS.UserKey
|
|
52
76
|
enableLogging: () => void
|
|
53
|
-
}) => void
|
|
77
|
+
}) => (() => void) | void
|
|
54
78
|
}
|
|
55
79
|
export type TestSetupOptions__SingleClient = TestSetupOptions & {
|
|
56
80
|
client: React.FC
|
|
@@ -105,10 +129,11 @@ export const setupRealtimeTestServer = (
|
|
|
105
129
|
},
|
|
106
130
|
IMPLICIT.STORE,
|
|
107
131
|
)
|
|
132
|
+
// prefixLogger(silo.store, `server`)
|
|
108
133
|
const socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)
|
|
109
134
|
|
|
110
135
|
const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
|
|
111
|
-
const address = httpServer.listen(
|
|
136
|
+
const address = httpServer.listen().address()
|
|
112
137
|
const port =
|
|
113
138
|
typeof address === `string` ? null : address === null ? null : address.port
|
|
114
139
|
if (port === null) throw new Error(`Could not determine port for test server`)
|
|
@@ -131,22 +156,25 @@ export const setupRealtimeTestServer = (
|
|
|
131
156
|
setIntoStore(silo.store, RTS.socketIndex, (index) =>
|
|
132
157
|
index.add(socketClaim),
|
|
133
158
|
)
|
|
134
|
-
// console.log(`${username} connected on ${socket.id}`)
|
|
135
159
|
next()
|
|
136
160
|
} else {
|
|
137
161
|
next(new Error(`Authentication error`))
|
|
138
162
|
}
|
|
139
163
|
})
|
|
140
164
|
|
|
165
|
+
const socketServices = new Set<() => void>()
|
|
166
|
+
const disposeAllSocketServices = () => {
|
|
167
|
+
for (const disposeService of socketServices) disposeService()
|
|
168
|
+
}
|
|
169
|
+
|
|
141
170
|
server.on(`connection`, (socket: SocketIO.Socket) => {
|
|
142
|
-
|
|
171
|
+
const userKeyState = findRelationsInStore(
|
|
172
|
+
RTS.usersOfSockets,
|
|
173
|
+
`socket::${socket.id}`,
|
|
174
|
+
silo.store,
|
|
175
|
+
).userKeyOfSocket
|
|
176
|
+
const userKey = getFromStore(silo.store, userKeyState)!
|
|
143
177
|
function enableLogging() {
|
|
144
|
-
const userKeyState = findRelationsInStore(
|
|
145
|
-
RTS.usersOfSockets,
|
|
146
|
-
`socket::${socket.id}`,
|
|
147
|
-
silo.store,
|
|
148
|
-
).userKeyOfSocket
|
|
149
|
-
userKey = getFromStore(silo.store, userKeyState)
|
|
150
178
|
prefixLogger(silo.store, `server`)
|
|
151
179
|
socket.onAny((event, ...args) => {
|
|
152
180
|
console.log(`🛰 `, userKey, event, ...args)
|
|
@@ -158,19 +186,30 @@ export const setupRealtimeTestServer = (
|
|
|
158
186
|
console.log(`${userKey} disconnected`)
|
|
159
187
|
})
|
|
160
188
|
}
|
|
161
|
-
options.server({
|
|
189
|
+
const disposeServices = options.server({
|
|
190
|
+
socket,
|
|
191
|
+
enableLogging,
|
|
192
|
+
silo,
|
|
193
|
+
userKey,
|
|
194
|
+
})
|
|
195
|
+
if (disposeServices) {
|
|
196
|
+
socketServices.add(disposeServices)
|
|
197
|
+
socket.on(`disconnect`, disposeServices)
|
|
198
|
+
}
|
|
162
199
|
})
|
|
163
200
|
|
|
164
201
|
const dispose = async () => {
|
|
202
|
+
disposeAllSocketServices()
|
|
165
203
|
await server.close()
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
204
|
+
|
|
205
|
+
// const roomKeys = getFromStore(silo.store, RT.roomIndex)
|
|
206
|
+
// for (const roomKey of roomKeys) {
|
|
207
|
+
// const roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)
|
|
208
|
+
// const room = getFromStore(silo.store, roomState)
|
|
209
|
+
// if (room && !(room instanceof Promise)) {
|
|
210
|
+
// room.process.kill()
|
|
211
|
+
// }
|
|
212
|
+
// } // ❗ POSSIBLY STILL NEEDED
|
|
174
213
|
silo.store.valueMap.clear()
|
|
175
214
|
}
|
|
176
215
|
|
|
@@ -212,7 +251,7 @@ export const setupRealtimeTestClient = (
|
|
|
212
251
|
}
|
|
213
252
|
|
|
214
253
|
const enableLogging = () => {
|
|
215
|
-
prefixLogger(silo.store, name)
|
|
254
|
+
// prefixLogger(silo.store, name)
|
|
216
255
|
socket.onAny((event, ...args) => {
|
|
217
256
|
console.log(`📡 `, name, event, ...args)
|
|
218
257
|
})
|
package/src/web/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./storage-sync"
|
|
@@ -5,13 +5,16 @@ export type StringInterface<T> = {
|
|
|
5
5
|
parse: (s: string) => T
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export const
|
|
8
|
+
export const storageSync =
|
|
9
9
|
<T>(
|
|
10
|
-
storage: Storage,
|
|
10
|
+
storage: Storage | undefined,
|
|
11
11
|
{ stringify, parse }: StringInterface<T>,
|
|
12
12
|
key: string,
|
|
13
13
|
): AtomEffect<T> =>
|
|
14
14
|
({ setSelf, onSet }) => {
|
|
15
|
+
if (!storage) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
15
18
|
const savedValue = storage.getItem(key)
|
|
16
19
|
if (savedValue != null) setSelf(parse(savedValue))
|
|
17
20
|
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AtomFamilyToken,
|
|
3
|
-
AtomToken,
|
|
4
|
-
MutableAtomFamilyToken,
|
|
5
|
-
MutableAtomToken,
|
|
6
|
-
ReadableFamilyToken,
|
|
7
|
-
ReadableToken,
|
|
8
|
-
ReadonlyPureSelectorFamilyToken,
|
|
9
|
-
ReadonlyPureSelectorToken,
|
|
10
|
-
RegularAtomFamilyToken,
|
|
11
|
-
RegularAtomToken,
|
|
12
|
-
SelectorFamilyToken,
|
|
13
|
-
SelectorToken,
|
|
14
|
-
WritableFamilyToken,
|
|
15
|
-
WritablePureSelectorFamilyToken,
|
|
16
|
-
WritablePureSelectorToken,
|
|
17
|
-
WritableToken,
|
|
18
|
-
} from "atom.io"
|
|
19
|
-
import type { Canonical } from "atom.io/json"
|
|
20
|
-
import { stringifyJson } from "atom.io/json"
|
|
21
|
-
|
|
22
|
-
import type { Transceiver } from "../mutable"
|
|
23
|
-
|
|
24
|
-
export const COUNTERFEIT: unique symbol = Symbol(`counterfeit`)
|
|
25
|
-
|
|
26
|
-
export const FAMILY_MEMBER_TOKEN_TYPES = {
|
|
27
|
-
atom_family: `atom`,
|
|
28
|
-
molecule_family: `molecule`,
|
|
29
|
-
mutable_atom_family: `mutable_atom`,
|
|
30
|
-
readonly_held_selector_family: `readonly_held_selector`,
|
|
31
|
-
readonly_pure_selector_family: `readonly_pure_selector`,
|
|
32
|
-
writable_held_selector_family: `writable_held_selector`,
|
|
33
|
-
writable_pure_selector_family: `writable_pure_selector`,
|
|
34
|
-
} as const
|
|
35
|
-
|
|
36
|
-
export function mint<
|
|
37
|
-
T extends Transceiver<any, any, any>,
|
|
38
|
-
K extends Canonical,
|
|
39
|
-
Key extends K,
|
|
40
|
-
>(token: MutableAtomFamilyToken<T, K>, key: Key): MutableAtomToken<T>
|
|
41
|
-
|
|
42
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
43
|
-
token: RegularAtomFamilyToken<T, K, E>,
|
|
44
|
-
key: Key,
|
|
45
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
46
|
-
): RegularAtomToken<T, Key, E>
|
|
47
|
-
|
|
48
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
49
|
-
token: AtomFamilyToken<T, K, E>,
|
|
50
|
-
key: Key,
|
|
51
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
52
|
-
): AtomToken<T, Key, E>
|
|
53
|
-
|
|
54
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
55
|
-
token: WritablePureSelectorFamilyToken<T, K, E>,
|
|
56
|
-
key: Key,
|
|
57
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
58
|
-
): WritablePureSelectorToken<T, Key, E>
|
|
59
|
-
|
|
60
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
61
|
-
token: ReadonlyPureSelectorFamilyToken<T, K, E>,
|
|
62
|
-
key: Key,
|
|
63
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
64
|
-
): ReadonlyPureSelectorToken<T, Key, E>
|
|
65
|
-
|
|
66
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
67
|
-
token: SelectorFamilyToken<T, K, E>,
|
|
68
|
-
key: Key,
|
|
69
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
70
|
-
): SelectorToken<T, Key, E>
|
|
71
|
-
|
|
72
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
73
|
-
token: WritableFamilyToken<T, K, E>,
|
|
74
|
-
key: Key,
|
|
75
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
76
|
-
): WritableToken<T, Key, E>
|
|
77
|
-
|
|
78
|
-
export function mint<T, K extends Canonical, Key extends K, E>(
|
|
79
|
-
token: ReadableFamilyToken<T, K, E>,
|
|
80
|
-
key: Key,
|
|
81
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
82
|
-
): ReadableToken<T, Key, E>
|
|
83
|
-
|
|
84
|
-
export function mint(
|
|
85
|
-
token: ReadableFamilyToken<any, any, any>,
|
|
86
|
-
key: Canonical,
|
|
87
|
-
counterfeit?: typeof COUNTERFEIT,
|
|
88
|
-
): ReadableToken<any, any, any> {
|
|
89
|
-
const subKey = stringifyJson(key)
|
|
90
|
-
const fullKey = `${token.key}(${subKey})`
|
|
91
|
-
const type = FAMILY_MEMBER_TOKEN_TYPES[token.type]
|
|
92
|
-
const stateToken: ReadableToken<any> & {
|
|
93
|
-
counterfeit?: boolean
|
|
94
|
-
} = {
|
|
95
|
-
key: fullKey,
|
|
96
|
-
type,
|
|
97
|
-
family: {
|
|
98
|
-
key: token.key,
|
|
99
|
-
subKey,
|
|
100
|
-
},
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (counterfeit) {
|
|
104
|
-
stateToken.counterfeit = true
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return stateToken
|
|
108
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type * as AtomIO from "atom.io"
|
|
2
|
-
import type { Fn, Store } from "atom.io/internal"
|
|
3
|
-
import { subscribeToTransaction } from "atom.io/internal"
|
|
4
|
-
import type { Socket } from "socket.io-client"
|
|
5
|
-
|
|
6
|
-
export function serverAction<F extends Fn>(
|
|
7
|
-
store: Store,
|
|
8
|
-
socket: Socket,
|
|
9
|
-
token: AtomIO.TransactionToken<F>,
|
|
10
|
-
): () => void {
|
|
11
|
-
const unsubscribeFromLocalUpdates = subscribeToTransaction(
|
|
12
|
-
store,
|
|
13
|
-
token,
|
|
14
|
-
`tx-run:${token.key}:${socket.id}`,
|
|
15
|
-
(clientUpdate) => {
|
|
16
|
-
socket.emit(`tx-run:${token.key}`, clientUpdate)
|
|
17
|
-
},
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
return () => {
|
|
21
|
-
unsubscribeFromLocalUpdates()
|
|
22
|
-
}
|
|
23
|
-
}
|