atom.io 0.40.7 → 0.40.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
  2. package/dist/data/index.js +1 -2
  3. package/dist/data/index.js.map +1 -1
  4. package/dist/eslint-plugin/index.js +2 -3
  5. package/dist/eslint-plugin/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +4 -3
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +1231 -176
  9. package/dist/internal/index.js.map +1 -1
  10. package/dist/introspection/index.d.ts.map +1 -1
  11. package/dist/introspection/index.js +13 -32
  12. package/dist/introspection/index.js.map +1 -1
  13. package/dist/json/index.d.ts.map +1 -1
  14. package/dist/json/index.js.map +1 -1
  15. package/dist/main/index.d.ts.map +1 -1
  16. package/dist/main/index.js +1 -2
  17. package/dist/main/index.js.map +1 -1
  18. package/dist/react/index.d.ts.map +1 -1
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/react-devtools/index.d.ts.map +1 -1
  21. package/dist/react-devtools/index.js +2 -4
  22. package/dist/react-devtools/index.js.map +1 -1
  23. package/dist/realtime/index.d.ts +29 -5
  24. package/dist/realtime/index.d.ts.map +1 -1
  25. package/dist/realtime/index.js +47 -5
  26. package/dist/realtime/index.js.map +1 -1
  27. package/dist/realtime-client/index.d.ts +2 -6
  28. package/dist/realtime-client/index.d.ts.map +1 -1
  29. package/dist/realtime-client/index.js +6 -22
  30. package/dist/realtime-client/index.js.map +1 -1
  31. package/dist/realtime-react/index.d.ts +6 -9
  32. package/dist/realtime-react/index.d.ts.map +1 -1
  33. package/dist/realtime-react/index.js +4 -16
  34. package/dist/realtime-react/index.js.map +1 -1
  35. package/dist/realtime-server/index.d.ts +38 -57
  36. package/dist/realtime-server/index.d.ts.map +1 -1
  37. package/dist/realtime-server/index.js +128 -178
  38. package/dist/realtime-server/index.js.map +1 -1
  39. package/dist/realtime-testing/index.d.ts +2 -0
  40. package/dist/realtime-testing/index.d.ts.map +1 -1
  41. package/dist/realtime-testing/index.js +15 -9
  42. package/dist/realtime-testing/index.js.map +1 -1
  43. package/dist/transceivers/set-rtx/index.d.ts +1 -1
  44. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  45. package/dist/transceivers/set-rtx/index.js +5 -9
  46. package/dist/transceivers/set-rtx/index.js.map +1 -1
  47. package/dist/transceivers/u-list/index.d.ts +29 -0
  48. package/dist/transceivers/u-list/index.d.ts.map +1 -0
  49. package/dist/transceivers/u-list/index.js +87 -0
  50. package/dist/transceivers/u-list/index.js.map +1 -0
  51. package/dist/web/index.js.map +1 -1
  52. package/package.json +17 -13
  53. package/src/internal/mutable/tracker.ts +61 -46
  54. package/src/internal/mutable/transceiver.ts +4 -4
  55. package/src/internal/set-state/index.ts +1 -0
  56. package/src/internal/subscribe/subscribe-to-state.ts +9 -0
  57. package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
  58. package/src/realtime/index.ts +2 -0
  59. package/src/realtime/shared-room-store.ts +12 -11
  60. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
  61. package/src/realtime-client/index.ts +0 -1
  62. package/src/realtime-client/push-state.ts +1 -2
  63. package/src/realtime-react/index.ts +0 -1
  64. package/src/realtime-react/use-single-effect.ts +1 -1
  65. package/src/realtime-server/continuity/continuity-store.ts +2 -27
  66. package/src/realtime-server/continuity/provide-continuity.ts +50 -0
  67. package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +16 -14
  68. package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +11 -10
  69. package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +8 -6
  70. package/src/realtime-server/continuity/receive-action-requests.ts +66 -0
  71. package/src/realtime-server/continuity/{prepare-to-track-client-acknowledgement.ts → track-acknowledgements.ts} +15 -9
  72. package/src/realtime-server/index.ts +1 -3
  73. package/src/realtime-server/ipc-sockets/custom-socket.ts +4 -5
  74. package/src/realtime-server/ipc-sockets/parent-socket.ts +21 -17
  75. package/src/realtime-server/realtime-family-provider.ts +1 -1
  76. package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
  77. package/src/realtime-server/realtime-mutable-provider.ts +1 -1
  78. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
  79. package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
  80. package/src/realtime-server/realtime-state-provider.ts +1 -1
  81. package/src/realtime-server/realtime-state-receiver.ts +3 -6
  82. package/src/realtime-server/server-config.ts +1 -3
  83. package/src/realtime-testing/setup-realtime-test.tsx +23 -18
  84. package/src/transceivers/set-rtx/set-rtx.ts +3 -3
  85. package/src/transceivers/u-list/index.ts +1 -0
  86. package/src/transceivers/u-list/u-list.ts +123 -0
  87. package/dist/employ-socket-D6wgByWh.js +0 -12
  88. package/dist/employ-socket-D6wgByWh.js.map +0 -1
  89. package/dist/has-role-hv4-hJMw.js +0 -1149
  90. package/dist/has-role-hv4-hJMw.js.map +0 -1
  91. package/dist/is-fn-DY1wZ-md.js +0 -10
  92. package/dist/is-fn-DY1wZ-md.js.map +0 -1
  93. package/dist/mutex-store-CSvxY9i3.js +0 -11
  94. package/dist/mutex-store-CSvxY9i3.js.map +0 -1
  95. package/dist/shared-room-store-COGGKqes.js +0 -32
  96. package/dist/shared-room-store-COGGKqes.js.map +0 -1
  97. package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
  98. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
  99. package/src/realtime-client/server-action.ts +0 -23
  100. package/src/realtime-react/use-server-action.ts +0 -19
  101. package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
  102. package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
  103. package/src/realtime-server/realtime-action-receiver.ts +0 -40
  104. /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
