atom.io 0.40.5 → 0.40.7

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.
Files changed (163) hide show
  1. package/README.md +1 -1
  2. package/dist/data/index.d.ts +1 -1
  3. package/dist/employ-socket-D6wgByWh.js +12 -0
  4. package/dist/employ-socket-D6wgByWh.js.map +1 -0
  5. package/dist/has-role-hv4-hJMw.js +1149 -0
  6. package/dist/has-role-hv4-hJMw.js.map +1 -0
  7. package/dist/internal/index.d.ts +248 -248
  8. package/dist/internal/index.d.ts.map +1 -1
  9. package/dist/internal/index.js +570 -1712
  10. package/dist/internal/index.js.map +1 -1
  11. package/dist/introspection/index.d.ts +1 -1
  12. package/dist/is-fn-DY1wZ-md.js +10 -0
  13. package/dist/is-fn-DY1wZ-md.js.map +1 -0
  14. package/dist/main/index.d.ts +33 -33
  15. package/dist/main/index.d.ts.map +1 -1
  16. package/dist/main/index.js +2 -2
  17. package/dist/main/index.js.map +1 -1
  18. package/dist/mutex-store-CSvxY9i3.js +11 -0
  19. package/dist/mutex-store-CSvxY9i3.js.map +1 -0
  20. package/dist/react/index.d.ts +5 -21
  21. package/dist/react/index.d.ts.map +1 -1
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/react-devtools/index.js +7 -7
  24. package/dist/react-devtools/index.js.map +1 -1
  25. package/dist/realtime/index.d.ts +7 -15
  26. package/dist/realtime/index.d.ts.map +1 -1
  27. package/dist/realtime/index.js +3 -33
  28. package/dist/realtime/index.js.map +1 -1
  29. package/dist/realtime-client/index.d.ts +5 -5
  30. package/dist/realtime-client/index.d.ts.map +1 -1
  31. package/dist/realtime-client/index.js +92 -69
  32. package/dist/realtime-client/index.js.map +1 -1
  33. package/dist/realtime-react/index.d.ts +17 -10
  34. package/dist/realtime-react/index.d.ts.map +1 -1
  35. package/dist/realtime-react/index.js +41 -41
  36. package/dist/realtime-react/index.js.map +1 -1
  37. package/dist/realtime-server/index.d.ts +60 -53
  38. package/dist/realtime-server/index.d.ts.map +1 -1
  39. package/dist/realtime-server/index.js +592 -485
  40. package/dist/realtime-server/index.js.map +1 -1
  41. package/dist/realtime-testing/index.d.ts +1 -2
  42. package/dist/realtime-testing/index.d.ts.map +1 -1
  43. package/dist/realtime-testing/index.js +25 -18
  44. package/dist/realtime-testing/index.js.map +1 -1
  45. package/dist/shared-room-store-COGGKqes.js +32 -0
  46. package/dist/shared-room-store-COGGKqes.js.map +1 -0
  47. package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
  48. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
  49. package/dist/web/index.d.ts +3 -3
  50. package/dist/web/index.d.ts.map +1 -1
  51. package/dist/web/index.js +4 -3
  52. package/dist/web/index.js.map +1 -1
  53. package/package.json +12 -12
  54. package/src/internal/atom/create-regular-atom.ts +5 -4
  55. package/src/internal/atom/dispose-atom.ts +7 -2
  56. package/src/internal/atom/has-role.ts +3 -3
  57. package/src/internal/caching.ts +4 -2
  58. package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
  59. package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
  60. package/src/internal/families/create-regular-atom-family.ts +2 -1
  61. package/src/internal/families/create-writable-held-selector-family.ts +2 -1
  62. package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
  63. package/src/internal/families/dispose-from-store.ts +4 -4
  64. package/src/internal/families/find-in-store.ts +10 -10
  65. package/src/internal/families/get-family-of-token.ts +2 -2
  66. package/src/internal/families/index.ts +1 -0
  67. package/src/internal/families/mint-in-store.ts +54 -19
  68. package/src/internal/families/seek-in-store.ts +1 -1
  69. package/src/internal/get-state/get-fallback.ts +2 -2
  70. package/src/internal/get-state/get-from-store.ts +5 -5
  71. package/src/internal/get-state/read-or-compute-value.ts +1 -1
  72. package/src/internal/get-state/reduce-reference.ts +8 -6
  73. package/src/internal/index.ts +2 -220
  74. package/src/internal/molecule.ts +1 -2
  75. package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
  76. package/src/internal/mutable/create-mutable-atom.ts +4 -2
  77. package/src/internal/mutable/get-json-family.ts +1 -1
  78. package/src/internal/mutable/get-update-family.ts +1 -1
  79. package/src/internal/mutable/tracker-family.ts +2 -1
  80. package/src/internal/mutable/tracker.ts +5 -8
  81. package/src/internal/safe-compute.ts +1 -1
  82. package/src/internal/selector/create-readonly-held-selector.ts +2 -1
  83. package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
  84. package/src/internal/selector/create-writable-held-selector.ts +2 -1
  85. package/src/internal/selector/create-writable-pure-selector.ts +2 -1
  86. package/src/internal/selector/dispose-selector.ts +3 -2
  87. package/src/internal/selector/register-selector.ts +8 -5
  88. package/src/internal/selector/trace-selector-atoms.ts +2 -1
  89. package/src/internal/set-state/dispatch-state-update.ts +3 -2
  90. package/src/internal/set-state/evict-downstream.ts +1 -1
  91. package/src/internal/set-state/operate-on-store.ts +16 -22
  92. package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
  93. package/src/internal/set-state/reset-in-store.ts +5 -5
  94. package/src/internal/set-state/set-atom-or-selector.ts +2 -2
  95. package/src/internal/set-state/set-atom.ts +4 -2
  96. package/src/internal/set-state/set-into-store.ts +21 -39
  97. package/src/internal/set-state/set-selector.ts +3 -2
  98. package/src/internal/state-types.ts +228 -0
  99. package/src/internal/store/deposit.ts +4 -4
  100. package/src/internal/store/index.ts +0 -1
  101. package/src/internal/store/store.ts +9 -9
  102. package/src/internal/store/withdraw.ts +4 -4
  103. package/src/internal/subscribe/recall-state.ts +1 -1
  104. package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
  105. package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
  106. package/src/internal/transaction/build-transaction.ts +3 -2
  107. package/src/internal/transaction/index.ts +1 -23
  108. package/src/internal/transaction/is-root-store.ts +4 -1
  109. package/src/internal/transaction/transaction-meta-progress.ts +22 -0
  110. package/src/main/atom.ts +1 -2
  111. package/src/main/find-state.ts +5 -5
  112. package/src/main/get-state.ts +4 -4
  113. package/src/main/realm.ts +2 -2
  114. package/src/main/set-state.ts +10 -10
  115. package/src/react/parse-state-overloads.ts +3 -3
  116. package/src/react/use-i.ts +6 -4
  117. package/src/react/use-loadable.ts +4 -30
  118. package/src/react/use-o.ts +6 -4
  119. package/src/react-devtools/store.ts +6 -6
  120. package/src/realtime/index.ts +1 -0
  121. package/src/realtime/mutex-store.ts +11 -0
  122. package/src/realtime/realtime-continuity.ts +1 -5
  123. package/src/realtime-client/pull-atom-family-member.ts +14 -17
  124. package/src/realtime-client/pull-atom.ts +1 -1
  125. package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
  126. package/src/realtime-client/pull-selector-family-member.ts +8 -35
  127. package/src/realtime-client/pull-selector-roots.ts +90 -0
  128. package/src/realtime-client/pull-selector.ts +2 -27
  129. package/src/realtime-client/push-state.ts +33 -5
  130. package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
  131. package/src/realtime-react/index.ts +2 -1
  132. package/src/realtime-react/realtime-context.tsx +9 -5
  133. package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
  134. package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
  135. package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
  136. package/src/realtime-react/use-push.ts +7 -3
  137. package/src/realtime-react/use-realtime-service.ts +11 -11
  138. package/src/realtime-react/use-single-effect.ts +11 -14
  139. package/src/realtime-server/{realtime-server-stores/server-sync-store.ts → continuity/continuity-store.ts} +1 -1
  140. package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +1 -1
  141. package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +3 -5
  142. package/src/realtime-server/continuity/subscribe-to-continuity-actions.ts +1 -1
  143. package/src/realtime-server/employ-socket.ts +14 -0
  144. package/src/realtime-server/index.ts +2 -20
  145. package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
  146. package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
  147. package/src/realtime-server/ipc-sockets/parent-socket.ts +81 -58
  148. package/src/realtime-server/realtime-family-provider.ts +78 -29
  149. package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
  150. package/src/realtime-server/realtime-mutable-provider.ts +30 -22
  151. package/src/realtime-server/realtime-server-stores/index.ts +0 -2
  152. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
  153. package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
  154. package/src/realtime-server/realtime-state-provider.ts +30 -29
  155. package/src/realtime-server/realtime-state-receiver.ts +62 -16
  156. package/src/realtime-server/server-config.ts +9 -0
  157. package/src/realtime-server/socket-interface.ts +14 -0
  158. package/src/realtime-testing/setup-realtime-test.tsx +56 -23
  159. package/src/web/index.ts +1 -1
  160. package/src/web/{persist-sync.ts → storage-sync.ts} +5 -2
  161. package/src/internal/store/mint-or-counterfeit.ts +0 -108
  162. package/src/realtime-react/on-mount.ts +0 -5
  163. 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