@@ -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
+ }
@@ -7,29 +7,29 @@ import {
7
7
  subscribeToTransaction,
8
8
  } from "atom.io/internal"
9
9
  import type { Json } from "atom.io/json"
10
- import type { ContinuityToken } from "atom.io/realtime"
10
+ import type { ContinuityToken, Socket } from "atom.io/realtime"
11
11
 
12
- import type { Socket, UserKey } from ".."
12
+ import type { UserKey } from ".."
13
13
  import {
14
14
  redactTransactionUpdateContent,
15
- userUnacknowledgedQueues,
15
+ unacknowledgedUpdatesAtoms,
16
16
  } from "./continuity-store"
17
17
 
18
- export function subscribeToContinuityActions(
18
+ export function provideOutcomes(
19
19
  store: Store,
20
+ socket: Socket,
20
21
  continuity: ContinuityToken,
21
22
  userKey: UserKey,
22
- socket: Socket | null,
23
- ): (() => void)[] {
23
+ ): () => void {
24
24
  const continuityKey = continuity.key
25
- const unsubscribeFunctions: (() => void)[] = []
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
- (update) => {
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
- update.subEvents,
62
+ outcomes.subEvents,
63
63
  )
64
64
  const redactedUpdate = {
65
- ...update,
65
+ ...outcomes,
66
66
  updates: redactedUpdates,
67
67
  }
68
- setIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {
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?.emit(
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.push(unsubscribeFromTransaction)
101
+ unsubscribeFunctions.add(unsubscribeFromTransaction)
102
+ }
103
+ return () => {
104
+ for (const unsubscribe of unsubscribeFunctions) unsubscribe()
102
105
  }
103
- return unsubscribeFunctions
104
106
  }
@@ -5,19 +5,18 @@ import {
5
5
  getJsonToken,
6
6
  subscribeToState,
7
7
  } from "atom.io/internal"
8
- import type { ContinuityToken } from "atom.io/realtime"
8
+ import type { ContinuityToken, Socket } from "atom.io/realtime"
9
9
 
10
- import type { Socket } from ".."
11
10
  import type { UserKey } from "../realtime-server-stores"
12
11
 
13
- export function subscribeToContinuityPerspectives(
12
+ export function providePerspectives(
14
13
  store: Store,
14
+ socket: Socket,
15
15
  continuity: ContinuityToken,
16
16
  userKey: UserKey,
17
- socket: Socket | null,
18
- ): (() => void)[] {
17
+ ): () => void {
19
18
  const continuityKey = continuity.key
20
- const unsubFns: (() => void)[] = []
19
+ const unsubFns = new Set<() => void>()
21
20
  for (const perspective of continuity.perspectives) {
22
21
  const { viewAtoms } = perspective
23
22
  const userViewState = findInStore(store, viewAtoms, userKey)
@@ -47,14 +46,16 @@ export function subscribeToContinuityPerspectives(
47
46
  { oldKeys, newKeys, revealed, concealed },
48
47
  )
49
48
  if (revealed.length > 0) {
50
- socket?.emit(`reveal:${continuityKey}`, revealed)
49
+ socket.emit(`reveal:${continuityKey}`, revealed)
51
50
  }
52
51
  if (concealed && concealed.length > 0) {
53
- socket?.emit(`conceal:${continuityKey}`, concealed)
52
+ socket.emit(`conceal:${continuityKey}`, concealed)
54
53
  }
55
54
  },
56
55
  )
57
- unsubFns.push(unsubscribeFromUserView)
56
+ unsubFns.add(unsubscribeFromUserView)
57
+ }
58
+ return () => {
59
+ for (const unsubscribe of unsubFns) unsubscribe()
58
60
  }
59
- return unsubFns
60
61
  }
@@ -6,18 +6,19 @@ import {
6
6
  isRootStore,
7
7
  } from "atom.io/internal"
8
8
  import type { Json } from "atom.io/json"
9
- import type { ContinuityToken } from "atom.io/realtime"
9
+ import type { ContinuityToken, Socket } from "atom.io/realtime"
10
+ import { employSocket } from "atom.io/realtime"
10
11
 
11
- import type { Socket, UserKey } from ".."
12
+ import type { UserKey } from ".."
12
13
 
13
- export function prepareToSendInitialPayload(
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
- return function sendInitialPayload(): void {
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?.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)
53
+ socket.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)
53
54
  }
55
+ return employSocket(socket, `get:${continuityKey}`, sendInitialPayload)
54
56
  }
@@ -0,0 +1,66 @@
1
+ import type { TransactionOutcomeEvent, TransactionToken } from "atom.io"
2
+ import type { Store } from "atom.io/internal"
3
+ import { actUponStore } from "atom.io/internal"
4
+ import type { Json, JsonIO } from "atom.io/json"
5
+ import type { ContinuityToken, Socket } from "atom.io/realtime"
6
+ import { employSocket } from "atom.io/realtime"
7
+
8
+ export function receiveActionRequests(
9
+ store: Store,
10
+ socket: Socket,
11
+ continuity: ContinuityToken,
12
+ userKey: string,
13
+ ): () => void {
14
+ const continuityKey = continuity.key
15
+
16
+ return employSocket(
17
+ socket,
18
+ `tx-run:${continuityKey}`,
19
+ function serveTransactionRequest(
20
+ txOutcome: Json.Serializable &
21
+ Pick<
22
+ TransactionOutcomeEvent<TransactionToken<JsonIO>>,
23
+ `id` | `params` | `token`
24
+ >,
25
+ ) {
26
+ store.logger.info(`🛎️`, `continuity`, continuityKey, `received`, txOutcome)
27
+ const transactionKey = txOutcome.token.key
28
+ const updateId = txOutcome.id
29
+ const performanceKey = `tx-run:${transactionKey}:${updateId}`
30
+ const performanceKeyStart = `${performanceKey}:start`
31
+ const performanceKeyEnd = `${performanceKey}:end`
32
+ performance.mark(performanceKeyStart)
33
+ try {
34
+ actUponStore(
35
+ store,
36
+ { type: `transaction`, key: transactionKey },
37
+ updateId,
38
+ )(...txOutcome.params)
39
+ } catch (thrown) {
40
+ if (thrown instanceof Error) {
41
+ store.logger.error(
42
+ `❌`,
43
+ `continuity`,
44
+ continuityKey,
45
+ `failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,
46
+ thrown.message,
47
+ )
48
+ }
49
+ }
50
+ performance.mark(performanceKeyEnd)
51
+ const metric = performance.measure(
52
+ performanceKey,
53
+ performanceKeyStart,
54
+ performanceKeyEnd,
55
+ )
56
+ store.logger.info(
57
+ `🚀`,
58
+ `transaction`,
59
+ transactionKey,
60
+ updateId,
61
+ userKey,
62
+ metric.duration,
63
+ )
64
+ },
65
+ )
66
+ }
@@ -1,19 +1,24 @@
1
1
  import type { Store } from "atom.io/internal"
2
- import { setIntoStore } from "atom.io/internal"
3
- import type { ContinuityToken } from "atom.io/realtime"
2
+ import { getFromStore, setIntoStore } from "atom.io/internal"
3
+ import type { ContinuityToken, Socket } from "atom.io/realtime"
4
+ import { employSocket } from "atom.io/realtime"
4
5
 
5
6
  import type { UserKey } from "../realtime-server-stores"
6
- import type { ContinuitySyncTransactionUpdate } from "./continuity-store"
7
- import { userUnacknowledgedQueues } from "./continuity-store"
7
+ import { unacknowledgedUpdatesAtoms } from "./continuity-store"
8
8
 
9
- export function prepareToTrackClientAcknowledgement(
9
+ export function trackAcknowledgements(
10
10
  store: Store,
11
+ socket: Socket,
11
12
  continuity: ContinuityToken,
12
13
  userKey: UserKey,
13
- userUnacknowledgedUpdates: ContinuitySyncTransactionUpdate[],
14
- ): (epoch: number) => void {
14
+ ): () => void {
15
15
  const continuityKey = continuity.key
16
- return function trackClientAcknowledgement(epoch) {
16
+ const userUnacknowledgedUpdates = getFromStore(
17
+ store,
18
+ unacknowledgedUpdatesAtoms,
19
+ userKey,
20
+ )
21
+ function trackClientAcknowledgement(epoch: number): void {
17
22
  store.logger.info(
18
23
  `👍`,
19
24
  `continuity`,
@@ -22,7 +27,7 @@ export function prepareToTrackClientAcknowledgement(
22
27
  )
23
28
  const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch
24
29
  if (isUnacknowledged) {
25
- setIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {
30
+ setIntoStore(store, unacknowledgedUpdatesAtoms, userKey, (updates) => {
26
31
  updates.shift()
27
32
  store.logger.info(
28
33
  `👍`,
@@ -36,4 +41,5 @@ export function prepareToTrackClientAcknowledgement(
36
41
  })
37
42
  }
38
43
  }
44
+ return employSocket(socket, `ack:${continuityKey}`, trackClientAcknowledgement)
39
45
  }
@@ -1,6 +1,5 @@
1
- export * from "./continuity/prepare-to-sync-realtime-continuity"
1
+ export * from "./continuity/provide-continuity"
2
2
  export * from "./ipc-sockets"
3
- export * from "./realtime-action-receiver"
4
3
  export * from "./realtime-family-provider"
5
4
  export * from "./realtime-mutable-family-provider"
6
5
  export * from "./realtime-mutable-provider"
@@ -8,4 +7,3 @@ export * from "./realtime-server-stores"
8
7
  export * from "./realtime-state-provider"
9
8
  export * from "./realtime-state-receiver"
10
9
  export type * from "./server-config"
11
- export type * from "./socket-interface"
@@ -1,13 +1,12 @@
1
1
  import type { Json, stringified } from "atom.io/json"
2
-
3
- import type { Socket } from "../socket-interface"
2
+ import type { Socket } from "atom.io/realtime"
4
3
 
5
4
  export type Events = Json.Object<string, Json.Serializable[]>
6
5
 
7
6
  export type EventPayload<
8
- E extends Events,
9
- K extends string & keyof E = string & keyof E,
10
- > = [string, ...E[K]]
7
+ receiveRelay extends Events,
8
+ K extends string & keyof receiveRelay = string & keyof receiveRelay,
9
+ > = [string, ...receiveRelay[K]]
11
10
 
12
11
  export interface EventBuffer<
13
12
  E extends Events,
@@ -3,8 +3,9 @@ import type { Readable, Writable } from "node:stream"
3
3
  import { Subject } from "atom.io/internal"
4
4
  import type { Json } from "atom.io/json"
5
5
  import { parseJson, stringifyJson } from "atom.io/json"
6
- import { SetRTX } from "atom.io/transceivers/set-rtx"
6
+ import { UList } from "atom.io/transceivers/u-list"
7
7
 
8
+ import type { UserKey } from "../realtime-server-stores"
8
9
  import type { StderrLog } from "./child-socket"
9
10
  import type { EventBuffer, EventPayload, Events } from "./custom-socket"
10
11
  import { CustomSocket } from "./custom-socket"
@@ -48,14 +49,14 @@ export type ParentProcess = {
48
49
 
49
50
  export class ParentSocket<
50
51
  I extends Events & {
51
- [id in string as `relay:${id}`]: [string, ...Json.Array[]]
52
+ [id in string as `relay::${id}`]: [string, ...Json.Array[]]
52
53
  },
53
54
  O extends Events & {
54
- [id in string as `user:${id}`]: [string, ...Json.Array[]]
55
+ [id in string as `user::${id}`]: [string, ...Json.Array[]]
55
56
  } & {
56
57
  /* eslint-disable quotes */
57
- "user-joins": [string]
58
- "user-leaves": [string]
58
+ "user-joins": [key: UserKey]
59
+ "user-leaves": [key: UserKey]
59
60
  /* eslint-enable quotes */
60
61
  },
61
62
  P extends ParentProcess = ParentProcess,
@@ -65,6 +66,7 @@ export class ParentSocket<
65
66
  protected relays: Map<string, SubjectSocket<any, any>>
66
67
  protected relayServices: ((
67
68
  socket: SubjectSocket<any, any>,
69
+ userKey: UserKey,
68
70
  ) => (() => void) | void)[]
69
71
  public proc: P
70
72
 
@@ -74,9 +76,7 @@ export class ParentSocket<
74
76
  this.proc.stderr.write(
75
77
  stringifyJson(
76
78
  args.map((arg) =>
77
- arg instanceof SetRTX
78
- ? `{ ${arg.toJSON().members.join(` | `)} }`
79
- : arg,
79
+ arg instanceof UList ? `{ ${arg.toJSON().members.join(` | `)} }` : arg,
80
80
  ),
81
81
  ) + `\x03`,
82
82
  )
@@ -171,22 +171,23 @@ export class ParentSocket<
171
171
  this.id = this.proc.pid?.toString()
172
172
  }
173
173
 
174
- this.on(`user-joins`, (username) => {
174
+ this.on(`user-joins`, (username: string) => {
175
175
  this.logger.info(`👤`, `user`, username, `joined`)
176
- const relay = new SubjectSocket(`user:${username}`)
176
+ const userKey = `user::${username}` satisfies UserKey
177
+ const relay = new SubjectSocket(userKey)
177
178
  this.relays.set(username, relay)
178
179
  this.logger.info(
179
180
  `🔗`,
180
181
  `attaching services:`,
181
182
  `[${[...this.relayServices.keys()].join(`, `)}]`,
182
183
  )
183
- for (const attachServices of this.relayServices) {
184
- const cleanup = attachServices(relay)
185
- if (cleanup) {
186
- relay.disposalFunctions.push(cleanup)
184
+ for (const attachRelay of this.relayServices) {
185
+ const cleanupRelay = attachRelay(relay, userKey)
186
+ if (cleanupRelay) {
187
+ relay.disposalFunctions.push(cleanupRelay)
187
188
  }
188
189
  }
189
- this.on(`user:${username}`, (...data) => {
190
+ this.on(userKey, (...data) => {
190
191
  relay.in.next(data)
191
192
  })
192
193
  relay.out.subscribe(`socket`, (data) => {
@@ -206,8 +207,11 @@ export class ParentSocket<
206
207
  this.proc.stdout.write(`ALIVE`)
207
208
  }
208
209
 
209
- public relay(
210
- attachServices: (socket: SubjectSocket<any, any>) => (() => void) | void,
210
+ public receiveRelay(
211
+ attachServices: (
212
+ socket: SubjectSocket<any, any>,
213
+ userKey: UserKey,
214
+ ) => (() => void) | void,
211
215
  ): void {
212
216
  this.logger.info(`🔗`, `running relay method`)
213
217
  this.relayServices.push(attachServices)
@@ -7,9 +7,9 @@ import {
7
7
  } from "atom.io/internal"
8
8
  import type { Canonical, Json, stringified } from "atom.io/json"
9
9
  import { stringifyJson } from "atom.io/json"
10
+ import { employSocket } from "atom.io/realtime"
10
11
 
11
12
  import type { ServerConfig } from "."
12
- import { employSocket } from "./employ-socket"
13
13
 
14
14
  export type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>
15
15
  export function realtimeAtomFamilyProvider({
@@ -10,9 +10,9 @@ import {
10
10
  } from "atom.io/internal"
11
11
  import type { Canonical, stringified } from "atom.io/json"
12
12
  import { stringifyJson } from "atom.io/json"
13
+ import { employSocket } from "atom.io/realtime"
13
14
 
14
15
  import type { ServerConfig } from "."
15
- import { employSocket } from "./employ-socket"
16
16
 
17
17
  export type MutableFamilyProvider = ReturnType<
18
18
  typeof realtimeMutableFamilyProvider
@@ -8,9 +8,9 @@ import {
8
8
  subscribeToState,
9
9
  } from "atom.io/internal"
10
10
  import type { Json } from "atom.io/json"
11
+ import { employSocket } from "atom.io/realtime"
11
12
 
12
13
  import type { ServerConfig } from "."
13
- import { employSocket } from "./employ-socket"
14
14
 
15
15
  export type MutableProvider = ReturnType<typeof realtimeMutableProvider>
16
16
  export function realtimeMutableProvider({
@@ -4,8 +4,8 @@ import { spawn } from "node:child_process"
4
4
  import type { TransactionIO, TransactionToken } from "atom.io"
5
5
  import { transaction } from "atom.io"
6
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"
7
+ import type { UserInRoomMeta } from "atom.io/realtime"
8
+ import { roomIndex, usersInRooms } from "atom.io/realtime"
9
9
 
10
10
  import { ChildSocket } from "../ipc-sockets"
11
11
  import type { RoomKey } from "./server-user-store"
@@ -6,9 +6,8 @@ import type {
6
6
  RegularAtomFamilyToken,
7
7
  } from "atom.io"
8
8
  import { atomFamily, join, mutableAtom, selectorFamily } from "atom.io"
9
- import { SetRTX } from "atom.io/transceivers/set-rtx"
10
-
11
- import type { Socket } from ".."
9
+ import type { Socket } from "atom.io/realtime"
10
+ import { UList } from "atom.io/transceivers/u-list"
12
11
 
13
12
  export type SocketKey = `socket::${string}`
14
13
  export type UserKey = `user::${string}`
@@ -29,17 +28,17 @@ export const socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey> =
29
28
  default: null,
30
29
  })
31
30
 
32
- export const socketIndex: MutableAtomToken<SetRTX<SocketKey>> = mutableAtom<
33
- SetRTX<SocketKey>
31
+ export const socketIndex: MutableAtomToken<UList<SocketKey>> = mutableAtom<
32
+ UList<SocketKey>
34
33
  >({
35
34
  key: `socketsIndex`,
36
- class: SetRTX,
35
+ class: UList,
37
36
  })
38
- export const userIndex: MutableAtomToken<SetRTX<UserKey>> = mutableAtom<
39
- SetRTX<UserKey>
37
+ export const userIndex: MutableAtomToken<UList<UserKey>> = mutableAtom<
38
+ UList<UserKey>
40
39
  >({
41
40
  key: `usersIndex`,
42
- class: SetRTX,
41
+ class: UList,
43
42
  })
44
43
  export const usersOfSockets: JoinToken<
45
44
  `user`,
@@ -1,9 +1,9 @@
1
1
  import type * as AtomIO from "atom.io"
2
2
  import { getFromStore, IMPLICIT, subscribeToState } from "atom.io/internal"
3
3
  import type { Json } from "atom.io/json"
4
+ import { employSocket } from "atom.io/realtime"
4
5
 
5
6
  import type { ServerConfig } from "."
6
- import { employSocket } from "./employ-socket"
7
7
 
8
8
  export type StateProvider = ReturnType<typeof realtimeStateProvider>
9
9
  export function realtimeStateProvider({
@@ -3,18 +3,15 @@ import {
3
3
  findInStore,
4
4
  getFromStore,
5
5
  IMPLICIT,
6
+ operateOnStore,
7
+ OWN_OP,
6
8
  setIntoStore,
7
9
  subscribeToState,
8
10
  } from "atom.io/internal"
9
- import {
10
- operateOnStore,
11
- OWN_OP,
12
- } from "atom.io/internal/set-state/operate-on-store"
13
11
  import type { Json } from "atom.io/json"
14
- import { mutexAtoms } from "atom.io/realtime/mutex-store"
12
+ import { employSocket, mutexAtoms } from "atom.io/realtime"
15
13
 
16
14
  import type { ServerConfig } from "."
17
- import { employSocket } from "./employ-socket"
18
15
 
19
16
  export type StateReceiver = ReturnType<typeof realtimeStateReceiver>
20
17
  export function realtimeStateReceiver({
@@ -1,9 +1,7 @@
1
1
  import type { RootStore } from "atom.io/internal"
2
-
3
- import type { Socket } from "./socket-interface"
2
+ import type { Socket } from "atom.io/realtime"
4
3
 
5
4
  export type ServerConfig = {
6
5
  socket: Socket
7
6
  store?: RootStore
8
- mutex?: Set<string>
9
7
  }
@@ -19,7 +19,7 @@ import * as AR from "atom.io/react"
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
+ import { UList } from "atom.io/transceivers/u-list"
23
23
  import * as Happy from "happy-dom"
24
24
  import * as React from "react"
25
25
  import * as SocketIO from "socket.io"
@@ -45,9 +45,8 @@ function prefixLogger(store: Store, prefix: string) {
45
45
  if (param instanceof ChildProcess) {
46
46
  params[idx] = `ChildProcess:${param.pid}`
47
47
  }
48
- if (param instanceof SetRTX) {
49
- params[idx] =
50
- `SetRTX(${param.size}) {${[...param].join(`, `)}} at ${param.cacheIdx}`
48
+ if (param instanceof UList) {
49
+ params[idx] = `UList(${param.size}) {${[...param].join(`, `)}}`
51
50
  }
52
51
  idx++
53
52
  }
@@ -72,6 +71,7 @@ export type TestSetupOptions = {
72
71
  server: (tools: {
73
72
  socket: SocketIO.Socket
74
73
  silo: AtomIO.Silo
74
+ userKey: RTS.UserKey
75
75
  enableLogging: () => void
76
76
  }) => (() => void) | void
77
77
  }
@@ -155,24 +155,25 @@ export const setupRealtimeTestServer = (
155
155
  setIntoStore(silo.store, RTS.socketIndex, (index) =>
156
156
  index.add(socketClaim),
157
157
  )
158
- // console.log(`${username} connected on ${socket.id}`)
159
158
  next()
160
159
  } else {
161
160
  next(new Error(`Authentication error`))
162
161
  }
163
162
  })
164
163
 
165
- const serviceDisposalFunctions: Array<() => void> = []
164
+ const socketServices = new Set<() => void>()
165
+ const disposeAllSocketServices = () => {
166
+ for (const disposeService of socketServices) disposeService()
167
+ }
166
168
 
167
169
  server.on(`connection`, (socket: SocketIO.Socket) => {
168
- let userKey: string | null = null
170
+ const userKeyState = findRelationsInStore(
171
+ RTS.usersOfSockets,
172
+ `socket::${socket.id}`,
173
+ silo.store,
174
+ ).userKeyOfSocket
175
+ const userKey = getFromStore(silo.store, userKeyState)!
169
176
  function enableLogging() {
170
- const userKeyState = findRelationsInStore(
171
- RTS.usersOfSockets,
172
- `socket::${socket.id}`,
173
- silo.store,
174
- ).userKeyOfSocket
175
- userKey = getFromStore(silo.store, userKeyState)
176
177
  prefixLogger(silo.store, `server`)
177
178
  socket.onAny((event, ...args) => {
178
179
  console.log(`🛰 `, userKey, event, ...args)
@@ -184,16 +185,20 @@ export const setupRealtimeTestServer = (
184
185
  console.log(`${userKey} disconnected`)
185
186
  })
186
187
  }
187
- const disposeServices = options.server({ socket, enableLogging, silo })
188
+ const disposeServices = options.server({
189
+ socket,
190
+ enableLogging,
191
+ silo,
192
+ userKey,
193
+ })
188
194
  if (disposeServices) {
189
- serviceDisposalFunctions.push(disposeServices)
195
+ socketServices.add(disposeServices)
196
+ socket.on(`disconnect`, disposeServices)
190
197
  }
191
198
  })
192
199
 
193
200
  const dispose = async () => {
194
- for (const disposeSocketServices of serviceDisposalFunctions) {
195
- disposeSocketServices()
196
- }
201
+ disposeAllSocketServices()
197
202
  await server.close()
198
203
 
199
204
  // const roomKeys = getFromStore(silo.store, RT.roomIndex)