- Loadable,
6
- ReadonlyPureSelectorFamilyToken,
7
- RegularAtomFamilyToken,
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 type RoomArguments =
14
- | [script: string, options: string[]]
15
- | [script: string]
13
+ export const ROOMS: Map<
14
+ string,
15
+ ChildSocket<any, any, ChildProcessWithoutNullStreams>
16
+ > = new Map()
16
17
 
17
- export const roomArgumentsAtoms: RegularAtomFamilyToken<RoomArguments, string> =
18
- atomFamily<RoomArguments, string>({
19
- key: `roomArguments`,
20
- default: [`echo`, [`Hello World!`]],
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 roomSelectors: ReadonlyPureSelectorFamilyToken<
24
- Loadable<ChildSocket<any, any>>,
25
- string
26
- > = selectorFamily<Loadable<ChildSocket<any, any>>, string>({
27
- key: `room`,
28
- get:
29
- (roomId) =>
30
- async ({ get, find }) => {
31
- const argumentsState = find(roomArgumentsAtoms, roomId)
32
- const args = get(argumentsState)
33
- const [script, options] = args
34
- const child = await new Promise<ChildProcessWithoutNullStreams>(
35
- (resolve) => {
36
- const room = spawn(script, options, { env: process.env })
37
- const resolver = (data: Buffer) => {
38
- if (data.toString() === `ALIVE`) {
39
- room.stdout.off(`data`, resolver)
40
- resolve(room)
41
- }
42
- }
43
- room.stdout.on(`data`, resolver)
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
- return new ChildSocket(child, roomId)
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
- let unsubscribeFromStateUpdates: (() => void) | undefined
16
-
17
- const fillSubRequest = () => {
18
- socket.emit(`serve:${token.key}`, getFromStore(store, token))
16
+ const subscriptions = new Set<() => void>()
17
+ const clearSubscriptions = () => {
18
+ for (const unsub of subscriptions) unsub()
19
+ subscriptions.clear()
20
+ }
19
21
 
20
- unsubscribeFromStateUpdates = subscribeToState(
21
- store,
22
- token,
23
- `expose-single:${socket.id}`,
24
- ({ newValue }) => {
25
- socket.emit(`serve:${token.key}`, newValue)
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
- socket.on(`sub:${token.key}`, fillSubRequest)
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 { IMPLICIT, setIntoStore } from "atom.io/internal"
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<J extends Json.Serializable>(
13
- token: WritableToken<J>,
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 publish = (newValue: J) => {
16
- setIntoStore(store, token, newValue)
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 fillPubUnclaim = () => {
20
- socket.off(`pub:${token.key}`, publish)
21
- socket.off(`unclaim:${token.key}`, fillPubUnclaim)
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
- const fillPubClaim = () => {
24
- socket.on(`pub:${token.key}`, publish)
25
- socket.on(`unclaim:${token.key}`, fillPubUnclaim)
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
- socket.on(`claim:${token.key}`, fillPubClaim)
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,9 @@
1
+ import type { RootStore } from "atom.io/internal"
2
+
3
+ import type { Socket } from "./socket-interface"
4
+
5
+ export type ServerConfig = {
6
+ socket: Socket
7
+ store?: RootStore
8
+ mutex?: Set<string>
9
+ }
@@ -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,49 @@ 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(`info`, undefined, {
34
- info: (...args) => {
35
- console.info(prefix, ...args)
36
- },
37
- warn: (...args) => {
38
- console.warn(prefix, ...args)
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
- error: (...args) => {
41
- console.error(prefix, ...args)
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
52
75
  enableLogging: () => void
53
- }) => void
76
+ }) => (() => void) | void
54
77
  }
55
78
  export type TestSetupOptions__SingleClient = TestSetupOptions & {
56
79
  client: React.FC
@@ -105,10 +128,11 @@ export const setupRealtimeTestServer = (
105
128
  },
106
129
  IMPLICIT.STORE,
107
130
  )
131
+ // prefixLogger(silo.store, `server`)
108
132
  const socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)
109
133
 
110
134
  const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
111
- const address = httpServer.listen(options.port).address()
135
+ const address = httpServer.listen().address()
112
136
  const port =
113
137
  typeof address === `string` ? null : address === null ? null : address.port
114
138
  if (port === null) throw new Error(`Could not determine port for test server`)
@@ -138,6 +162,8 @@ export const setupRealtimeTestServer = (
138
162
  }
139
163
  })
140
164
 
165
+ const serviceDisposalFunctions: Array<() => void> = []
166
+
141
167
  server.on(`connection`, (socket: SocketIO.Socket) => {
142
168
  let userKey: string | null = null
143
169
  function enableLogging() {
@@ -158,19 +184,26 @@ export const setupRealtimeTestServer = (
158
184
  console.log(`${userKey} disconnected`)
159
185
  })
160
186
  }
161
- options.server({ socket, enableLogging, silo })
187
+ const disposeServices = options.server({ socket, enableLogging, silo })
188
+ if (disposeServices) {
189
+ serviceDisposalFunctions.push(disposeServices)
190
+ }
162
191
  })
163
192
 
164
193
  const dispose = async () => {
165
- await server.close()
166
- const roomKeys = getFromStore(silo.store, RT.roomIndex)
167
- for (const roomKey of roomKeys) {
168
- const roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)
169
- const room = getFromStore(silo.store, roomState)
170
- if (room && !(room instanceof Promise)) {
171
- room.process.kill()
172
- }
194
+ for (const disposeSocketServices of serviceDisposalFunctions) {
195
+ disposeSocketServices()
173
196
  }
197
+ await server.close()
198
+
199
+ // const roomKeys = getFromStore(silo.store, RT.roomIndex)
200
+ // for (const roomKey of roomKeys) {
201
+ // const roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)
202
+ // const room = getFromStore(silo.store, roomState)
203
+ // if (room && !(room instanceof Promise)) {
204
+ // room.process.kill()
205
+ // }
206
+ // } // ❗ POSSIBLY STILL NEEDED
174
207
  silo.store.valueMap.clear()
175
208
  }
176
209
 
@@ -212,7 +245,7 @@ export const setupRealtimeTestClient = (
212
245
  }
213
246
 
214
247
  const enableLogging = () => {
215
- prefixLogger(silo.store, name)
248
+ // prefixLogger(silo.store, name)
216
249
  socket.onAny((event, ...args) => {
217
250
  console.log(`📡 `, name, event, ...args)
218
251
  })
package/src/web/index.ts CHANGED
@@ -1 +1 @@
1
- export * from "./persist-sync"
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 persistSync =
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,5 +0,0 @@
1
- import { useSingleEffect } from "./use-single-effect"
2
-
3
- export function onMount(effect: () => (() => void) | undefined | void): void {
4
- useSingleEffect(effect, [])
5
- }