atom.io 0.38.2 → 0.39.1

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 (91) hide show
  1. package/dist/data/index.js.map +1 -1
  2. package/dist/eslint-plugin/index.js +2 -1
  3. package/dist/eslint-plugin/index.js.map +1 -1
  4. package/dist/internal/index.d.ts +128 -85
  5. package/dist/internal/index.d.ts.map +1 -1
  6. package/dist/internal/index.js +429 -286
  7. package/dist/internal/index.js.map +1 -1
  8. package/dist/introspection/index.d.ts.map +1 -1
  9. package/dist/introspection/index.js.map +1 -1
  10. package/dist/json/index.d.ts.map +1 -1
  11. package/dist/json/index.js.map +1 -1
  12. package/dist/main/index.d.ts +45 -35
  13. package/dist/main/index.d.ts.map +1 -1
  14. package/dist/main/index.js.map +1 -1
  15. package/dist/react/index.d.ts.map +1 -1
  16. package/dist/react/index.js +43 -2
  17. package/dist/react/index.js.map +1 -1
  18. package/dist/react-devtools/index.d.ts.map +1 -1
  19. package/dist/react-devtools/index.js +4 -5
  20. package/dist/react-devtools/index.js.map +1 -1
  21. package/dist/realtime/index.d.ts.map +1 -1
  22. package/dist/realtime/index.js.map +1 -1
  23. package/dist/realtime-client/index.js +5 -5
  24. package/dist/realtime-client/index.js.map +1 -1
  25. package/dist/realtime-react/index.js.map +1 -1
  26. package/dist/realtime-server/index.d.ts.map +1 -1
  27. package/dist/realtime-server/index.js +4 -4
  28. package/dist/realtime-server/index.js.map +1 -1
  29. package/dist/realtime-testing/index.d.ts.map +1 -1
  30. package/dist/realtime-testing/index.js.map +1 -1
  31. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  32. package/dist/transceivers/set-rtx/index.js.map +1 -1
  33. package/dist/web/index.js.map +1 -1
  34. package/package.json +10 -11
  35. package/src/internal/atom/create-regular-atom.ts +2 -6
  36. package/src/internal/caching.ts +2 -4
  37. package/src/internal/{ingest-updates → events}/ingest-atom-update.ts +4 -5
  38. package/src/internal/{ingest-updates → events}/ingest-creation-disposal.ts +37 -37
  39. package/src/internal/{ingest-updates → events}/ingest-selector-update.ts +5 -5
  40. package/src/internal/events/ingest-transaction-update.ts +45 -0
  41. package/src/internal/families/create-readonly-held-selector-family.ts +1 -1
  42. package/src/internal/families/create-readonly-pure-selector-family.ts +1 -1
  43. package/src/internal/families/create-regular-atom-family.ts +4 -3
  44. package/src/internal/families/create-writable-held-selector-family.ts +1 -1
  45. package/src/internal/families/create-writable-pure-selector-family.ts +1 -1
  46. package/src/internal/families/find-in-store.ts +2 -2
  47. package/src/internal/families/get-family-of-token.ts +1 -0
  48. package/src/internal/families/index.ts +0 -1
  49. package/src/internal/families/mint-in-store.ts +30 -64
  50. package/src/internal/get-state/get-from-store.ts +2 -3
  51. package/src/internal/get-state/read-or-compute-value.ts +6 -15
  52. package/src/internal/get-state/reduce-reference.ts +52 -11
  53. package/src/internal/index.ts +2 -2
  54. package/src/internal/is-fn.ts +9 -0
  55. package/src/internal/junction.ts +177 -133
  56. package/src/internal/mutable/create-mutable-atom-family.ts +1 -1
  57. package/src/internal/overlays/index.ts +3 -0
  58. package/src/internal/overlays/map-overlay.ts +86 -0
  59. package/src/internal/{lazy-map.ts → overlays/relations-overlay.ts} +6 -6
  60. package/src/internal/overlays/set-overlay.ts +55 -0
  61. package/src/internal/selector/create-readonly-held-selector.ts +8 -11
  62. package/src/internal/selector/create-readonly-pure-selector.ts +8 -10
  63. package/src/internal/selector/create-writable-held-selector.ts +6 -6
  64. package/src/internal/selector/create-writable-pure-selector.ts +2 -2
  65. package/src/internal/selector/register-selector.ts +3 -4
  66. package/src/internal/set-state/become.ts +11 -6
  67. package/src/internal/set-state/dispatch-state-update.ts +47 -12
  68. package/src/internal/set-state/operate-on-store.ts +10 -8
  69. package/src/internal/set-state/reset-atom-or-selector.ts +7 -7
  70. package/src/internal/set-state/set-atom-or-selector.ts +3 -2
  71. package/src/internal/set-state/set-atom.ts +5 -4
  72. package/src/internal/set-state/set-selector.ts +9 -8
  73. package/src/internal/store/withdraw.ts +4 -4
  74. package/src/internal/timeline/time-travel.ts +11 -11
  75. package/src/internal/transaction/apply-transaction.ts +5 -5
  76. package/src/internal/transaction/build-transaction.ts +17 -26
  77. package/src/internal/transaction/create-transaction.ts +1 -1
  78. package/src/internal/transaction/is-root-store.ts +2 -2
  79. package/src/main/events.ts +14 -3
  80. package/src/main/logger.ts +43 -32
  81. package/src/react-devtools/json-editor/editors-by-type/array-editor.tsx +1 -1
  82. package/src/react-devtools/json-editor/editors-by-type/object-editor.tsx +2 -3
  83. package/src/react-devtools/json-editor/editors-by-type/utilities/array-elements.ts +1 -1
  84. package/src/react-devtools/json-editor/editors-by-type/utilities/object-properties.ts +1 -1
  85. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +5 -5
  86. package/src/realtime-server/continuity/subscribe-to-continuity-perpectives.ts +4 -4
  87. package/dist/use-o-DXPncKmZ.js +0 -47
  88. package/dist/use-o-DXPncKmZ.js.map +0 -1
  89. package/src/internal/families/init-family-member.ts +0 -33
  90. package/src/internal/ingest-updates/ingest-transaction-update.ts +0 -47
  91. /package/src/internal/{ingest-updates → events}/index.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["process","roomArgumentsAtoms: RegularAtomFamilyToken<RoomArguments, string>","roomSelectors: ReadonlyPureSelectorFamilyToken<\n\tLoadable<ChildSocket<any, any>>,\n\tstring\n>","createRoomTX: AtomIO.TransactionToken<\n\t(\n\t\troomKey: RoomKey,\n\t\tscript: string,\n\t\toptions?: string[],\n\t) => Loadable<ChildSocket<any, any>>\n>","args: RoomArguments","joinRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string, enteredAtEpoch: number) => UserInRoomMeta\n>","leaveRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string) => void\n>","destroyRoomTX: AtomIO.TransactionToken<(roomKey: RoomKey) => void>","redactorAtoms: RegularAtomFamilyToken<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n>","userUnacknowledgedQueues: RegularAtomFamilyToken<\n\tContinuitySyncTransactionUpdate[],\n\tUserKey\n>","socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey>","socketIndex: MutableAtomToken<SetRTX<SocketKey>>","userIndex: MutableAtomToken<SetRTX<UserKey>>","usersOfSockets: JoinToken<\n\t`user`,\n\tUserKey,\n\t`socket`,\n\tSocketKey,\n\t`1:1`\n>","initialPayload: Json.Serializable[]","unsubscribeFunctions: (() => void)[]","unsubFns: (() => void)[]","socket: Socket | null","unsubscribeFunctions: (() => void)[]","unsubscribeFromStateUpdates: (() => void) | null","unsubscribeFromStateUpdates: (() => void) | undefined"],"sources":["../../src/realtime-server/ipc-sockets/custom-socket.ts","../../src/realtime-server/ipc-sockets/child-socket.ts","../../src/realtime-server/ipc-sockets/parent-socket.ts","../../src/realtime-server/realtime-server-stores/server-room-external-store.ts","../../src/realtime-server/realtime-server-stores/server-room-external-actions.ts","../../src/realtime-server/realtime-server-stores/server-sync-store.ts","../../src/realtime-server/realtime-server-stores/server-user-store.ts","../../src/realtime-server/continuity/prepare-to-send-initial-payload.ts","../../src/realtime-server/continuity/prepare-to-serve-transaction-request.ts","../../src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts","../../src/realtime-server/continuity/subscribe-to-continuity-actions.ts","../../src/realtime-server/continuity/subscribe-to-continuity-perpectives.ts","../../src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts","../../src/realtime-server/realtime-action-receiver.ts","../../src/realtime-server/realtime-family-provider.ts","../../src/realtime-server/realtime-mutable-family-provider.ts","../../src/realtime-server/realtime-mutable-provider.ts","../../src/realtime-server/realtime-state-provider.ts","../../src/realtime-server/realtime-state-receiver.ts"],"sourcesContent":["import type { Json, stringified } from \"atom.io/json\"\n\nimport type { Socket } from \"..\"\n\nexport type Events = Json.Object<string, Json.Serializable[]>\n\nexport type StringifiedEvent<\n\tKey extends string,\n\tParams extends Json.Serializable[],\n> = stringified<[Key, ...Params]>\n\nexport interface EventBuffer<\n\tKey extends string,\n\tParams extends Json.Serializable[],\n> extends Buffer {\n\ttoString(): StringifiedEvent<Key, Params>\n}\n\nexport class CustomSocket<I extends Events, O extends Events> implements Socket {\n\tprotected listeners: Map<keyof O, Set<(...args: Json.Array) => void>>\n\tprotected globalListeners: Set<(event: string, ...args: Json.Array) => void>\n\tprotected handleEvent<Event extends keyof I>(\n\t\tevent: string,\n\t\t...args: I[Event]\n\t): void {\n\t\tfor (const listener of this.globalListeners) {\n\t\t\tlistener(event, ...args)\n\t\t}\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener(...args)\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic id = `no_id_retrieved`\n\tpublic emit: <Event extends keyof I>(\n\t\tevent: Event,\n\t\t...args: I[Event]\n\t) => CustomSocket<I, O>\n\n\tpublic constructor(\n\t\temit: <Event extends keyof I>(\n\t\t\tevent: Event,\n\t\t\t...args: I[Event]\n\t\t) => CustomSocket<I, O>,\n\t) {\n\t\tthis.emit = emit\n\t\tthis.listeners = new Map()\n\t\tthis.globalListeners = new Set()\n\t}\n\n\tpublic on<Event extends keyof O>(\n\t\tevent: Event,\n\t\tlistener: (...args: O[Event]) => void,\n\t): this {\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tlisteners.add(listener)\n\t\t} else {\n\t\t\tthis.listeners.set(event, new Set([listener]))\n\t\t}\n\t\treturn this\n\t}\n\n\tpublic onAny(listener: (event: string, ...args: Json.Array) => void): this {\n\t\tthis.globalListeners.add(listener)\n\t\treturn this\n\t}\n\n\tpublic off<Event extends keyof O>(\n\t\tevent: Event,\n\t\tlistener?: (...args: O[Event]) => void,\n\t): this {\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tif (listener) {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t} else {\n\t\t\t\tthis.listeners.delete(event)\n\t\t\t}\n\t\t}\n\t\treturn this\n\t}\n\n\tpublic offAny(listener: (event: string, ...args: Json.Array) => void): this {\n\t\tthis.globalListeners.delete(listener)\n\t\treturn this\n\t}\n}\n","import type { ChildProcessWithoutNullStreams } from \"node:child_process\"\n\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\n\nimport type { EventBuffer, Events } from \"./custom-socket\"\nimport { CustomSocket } from \"./custom-socket\"\n\n/* eslint-disable no-console */\n\nexport class ChildSocket<\n\tI extends Events,\n\tO extends Events,\n> extends CustomSocket<I, O> {\n\tprotected incompleteData = ``\n\tprotected unprocessedEvents: string[] = []\n\tprotected incompleteLog = ``\n\tprotected unprocessedLogs: string[] = []\n\n\tpublic id = `#####`\n\n\tpublic process: ChildProcessWithoutNullStreams\n\tpublic key: string\n\tpublic logger: Pick<Console, `error` | `info` | `warn`>\n\n\tprotected handleLog(arg: Json.Serializable): void {\n\t\tif (Array.isArray(arg)) {\n\t\t\tconst [level, ...rest] = arg\n\t\t\tswitch (level) {\n\t\t\t\tcase `i`:\n\t\t\t\t\tthis.logger.info(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tcase `w`:\n\t\t\t\t\tthis.logger.warn(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tcase `e`:\n\t\t\t\t\tthis.logger.error(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic constructor(\n\t\tprocess: ChildProcessWithoutNullStreams,\n\t\tkey: string,\n\t\tlogger?: Pick<Console, `error` | `info` | `warn`>,\n\t) {\n\t\tsuper((event, ...args) => {\n\t\t\tconst stringifiedEvent = JSON.stringify([event, ...args]) + `\\x03`\n\t\t\tconst errorHandler = (err: { code: string }) => {\n\t\t\t\tif (err.code === `EPIPE`) {\n\t\t\t\t\tconsole.error(`EPIPE error during write`, this.process.stdin)\n\t\t\t\t}\n\t\t\t\tthis.process.stdin.removeListener(`error`, errorHandler)\n\t\t\t}\n\n\t\t\tthis.process.stdin.once(`error`, errorHandler)\n\t\t\tthis.process.stdin.write(stringifiedEvent)\n\n\t\t\treturn this\n\t\t})\n\t\tthis.process = process\n\t\tthis.key = key\n\t\tthis.logger = logger ?? {\n\t\t\tinfo: (...args: unknown[]) => {\n\t\t\t\tconsole.info(this.id, this.key, ...args)\n\t\t\t},\n\t\t\twarn: (...args: unknown[]) => {\n\t\t\t\tconsole.warn(this.id, this.key, ...args)\n\t\t\t},\n\t\t\terror: (...args: unknown[]) => {\n\t\t\t\tconsole.error(this.id, this.key, ...args)\n\t\t\t},\n\t\t}\n\t\tthis.process.stdout.on(\n\t\t\t`data`,\n\t\t\t<Event extends keyof I>(buffer: EventBuffer<string, I[Event]>) => {\n\t\t\t\tconst chunk = buffer.toString()\n\n\t\t\t\tif (chunk === `ALIVE`) {\n\t\t\t\t\t// console.log(chunk)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.unprocessedEvents.push(...chunk.split(`\\x03`))\n\t\t\t\t// console.log(`🤓`, chunk.length)\n\t\t\t\t// console.log(`🤓`, this.unprocessedEvents.length)\n\t\t\t\t// console.log(`🤓`, ...this.unprocessedEvents.map((x) => x.length))\n\t\t\t\tconst newInput = this.unprocessedEvents.shift()\n\t\t\t\tthis.incompleteData += newInput ?? ``\n\t\t\t\ttry {\n\t\t\t\t\tif (this.incompleteData.startsWith(`error`)) {\n\t\t\t\t\t\tconsole.log(`❗`, this.incompleteData)\n\t\t\t\t\t}\n\t\t\t\t\tlet parsedEvent = parseJson(this.incompleteData)\n\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\twhile (this.unprocessedEvents.length > 0) {\n\t\t\t\t\t\tconst event = this.unprocessedEvents.shift()\n\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\tif (this.unprocessedEvents.length === 0) {\n\t\t\t\t\t\t\t\tthis.incompleteData = event\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tparsedEvent = parseJson(event)\n\t\t\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.incompleteData = ``\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.warn(`⚠️----------------⚠️`)\n\t\t\t\t\tconsole.warn(this.incompleteData)\n\t\t\t\t\tconsole.warn(`⚠️----------------⚠️`)\n\t\t\t\t\tconsole.error(error)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tthis.process.stderr.on(`data`, (buf) => {\n\t\t\tconst chunk = buf.toString()\n\t\t\tthis.unprocessedLogs.push(...chunk.split(`\\x03`))\n\t\t\t// console.log(`🤫`, chunk.length)\n\t\t\t// console.log(`🤫`, this.unprocessedLogs.length)\n\t\t\t// console.log(`🤫`, ...this.unprocessedLogs.map((x) => x.length))\n\t\t\tconst newInput = this.unprocessedLogs.shift()\n\t\t\tthis.incompleteLog += newInput ?? ``\n\t\t\ttry {\n\t\t\t\tlet parsedLog = parseJson(this.incompleteLog)\n\t\t\t\t// console.log(`🤫`, parsedLog)\n\t\t\t\tthis.handleLog(parsedLog)\n\t\t\t\twhile (this.unprocessedLogs.length > 0) {\n\t\t\t\t\tthis.incompleteLog = this.unprocessedLogs.shift() ?? ``\n\t\t\t\t\tif (this.incompleteLog) {\n\t\t\t\t\t\tparsedLog = parseJson(this.incompleteLog)\n\t\t\t\t\t\tthis.handleLog(parsedLog)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`❌❌❌`)\n\t\t\t\tconsole.error(this.incompleteLog)\n\t\t\t\tconsole.error(error)\n\t\t\t\tconsole.error(`❌❌❌️`)\n\t\t\t}\n\t\t})\n\t\tif (process.pid) {\n\t\t\tthis.id = process.pid.toString()\n\t\t}\n\t}\n}\n","import { Subject } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\nimport { SetRTX } from \"atom.io/transceivers/set-rtx\"\n\nimport type { EventBuffer, Events } from \"./custom-socket\"\nimport { CustomSocket } from \"./custom-socket\"\n\nexport class SubjectSocket<\n\tI extends Events,\n\tO extends Events,\n> extends CustomSocket<I, O> {\n\tpublic in: Subject<[string, ...Json.Serializable[]]>\n\tpublic out: Subject<[string, ...Json.Serializable[]]>\n\tpublic id = `no_id_retrieved`\n\tpublic disposalFunctions: (() => void)[] = []\n\n\tpublic constructor(id: string) {\n\t\tsuper((...args) => {\n\t\t\tthis.out.next(args as any)\n\t\t\treturn this\n\t\t})\n\t\tthis.id = id\n\t\tthis.in = new Subject()\n\t\tthis.out = new Subject()\n\t\tthis.in.subscribe(`socket`, (event) => {\n\t\t\tthis.handleEvent(...(event as [string, ...I[keyof I]]))\n\t\t})\n\t}\n\n\tpublic dispose(): void {\n\t\tfor (const dispose of this.disposalFunctions) {\n\t\t\tdispose()\n\t\t}\n\t}\n}\n\nexport class ParentSocket<\n\tI extends Events & {\n\t\t[id in string as `relay:${id}`]: [string, ...Json.Serializable[]]\n\t},\n\tO extends Events & {\n\t\t[id in string as `user:${id}`]: [string, ...Json.Serializable[]]\n\t} & {\n\t\t/* eslint-disable quotes */\n\t\t\"user-joins\": [string]\n\t\t\"user-leaves\": [string]\n\t\t/* eslint-enable quotes */\n\t},\n> extends CustomSocket<I, O> {\n\tprotected incompleteData = ``\n\tprotected unprocessedEvents: string[] = []\n\tprotected relays: Map<string, SubjectSocket<any, any>>\n\tprotected relayServices: ((\n\t\tsocket: SubjectSocket<any, any>,\n\t) => (() => void) | void)[]\n\tprotected process: NodeJS.Process\n\n\tpublic id = `#####`\n\n\tprotected log(...args: any[]): void {\n\t\tthis.process.stderr.write(\n\t\t\tstringifyJson(\n\t\t\t\targs.map((arg) =>\n\t\t\t\t\targ instanceof SetRTX\n\t\t\t\t\t\t? `{ ${arg.toJSON().members.join(` | `)} }`\n\t\t\t\t\t\t: arg,\n\t\t\t\t),\n\t\t\t) + `\\x03`,\n\t\t)\n\t}\n\tpublic logger = {\n\t\tinfo: (...args: any[]): void => {\n\t\t\tthis.log(`i`, ...args)\n\t\t},\n\t\twarn: (...args: any[]): void => {\n\t\t\tthis.log(`w`, ...args)\n\t\t},\n\t\terror: (...args: any[]): void => {\n\t\t\tthis.log(`e`, ...args)\n\t\t},\n\t}\n\n\tpublic constructor() {\n\t\tsuper((event, ...args) => {\n\t\t\tconst stringifiedEvent = JSON.stringify([event, ...args])\n\t\t\tthis.process.stdout.write(stringifiedEvent + `\\x03`)\n\t\t\treturn this\n\t\t})\n\t\tthis.process = process\n\t\tthis.process.stdin.resume()\n\t\tthis.relays = new Map()\n\t\tthis.relayServices = []\n\t\t// this.logger.info(`🔗`, `uplink`, process.pid)\n\n\t\tthis.process.stdin.on(\n\t\t\t`data`,\n\t\t\t<Event extends keyof I>(buffer: EventBuffer<string, I[Event]>) => {\n\t\t\t\tconst chunk = buffer.toString()\n\t\t\t\tthis.unprocessedEvents.push(...chunk.split(`\\x03`))\n\t\t\t\tconst newInput = this.unprocessedEvents.shift()\n\t\t\t\tthis.incompleteData += newInput ?? ``\n\n\t\t\t\ttry {\n\t\t\t\t\tconst parsedData = parseJson(this.incompleteData)\n\t\t\t\t\tthis.logger.info(`🎰`, `received`, parsedData)\n\t\t\t\t\tthis.handleEvent(...(parsedData as [string, ...I[keyof I]]))\n\t\t\t\t\twhile (this.unprocessedEvents.length > 0) {\n\t\t\t\t\t\tconst event = this.unprocessedEvents.shift()\n\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\tif (this.unprocessedEvents.length === 0) {\n\t\t\t\t\t\t\t\tthis.incompleteData = event\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst parsedEvent = parseJson(event)\n\t\t\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.incompleteData = ``\n\t\t\t\t} catch (thrown) {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tthis.logger.error(`❗`, thrown.message, thrown.cause, thrown.stack)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\n\t\tthis.on(`exit`, () => {\n\t\t\tthis.logger.info(`🔥`, this.id, `received \"exit\"`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`exit`, (code) => {\n\t\t\tthis.logger.info(`🔥`, this.id, `exited with code ${code}`)\n\t\t})\n\t\tprocess.on(`end`, () => {\n\t\t\tthis.logger.info(`🔥`, this.id, `ended`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`SIGTERM`, () => {\n\t\t\tthis.logger.error(`🔥`, this.id, `terminated`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`SIGINT`, () => {\n\t\t\tthis.logger.error(`🔥`, this.id, `interrupted`)\n\t\t\tprocess.exit(0)\n\t\t})\n\n\t\tif (process.pid) {\n\t\t\tthis.id = process.pid?.toString()\n\t\t}\n\n\t\tthis.on(`user-joins`, (username) => {\n\t\t\tthis.logger.info(`👤`, `user`, username, `joined`)\n\t\t\tconst relay = new SubjectSocket(`user:${username}`)\n\t\t\tthis.relays.set(username, relay)\n\t\t\tthis.logger.info(\n\t\t\t\t`🔗`,\n\t\t\t\t`attaching services:`,\n\t\t\t\t`[${[...this.relayServices.keys()].join(`, `)}]`,\n\t\t\t)\n\t\t\tfor (const attachServices of this.relayServices) {\n\t\t\t\tconst cleanup = attachServices(relay)\n\t\t\t\tif (cleanup) {\n\t\t\t\t\trelay.disposalFunctions.push(cleanup)\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.on(`user:${username}`, (...data) => {\n\t\t\t\trelay.in.next(data)\n\t\t\t})\n\t\t\trelay.out.subscribe(`socket`, (data) => {\n\t\t\t\tthis.emit(...(data as [string, ...I[keyof I]]))\n\t\t\t})\n\t\t})\n\n\t\tthis.on(`user-leaves`, (username) => {\n\t\t\tconst relay = this.relays.get(username)\n\t\t\tthis.off(`relay:${username}`)\n\t\t\tif (relay) {\n\t\t\t\trelay.dispose()\n\t\t\t\tthis.relays.delete(username)\n\t\t\t}\n\t\t})\n\n\t\tprocess.stdout.write(`ALIVE`)\n\t}\n\n\tpublic relay(\n\t\tattachServices: (socket: SubjectSocket<any, any>) => (() => void) | void,\n\t): void {\n\t\tthis.logger.info(`🔗`, `running relay method`)\n\t\tthis.relayServices.push(attachServices)\n\t}\n}\n","import type { ChildProcessWithoutNullStreams } from \"node:child_process\"\nimport { spawn } from \"node:child_process\"\n\nimport type {\n\tLoadable,\n\tReadonlyPureSelectorFamilyToken,\n\tRegularAtomFamilyToken,\n} from \"atom.io\"\nimport { atomFamily, selectorFamily } from \"atom.io\"\n\nimport { ChildSocket } from \"../ipc-sockets\"\n\nexport type RoomArguments =\n\t| [script: string, options: string[]]\n\t| [script: string]\n\nexport const roomArgumentsAtoms: RegularAtomFamilyToken<RoomArguments, string> =\n\tatomFamily<RoomArguments, string>({\n\t\tkey: `roomArguments`,\n\t\tdefault: [`echo`, [`Hello World!`]],\n\t})\n\nexport const roomSelectors: ReadonlyPureSelectorFamilyToken<\n\tLoadable<ChildSocket<any, any>>,\n\tstring\n> = selectorFamily<Loadable<ChildSocket<any, any>>, string>({\n\tkey: `room`,\n\tget:\n\t\t(roomId) =>\n\t\tasync ({ get, find }) => {\n\t\t\tconst argumentsState = find(roomArgumentsAtoms, roomId)\n\t\t\tconst args = get(argumentsState)\n\t\t\tconst [script, options] = args\n\t\t\tconst child = await new Promise<ChildProcessWithoutNullStreams>(\n\t\t\t\t(resolve) => {\n\t\t\t\t\tconst room = spawn(script, options, { env: process.env })\n\t\t\t\t\tconst resolver = (data: Buffer) => {\n\t\t\t\t\t\tif (data.toString() === `ALIVE`) {\n\t\t\t\t\t\t\troom.stdout.off(`data`, resolver)\n\t\t\t\t\t\t\tresolve(room)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\troom.stdout.on(`data`, resolver)\n\t\t\t\t},\n\t\t\t)\n\t\t\treturn new ChildSocket(child, roomId)\n\t\t},\n})\n","import type { Loadable } from \"atom.io\"\nimport * as AtomIO from \"atom.io\"\nimport { editRelationsInStore } from \"atom.io/internal\"\nimport type { UserInRoomMeta } from \"atom.io/realtime\"\nimport { roomIndex, usersInRooms } from \"atom.io/realtime\"\n\nimport type { ChildSocket } from \"../ipc-sockets\"\nimport type { RoomArguments } from \"./server-room-external-store\"\nimport { roomArgumentsAtoms, roomSelectors } from \"./server-room-external-store\"\nimport type { RoomKey } from \"./server-user-store\"\n\nexport const createRoomTX: AtomIO.TransactionToken<\n\t(\n\t\troomKey: RoomKey,\n\t\tscript: string,\n\t\toptions?: string[],\n\t) => Loadable<ChildSocket<any, any>>\n> = AtomIO.transaction({\n\tkey: `createRoom`,\n\tdo: ({ get, set, find }, roomId, script, options) => {\n\t\tconst args: RoomArguments = options ? [script, options] : [script]\n\t\tconst roomArgumentsState = find(roomArgumentsAtoms, roomId)\n\t\tset(roomArgumentsState, args)\n\t\tset(roomIndex, (s) => s.add(roomId))\n\t\tconst roomState = find(roomSelectors, roomId)\n\t\tconst room = get(roomState)\n\t\treturn room\n\t},\n})\nexport type CreateRoomIO = AtomIO.TransactionIO<typeof createRoomTX>\n\nexport const joinRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string, enteredAtEpoch: number) => UserInRoomMeta\n> = AtomIO.transaction({\n\tkey: `joinRoom`,\n\tdo: (tools, roomId, userId, enteredAtEpoch) => {\n\t\tconst meta = { enteredAtEpoch }\n\t\teditRelationsInStore(\n\t\t\tusersInRooms,\n\t\t\t(relations) => {\n\t\t\t\trelations.set({ room: roomId, user: userId }, meta)\n\t\t\t},\n\t\t\ttools.env().store,\n\t\t)\n\t\treturn meta\n\t},\n})\nexport type JoinRoomIO = AtomIO.TransactionIO<typeof joinRoomTX>\n\nexport const leaveRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string) => void\n> = AtomIO.transaction({\n\tkey: `leaveRoom`,\n\tdo: (tools, roomId, userId) => {\n\t\teditRelationsInStore(\n\t\t\tusersInRooms,\n\t\t\t(relations) => {\n\t\t\t\trelations.delete({ room: roomId, user: userId })\n\t\t\t},\n\t\t\ttools.env().store,\n\t\t)\n\t},\n})\nexport type LeaveRoomIO = AtomIO.TransactionIO<typeof leaveRoomTX>\n\nexport const destroyRoomTX: AtomIO.TransactionToken<(roomKey: RoomKey) => void> =\n\tAtomIO.transaction({\n\t\tkey: `destroyRoom`,\n\t\tdo: (tools, roomKey) => {\n\t\t\teditRelationsInStore(\n\t\t\t\tusersInRooms,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.delete({ room: roomKey })\n\t\t\t\t},\n\t\t\t\ttools.env().store,\n\t\t\t)\n\t\t\ttools.set(roomIndex, (s) => (s.delete(roomKey), s))\n\t\t},\n\t})\n","import type {\n\tRegularAtomFamilyToken,\n\tTransactionOutcomeEvent,\n\tTransactionSubEvent,\n} from \"atom.io\"\nimport { atomFamily } from \"atom.io\"\n\nimport type { UserKey } from \"./server-user-store\"\n\n// export const completeUpdateAtoms = atomFamily<\n// \tTransactionUpdate<any> | null,\n// \tstring\n// >({\n// \tkey: `completeUpdate`,\n// \tdefault: null,\n// })\n\nexport function redactTransactionUpdateContent(\n\tvisibleStateKeys: string[],\n\tupdates: TransactionSubEvent[],\n): TransactionSubEvent[] {\n\treturn updates\n\t\t.map((update): TransactionSubEvent => {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase `transaction_outcome`: {\n\t\t\t\t\tconst redacted = redactTransactionUpdateContent(\n\t\t\t\t\t\tvisibleStateKeys,\n\t\t\t\t\t\tupdate.subEvents,\n\t\t\t\t\t)\n\t\t\t\t\treturn { ...update, subEvents: redacted }\n\t\t\t\t}\n\t\t\t\tcase `atom_update`:\n\t\t\t\tcase `molecule_creation`:\n\t\t\t\tcase `molecule_disposal`:\n\t\t\t\tcase `molecule_transfer`:\n\t\t\t\tcase `state_creation`:\n\t\t\t\tcase `state_disposal`:\n\t\t\t\t\treturn update\n\t\t\t}\n\t\t})\n\t\t.filter((update) => {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase `atom_update`:\n\t\t\t\tcase `state_creation`:\n\t\t\t\tcase `state_disposal`:\n\t\t\t\t\treturn visibleStateKeys.includes(update.token.key)\n\t\t\t\tcase `molecule_creation`:\n\t\t\t\tcase `transaction_outcome`:\n\t\t\t\tcase `molecule_disposal`:\n\t\t\t\tcase `molecule_transfer`:\n\t\t\t\t\treturn true\n\t\t\t}\n\t\t})\n}\n\nexport const redactorAtoms: RegularAtomFamilyToken<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n> = atomFamily<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n>({\n\tkey: `redactor`,\n\tdefault: { occlude: (updates) => updates },\n})\n// export const redactedUpdateSelectors = selectorFamily<\n// \tTransactionUpdate<any> | null,\n// \t[transactionKey: string, updateId: string]\n// >({\n// \tkey: `redactedUpdate`,\n// \tget:\n// \t\t([transactionKey, updateId]) =>\n// \t\t({ get, find }) => {\n// \t\t\tconst update = get(find(completeUpdateAtoms, updateId))\n// \t\t\tconst { filter } = get(find(transactionRedactorAtoms, transactionKey))\n\n// \t\t\tif (update && filter) {\n// \t\t\t\treturn { ...update, updates: filter(update.updates) }\n// \t\t\t}\n// \t\t\treturn null\n// \t\t},\n// })\n\nexport type ContinuitySyncTransactionUpdate = Pick<\n\tTransactionOutcomeEvent<any>,\n\t`epoch` | `id` | `output` | `subEvents` | `token`\n>\nexport const userUnacknowledgedQueues: RegularAtomFamilyToken<\n\tContinuitySyncTransactionUpdate[],\n\tUserKey\n> = atomFamily<ContinuitySyncTransactionUpdate[], UserKey>({\n\tkey: `unacknowledgedUpdates`,\n\tdefault: () => [],\n})\n","import type {\n\tHierarchy,\n\tJoinToken,\n\tMutableAtomToken,\n\tRegularAtomFamilyToken,\n} from \"atom.io\"\nimport { atomFamily, join, mutableAtom } from \"atom.io\"\nimport { SetRTX } from \"atom.io/transceivers/set-rtx\"\n\nimport type { Socket } from \"..\"\n\nexport type SocketKey = `socket::${string}`\nexport type UserKey = `user::${string}`\nexport type RoomKey = `room::${string}`\n\nexport type SocketSystemHierarchy = Hierarchy<\n\t[\n\t\t{\n\t\t\tabove: `root`\n\t\t\tbelow: [UserKey, SocketKey, RoomKey]\n\t\t},\n\t]\n>\n\nexport const socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey> =\n\tatomFamily<Socket | null, SocketKey>({\n\t\tkey: `sockets`,\n\t\tdefault: null,\n\t})\n\nexport const socketIndex: MutableAtomToken<SetRTX<SocketKey>> = mutableAtom<\n\tSetRTX<SocketKey>\n>({\n\tkey: `socketsIndex`,\n\tclass: SetRTX,\n})\nexport const userIndex: MutableAtomToken<SetRTX<UserKey>> = mutableAtom<\n\tSetRTX<UserKey>\n>({\n\tkey: `usersIndex`,\n\tclass: SetRTX,\n})\nexport const usersOfSockets: JoinToken<\n\t`user`,\n\tUserKey,\n\t`socket`,\n\tSocketKey,\n\t`1:1`\n> = join({\n\tkey: `usersOfSockets`,\n\tbetween: [`user`, `socket`],\n\tcardinality: `1:1`,\n\tisAType: (s): s is UserKey => s.startsWith(`user::`),\n\tisBType: (s): s is SocketKey => s.startsWith(`socket::`),\n})\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tisRootStore,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket, UserKey } from \"..\"\n\nexport function prepareToSendInitialPayload(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): () => void {\n\tconst continuityKey = continuity.key\n\treturn function sendInitialPayload(): void {\n\t\tconst initialPayload: Json.Serializable[] = []\n\t\tfor (const atom of continuity.globals) {\n\t\t\tconst resourceToken =\n\t\t\t\tatom.type === `mutable_atom` ? getJsonToken(store, atom) : atom\n\t\t\tconst resource = getFromStore(store, resourceToken)\n\t\t\tinitialPayload.push(resourceToken, resource)\n\t\t}\n\t\tfor (const perspective of continuity.perspectives) {\n\t\t\tconst { viewAtoms, resourceAtoms } = perspective\n\t\t\tconst userViewState = findInStore(store, viewAtoms, userKey)\n\t\t\tconst userView = getFromStore(store, userViewState)\n\t\t\tstore.logger.info(`👁`, `atom`, resourceAtoms.key, `${userKey} can see`, {\n\t\t\t\tviewAtoms,\n\t\t\t\tresourceAtoms,\n\t\t\t\tuserView,\n\t\t\t})\n\t\t\tfor (const visibleToken of userView) {\n\t\t\t\tconst resourceToken =\n\t\t\t\t\tvisibleToken.type === `mutable_atom`\n\t\t\t\t\t\t? getJsonToken(store, visibleToken)\n\t\t\t\t\t\t: visibleToken\n\t\t\t\tconst resource = getFromStore(store, resourceToken)\n\n\t\t\t\tinitialPayload.push(resourceToken, resource)\n\t\t\t}\n\t\t}\n\n\t\tconst epoch = isRootStore(store)\n\t\t\t? (store.transactionMeta.epoch.get(continuityKey) ?? null)\n\t\t\t: null\n\n\t\tsocket?.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)\n\t}\n}\n","import type { TransactionOutcomeEvent, TransactionToken } from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport { actUponStore } from \"atom.io/internal\"\nimport type { Json, JsonIO } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nexport function prepareToServeTransactionRequest(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: string,\n): (\n\tevent: Json.Serializable &\n\t\tPick<\n\t\t\tTransactionOutcomeEvent<TransactionToken<JsonIO>>,\n\t\t\t`id` | `params` | `token`\n\t\t>,\n) => void {\n\tconst continuityKey = continuity.key\n\treturn function serveTransactionRequest(txOutcome) {\n\t\tstore.logger.info(`🛎️`, `continuity`, continuityKey, `received`, txOutcome)\n\t\tconst transactionKey = txOutcome.token.key\n\t\tconst updateId = txOutcome.id\n\t\tconst performanceKey = `tx-run:${transactionKey}:${updateId}`\n\t\tconst performanceKeyStart = `${performanceKey}:start`\n\t\tconst performanceKeyEnd = `${performanceKey}:end`\n\t\tperformance.mark(performanceKeyStart)\n\t\ttry {\n\t\t\tactUponStore(\n\t\t\t\tstore,\n\t\t\t\t{ type: `transaction`, key: transactionKey },\n\t\t\t\tupdateId,\n\t\t\t)(...txOutcome.params)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,\n\t\t\t\t\tthrown.message,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tperformance.mark(performanceKeyEnd)\n\t\tconst metric = performance.measure(\n\t\t\tperformanceKey,\n\t\t\tperformanceKeyStart,\n\t\t\tperformanceKeyEnd,\n\t\t)\n\t\tstore?.logger.info(\n\t\t\t`🚀`,\n\t\t\t`transaction`,\n\t\t\ttransactionKey,\n\t\t\tupdateId,\n\t\t\tuserKey,\n\t\t\tmetric.duration,\n\t\t)\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport { setIntoStore } from \"atom.io/internal\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type {\n\tContinuitySyncTransactionUpdate,\n\tUserKey,\n} from \"../realtime-server-stores\"\nimport { userUnacknowledgedQueues } from \"../realtime-server-stores\"\n\nexport function prepareToTrackClientAcknowledgement(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tuserUnacknowledgedUpdates: ContinuitySyncTransactionUpdate[],\n): (epoch: number) => void {\n\tconst continuityKey = continuity.key\n\treturn function trackClientAcknowledgement(epoch) {\n\t\tstore.logger.info(\n\t\t\t`👍`,\n\t\t\t`continuity`,\n\t\t\tcontinuityKey,\n\t\t\t`${userKey} acknowledged epoch ${epoch}`,\n\t\t)\n\t\tconst isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch\n\t\tif (isUnacknowledged) {\n\t\t\tsetIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {\n\t\t\t\tupdates.shift()\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👍`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`${userKey} unacknowledged update queue now has`,\n\t\t\t\t\tupdates.length,\n\t\t\t\t\t`items`,\n\t\t\t\t)\n\t\t\t\treturn updates\n\t\t\t})\n\t\t}\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetUpdateToken,\n\tsetIntoStore,\n\tsubscribeToTransaction,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket, UserKey } from \"..\"\nimport {\n\tredactTransactionUpdateContent,\n\tuserUnacknowledgedQueues,\n} from \"../realtime-server-stores\"\n\nexport function subscribeToContinuityActions(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): (() => void)[] {\n\tconst continuityKey = continuity.key\n\tconst unsubscribeFunctions: (() => void)[] = []\n\n\tfor (const transaction of continuity.actions) {\n\t\tconst unsubscribeFromTransaction = subscribeToTransaction(\n\t\t\tstore,\n\t\t\ttransaction,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}`,\n\t\t\t(update) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst visibleKeys = continuity.globals\n\t\t\t\t\t\t.map((atom) => {\n\t\t\t\t\t\t\tif (atom.type === `atom`) {\n\t\t\t\t\t\t\t\treturn atom.key\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn getUpdateToken(atom).key\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.concat(\n\t\t\t\t\t\t\tcontinuity.perspectives.flatMap((perspective) => {\n\t\t\t\t\t\t\t\tconst { viewAtoms } = perspective\n\t\t\t\t\t\t\t\tconst userPerspectiveTokenState = findInStore(\n\t\t\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\t\t\tviewAtoms,\n\t\t\t\t\t\t\t\t\tuserKey,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tconst visibleTokens = getFromStore(\n\t\t\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\t\t\tuserPerspectiveTokenState,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn visibleTokens.map((token) => {\n\t\t\t\t\t\t\t\t\tconst key =\n\t\t\t\t\t\t\t\t\t\ttoken.type === `mutable_atom` ? `*` + token.key : token.key\n\t\t\t\t\t\t\t\t\treturn key\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\tconst redactedUpdates = redactTransactionUpdateContent(\n\t\t\t\t\t\tvisibleKeys,\n\t\t\t\t\t\tupdate.subEvents,\n\t\t\t\t\t)\n\t\t\t\t\tconst redactedUpdate = {\n\t\t\t\t\t\t...update,\n\t\t\t\t\t\tupdates: redactedUpdates,\n\t\t\t\t\t}\n\t\t\t\t\tsetIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {\n\t\t\t\t\t\tif (redactedUpdate) {\n\t\t\t\t\t\t\tupdates.push(redactedUpdate)\n\t\t\t\t\t\t\tupdates.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t`👍`,\n\t\t\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t\t\t`${userKey} unacknowledged update queue now has`,\n\t\t\t\t\t\t\t\tupdates.length,\n\t\t\t\t\t\t\t\t`items`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn updates\n\t\t\t\t\t})\n\n\t\t\t\t\tsocket?.emit(\n\t\t\t\t\t\t`tx-new:${continuityKey}`,\n\t\t\t\t\t\tredactedUpdate as Json.Serializable,\n\t\t\t\t\t)\n\t\t\t\t} catch (thrown) {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t\t`${userKey} failed to send update from transaction ${transaction.key} to ${userKey}`,\n\t\t\t\t\t\t\tthrown.message,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tunsubscribeFunctions.push(unsubscribeFromTransaction)\n\t}\n\treturn unsubscribeFunctions\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket } from \"..\"\nimport type { UserKey } from \"../realtime-server-stores\"\n\nexport function subscribeToContinuityPerspectives(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): (() => void)[] {\n\tconst continuityKey = continuity.key\n\tconst unsubFns: (() => void)[] = []\n\tfor (const perspective of continuity.perspectives) {\n\t\tconst { viewAtoms } = perspective\n\t\tconst userViewState = findInStore(store, viewAtoms, userKey)\n\t\tconst unsubscribeFromUserView = subscribeToState(\n\t\t\tstore,\n\t\t\tuserViewState,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}:perspective:${perspective.resourceAtoms.key}`,\n\t\t\t({ oldValue, newValue }) => {\n\t\t\t\tconst oldKeys = oldValue.map((token) => token.key)\n\t\t\t\tconst newKeys = newValue.map((token) => token.key)\n\t\t\t\tconst concealed = oldValue.filter(\n\t\t\t\t\t(token) => !newKeys.includes(token.key),\n\t\t\t\t)\n\t\t\t\tconst revealed = newValue\n\t\t\t\t\t.filter((token) => !oldKeys.includes(token.key))\n\t\t\t\t\t.flatMap((token) => {\n\t\t\t\t\t\tconst resourceToken =\n\t\t\t\t\t\t\ttoken.type === `mutable_atom` ? getJsonToken(store, token) : token\n\t\t\t\t\t\tconst resource = getFromStore(store, resourceToken)\n\t\t\t\t\t\treturn [resourceToken, resource]\n\t\t\t\t\t})\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👁`,\n\t\t\t\t\t`atom`,\n\t\t\t\t\tperspective.resourceAtoms.key,\n\t\t\t\t\t`${userKey} has a new perspective`,\n\t\t\t\t\t{ oldKeys, newKeys, revealed, concealed },\n\t\t\t\t)\n\t\t\t\tif (revealed.length > 0) {\n\t\t\t\t\tsocket?.emit(`reveal:${continuityKey}`, revealed)\n\t\t\t\t}\n\t\t\t\tif (concealed.length > 0) {\n\t\t\t\t\tsocket?.emit(`conceal:${continuityKey}`, concealed)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tunsubFns.push(unsubscribeFromUserView)\n\t}\n\treturn unsubFns\n}\n","import {\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { ServerConfig, Socket } from \"..\"\nimport { socketAtoms, usersOfSockets } from \"..\"\nimport { userUnacknowledgedQueues } from \"../realtime-server-stores\"\nimport { prepareToSendInitialPayload } from \"./prepare-to-send-initial-payload\"\nimport { prepareToServeTransactionRequest } from \"./prepare-to-serve-transaction-request\"\nimport { prepareToTrackClientAcknowledgement } from \"./prepare-to-track-client-acknowledgement\"\nimport { subscribeToContinuityActions } from \"./subscribe-to-continuity-actions\"\nimport { subscribeToContinuityPerspectives } from \"./subscribe-to-continuity-perpectives\"\n\nexport type ExposeRealtimeContinuity = (\n\tcontinuity: ContinuityToken,\n) => () => void\nexport function prepareToExposeRealtimeContinuity({\n\tsocket: initialSocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig): ExposeRealtimeContinuity {\n\treturn function syncRealtimeContinuity(continuity) {\n\t\tlet socket: Socket | null = initialSocket\n\n\t\tconst continuityKey = continuity.key\n\t\tconst userKeyState = findRelationsInStore(\n\t\t\tusersOfSockets,\n\t\t\t`socket::${socket.id}`,\n\t\t\tstore,\n\t\t).userKeyOfSocket\n\t\tconst userKey = getFromStore(store, userKeyState)\n\t\tif (!userKey) {\n\t\t\tstore.logger.error(\n\t\t\t\t`❌`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`Tried to create a synchronizer for a socket (${socket.id}) that is not connected to a user.`,\n\t\t\t)\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst socketKeyState = findRelationsInStore(\n\t\t\tusersOfSockets,\n\t\t\tuserKey,\n\t\t\tstore,\n\t\t).socketKeyOfUser\n\t\tconst _unsubscribeFromSocketTracking = subscribeToState(\n\t\t\tstore,\n\t\t\tsocketKeyState,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}`,\n\t\t\t({ newValue: newSocketKey }) => {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👋`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`seeing ${userKey} on new socket ${newSocketKey}`,\n\t\t\t\t)\n\t\t\t\tif (newSocketKey === null) {\n\t\t\t\t\tstore.logger.warn(\n\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`User (${userKey}) is not connected to a socket, waiting for them to reappear.`,\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst newSocketState = findInStore(store, socketAtoms, newSocketKey)\n\t\t\t\tconst newSocket = getFromStore(store, newSocketState)\n\t\t\t\tsocket = newSocket\n\t\t\t\tfor (const unacknowledgedUpdate of userUnacknowledgedUpdates) {\n\t\t\t\t\tsocket?.emit(\n\t\t\t\t\t\t`tx-new:${continuityKey}`,\n\t\t\t\t\t\tunacknowledgedUpdate as Json.Serializable,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\n\t\tconst userUnacknowledgedUpdates = getFromStore(\n\t\t\tstore,\n\t\t\tuserUnacknowledgedQueues,\n\t\t\tuserKey,\n\t\t)\n\n\t\tconst unsubscribeFunctions: (() => void)[] = []\n\n\t\tconst unsubscribeFromPerspectives = subscribeToContinuityPerspectives(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tsocket,\n\t\t)\n\t\tconst unsubscribeFromTransactions = subscribeToContinuityActions(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tsocket,\n\t\t)\n\t\tunsubscribeFunctions.push(\n\t\t\t...unsubscribeFromPerspectives,\n\t\t\t...unsubscribeFromTransactions,\n\t\t)\n\n\t\tconst sendInitialPayload = prepareToSendInitialPayload(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tinitialSocket,\n\t\t)\n\n\t\tsocket.off(`get:${continuityKey}`, sendInitialPayload)\n\t\tsocket.on(`get:${continuityKey}`, sendInitialPayload)\n\n\t\tconst fillTransactionRequest = prepareToServeTransactionRequest(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t)\n\n\t\tsocket.off(`tx-run:${continuityKey}`, fillTransactionRequest)\n\t\tsocket.on(`tx-run:${continuityKey}`, fillTransactionRequest)\n\n\t\tconst trackClientAcknowledgement = prepareToTrackClientAcknowledgement(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tuserUnacknowledgedUpdates,\n\t\t)\n\n\t\tsocket?.on(`ack:${continuityKey}`, trackClientAcknowledgement)\n\n\t\treturn () => {\n\t\t\t// clearInterval(retryTimeout)\n\t\t\tfor (const unsubscribe of unsubscribeFunctions) unsubscribe()\n\t\t\tsocket?.off(`ack:${continuityKey}`, trackClientAcknowledgement)\n\t\t\tsocket?.off(`get:${continuityKey}`, sendInitialPayload)\n\t\t\tsocket?.off(`tx-run:${continuityKey}`, fillTransactionRequest)\n\t\t}\n\t}\n}\n","import type { TransactionOutcomeEvent, TransactionToken } from \"atom.io\"\nimport { actUponStore, IMPLICIT } from \"atom.io/internal\"\nimport type { JsonIO } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type ActionReceiver = ReturnType<typeof realtimeActionReceiver>\nexport function realtimeActionReceiver({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function actionReceiver<F extends JsonIO>(\n\t\ttx: TransactionToken<F>,\n\t): () => void {\n\t\tconst fillTransactionRequest = (\n\t\t\tupdate: Pick<\n\t\t\t\tTransactionOutcomeEvent<TransactionToken<F>>,\n\t\t\t\t`id` | `params`\n\t\t\t>,\n\t\t) => {\n\t\t\tconst performanceKey = `tx-run:${tx.key}:${update.id}`\n\t\t\tconst performanceKeyStart = `${performanceKey}:start`\n\t\t\tconst performanceKeyEnd = `${performanceKey}:end`\n\t\t\tperformance.mark(performanceKeyStart)\n\t\t\tactUponStore<F>(store, tx, update.id)(...update.params)\n\t\t\tperformance.mark(performanceKeyEnd)\n\t\t\tconst metric = performance.measure(\n\t\t\t\tperformanceKey,\n\t\t\t\tperformanceKeyStart,\n\t\t\t\tperformanceKeyEnd,\n\t\t\t)\n\t\t\tstore?.logger.info(`🚀`, `transaction`, tx.key, update.id, metric.duration)\n\t\t}\n\t\tsocket.on(`tx-run:${tx.key}`, fillTransactionRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`tx-run:${tx.key}`, fillTransactionRequest)\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Canonical, Json } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>\nexport function realtimeAtomFamilyProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function familyProvider<\n\t\tJ extends Json.Serializable,\n\t\tK extends Canonical,\n\t>(\n\t\tfamily: AtomIO.RegularAtomFamilyToken<J, K>,\n\t\tindex: AtomIO.ReadableToken<Iterable<K>>,\n\t): () => void {\n\t\tconst unsubCallbacksByKey = new Map<string, () => void>()\n\n\t\tconst fillUnsubRequest = (key: string) => {\n\t\t\tsocket.off(`unsub:${key}`, fillUnsubRequest)\n\t\t\tconst unsub = unsubCallbacksByKey.get(key)\n\t\t\tif (unsub) {\n\t\t\t\tunsub()\n\t\t\t\tunsubCallbacksByKey.delete(key)\n\t\t\t}\n\t\t}\n\n\t\tconst fillSubRequest = (subKey: K) => {\n\t\t\tconst exposedSubKeys = getFromStore(store, index)\n\t\t\tfor (const exposedSubKey of exposedSubKeys) {\n\t\t\t\tif (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {\n\t\t\t\t\tconst token = findInStore(store, family, subKey)\n\t\t\t\t\tsocket.emit(`serve:${token.key}`, getFromStore(store, token))\n\t\t\t\t\tconst unsubscribe = subscribeToState(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t`expose-family:${family.key}:${socket.id}`,\n\t\t\t\t\t\t({ newValue }) => {\n\t\t\t\t\t\t\tsocket.emit(`serve:${token.key}`, newValue)\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tunsubCallbacksByKey.set(token.key, unsubscribe)\n\t\t\t\t\tsocket.on(`unsub:${token.key}`, () => {\n\t\t\t\t\t\tfillUnsubRequest(token.key)\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsocket.on(`sub:${family.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${family.key}`, fillSubRequest)\n\n\t\t\tfor (const [, unsub] of unsubCallbacksByKey) {\n\t\t\t\tunsub()\n\t\t\t}\n\t\t\tunsubCallbacksByKey.clear()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tgetUpdateToken,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Canonical } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type MutableFamilyProvider = ReturnType<\n\ttypeof realtimeMutableFamilyProvider\n>\nexport function realtimeMutableFamilyProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function mutableFamilyProvider<\n\t\tT extends Transceiver<any, any, any>,\n\t\tK extends Canonical,\n\t>(\n\t\tfamily: AtomIO.MutableAtomFamilyToken<T, K>,\n\t\tindex: AtomIO.ReadableToken<Iterable<K>>,\n\t): () => void {\n\t\tconst unsubCallbacksByKey = new Map<string, () => void>()\n\n\t\tconst fillUnsubRequest = (key: string) => {\n\t\t\tsocket.off(`unsub:${key}`, fillUnsubRequest)\n\t\t\tconst unsub = unsubCallbacksByKey.get(key)\n\t\t\tif (unsub) {\n\t\t\t\tunsub()\n\t\t\t\tunsubCallbacksByKey.delete(key)\n\t\t\t}\n\t\t}\n\n\t\tconst fillSubRequest = (subKey: K) => {\n\t\t\tconst exposedSubKeys = getFromStore(store, index)\n\t\t\tfor (const exposedSubKey of exposedSubKeys) {\n\t\t\t\tif (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {\n\t\t\t\t\tconst token = findInStore(store, family, subKey)\n\t\t\t\t\tgetFromStore(store, token)\n\t\t\t\t\tconst jsonToken = getJsonToken(store, token)\n\t\t\t\t\tconst updateToken = getUpdateToken(token)\n\t\t\t\t\tsocket.emit(`init:${token.key}`, getFromStore(store, jsonToken))\n\t\t\t\t\tconst unsubscribe = subscribeToState(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\tupdateToken,\n\t\t\t\t\t\t`expose-family:${family.key}:${socket.id}`,\n\t\t\t\t\t\t({ newValue }) => {\n\t\t\t\t\t\t\tsocket.emit(`next:${token.key}`, newValue)\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tunsubCallbacksByKey.set(token.key, unsubscribe)\n\t\t\t\t\tsocket.on(`unsub:${token.key}`, () => {\n\t\t\t\t\t\tfillUnsubRequest(token.key)\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsocket.on(`sub:${family.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${family.key}`, fillSubRequest)\n\t\t\tfor (const [, unsub] of unsubCallbacksByKey) {\n\t\t\t\tunsub()\n\t\t\t}\n\t\t\tunsubCallbacksByKey.clear()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport {\n\tgetFromStore,\n\tgetJsonToken,\n\tgetUpdateToken,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type MutableProvider = ReturnType<typeof realtimeMutableProvider>\nexport function realtimeMutableProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function mutableProvider<\n\t\tCore extends Transceiver<any, Json.Serializable, Json.Serializable>,\n\t>(token: AtomIO.MutableAtomToken<Core>): () => void {\n\t\tlet unsubscribeFromStateUpdates: (() => void) | null = null\n\n\t\tconst jsonToken = getJsonToken(store, token)\n\t\tconst trackerToken = getUpdateToken(token)\n\n\t\tconst fillUnsubRequest = () => {\n\t\t\tsocket.off(`unsub:${token.key}`, fillUnsubRequest)\n\t\t\tunsubscribeFromStateUpdates?.()\n\t\t\tunsubscribeFromStateUpdates = null\n\t\t}\n\n\t\tconst fillSubRequest = () => {\n\t\t\tsocket.emit(`init:${token.key}`, getFromStore(store, jsonToken))\n\t\t\tunsubscribeFromStateUpdates = subscribeToState(\n\t\t\t\tstore,\n\t\t\t\ttrackerToken,\n\t\t\t\t`expose-single:${socket.id}`,\n\t\t\t\t({ newValue }) => {\n\t\t\t\t\tsocket.emit(`next:${token.key}`, newValue)\n\t\t\t\t},\n\t\t\t)\n\t\t\tsocket.on(`unsub:${token.key}`, fillUnsubRequest)\n\t\t}\n\n\t\tsocket.on(`sub:${token.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${token.key}`, fillSubRequest)\n\t\t\tunsubscribeFromStateUpdates?.()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { getFromStore, IMPLICIT, subscribeToState } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type StateProvider = ReturnType<typeof realtimeStateProvider>\nexport function realtimeStateProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function stateProvider<J extends Json.Serializable>(\n\t\ttoken: AtomIO.WritableToken<J>,\n\t): () => void {\n\t\tlet unsubscribeFromStateUpdates: (() => void) | undefined\n\n\t\tconst fillSubRequest = () => {\n\t\t\tsocket.emit(`serve:${token.key}`, getFromStore(store, token))\n\n\t\t\tunsubscribeFromStateUpdates = subscribeToState(\n\t\t\t\tstore,\n\t\t\t\ttoken,\n\t\t\t\t`expose-single:${socket.id}`,\n\t\t\t\t({ newValue }) => {\n\t\t\t\t\tsocket.emit(`serve:${token.key}`, newValue)\n\t\t\t\t},\n\t\t\t)\n\n\t\t\tconst fillUnsubRequest = () => {\n\t\t\t\tsocket.off(`unsub:${token.key}`, fillUnsubRequest)\n\t\t\t\tif (unsubscribeFromStateUpdates) {\n\t\t\t\t\tunsubscribeFromStateUpdates()\n\t\t\t\t\tunsubscribeFromStateUpdates = undefined\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsocket.on(`unsub:${token.key}`, fillUnsubRequest)\n\t\t}\n\n\t\tsocket.on(`sub:${token.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${token.key}`, fillSubRequest)\n\t\t\tif (unsubscribeFromStateUpdates) {\n\t\t\t\tunsubscribeFromStateUpdates()\n\t\t\t\tunsubscribeFromStateUpdates = undefined\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { WritableToken } from \"atom.io\"\nimport { IMPLICIT, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type StateReceiver = ReturnType<typeof realtimeStateReceiver>\nexport function realtimeStateReceiver({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function stateReceiver<J extends Json.Serializable>(\n\t\ttoken: WritableToken<J>,\n\t): () => void {\n\t\tconst publish = (newValue: J) => {\n\t\t\tsetIntoStore(store, token, newValue)\n\t\t}\n\n\t\tconst fillPubUnclaim = () => {\n\t\t\tsocket.off(`pub:${token.key}`, publish)\n\t\t\tsocket.off(`unclaim:${token.key}`, fillPubUnclaim)\n\t\t}\n\t\tconst fillPubClaim = () => {\n\t\t\tsocket.on(`pub:${token.key}`, publish)\n\t\t\tsocket.on(`unclaim:${token.key}`, fillPubUnclaim)\n\t\t}\n\n\t\tsocket.on(`claim:${token.key}`, fillPubClaim)\n\n\t\treturn () => {\n\t\t\tsocket.off(`claim:${token.key}`, fillPubClaim)\n\t\t\tsocket.off(`pub:${token.key}`, publish)\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["process","roomArgumentsAtoms: RegularAtomFamilyToken<RoomArguments, string>","roomSelectors: ReadonlyPureSelectorFamilyToken<\n\tLoadable<ChildSocket<any, any>>,\n\tstring\n>","createRoomTX: AtomIO.TransactionToken<\n\t(\n\t\troomKey: RoomKey,\n\t\tscript: string,\n\t\toptions?: string[],\n\t) => Loadable<ChildSocket<any, any>>\n>","args: RoomArguments","joinRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string, enteredAtEpoch: number) => UserInRoomMeta\n>","leaveRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string) => void\n>","destroyRoomTX: AtomIO.TransactionToken<(roomKey: RoomKey) => void>","redactorAtoms: RegularAtomFamilyToken<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n>","userUnacknowledgedQueues: RegularAtomFamilyToken<\n\tContinuitySyncTransactionUpdate[],\n\tUserKey\n>","socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey>","socketIndex: MutableAtomToken<SetRTX<SocketKey>>","userIndex: MutableAtomToken<SetRTX<UserKey>>","usersOfSockets: JoinToken<\n\t`user`,\n\tUserKey,\n\t`socket`,\n\tSocketKey,\n\t`1:1`\n>","initialPayload: Json.Serializable[]","unsubscribeFunctions: (() => void)[]","unsubFns: (() => void)[]","socket: Socket | null","unsubscribeFunctions: (() => void)[]","unsubscribeFromStateUpdates: (() => void) | null","unsubscribeFromStateUpdates: (() => void) | undefined"],"sources":["../../src/realtime-server/ipc-sockets/custom-socket.ts","../../src/realtime-server/ipc-sockets/child-socket.ts","../../src/realtime-server/ipc-sockets/parent-socket.ts","../../src/realtime-server/realtime-server-stores/server-room-external-store.ts","../../src/realtime-server/realtime-server-stores/server-room-external-actions.ts","../../src/realtime-server/realtime-server-stores/server-sync-store.ts","../../src/realtime-server/realtime-server-stores/server-user-store.ts","../../src/realtime-server/continuity/prepare-to-send-initial-payload.ts","../../src/realtime-server/continuity/prepare-to-serve-transaction-request.ts","../../src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts","../../src/realtime-server/continuity/subscribe-to-continuity-actions.ts","../../src/realtime-server/continuity/subscribe-to-continuity-perpectives.ts","../../src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts","../../src/realtime-server/realtime-action-receiver.ts","../../src/realtime-server/realtime-family-provider.ts","../../src/realtime-server/realtime-mutable-family-provider.ts","../../src/realtime-server/realtime-mutable-provider.ts","../../src/realtime-server/realtime-state-provider.ts","../../src/realtime-server/realtime-state-receiver.ts"],"sourcesContent":["import type { Json, stringified } from \"atom.io/json\"\n\nimport type { Socket } from \"..\"\n\nexport type Events = Json.Object<string, Json.Serializable[]>\n\nexport type StringifiedEvent<\n\tKey extends string,\n\tParams extends Json.Serializable[],\n> = stringified<[Key, ...Params]>\n\nexport interface EventBuffer<\n\tKey extends string,\n\tParams extends Json.Serializable[],\n> extends Buffer {\n\ttoString(): StringifiedEvent<Key, Params>\n}\n\nexport class CustomSocket<I extends Events, O extends Events> implements Socket {\n\tprotected listeners: Map<keyof O, Set<(...args: Json.Array) => void>>\n\tprotected globalListeners: Set<(event: string, ...args: Json.Array) => void>\n\tprotected handleEvent<Event extends keyof I>(\n\t\tevent: string,\n\t\t...args: I[Event]\n\t): void {\n\t\tfor (const listener of this.globalListeners) {\n\t\t\tlistener(event, ...args)\n\t\t}\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener(...args)\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic id = `no_id_retrieved`\n\tpublic emit: <Event extends keyof I>(\n\t\tevent: Event,\n\t\t...args: I[Event]\n\t) => CustomSocket<I, O>\n\n\tpublic constructor(\n\t\temit: <Event extends keyof I>(\n\t\t\tevent: Event,\n\t\t\t...args: I[Event]\n\t\t) => CustomSocket<I, O>,\n\t) {\n\t\tthis.emit = emit\n\t\tthis.listeners = new Map()\n\t\tthis.globalListeners = new Set()\n\t}\n\n\tpublic on<Event extends keyof O>(\n\t\tevent: Event,\n\t\tlistener: (...args: O[Event]) => void,\n\t): this {\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tlisteners.add(listener)\n\t\t} else {\n\t\t\tthis.listeners.set(event, new Set([listener]))\n\t\t}\n\t\treturn this\n\t}\n\n\tpublic onAny(listener: (event: string, ...args: Json.Array) => void): this {\n\t\tthis.globalListeners.add(listener)\n\t\treturn this\n\t}\n\n\tpublic off<Event extends keyof O>(\n\t\tevent: Event,\n\t\tlistener?: (...args: O[Event]) => void,\n\t): this {\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tif (listener) {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t} else {\n\t\t\t\tthis.listeners.delete(event)\n\t\t\t}\n\t\t}\n\t\treturn this\n\t}\n\n\tpublic offAny(listener: (event: string, ...args: Json.Array) => void): this {\n\t\tthis.globalListeners.delete(listener)\n\t\treturn this\n\t}\n}\n","import type { ChildProcessWithoutNullStreams } from \"node:child_process\"\n\nimport type { Json } from \"atom.io/json\"\nimport { parseJson } from \"atom.io/json\"\n\nimport type { EventBuffer, Events } from \"./custom-socket\"\nimport { CustomSocket } from \"./custom-socket\"\n\n/* eslint-disable no-console */\n\nexport class ChildSocket<\n\tI extends Events,\n\tO extends Events,\n> extends CustomSocket<I, O> {\n\tprotected incompleteData = ``\n\tprotected unprocessedEvents: string[] = []\n\tprotected incompleteLog = ``\n\tprotected unprocessedLogs: string[] = []\n\n\tpublic id = `#####`\n\n\tpublic process: ChildProcessWithoutNullStreams\n\tpublic key: string\n\tpublic logger: Pick<Console, `error` | `info` | `warn`>\n\n\tprotected handleLog(arg: Json.Serializable): void {\n\t\tif (Array.isArray(arg)) {\n\t\t\tconst [level, ...rest] = arg\n\t\t\tswitch (level) {\n\t\t\t\tcase `i`:\n\t\t\t\t\tthis.logger.info(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tcase `w`:\n\t\t\t\t\tthis.logger.warn(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tcase `e`:\n\t\t\t\t\tthis.logger.error(...rest)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic constructor(\n\t\tprocess: ChildProcessWithoutNullStreams,\n\t\tkey: string,\n\t\tlogger?: Pick<Console, `error` | `info` | `warn`>,\n\t) {\n\t\tsuper((event, ...args) => {\n\t\t\tconst stringifiedEvent = JSON.stringify([event, ...args]) + `\\x03`\n\t\t\tconst errorHandler = (err: { code: string }) => {\n\t\t\t\tif (err.code === `EPIPE`) {\n\t\t\t\t\tconsole.error(`EPIPE error during write`, this.process.stdin)\n\t\t\t\t}\n\t\t\t\tthis.process.stdin.removeListener(`error`, errorHandler)\n\t\t\t}\n\n\t\t\tthis.process.stdin.once(`error`, errorHandler)\n\t\t\tthis.process.stdin.write(stringifiedEvent)\n\n\t\t\treturn this\n\t\t})\n\t\tthis.process = process\n\t\tthis.key = key\n\t\tthis.logger = logger ?? {\n\t\t\tinfo: (...args: unknown[]) => {\n\t\t\t\tconsole.info(this.id, this.key, ...args)\n\t\t\t},\n\t\t\twarn: (...args: unknown[]) => {\n\t\t\t\tconsole.warn(this.id, this.key, ...args)\n\t\t\t},\n\t\t\terror: (...args: unknown[]) => {\n\t\t\t\tconsole.error(this.id, this.key, ...args)\n\t\t\t},\n\t\t}\n\t\tthis.process.stdout.on(\n\t\t\t`data`,\n\t\t\t<Event extends keyof I>(buffer: EventBuffer<string, I[Event]>) => {\n\t\t\t\tconst chunk = buffer.toString()\n\n\t\t\t\tif (chunk === `ALIVE`) {\n\t\t\t\t\t// console.log(chunk)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.unprocessedEvents.push(...chunk.split(`\\x03`))\n\t\t\t\t// console.log(`🤓`, chunk.length)\n\t\t\t\t// console.log(`🤓`, this.unprocessedEvents.length)\n\t\t\t\t// console.log(`🤓`, ...this.unprocessedEvents.map((x) => x.length))\n\t\t\t\tconst newInput = this.unprocessedEvents.shift()\n\t\t\t\tthis.incompleteData += newInput ?? ``\n\t\t\t\ttry {\n\t\t\t\t\tif (this.incompleteData.startsWith(`error`)) {\n\t\t\t\t\t\tconsole.log(`❗`, this.incompleteData)\n\t\t\t\t\t}\n\t\t\t\t\tlet parsedEvent = parseJson(this.incompleteData)\n\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\twhile (this.unprocessedEvents.length > 0) {\n\t\t\t\t\t\tconst event = this.unprocessedEvents.shift()\n\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\tif (this.unprocessedEvents.length === 0) {\n\t\t\t\t\t\t\t\tthis.incompleteData = event\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tparsedEvent = parseJson(event)\n\t\t\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.incompleteData = ``\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.warn(`⚠️----------------⚠️`)\n\t\t\t\t\tconsole.warn(this.incompleteData)\n\t\t\t\t\tconsole.warn(`⚠️----------------⚠️`)\n\t\t\t\t\tconsole.error(error)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tthis.process.stderr.on(`data`, (buf) => {\n\t\t\tconst chunk = buf.toString()\n\t\t\tthis.unprocessedLogs.push(...chunk.split(`\\x03`))\n\t\t\t// console.log(`🤫`, chunk.length)\n\t\t\t// console.log(`🤫`, this.unprocessedLogs.length)\n\t\t\t// console.log(`🤫`, ...this.unprocessedLogs.map((x) => x.length))\n\t\t\tconst newInput = this.unprocessedLogs.shift()\n\t\t\tthis.incompleteLog += newInput ?? ``\n\t\t\ttry {\n\t\t\t\tlet parsedLog = parseJson(this.incompleteLog)\n\t\t\t\t// console.log(`🤫`, parsedLog)\n\t\t\t\tthis.handleLog(parsedLog)\n\t\t\t\twhile (this.unprocessedLogs.length > 0) {\n\t\t\t\t\tthis.incompleteLog = this.unprocessedLogs.shift() ?? ``\n\t\t\t\t\tif (this.incompleteLog) {\n\t\t\t\t\t\tparsedLog = parseJson(this.incompleteLog)\n\t\t\t\t\t\tthis.handleLog(parsedLog)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`❌❌❌`)\n\t\t\t\tconsole.error(this.incompleteLog)\n\t\t\t\tconsole.error(error)\n\t\t\t\tconsole.error(`❌❌❌️`)\n\t\t\t}\n\t\t})\n\t\tif (process.pid) {\n\t\t\tthis.id = process.pid.toString()\n\t\t}\n\t}\n}\n","import { Subject } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\nimport { SetRTX } from \"atom.io/transceivers/set-rtx\"\n\nimport type { EventBuffer, Events } from \"./custom-socket\"\nimport { CustomSocket } from \"./custom-socket\"\n\nexport class SubjectSocket<\n\tI extends Events,\n\tO extends Events,\n> extends CustomSocket<I, O> {\n\tpublic in: Subject<[string, ...Json.Serializable[]]>\n\tpublic out: Subject<[string, ...Json.Serializable[]]>\n\tpublic id = `no_id_retrieved`\n\tpublic disposalFunctions: (() => void)[] = []\n\n\tpublic constructor(id: string) {\n\t\tsuper((...args) => {\n\t\t\tthis.out.next(args as any)\n\t\t\treturn this\n\t\t})\n\t\tthis.id = id\n\t\tthis.in = new Subject()\n\t\tthis.out = new Subject()\n\t\tthis.in.subscribe(`socket`, (event) => {\n\t\t\tthis.handleEvent(...(event as [string, ...I[keyof I]]))\n\t\t})\n\t}\n\n\tpublic dispose(): void {\n\t\tfor (const dispose of this.disposalFunctions) {\n\t\t\tdispose()\n\t\t}\n\t}\n}\n\nexport class ParentSocket<\n\tI extends Events & {\n\t\t[id in string as `relay:${id}`]: [string, ...Json.Serializable[]]\n\t},\n\tO extends Events & {\n\t\t[id in string as `user:${id}`]: [string, ...Json.Serializable[]]\n\t} & {\n\t\t/* eslint-disable quotes */\n\t\t\"user-joins\": [string]\n\t\t\"user-leaves\": [string]\n\t\t/* eslint-enable quotes */\n\t},\n> extends CustomSocket<I, O> {\n\tprotected incompleteData = ``\n\tprotected unprocessedEvents: string[] = []\n\tprotected relays: Map<string, SubjectSocket<any, any>>\n\tprotected relayServices: ((\n\t\tsocket: SubjectSocket<any, any>,\n\t) => (() => void) | void)[]\n\tprotected process: NodeJS.Process\n\n\tpublic id = `#####`\n\n\tprotected log(...args: any[]): void {\n\t\tthis.process.stderr.write(\n\t\t\tstringifyJson(\n\t\t\t\targs.map((arg) =>\n\t\t\t\t\targ instanceof SetRTX\n\t\t\t\t\t\t? `{ ${arg.toJSON().members.join(` | `)} }`\n\t\t\t\t\t\t: arg,\n\t\t\t\t),\n\t\t\t) + `\\x03`,\n\t\t)\n\t}\n\tpublic logger = {\n\t\tinfo: (...args: any[]): void => {\n\t\t\tthis.log(`i`, ...args)\n\t\t},\n\t\twarn: (...args: any[]): void => {\n\t\t\tthis.log(`w`, ...args)\n\t\t},\n\t\terror: (...args: any[]): void => {\n\t\t\tthis.log(`e`, ...args)\n\t\t},\n\t}\n\n\tpublic constructor() {\n\t\tsuper((event, ...args) => {\n\t\t\tconst stringifiedEvent = JSON.stringify([event, ...args])\n\t\t\tthis.process.stdout.write(stringifiedEvent + `\\x03`)\n\t\t\treturn this\n\t\t})\n\t\tthis.process = process\n\t\tthis.process.stdin.resume()\n\t\tthis.relays = new Map()\n\t\tthis.relayServices = []\n\t\t// this.logger.info(`🔗`, `uplink`, process.pid)\n\n\t\tthis.process.stdin.on(\n\t\t\t`data`,\n\t\t\t<Event extends keyof I>(buffer: EventBuffer<string, I[Event]>) => {\n\t\t\t\tconst chunk = buffer.toString()\n\t\t\t\tthis.unprocessedEvents.push(...chunk.split(`\\x03`))\n\t\t\t\tconst newInput = this.unprocessedEvents.shift()\n\t\t\t\tthis.incompleteData += newInput ?? ``\n\n\t\t\t\ttry {\n\t\t\t\t\tconst parsedData = parseJson(this.incompleteData)\n\t\t\t\t\tthis.logger.info(`🎰`, `received`, parsedData)\n\t\t\t\t\tthis.handleEvent(...(parsedData as [string, ...I[keyof I]]))\n\t\t\t\t\twhile (this.unprocessedEvents.length > 0) {\n\t\t\t\t\t\tconst event = this.unprocessedEvents.shift()\n\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\tif (this.unprocessedEvents.length === 0) {\n\t\t\t\t\t\t\t\tthis.incompleteData = event\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst parsedEvent = parseJson(event)\n\t\t\t\t\t\t\tthis.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.incompleteData = ``\n\t\t\t\t} catch (thrown) {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tthis.logger.error(`❗`, thrown.message, thrown.cause, thrown.stack)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\n\t\tthis.on(`exit`, () => {\n\t\t\tthis.logger.info(`🔥`, this.id, `received \"exit\"`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`exit`, (code) => {\n\t\t\tthis.logger.info(`🔥`, this.id, `exited with code ${code}`)\n\t\t})\n\t\tprocess.on(`end`, () => {\n\t\t\tthis.logger.info(`🔥`, this.id, `ended`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`SIGTERM`, () => {\n\t\t\tthis.logger.error(`🔥`, this.id, `terminated`)\n\t\t\tprocess.exit(0)\n\t\t})\n\t\tprocess.on(`SIGINT`, () => {\n\t\t\tthis.logger.error(`🔥`, this.id, `interrupted`)\n\t\t\tprocess.exit(0)\n\t\t})\n\n\t\tif (process.pid) {\n\t\t\tthis.id = process.pid?.toString()\n\t\t}\n\n\t\tthis.on(`user-joins`, (username) => {\n\t\t\tthis.logger.info(`👤`, `user`, username, `joined`)\n\t\t\tconst relay = new SubjectSocket(`user:${username}`)\n\t\t\tthis.relays.set(username, relay)\n\t\t\tthis.logger.info(\n\t\t\t\t`🔗`,\n\t\t\t\t`attaching services:`,\n\t\t\t\t`[${[...this.relayServices.keys()].join(`, `)}]`,\n\t\t\t)\n\t\t\tfor (const attachServices of this.relayServices) {\n\t\t\t\tconst cleanup = attachServices(relay)\n\t\t\t\tif (cleanup) {\n\t\t\t\t\trelay.disposalFunctions.push(cleanup)\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.on(`user:${username}`, (...data) => {\n\t\t\t\trelay.in.next(data)\n\t\t\t})\n\t\t\trelay.out.subscribe(`socket`, (data) => {\n\t\t\t\tthis.emit(...(data as [string, ...I[keyof I]]))\n\t\t\t})\n\t\t})\n\n\t\tthis.on(`user-leaves`, (username) => {\n\t\t\tconst relay = this.relays.get(username)\n\t\t\tthis.off(`relay:${username}`)\n\t\t\tif (relay) {\n\t\t\t\trelay.dispose()\n\t\t\t\tthis.relays.delete(username)\n\t\t\t}\n\t\t})\n\n\t\tprocess.stdout.write(`ALIVE`)\n\t}\n\n\tpublic relay(\n\t\tattachServices: (socket: SubjectSocket<any, any>) => (() => void) | void,\n\t): void {\n\t\tthis.logger.info(`🔗`, `running relay method`)\n\t\tthis.relayServices.push(attachServices)\n\t}\n}\n","import type { ChildProcessWithoutNullStreams } from \"node:child_process\"\nimport { spawn } from \"node:child_process\"\n\nimport type {\n\tLoadable,\n\tReadonlyPureSelectorFamilyToken,\n\tRegularAtomFamilyToken,\n} from \"atom.io\"\nimport { atomFamily, selectorFamily } from \"atom.io\"\n\nimport { ChildSocket } from \"../ipc-sockets\"\n\nexport type RoomArguments =\n\t| [script: string, options: string[]]\n\t| [script: string]\n\nexport const roomArgumentsAtoms: RegularAtomFamilyToken<RoomArguments, string> =\n\tatomFamily<RoomArguments, string>({\n\t\tkey: `roomArguments`,\n\t\tdefault: [`echo`, [`Hello World!`]],\n\t})\n\nexport const roomSelectors: ReadonlyPureSelectorFamilyToken<\n\tLoadable<ChildSocket<any, any>>,\n\tstring\n> = selectorFamily<Loadable<ChildSocket<any, any>>, string>({\n\tkey: `room`,\n\tget:\n\t\t(roomId) =>\n\t\tasync ({ get, find }) => {\n\t\t\tconst argumentsState = find(roomArgumentsAtoms, roomId)\n\t\t\tconst args = get(argumentsState)\n\t\t\tconst [script, options] = args\n\t\t\tconst child = await new Promise<ChildProcessWithoutNullStreams>(\n\t\t\t\t(resolve) => {\n\t\t\t\t\tconst room = spawn(script, options, { env: process.env })\n\t\t\t\t\tconst resolver = (data: Buffer) => {\n\t\t\t\t\t\tif (data.toString() === `ALIVE`) {\n\t\t\t\t\t\t\troom.stdout.off(`data`, resolver)\n\t\t\t\t\t\t\tresolve(room)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\troom.stdout.on(`data`, resolver)\n\t\t\t\t},\n\t\t\t)\n\t\t\treturn new ChildSocket(child, roomId)\n\t\t},\n})\n","import type { Loadable } from \"atom.io\"\nimport * as AtomIO from \"atom.io\"\nimport { editRelationsInStore } from \"atom.io/internal\"\nimport type { UserInRoomMeta } from \"atom.io/realtime\"\nimport { roomIndex, usersInRooms } from \"atom.io/realtime\"\n\nimport type { ChildSocket } from \"../ipc-sockets\"\nimport type { RoomArguments } from \"./server-room-external-store\"\nimport { roomArgumentsAtoms, roomSelectors } from \"./server-room-external-store\"\nimport type { RoomKey } from \"./server-user-store\"\n\nexport const createRoomTX: AtomIO.TransactionToken<\n\t(\n\t\troomKey: RoomKey,\n\t\tscript: string,\n\t\toptions?: string[],\n\t) => Loadable<ChildSocket<any, any>>\n> = AtomIO.transaction({\n\tkey: `createRoom`,\n\tdo: ({ get, set, find }, roomId, script, options) => {\n\t\tconst args: RoomArguments = options ? [script, options] : [script]\n\t\tconst roomArgumentsState = find(roomArgumentsAtoms, roomId)\n\t\tset(roomArgumentsState, args)\n\t\tset(roomIndex, (s) => s.add(roomId))\n\t\tconst roomState = find(roomSelectors, roomId)\n\t\tconst room = get(roomState)\n\t\treturn room\n\t},\n})\nexport type CreateRoomIO = AtomIO.TransactionIO<typeof createRoomTX>\n\nexport const joinRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string, enteredAtEpoch: number) => UserInRoomMeta\n> = AtomIO.transaction({\n\tkey: `joinRoom`,\n\tdo: (tools, roomId, userId, enteredAtEpoch) => {\n\t\tconst meta = { enteredAtEpoch }\n\t\teditRelationsInStore(\n\t\t\tusersInRooms,\n\t\t\t(relations) => {\n\t\t\t\trelations.set({ room: roomId, user: userId }, meta)\n\t\t\t},\n\t\t\ttools.env().store,\n\t\t)\n\t\treturn meta\n\t},\n})\nexport type JoinRoomIO = AtomIO.TransactionIO<typeof joinRoomTX>\n\nexport const leaveRoomTX: AtomIO.TransactionToken<\n\t(roomId: string, userId: string) => void\n> = AtomIO.transaction({\n\tkey: `leaveRoom`,\n\tdo: (tools, roomId, userId) => {\n\t\teditRelationsInStore(\n\t\t\tusersInRooms,\n\t\t\t(relations) => {\n\t\t\t\trelations.delete({ room: roomId, user: userId })\n\t\t\t},\n\t\t\ttools.env().store,\n\t\t)\n\t},\n})\nexport type LeaveRoomIO = AtomIO.TransactionIO<typeof leaveRoomTX>\n\nexport const destroyRoomTX: AtomIO.TransactionToken<(roomKey: RoomKey) => void> =\n\tAtomIO.transaction({\n\t\tkey: `destroyRoom`,\n\t\tdo: (tools, roomKey) => {\n\t\t\teditRelationsInStore(\n\t\t\t\tusersInRooms,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.delete({ room: roomKey })\n\t\t\t\t},\n\t\t\t\ttools.env().store,\n\t\t\t)\n\t\t\ttools.set(roomIndex, (s) => (s.delete(roomKey), s))\n\t\t},\n\t})\n","import type {\n\tRegularAtomFamilyToken,\n\tTransactionOutcomeEvent,\n\tTransactionSubEvent,\n} from \"atom.io\"\nimport { atomFamily } from \"atom.io\"\n\nimport type { UserKey } from \"./server-user-store\"\n\n// export const completeUpdateAtoms = atomFamily<\n// \tTransactionUpdate<any> | null,\n// \tstring\n// >({\n// \tkey: `completeUpdate`,\n// \tdefault: null,\n// })\n\nexport function redactTransactionUpdateContent(\n\tvisibleStateKeys: string[],\n\tupdates: TransactionSubEvent[],\n): TransactionSubEvent[] {\n\treturn updates\n\t\t.map((update): TransactionSubEvent => {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase `transaction_outcome`: {\n\t\t\t\t\tconst redacted = redactTransactionUpdateContent(\n\t\t\t\t\t\tvisibleStateKeys,\n\t\t\t\t\t\tupdate.subEvents,\n\t\t\t\t\t)\n\t\t\t\t\treturn { ...update, subEvents: redacted }\n\t\t\t\t}\n\t\t\t\tcase `atom_update`:\n\t\t\t\tcase `molecule_creation`:\n\t\t\t\tcase `molecule_disposal`:\n\t\t\t\tcase `molecule_transfer`:\n\t\t\t\tcase `state_creation`:\n\t\t\t\tcase `state_disposal`:\n\t\t\t\t\treturn update\n\t\t\t}\n\t\t})\n\t\t.filter((update) => {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase `atom_update`:\n\t\t\t\tcase `state_creation`:\n\t\t\t\tcase `state_disposal`:\n\t\t\t\t\treturn visibleStateKeys.includes(update.token.key)\n\t\t\t\tcase `molecule_creation`:\n\t\t\t\tcase `transaction_outcome`:\n\t\t\t\tcase `molecule_disposal`:\n\t\t\t\tcase `molecule_transfer`:\n\t\t\t\t\treturn true\n\t\t\t}\n\t\t})\n}\n\nexport const redactorAtoms: RegularAtomFamilyToken<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n> = atomFamily<\n\t{\n\t\tocclude: (updates: TransactionSubEvent[]) => TransactionSubEvent[]\n\t},\n\tUserKey\n>({\n\tkey: `redactor`,\n\tdefault: { occlude: (updates) => updates },\n})\n// export const redactedUpdateSelectors = selectorFamily<\n// \tTransactionUpdate<any> | null,\n// \t[transactionKey: string, updateId: string]\n// >({\n// \tkey: `redactedUpdate`,\n// \tget:\n// \t\t([transactionKey, updateId]) =>\n// \t\t({ get, find }) => {\n// \t\t\tconst update = get(find(completeUpdateAtoms, updateId))\n// \t\t\tconst { filter } = get(find(transactionRedactorAtoms, transactionKey))\n\n// \t\t\tif (update && filter) {\n// \t\t\t\treturn { ...update, updates: filter(update.updates) }\n// \t\t\t}\n// \t\t\treturn null\n// \t\t},\n// })\n\nexport type ContinuitySyncTransactionUpdate = Pick<\n\tTransactionOutcomeEvent<any>,\n\t`epoch` | `id` | `output` | `subEvents` | `token`\n>\nexport const userUnacknowledgedQueues: RegularAtomFamilyToken<\n\tContinuitySyncTransactionUpdate[],\n\tUserKey\n> = atomFamily<ContinuitySyncTransactionUpdate[], UserKey>({\n\tkey: `unacknowledgedUpdates`,\n\tdefault: () => [],\n})\n","import type {\n\tHierarchy,\n\tJoinToken,\n\tMutableAtomToken,\n\tRegularAtomFamilyToken,\n} from \"atom.io\"\nimport { atomFamily, join, mutableAtom } from \"atom.io\"\nimport { SetRTX } from \"atom.io/transceivers/set-rtx\"\n\nimport type { Socket } from \"..\"\n\nexport type SocketKey = `socket::${string}`\nexport type UserKey = `user::${string}`\nexport type RoomKey = `room::${string}`\n\nexport type SocketSystemHierarchy = Hierarchy<\n\t[\n\t\t{\n\t\t\tabove: `root`\n\t\t\tbelow: [UserKey, SocketKey, RoomKey]\n\t\t},\n\t]\n>\n\nexport const socketAtoms: RegularAtomFamilyToken<Socket | null, SocketKey> =\n\tatomFamily<Socket | null, SocketKey>({\n\t\tkey: `sockets`,\n\t\tdefault: null,\n\t})\n\nexport const socketIndex: MutableAtomToken<SetRTX<SocketKey>> = mutableAtom<\n\tSetRTX<SocketKey>\n>({\n\tkey: `socketsIndex`,\n\tclass: SetRTX,\n})\nexport const userIndex: MutableAtomToken<SetRTX<UserKey>> = mutableAtom<\n\tSetRTX<UserKey>\n>({\n\tkey: `usersIndex`,\n\tclass: SetRTX,\n})\nexport const usersOfSockets: JoinToken<\n\t`user`,\n\tUserKey,\n\t`socket`,\n\tSocketKey,\n\t`1:1`\n> = join({\n\tkey: `usersOfSockets`,\n\tbetween: [`user`, `socket`],\n\tcardinality: `1:1`,\n\tisAType: (s): s is UserKey => s.startsWith(`user::`),\n\tisBType: (s): s is SocketKey => s.startsWith(`socket::`),\n})\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tisRootStore,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket, UserKey } from \"..\"\n\nexport function prepareToSendInitialPayload(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): () => void {\n\tconst continuityKey = continuity.key\n\treturn function sendInitialPayload(): void {\n\t\tconst initialPayload: Json.Serializable[] = []\n\t\tfor (const atom of continuity.globals) {\n\t\t\tconst resourceToken =\n\t\t\t\tatom.type === `mutable_atom` ? getJsonToken(store, atom) : atom\n\t\t\tconst resource = getFromStore(store, resourceToken)\n\t\t\tinitialPayload.push(resourceToken, resource)\n\t\t}\n\t\tfor (const perspective of continuity.perspectives) {\n\t\t\tconst { viewAtoms, resourceAtoms } = perspective\n\t\t\tconst userViewState = findInStore(store, viewAtoms, userKey)\n\t\t\tconst userView = getFromStore(store, userViewState)\n\t\t\tstore.logger.info(`👁`, `atom`, resourceAtoms.key, `${userKey} can see`, {\n\t\t\t\tviewAtoms,\n\t\t\t\tresourceAtoms,\n\t\t\t\tuserView,\n\t\t\t})\n\t\t\tfor (const visibleToken of userView) {\n\t\t\t\tconst resourceToken =\n\t\t\t\t\tvisibleToken.type === `mutable_atom`\n\t\t\t\t\t\t? getJsonToken(store, visibleToken)\n\t\t\t\t\t\t: visibleToken\n\t\t\t\tconst resource = getFromStore(store, resourceToken)\n\n\t\t\t\tinitialPayload.push(resourceToken, resource)\n\t\t\t}\n\t\t}\n\n\t\tconst epoch = isRootStore(store)\n\t\t\t? (store.transactionMeta.epoch.get(continuityKey) ?? null)\n\t\t\t: null\n\n\t\tsocket?.emit(`continuity-init:${continuityKey}`, epoch, initialPayload)\n\t}\n}\n","import type { TransactionOutcomeEvent, TransactionToken } from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport { actUponStore } from \"atom.io/internal\"\nimport type { Json, JsonIO } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nexport function prepareToServeTransactionRequest(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: string,\n): (\n\tevent: Json.Serializable &\n\t\tPick<\n\t\t\tTransactionOutcomeEvent<TransactionToken<JsonIO>>,\n\t\t\t`id` | `params` | `token`\n\t\t>,\n) => void {\n\tconst continuityKey = continuity.key\n\treturn function serveTransactionRequest(txOutcome) {\n\t\tstore.logger.info(`🛎️`, `continuity`, continuityKey, `received`, txOutcome)\n\t\tconst transactionKey = txOutcome.token.key\n\t\tconst updateId = txOutcome.id\n\t\tconst performanceKey = `tx-run:${transactionKey}:${updateId}`\n\t\tconst performanceKeyStart = `${performanceKey}:start`\n\t\tconst performanceKeyEnd = `${performanceKey}:end`\n\t\tperformance.mark(performanceKeyStart)\n\t\ttry {\n\t\t\tactUponStore(\n\t\t\t\tstore,\n\t\t\t\t{ type: `transaction`, key: transactionKey },\n\t\t\t\tupdateId,\n\t\t\t)(...txOutcome.params)\n\t\t} catch (thrown) {\n\t\t\tif (thrown instanceof Error) {\n\t\t\t\tstore.logger.error(\n\t\t\t\t\t`❌`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,\n\t\t\t\t\tthrown.message,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tperformance.mark(performanceKeyEnd)\n\t\tconst metric = performance.measure(\n\t\t\tperformanceKey,\n\t\t\tperformanceKeyStart,\n\t\t\tperformanceKeyEnd,\n\t\t)\n\t\tstore?.logger.info(\n\t\t\t`🚀`,\n\t\t\t`transaction`,\n\t\t\ttransactionKey,\n\t\t\tupdateId,\n\t\t\tuserKey,\n\t\t\tmetric.duration,\n\t\t)\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport { setIntoStore } from \"atom.io/internal\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type {\n\tContinuitySyncTransactionUpdate,\n\tUserKey,\n} from \"../realtime-server-stores\"\nimport { userUnacknowledgedQueues } from \"../realtime-server-stores\"\n\nexport function prepareToTrackClientAcknowledgement(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tuserUnacknowledgedUpdates: ContinuitySyncTransactionUpdate[],\n): (epoch: number) => void {\n\tconst continuityKey = continuity.key\n\treturn function trackClientAcknowledgement(epoch) {\n\t\tstore.logger.info(\n\t\t\t`👍`,\n\t\t\t`continuity`,\n\t\t\tcontinuityKey,\n\t\t\t`${userKey} acknowledged epoch ${epoch}`,\n\t\t)\n\t\tconst isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch\n\t\tif (isUnacknowledged) {\n\t\t\tsetIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {\n\t\t\t\tupdates.shift()\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👍`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`${userKey} unacknowledged update queue now has`,\n\t\t\t\t\tupdates.length,\n\t\t\t\t\t`items`,\n\t\t\t\t)\n\t\t\t\treturn updates\n\t\t\t})\n\t\t}\n\t}\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetUpdateToken,\n\tsetIntoStore,\n\tsubscribeToTransaction,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket, UserKey } from \"..\"\nimport {\n\tredactTransactionUpdateContent,\n\tuserUnacknowledgedQueues,\n} from \"../realtime-server-stores\"\n\nexport function subscribeToContinuityActions(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): (() => void)[] {\n\tconst continuityKey = continuity.key\n\tconst unsubscribeFunctions: (() => void)[] = []\n\n\tfor (const transaction of continuity.actions) {\n\t\tconst unsubscribeFromTransaction = subscribeToTransaction(\n\t\t\tstore,\n\t\t\ttransaction,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}`,\n\t\t\t(update) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst visibleKeys = continuity.globals\n\t\t\t\t\t\t.map((atom) => {\n\t\t\t\t\t\t\tif (atom.type === `atom`) {\n\t\t\t\t\t\t\t\treturn atom.key\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn getUpdateToken(atom).key\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.concat(\n\t\t\t\t\t\t\tcontinuity.perspectives.flatMap((perspective) => {\n\t\t\t\t\t\t\t\tconst { viewAtoms } = perspective\n\t\t\t\t\t\t\t\tconst userPerspectiveTokenState = findInStore(\n\t\t\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\t\t\tviewAtoms,\n\t\t\t\t\t\t\t\t\tuserKey,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tconst visibleTokens = getFromStore(\n\t\t\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\t\t\tuserPerspectiveTokenState,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn visibleTokens.map((token) => {\n\t\t\t\t\t\t\t\t\tconst key =\n\t\t\t\t\t\t\t\t\t\ttoken.type === `mutable_atom` ? `*` + token.key : token.key\n\t\t\t\t\t\t\t\t\treturn key\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\tconst redactedUpdates = redactTransactionUpdateContent(\n\t\t\t\t\t\tvisibleKeys,\n\t\t\t\t\t\tupdate.subEvents,\n\t\t\t\t\t)\n\t\t\t\t\tconst redactedUpdate = {\n\t\t\t\t\t\t...update,\n\t\t\t\t\t\tupdates: redactedUpdates,\n\t\t\t\t\t}\n\t\t\t\t\tsetIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {\n\t\t\t\t\t\tif (redactedUpdate) {\n\t\t\t\t\t\t\tupdates.push(redactedUpdate)\n\t\t\t\t\t\t\tupdates.sort((a, b) => a.epoch - b.epoch)\n\t\t\t\t\t\t\tstore.logger.info(\n\t\t\t\t\t\t\t\t`👍`,\n\t\t\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t\t\t`${userKey} unacknowledged update queue now has`,\n\t\t\t\t\t\t\t\tupdates.length,\n\t\t\t\t\t\t\t\t`items`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn updates\n\t\t\t\t\t})\n\n\t\t\t\t\tsocket?.emit(\n\t\t\t\t\t\t`tx-new:${continuityKey}`,\n\t\t\t\t\t\tredactedUpdate as Json.Serializable,\n\t\t\t\t\t)\n\t\t\t\t} catch (thrown) {\n\t\t\t\t\tif (thrown instanceof Error) {\n\t\t\t\t\t\tstore.logger.error(\n\t\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t\t`${userKey} failed to send update from transaction ${transaction.key} to ${userKey}`,\n\t\t\t\t\t\t\tthrown.message,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tunsubscribeFunctions.push(unsubscribeFromTransaction)\n\t}\n\treturn unsubscribeFunctions\n}\n","import type { Store } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { Socket } from \"..\"\nimport type { UserKey } from \"../realtime-server-stores\"\n\nexport function subscribeToContinuityPerspectives(\n\tstore: Store,\n\tcontinuity: ContinuityToken,\n\tuserKey: UserKey,\n\tsocket: Socket | null,\n): (() => void)[] {\n\tconst continuityKey = continuity.key\n\tconst unsubFns: (() => void)[] = []\n\tfor (const perspective of continuity.perspectives) {\n\t\tconst { viewAtoms } = perspective\n\t\tconst userViewState = findInStore(store, viewAtoms, userKey)\n\t\tconst unsubscribeFromUserView = subscribeToState(\n\t\t\tstore,\n\t\t\tuserViewState,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}:perspective:${perspective.resourceAtoms.key}`,\n\t\t\t({ oldValue, newValue }) => {\n\t\t\t\tconst oldKeys = oldValue?.map((token) => token.key)\n\t\t\t\tconst newKeys = newValue.map((token) => token.key)\n\t\t\t\tconst concealed = oldValue?.filter(\n\t\t\t\t\t(token) => !newKeys.includes(token.key),\n\t\t\t\t)\n\t\t\t\tconst revealed = newValue\n\t\t\t\t\t.filter((token) => !oldKeys?.includes(token.key))\n\t\t\t\t\t.flatMap((token) => {\n\t\t\t\t\t\tconst resourceToken =\n\t\t\t\t\t\t\ttoken.type === `mutable_atom` ? getJsonToken(store, token) : token\n\t\t\t\t\t\tconst resource = getFromStore(store, resourceToken)\n\t\t\t\t\t\treturn [resourceToken, resource]\n\t\t\t\t\t})\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👁`,\n\t\t\t\t\t`atom`,\n\t\t\t\t\tperspective.resourceAtoms.key,\n\t\t\t\t\t`${userKey} has a new perspective`,\n\t\t\t\t\t{ oldKeys, newKeys, revealed, concealed },\n\t\t\t\t)\n\t\t\t\tif (revealed.length > 0) {\n\t\t\t\t\tsocket?.emit(`reveal:${continuityKey}`, revealed)\n\t\t\t\t}\n\t\t\t\tif (concealed && concealed.length > 0) {\n\t\t\t\t\tsocket?.emit(`conceal:${continuityKey}`, concealed)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\t\tunsubFns.push(unsubscribeFromUserView)\n\t}\n\treturn unsubFns\n}\n","import {\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport type { ContinuityToken } from \"atom.io/realtime\"\n\nimport type { ServerConfig, Socket } from \"..\"\nimport { socketAtoms, usersOfSockets } from \"..\"\nimport { userUnacknowledgedQueues } from \"../realtime-server-stores\"\nimport { prepareToSendInitialPayload } from \"./prepare-to-send-initial-payload\"\nimport { prepareToServeTransactionRequest } from \"./prepare-to-serve-transaction-request\"\nimport { prepareToTrackClientAcknowledgement } from \"./prepare-to-track-client-acknowledgement\"\nimport { subscribeToContinuityActions } from \"./subscribe-to-continuity-actions\"\nimport { subscribeToContinuityPerspectives } from \"./subscribe-to-continuity-perpectives\"\n\nexport type ExposeRealtimeContinuity = (\n\tcontinuity: ContinuityToken,\n) => () => void\nexport function prepareToExposeRealtimeContinuity({\n\tsocket: initialSocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig): ExposeRealtimeContinuity {\n\treturn function syncRealtimeContinuity(continuity) {\n\t\tlet socket: Socket | null = initialSocket\n\n\t\tconst continuityKey = continuity.key\n\t\tconst userKeyState = findRelationsInStore(\n\t\t\tusersOfSockets,\n\t\t\t`socket::${socket.id}`,\n\t\t\tstore,\n\t\t).userKeyOfSocket\n\t\tconst userKey = getFromStore(store, userKeyState)\n\t\tif (!userKey) {\n\t\t\tstore.logger.error(\n\t\t\t\t`❌`,\n\t\t\t\t`continuity`,\n\t\t\t\tcontinuityKey,\n\t\t\t\t`Tried to create a synchronizer for a socket (${socket.id}) that is not connected to a user.`,\n\t\t\t)\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst socketKeyState = findRelationsInStore(\n\t\t\tusersOfSockets,\n\t\t\tuserKey,\n\t\t\tstore,\n\t\t).socketKeyOfUser\n\t\tconst _unsubscribeFromSocketTracking = subscribeToState(\n\t\t\tstore,\n\t\t\tsocketKeyState,\n\t\t\t`sync-continuity:${continuityKey}:${userKey}`,\n\t\t\t({ newValue: newSocketKey }) => {\n\t\t\t\tstore.logger.info(\n\t\t\t\t\t`👋`,\n\t\t\t\t\t`continuity`,\n\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t`seeing ${userKey} on new socket ${newSocketKey}`,\n\t\t\t\t)\n\t\t\t\tif (newSocketKey === null) {\n\t\t\t\t\tstore.logger.warn(\n\t\t\t\t\t\t`❌`,\n\t\t\t\t\t\t`continuity`,\n\t\t\t\t\t\tcontinuityKey,\n\t\t\t\t\t\t`User (${userKey}) is not connected to a socket, waiting for them to reappear.`,\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst newSocketState = findInStore(store, socketAtoms, newSocketKey)\n\t\t\t\tconst newSocket = getFromStore(store, newSocketState)\n\t\t\t\tsocket = newSocket\n\t\t\t\tfor (const unacknowledgedUpdate of userUnacknowledgedUpdates) {\n\t\t\t\t\tsocket?.emit(\n\t\t\t\t\t\t`tx-new:${continuityKey}`,\n\t\t\t\t\t\tunacknowledgedUpdate as Json.Serializable,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t},\n\t\t)\n\n\t\tconst userUnacknowledgedUpdates = getFromStore(\n\t\t\tstore,\n\t\t\tuserUnacknowledgedQueues,\n\t\t\tuserKey,\n\t\t)\n\n\t\tconst unsubscribeFunctions: (() => void)[] = []\n\n\t\tconst unsubscribeFromPerspectives = subscribeToContinuityPerspectives(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tsocket,\n\t\t)\n\t\tconst unsubscribeFromTransactions = subscribeToContinuityActions(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tsocket,\n\t\t)\n\t\tunsubscribeFunctions.push(\n\t\t\t...unsubscribeFromPerspectives,\n\t\t\t...unsubscribeFromTransactions,\n\t\t)\n\n\t\tconst sendInitialPayload = prepareToSendInitialPayload(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tinitialSocket,\n\t\t)\n\n\t\tsocket.off(`get:${continuityKey}`, sendInitialPayload)\n\t\tsocket.on(`get:${continuityKey}`, sendInitialPayload)\n\n\t\tconst fillTransactionRequest = prepareToServeTransactionRequest(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t)\n\n\t\tsocket.off(`tx-run:${continuityKey}`, fillTransactionRequest)\n\t\tsocket.on(`tx-run:${continuityKey}`, fillTransactionRequest)\n\n\t\tconst trackClientAcknowledgement = prepareToTrackClientAcknowledgement(\n\t\t\tstore,\n\t\t\tcontinuity,\n\t\t\tuserKey,\n\t\t\tuserUnacknowledgedUpdates,\n\t\t)\n\n\t\tsocket?.on(`ack:${continuityKey}`, trackClientAcknowledgement)\n\n\t\treturn () => {\n\t\t\t// clearInterval(retryTimeout)\n\t\t\tfor (const unsubscribe of unsubscribeFunctions) unsubscribe()\n\t\t\tsocket?.off(`ack:${continuityKey}`, trackClientAcknowledgement)\n\t\t\tsocket?.off(`get:${continuityKey}`, sendInitialPayload)\n\t\t\tsocket?.off(`tx-run:${continuityKey}`, fillTransactionRequest)\n\t\t}\n\t}\n}\n","import type { TransactionOutcomeEvent, TransactionToken } from \"atom.io\"\nimport { actUponStore, IMPLICIT } from \"atom.io/internal\"\nimport type { JsonIO } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type ActionReceiver = ReturnType<typeof realtimeActionReceiver>\nexport function realtimeActionReceiver({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function actionReceiver<F extends JsonIO>(\n\t\ttx: TransactionToken<F>,\n\t): () => void {\n\t\tconst fillTransactionRequest = (\n\t\t\tupdate: Pick<\n\t\t\t\tTransactionOutcomeEvent<TransactionToken<F>>,\n\t\t\t\t`id` | `params`\n\t\t\t>,\n\t\t) => {\n\t\t\tconst performanceKey = `tx-run:${tx.key}:${update.id}`\n\t\t\tconst performanceKeyStart = `${performanceKey}:start`\n\t\t\tconst performanceKeyEnd = `${performanceKey}:end`\n\t\t\tperformance.mark(performanceKeyStart)\n\t\t\tactUponStore<F>(store, tx, update.id)(...update.params)\n\t\t\tperformance.mark(performanceKeyEnd)\n\t\t\tconst metric = performance.measure(\n\t\t\t\tperformanceKey,\n\t\t\t\tperformanceKeyStart,\n\t\t\t\tperformanceKeyEnd,\n\t\t\t)\n\t\t\tstore?.logger.info(`🚀`, `transaction`, tx.key, update.id, metric.duration)\n\t\t}\n\t\tsocket.on(`tx-run:${tx.key}`, fillTransactionRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`tx-run:${tx.key}`, fillTransactionRequest)\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Canonical, Json } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>\nexport function realtimeAtomFamilyProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function familyProvider<\n\t\tJ extends Json.Serializable,\n\t\tK extends Canonical,\n\t>(\n\t\tfamily: AtomIO.RegularAtomFamilyToken<J, K>,\n\t\tindex: AtomIO.ReadableToken<Iterable<K>>,\n\t): () => void {\n\t\tconst unsubCallbacksByKey = new Map<string, () => void>()\n\n\t\tconst fillUnsubRequest = (key: string) => {\n\t\t\tsocket.off(`unsub:${key}`, fillUnsubRequest)\n\t\t\tconst unsub = unsubCallbacksByKey.get(key)\n\t\t\tif (unsub) {\n\t\t\t\tunsub()\n\t\t\t\tunsubCallbacksByKey.delete(key)\n\t\t\t}\n\t\t}\n\n\t\tconst fillSubRequest = (subKey: K) => {\n\t\t\tconst exposedSubKeys = getFromStore(store, index)\n\t\t\tfor (const exposedSubKey of exposedSubKeys) {\n\t\t\t\tif (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {\n\t\t\t\t\tconst token = findInStore(store, family, subKey)\n\t\t\t\t\tsocket.emit(`serve:${token.key}`, getFromStore(store, token))\n\t\t\t\t\tconst unsubscribe = subscribeToState(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t`expose-family:${family.key}:${socket.id}`,\n\t\t\t\t\t\t({ newValue }) => {\n\t\t\t\t\t\t\tsocket.emit(`serve:${token.key}`, newValue)\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tunsubCallbacksByKey.set(token.key, unsubscribe)\n\t\t\t\t\tsocket.on(`unsub:${token.key}`, () => {\n\t\t\t\t\t\tfillUnsubRequest(token.key)\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsocket.on(`sub:${family.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${family.key}`, fillSubRequest)\n\n\t\t\tfor (const [, unsub] of unsubCallbacksByKey) {\n\t\t\t\tunsub()\n\t\t\t}\n\t\t\tunsubCallbacksByKey.clear()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport {\n\tfindInStore,\n\tgetFromStore,\n\tgetJsonToken,\n\tgetUpdateToken,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Canonical } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type MutableFamilyProvider = ReturnType<\n\ttypeof realtimeMutableFamilyProvider\n>\nexport function realtimeMutableFamilyProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function mutableFamilyProvider<\n\t\tT extends Transceiver<any, any, any>,\n\t\tK extends Canonical,\n\t>(\n\t\tfamily: AtomIO.MutableAtomFamilyToken<T, K>,\n\t\tindex: AtomIO.ReadableToken<Iterable<K>>,\n\t): () => void {\n\t\tconst unsubCallbacksByKey = new Map<string, () => void>()\n\n\t\tconst fillUnsubRequest = (key: string) => {\n\t\t\tsocket.off(`unsub:${key}`, fillUnsubRequest)\n\t\t\tconst unsub = unsubCallbacksByKey.get(key)\n\t\t\tif (unsub) {\n\t\t\t\tunsub()\n\t\t\t\tunsubCallbacksByKey.delete(key)\n\t\t\t}\n\t\t}\n\n\t\tconst fillSubRequest = (subKey: K) => {\n\t\t\tconst exposedSubKeys = getFromStore(store, index)\n\t\t\tfor (const exposedSubKey of exposedSubKeys) {\n\t\t\t\tif (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {\n\t\t\t\t\tconst token = findInStore(store, family, subKey)\n\t\t\t\t\tgetFromStore(store, token)\n\t\t\t\t\tconst jsonToken = getJsonToken(store, token)\n\t\t\t\t\tconst updateToken = getUpdateToken(token)\n\t\t\t\t\tsocket.emit(`init:${token.key}`, getFromStore(store, jsonToken))\n\t\t\t\t\tconst unsubscribe = subscribeToState(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\tupdateToken,\n\t\t\t\t\t\t`expose-family:${family.key}:${socket.id}`,\n\t\t\t\t\t\t({ newValue }) => {\n\t\t\t\t\t\t\tsocket.emit(`next:${token.key}`, newValue)\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tunsubCallbacksByKey.set(token.key, unsubscribe)\n\t\t\t\t\tsocket.on(`unsub:${token.key}`, () => {\n\t\t\t\t\t\tfillUnsubRequest(token.key)\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsocket.on(`sub:${family.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${family.key}`, fillSubRequest)\n\t\t\tfor (const [, unsub] of unsubCallbacksByKey) {\n\t\t\t\tunsub()\n\t\t\t}\n\t\t\tunsubCallbacksByKey.clear()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport type { Transceiver } from \"atom.io/internal\"\nimport {\n\tgetFromStore,\n\tgetJsonToken,\n\tgetUpdateToken,\n\tIMPLICIT,\n\tsubscribeToState,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type MutableProvider = ReturnType<typeof realtimeMutableProvider>\nexport function realtimeMutableProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function mutableProvider<\n\t\tCore extends Transceiver<any, Json.Serializable, Json.Serializable>,\n\t>(token: AtomIO.MutableAtomToken<Core>): () => void {\n\t\tlet unsubscribeFromStateUpdates: (() => void) | null = null\n\n\t\tconst jsonToken = getJsonToken(store, token)\n\t\tconst trackerToken = getUpdateToken(token)\n\n\t\tconst fillUnsubRequest = () => {\n\t\t\tsocket.off(`unsub:${token.key}`, fillUnsubRequest)\n\t\t\tunsubscribeFromStateUpdates?.()\n\t\t\tunsubscribeFromStateUpdates = null\n\t\t}\n\n\t\tconst fillSubRequest = () => {\n\t\t\tsocket.emit(`init:${token.key}`, getFromStore(store, jsonToken))\n\t\t\tunsubscribeFromStateUpdates = subscribeToState(\n\t\t\t\tstore,\n\t\t\t\ttrackerToken,\n\t\t\t\t`expose-single:${socket.id}`,\n\t\t\t\t({ newValue }) => {\n\t\t\t\t\tsocket.emit(`next:${token.key}`, newValue)\n\t\t\t\t},\n\t\t\t)\n\t\t\tsocket.on(`unsub:${token.key}`, fillUnsubRequest)\n\t\t}\n\n\t\tsocket.on(`sub:${token.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${token.key}`, fillSubRequest)\n\t\t\tunsubscribeFromStateUpdates?.()\n\t\t}\n\t}\n}\n","import type * as AtomIO from \"atom.io\"\nimport { getFromStore, IMPLICIT, subscribeToState } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type StateProvider = ReturnType<typeof realtimeStateProvider>\nexport function realtimeStateProvider({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function stateProvider<J extends Json.Serializable>(\n\t\ttoken: AtomIO.WritableToken<J>,\n\t): () => void {\n\t\tlet unsubscribeFromStateUpdates: (() => void) | undefined\n\n\t\tconst fillSubRequest = () => {\n\t\t\tsocket.emit(`serve:${token.key}`, getFromStore(store, token))\n\n\t\t\tunsubscribeFromStateUpdates = subscribeToState(\n\t\t\t\tstore,\n\t\t\t\ttoken,\n\t\t\t\t`expose-single:${socket.id}`,\n\t\t\t\t({ newValue }) => {\n\t\t\t\t\tsocket.emit(`serve:${token.key}`, newValue)\n\t\t\t\t},\n\t\t\t)\n\n\t\t\tconst fillUnsubRequest = () => {\n\t\t\t\tsocket.off(`unsub:${token.key}`, fillUnsubRequest)\n\t\t\t\tif (unsubscribeFromStateUpdates) {\n\t\t\t\t\tunsubscribeFromStateUpdates()\n\t\t\t\t\tunsubscribeFromStateUpdates = undefined\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsocket.on(`unsub:${token.key}`, fillUnsubRequest)\n\t\t}\n\n\t\tsocket.on(`sub:${token.key}`, fillSubRequest)\n\n\t\treturn () => {\n\t\t\tsocket.off(`sub:${token.key}`, fillSubRequest)\n\t\t\tif (unsubscribeFromStateUpdates) {\n\t\t\t\tunsubscribeFromStateUpdates()\n\t\t\t\tunsubscribeFromStateUpdates = undefined\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { WritableToken } from \"atom.io\"\nimport { IMPLICIT, setIntoStore } from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\n\nimport type { ServerConfig } from \".\"\n\nexport type StateReceiver = ReturnType<typeof realtimeStateReceiver>\nexport function realtimeStateReceiver({\n\tsocket,\n\tstore = IMPLICIT.STORE,\n}: ServerConfig) {\n\treturn function stateReceiver<J extends Json.Serializable>(\n\t\ttoken: WritableToken<J>,\n\t): () => void {\n\t\tconst publish = (newValue: J) => {\n\t\t\tsetIntoStore(store, token, newValue)\n\t\t}\n\n\t\tconst fillPubUnclaim = () => {\n\t\t\tsocket.off(`pub:${token.key}`, publish)\n\t\t\tsocket.off(`unclaim:${token.key}`, fillPubUnclaim)\n\t\t}\n\t\tconst fillPubClaim = () => {\n\t\t\tsocket.on(`pub:${token.key}`, publish)\n\t\t\tsocket.on(`unclaim:${token.key}`, fillPubUnclaim)\n\t\t}\n\n\t\tsocket.on(`claim:${token.key}`, fillPubClaim)\n\n\t\treturn () => {\n\t\t\tsocket.off(`claim:${token.key}`, fillPubClaim)\n\t\t\tsocket.off(`pub:${token.key}`, publish)\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":[],"mappings":";;;;;;;KA6CY,gBAAA;;EAAZ,QAAY,CAAA,EAAA;IAAA,MAAA,CAAA,EAAA,OAAA;;QAKJ,EAAA,CAAA,KAAO,EAAA;IAAA,MAAA,EADL,QAAA,CAAS,MACJ;IAIf,IAAY,EAJJ,MAAA,CAAO,IAIH;IAAA,aAAA,EAAA,GAAA,GAAA,IAAA;QAAiC,IAAA;;AAC9B,KADH,8BAAA,GAAiC,gBAC9B,GAAA;EAEf,MAAY,EAFH,OAAA,CAAM,EAEH;CAAA;AACX,KADW,6BACX,CAAA,oBAAA,MAAA,CAAA,GAAA,gBAAA,GAAA;SAEQ,EAAA,QAAA,WAAA,GAAc,OAAA,CAAM,EAApB,EAAA;;AAAoB,KAIjB,iBAAA,GAJiB;EAI7B,IAAY,EAAA,MAAA;EAIZ,IAAY,EAFL,MAAA,CAAO,IAEF;CAAA;AAAqB,KAArB,kBAAA,GAAqB,iBAAA,GAAA;cAClB,EAAA,YAAA;aAGN,EAAA,GAAA,GAAA,IAAA;EAAA,aAAA,EAAA,GAAA,GAAA,IAAA;EAET,MAAY,EAFH,MAEG;AAKZ,CAAA;AAAY,KALA,yBAAA,GAKA;SAAqB,EAAA,GAAA,GAAA,IAAA;QACjB,GAAA,GAJH,kBAIG;CAAA;AAIJ,KALA,kBAAA,GAAqB,iBAKrB,GAAA;EAAA,OAAA,EAAA,GAAA,GAJI,OAIJ,CAAA,IAAA,CAAA;QACH,MAAA;;AACQ,KAFL,eAAA,GAEK;EAEjB,MAAY,EAHH,kBAGG;EAAA,QAAA,EAAA,GAAA,GAFK,OAEL,CAAA,IAAA,CAAA;;AACH,KADG,6BAAA,GAAgC,eACnC,GAAA;EAAA,MAAA,EAAA,yBAAA;AAET,CAAA;AAAY,KAAA,4BAAA,CAAA,oBAAA,MAAA,CAAA,GACX,eADW,GAAA;SACX,EACU,MADV,CACiB,WADjB,EAC8B,yBAD9B,CAAA;;AAC8B,cAGlB,uBAHkB,EAAA,CAAA,OAAA,EAIrB,gBAJqB,EAAA,GAK5B,kBAL4B;AAApB,cA0FE,uBA1FF,EAAA,CAAA,OAAA,EA2FD,8BA3FC,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,GA8FR,yBA9FQ;AAAA,cAqJE,YArJF,EAAA,CAAA,OAAA,EAsJD,8BAtJC,EAAA,GAuJR,6BAvJQ;AAGE,cAkKA,WAhKV,EAAA,CAAA,oBAAA,MAAA,CAAA,CAAA,OAAA,EAiKO,6BAjKP,CAiKqC,WAjKrC,CAAA,EAAA,GAkKA,4BAlKA,CAkK6B,WAlK7B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":[],"mappings":";;;;;;;KA6CY,gBAAA;;EAAZ,QAAY,CAAA,EAAA;IAAA,MAAA,CAAA,EAAA,OAAA;;QAKJ,EAAA,CAAA,KAAO,EAAA;YADL,QAAA,CAAS;IAKnB,IAAY,EAJJ,MAAA,CAAO,IAIH;IAAA,aAAA,EAAA,GAAA,GAAA,IAAA;QAAiC,IAAA;;KAAjC,8BAAA,GAAiC;EAG7C,MAAY,EAFH,OAAA,CAAM,EAEH;CAAA;AACX,KADW,6BACX,CAAA,oBAAA,MAAA,CAAA,GAAA,gBAAA,GAAA;SAEQ,EAAA,QAAA,WAAA,GAAc,OAAA,CAAM,EAApB,EAAA;;KAIG,iBAAA;EAAZ,IAAY,EAAA,MAAA;EAIZ,IAAY,EAFL,MAAA,CAAO,IAEF;CAAA;AAAqB,KAArB,kBAAA,GAAqB,iBAAA,GAAA;cAClB,EAAA,YAAA;aAGN,EAAA,GAAA,GAAA,IAAA;;EAET,MAAY,EAFH,MAEG;AAKZ,CAAA;AAAY,KALA,yBAAA,GAKA;SAAqB,EAAA,GAAA,GAAA,IAAA;QACjB,GAAA,GAJH,kBAIG;;AAIJ,KALA,kBAAA,GAAqB,iBAKrB,GAAA;EAAA,OAAA,EAAA,GAAA,GAJI,OAIJ,CAAA,IAAA,CAAA;QACH,MAAA;;KADG,eAAA;EAIZ,MAAY,EAHH,kBAGG;EAAA,QAAA,EAAA,GAAA,GAFK,OAEL,CAAA,IAAA,CAAA;;AACH,KADG,6BAAA,GAAgC,eACnC,GAAA;UAAA;AAET,CAAA;AAAY,KAAA,4BAAA,CAAA,oBAAA,MAAA,CAAA,GACX,eADW,GAAA;SACX,EACU,MADV,CACiB,WADjB,EAC8B,yBAD9B,CAAA;;AAC8B,cAGlB,uBAHkB,EAAA,CAAA,OAAA,EAIrB,gBAJqB,EAAA,GAK5B,kBAL4B;AAApB,cA0FE,uBA1FF,EAAA,CAAA,OAAA,EA2FD,8BA3FC,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,GA8FR,yBA9FQ;cAqJE,wBACH,mCACP;AApJU,cAkKA,WAhKV,EAAA,CAAA,oBAAA,MAAA,CAAA,CAAA,OAAA,EAiKO,6BAjKP,CAiKqC,WAjKrC,CAAA,EAAA,GAkKA,4BAlKA,CAkK6B,WAlK7B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["userKey: string | null","socket: ClientSocket"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":["import * as http from \"node:http\"\n\nimport type { RenderResult } from \"@testing-library/react\"\nimport { prettyDOM, render } from \"@testing-library/react\"\nimport * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport {\n\tclearStore,\n\teditRelationsInStore,\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport { toEntries } from \"atom.io/json\"\nimport * as AR from \"atom.io/react\"\nimport * as RT from \"atom.io/realtime\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as RTR from \"atom.io/realtime-react\"\nimport * as RTS from \"atom.io/realtime-server\"\nimport * as Happy from \"happy-dom\"\nimport * as React from \"react\"\nimport * as SocketIO from \"socket.io\"\nimport type { Socket as ClientSocket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nlet testNumber = 0\n\n/* eslint-disable no-console */\n\nfunction prefixLogger(store: Store, prefix: string) {\n\tstore.loggers[0] = new AtomIO.AtomIOLogger(`info`, undefined, {\n\t\tinfo: (...args) => {\n\t\t\tconsole.info(prefix, ...args)\n\t\t},\n\t\twarn: (...args) => {\n\t\t\tconsole.warn(prefix, ...args)\n\t\t},\n\t\terror: (...args) => {\n\t\t\tconsole.error(prefix, ...args)\n\t\t},\n\t})\n}\n\nexport type TestSetupOptions = {\n\tport: number\n\timmortal?: { server?: boolean }\n\tserver: (tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}) => void\n}\nexport type TestSetupOptions__SingleClient = TestSetupOptions & {\n\tclient: React.FC\n}\nexport type TestSetupOptions__MultiClient<ClientNames extends string> =\n\tTestSetupOptions & {\n\t\tclients: {\n\t\t\t[K in ClientNames]: React.FC\n\t\t}\n\t}\n\nexport type RealtimeTestTools = {\n\tname: string\n\tsilo: AtomIO.Silo\n}\nexport type RealtimeTestClient = RealtimeTestTools & {\n\trenderResult: RenderResult\n\tprettyPrint: () => void\n\tenableLogging: () => void\n\tsocket: ClientSocket\n}\nexport type RealtimeTestClientBuilder = {\n\tdispose: () => void\n\tinit: () => RealtimeTestClient\n}\n\nexport type RealtimeTestServer = RealtimeTestTools & {\n\tdispose: () => Promise<void>\n\tport: number\n}\n\nexport type RealtimeTestAPI = {\n\tserver: RealtimeTestServer\n\tteardown: () => Promise<void>\n}\nexport type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {\n\tclient: RealtimeTestClientBuilder\n}\nexport type RealtimeTestAPI__MultiClient<ClientNames extends string> =\n\tRealtimeTestAPI & {\n\t\tclients: Record<ClientNames, RealtimeTestClientBuilder>\n\t}\n\nexport const setupRealtimeTestServer = (\n\toptions: TestSetupOptions,\n): RealtimeTestServer => {\n\t++testNumber\n\tconst silo = new AtomIO.Silo(\n\t\t{\n\t\t\tname: `SERVER-${testNumber}`,\n\t\t\tlifespan: options.immortal?.server ? `immortal` : `ephemeral`,\n\t\t},\n\t\tIMPLICIT.STORE,\n\t)\n\tconst socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)\n\n\tconst httpServer = http.createServer((_, res) => res.end(`Hello World!`))\n\tconst address = httpServer.listen(options.port).address()\n\tconst port =\n\t\ttypeof address === `string` ? null : address === null ? null : address.port\n\tif (port === null) throw new Error(`Could not determine port for test server`)\n\n\tconst server = new SocketIO.Server(httpServer).use((socket, next) => {\n\t\tconst { token, username } = socket.handshake.auth\n\t\tif (token === `test` && socket.id) {\n\t\t\tconst userClaim = socketRealm.allocate(`root`, `user::${username}`)\n\t\t\tconst socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`)\n\t\t\tconst socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim)\n\t\t\tsetIntoStore(silo.store, socketState, socket)\n\t\t\teditRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.set(userClaim, socketClaim)\n\t\t\t\t},\n\t\t\t\tsilo.store,\n\t\t\t)\n\t\t\tsetIntoStore(silo.store, RTS.userIndex, (index) => index.add(userClaim))\n\t\t\tsetIntoStore(silo.store, RTS.socketIndex, (index) =>\n\t\t\t\tindex.add(socketClaim),\n\t\t\t)\n\t\t\t// console.log(`${username} connected on ${socket.id}`)\n\t\t\tnext()\n\t\t} else {\n\t\t\tnext(new Error(`Authentication error`))\n\t\t}\n\t})\n\n\tserver.on(`connection`, (socket: SocketIO.Socket) => {\n\t\tlet userKey: string | null = null\n\t\tfunction enableLogging() {\n\t\t\tconst userKeyState = findRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t`socket::${socket.id}`,\n\t\t\t\tsilo.store,\n\t\t\t).userKeyOfSocket\n\t\t\tuserKey = getFromStore(silo.store, userKeyState)\n\t\t\tprefixLogger(silo.store, `server`)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 `, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 >>`, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.on(`disconnect`, () => {\n\t\t\t\tconsole.log(`${userKey} disconnected`)\n\t\t\t})\n\t\t}\n\t\toptions.server({ socket, enableLogging, silo })\n\t})\n\n\tconst dispose = async () => {\n\t\tawait server.close()\n\t\tconst roomKeys = getFromStore(silo.store, RT.roomIndex)\n\t\tfor (const roomKey of roomKeys) {\n\t\t\tconst roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)\n\t\t\tconst room = getFromStore(silo.store, roomState)\n\t\t\tif (room && !(room instanceof Promise)) {\n\t\t\t\troom.process.kill()\n\t\t\t}\n\t\t}\n\t\tsilo.store.valueMap.clear()\n\t}\n\n\treturn {\n\t\tname: `SERVER`,\n\t\tsilo,\n\t\tdispose,\n\t\tport,\n\t}\n}\nexport const setupRealtimeTestClient = (\n\toptions: TestSetupOptions__SingleClient,\n\tname: string,\n\tport: number,\n): RealtimeTestClientBuilder => {\n\tconst testClient = { dispose: () => {} }\n\tconst init = () => {\n\t\tconst socket: ClientSocket = io(`http://localhost:${port}/`, {\n\t\t\tauth: { token: `test`, username: `${name}-${testNumber}` },\n\t\t})\n\t\tconst silo = new AtomIO.Silo({ name, lifespan: `ephemeral` }, IMPLICIT.STORE)\n\t\tsilo.setState(RTC.myUsernameState, `${name}-${testNumber}`)\n\n\t\tconst { document } = new Happy.Window()\n\t\tdocument.body.innerHTML = `<div id=\"app\"></div>`\n\t\tconst renderResult = render(\n\t\t\t<AR.StoreProvider store={silo.store}>\n\t\t\t\t<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t\t<options.client />\n\t\t\t\t</RTR.RealtimeProvider>\n\t\t\t</AR.StoreProvider>,\n\t\t\t{\n\t\t\t\tcontainer: document.querySelector(`#app`) as unknown as HTMLElement,\n\t\t\t},\n\t\t)\n\n\t\tconst prettyPrint = () => {\n\t\t\tconsole.log(prettyDOM(renderResult.container))\n\t\t}\n\n\t\tconst enableLogging = () => {\n\t\t\tprefixLogger(silo.store, name)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`📡 `, name, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`📡 >>`, name, event, ...args)\n\t\t\t})\n\t\t}\n\n\t\tconst dispose = () => {\n\t\t\trenderResult.unmount()\n\t\t\tsocket.disconnect()\n\t\t\tclearStore(silo.store)\n\t\t}\n\t\ttestClient.dispose = dispose\n\n\t\treturn {\n\t\t\tname,\n\t\t\tsilo,\n\t\t\tsocket,\n\t\t\trenderResult,\n\t\t\tprettyPrint,\n\t\t\tenableLogging,\n\t\t}\n\t}\n\treturn Object.assign(testClient, { init })\n}\n\nexport const singleClient = (\n\toptions: TestSetupOptions__SingleClient,\n): RealtimeTestAPI__SingleClient => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst client = setupRealtimeTestClient(options, `CLIENT`, server.port)\n\n\treturn {\n\t\tclient,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tclient.dispose()\n\t\t},\n\t}\n}\n\nexport const multiClient = <ClientNames extends string>(\n\toptions: TestSetupOptions__MultiClient<ClientNames>,\n): RealtimeTestAPI__MultiClient<ClientNames> => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst clients = toEntries(options.clients).reduce(\n\t\t(clientRecord, [name, client]) => {\n\t\t\tclientRecord[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clientRecord\n\t\t},\n\t\t{} as Record<ClientNames, RealtimeTestClientBuilder>,\n\t)\n\n\treturn {\n\t\tclients,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tfor (const [, client] of toEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["userKey: string | null","socket: ClientSocket"],"sources":["../../src/realtime-testing/setup-realtime-test.tsx"],"sourcesContent":["import * as http from \"node:http\"\n\nimport type { RenderResult } from \"@testing-library/react\"\nimport { prettyDOM, render } from \"@testing-library/react\"\nimport * as AtomIO from \"atom.io\"\nimport type { Store } from \"atom.io/internal\"\nimport {\n\tclearStore,\n\teditRelationsInStore,\n\tfindInStore,\n\tfindRelationsInStore,\n\tgetFromStore,\n\tIMPLICIT,\n\tsetIntoStore,\n} from \"atom.io/internal\"\nimport { toEntries } from \"atom.io/json\"\nimport * as AR from \"atom.io/react\"\nimport * as RT from \"atom.io/realtime\"\nimport * as RTC from \"atom.io/realtime-client\"\nimport * as RTR from \"atom.io/realtime-react\"\nimport * as RTS from \"atom.io/realtime-server\"\nimport * as Happy from \"happy-dom\"\nimport * as React from \"react\"\nimport * as SocketIO from \"socket.io\"\nimport type { Socket as ClientSocket } from \"socket.io-client\"\nimport { io } from \"socket.io-client\"\n\nlet testNumber = 0\n\n/* eslint-disable no-console */\n\nfunction prefixLogger(store: Store, prefix: string) {\n\tstore.loggers[0] = new AtomIO.AtomIOLogger(`info`, undefined, {\n\t\tinfo: (...args) => {\n\t\t\tconsole.info(prefix, ...args)\n\t\t},\n\t\twarn: (...args) => {\n\t\t\tconsole.warn(prefix, ...args)\n\t\t},\n\t\terror: (...args) => {\n\t\t\tconsole.error(prefix, ...args)\n\t\t},\n\t})\n}\n\nexport type TestSetupOptions = {\n\tport: number\n\timmortal?: { server?: boolean }\n\tserver: (tools: {\n\t\tsocket: SocketIO.Socket\n\t\tsilo: AtomIO.Silo\n\t\tenableLogging: () => void\n\t}) => void\n}\nexport type TestSetupOptions__SingleClient = TestSetupOptions & {\n\tclient: React.FC\n}\nexport type TestSetupOptions__MultiClient<ClientNames extends string> =\n\tTestSetupOptions & {\n\t\tclients: {\n\t\t\t[K in ClientNames]: React.FC\n\t\t}\n\t}\n\nexport type RealtimeTestTools = {\n\tname: string\n\tsilo: AtomIO.Silo\n}\nexport type RealtimeTestClient = RealtimeTestTools & {\n\trenderResult: RenderResult\n\tprettyPrint: () => void\n\tenableLogging: () => void\n\tsocket: ClientSocket\n}\nexport type RealtimeTestClientBuilder = {\n\tdispose: () => void\n\tinit: () => RealtimeTestClient\n}\n\nexport type RealtimeTestServer = RealtimeTestTools & {\n\tdispose: () => Promise<void>\n\tport: number\n}\n\nexport type RealtimeTestAPI = {\n\tserver: RealtimeTestServer\n\tteardown: () => Promise<void>\n}\nexport type RealtimeTestAPI__SingleClient = RealtimeTestAPI & {\n\tclient: RealtimeTestClientBuilder\n}\nexport type RealtimeTestAPI__MultiClient<ClientNames extends string> =\n\tRealtimeTestAPI & {\n\t\tclients: Record<ClientNames, RealtimeTestClientBuilder>\n\t}\n\nexport const setupRealtimeTestServer = (\n\toptions: TestSetupOptions,\n): RealtimeTestServer => {\n\t++testNumber\n\tconst silo = new AtomIO.Silo(\n\t\t{\n\t\t\tname: `SERVER-${testNumber}`,\n\t\t\tlifespan: options.immortal?.server ? `immortal` : `ephemeral`,\n\t\t},\n\t\tIMPLICIT.STORE,\n\t)\n\tconst socketRealm = new AtomIO.Realm<RTS.SocketSystemHierarchy>(silo.store)\n\n\tconst httpServer = http.createServer((_, res) => res.end(`Hello World!`))\n\tconst address = httpServer.listen(options.port).address()\n\tconst port =\n\t\ttypeof address === `string` ? null : address === null ? null : address.port\n\tif (port === null) throw new Error(`Could not determine port for test server`)\n\n\tconst server = new SocketIO.Server(httpServer).use((socket, next) => {\n\t\tconst { token, username } = socket.handshake.auth\n\t\tif (token === `test` && socket.id) {\n\t\t\tconst userClaim = socketRealm.allocate(`root`, `user::${username}`)\n\t\t\tconst socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`)\n\t\t\tconst socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim)\n\t\t\tsetIntoStore(silo.store, socketState, socket)\n\t\t\teditRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t(relations) => {\n\t\t\t\t\trelations.set(userClaim, socketClaim)\n\t\t\t\t},\n\t\t\t\tsilo.store,\n\t\t\t)\n\t\t\tsetIntoStore(silo.store, RTS.userIndex, (index) => index.add(userClaim))\n\t\t\tsetIntoStore(silo.store, RTS.socketIndex, (index) =>\n\t\t\t\tindex.add(socketClaim),\n\t\t\t)\n\t\t\t// console.log(`${username} connected on ${socket.id}`)\n\t\t\tnext()\n\t\t} else {\n\t\t\tnext(new Error(`Authentication error`))\n\t\t}\n\t})\n\n\tserver.on(`connection`, (socket: SocketIO.Socket) => {\n\t\tlet userKey: string | null = null\n\t\tfunction enableLogging() {\n\t\t\tconst userKeyState = findRelationsInStore(\n\t\t\t\tRTS.usersOfSockets,\n\t\t\t\t`socket::${socket.id}`,\n\t\t\t\tsilo.store,\n\t\t\t).userKeyOfSocket\n\t\t\tuserKey = getFromStore(silo.store, userKeyState)\n\t\t\tprefixLogger(silo.store, `server`)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 `, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`🛰 >>`, userKey, event, ...args)\n\t\t\t})\n\t\t\tsocket.on(`disconnect`, () => {\n\t\t\t\tconsole.log(`${userKey} disconnected`)\n\t\t\t})\n\t\t}\n\t\toptions.server({ socket, enableLogging, silo })\n\t})\n\n\tconst dispose = async () => {\n\t\tawait server.close()\n\t\tconst roomKeys = getFromStore(silo.store, RT.roomIndex)\n\t\tfor (const roomKey of roomKeys) {\n\t\t\tconst roomState = findInStore(silo.store, RTS.roomSelectors, roomKey)\n\t\t\tconst room = getFromStore(silo.store, roomState)\n\t\t\tif (room && !(room instanceof Promise)) {\n\t\t\t\troom.process.kill()\n\t\t\t}\n\t\t}\n\t\tsilo.store.valueMap.clear()\n\t}\n\n\treturn {\n\t\tname: `SERVER`,\n\t\tsilo,\n\t\tdispose,\n\t\tport,\n\t}\n}\nexport const setupRealtimeTestClient = (\n\toptions: TestSetupOptions__SingleClient,\n\tname: string,\n\tport: number,\n): RealtimeTestClientBuilder => {\n\tconst testClient = { dispose: () => {} }\n\tconst init = () => {\n\t\tconst socket: ClientSocket = io(`http://localhost:${port}/`, {\n\t\t\tauth: { token: `test`, username: `${name}-${testNumber}` },\n\t\t})\n\t\tconst silo = new AtomIO.Silo({ name, lifespan: `ephemeral` }, IMPLICIT.STORE)\n\t\tsilo.setState(RTC.myUsernameState, `${name}-${testNumber}`)\n\n\t\tconst { document } = new Happy.Window()\n\t\tdocument.body.innerHTML = `<div id=\"app\"></div>`\n\t\tconst renderResult = render(\n\t\t\t<AR.StoreProvider store={silo.store}>\n\t\t\t\t<RTR.RealtimeProvider socket={socket}>\n\t\t\t\t\t<options.client />\n\t\t\t\t</RTR.RealtimeProvider>\n\t\t\t</AR.StoreProvider>,\n\t\t\t{\n\t\t\t\tcontainer: document.querySelector(`#app`) as unknown as HTMLElement,\n\t\t\t},\n\t\t)\n\n\t\tconst prettyPrint = () => {\n\t\t\tconsole.log(prettyDOM(renderResult.container))\n\t\t}\n\n\t\tconst enableLogging = () => {\n\t\t\tprefixLogger(silo.store, name)\n\t\t\tsocket.onAny((event, ...args) => {\n\t\t\t\tconsole.log(`📡 `, name, event, ...args)\n\t\t\t})\n\t\t\tsocket.onAnyOutgoing((event, ...args) => {\n\t\t\t\tconsole.log(`📡 >>`, name, event, ...args)\n\t\t\t})\n\t\t}\n\n\t\tconst dispose = () => {\n\t\t\trenderResult.unmount()\n\t\t\tsocket.disconnect()\n\t\t\tclearStore(silo.store)\n\t\t}\n\t\ttestClient.dispose = dispose\n\n\t\treturn {\n\t\t\tname,\n\t\t\tsilo,\n\t\t\tsocket,\n\t\t\trenderResult,\n\t\t\tprettyPrint,\n\t\t\tenableLogging,\n\t\t}\n\t}\n\treturn Object.assign(testClient, { init })\n}\n\nexport const singleClient = (\n\toptions: TestSetupOptions__SingleClient,\n): RealtimeTestAPI__SingleClient => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst client = setupRealtimeTestClient(options, `CLIENT`, server.port)\n\n\treturn {\n\t\tclient,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tclient.dispose()\n\t\t},\n\t}\n}\n\nexport const multiClient = <ClientNames extends string>(\n\toptions: TestSetupOptions__MultiClient<ClientNames>,\n): RealtimeTestAPI__MultiClient<ClientNames> => {\n\tconst server = setupRealtimeTestServer(options)\n\tconst clients = toEntries(options.clients).reduce(\n\t\t(clientRecord, [name, client]) => {\n\t\t\tclientRecord[name] = setupRealtimeTestClient(\n\t\t\t\t{ ...options, client },\n\t\t\t\tname,\n\t\t\t\tserver.port,\n\t\t\t)\n\t\t\treturn clientRecord\n\t\t},\n\t\t{} as Record<ClientNames, RealtimeTestClientBuilder>,\n\t)\n\n\treturn {\n\t\tclients,\n\t\tserver,\n\t\tteardown: async () => {\n\t\t\tawait server.dispose()\n\t\t\tfor (const [, client] of toEntries(clients)) {\n\t\t\t\tclient.dispose()\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":[],"mappings":";;;;KAKY,aAAA;AAAA,KACA,SAAA,GADA,GACe,aADf,IAAA,MAAA,EAAA;AACA,KACA,iBAAA,GADe,GAAA,MAAA,IACkB,SADlB,EAAA;AACf,UAEK,UAFL,CAAA,UAE0B,SAFO,CAAA,SAEY,WAFZ,CAEwB,CAFxB,CAAA,CAAA;EAE7C,SAAiB,KAAA,EACA,aADA,CACc,iBADd,GAAA,IAAA,CAAA;EAAA,SAAA,UAAA,EAAA,MAAA;WAAqB,QAAA,EAAA,MAAA;WAA+B,iBAAA,EAAA,MAAA;;AACpD,UAMA,UANA,CAAA,UAMqB,SANrB,CAAA,SAMwC,IAAA,CAAK,MAN7C,CAAA;SADwC,EAQ/C,CAR+C,EAAA;EAAA,KAAA,EAAA,CAShD,iBATgD,GAAA,IAAA,CAAA,EAAA;EAOzD,UAAiB,EAAA,MAAA;EAAA,QAAA,EAAA,MAAA;mBAAqB,EAAA,MAAA;;AAE7B,cAKI,MALJ,CAAA,UAKqB,SALrB,CAAA,SAMA,GANA,CAMI,CANJ,CAAA,YAQP,WARO,CAQK,UARL,CAQgB,CARhB,CAAA,EAQoB,iBARpB,EAQuC,UARvC,CAQkD,CARlD,CAAA,CAAA,EASP,OATO,CAAA;QAWK,eAbgD;EAAA,SAAA,OAAA,EAcpC,OAdoC,CAc5B,SAd4B,CAAA;EAO9D,UAAa,EAAA,MAAA;EAAA,KAAA,EAAA,CASG,iBATH,GAAA,IAAA,CAAA,EAAA;UAAiB,EAAA,MAAA;mBACjB,EAAA,MAAA;aAEY,CAAA,MAAA,CAAA,EAUI,QAVJ,CAUa,CAVb,CAAA,EAAA,UAAA,CAAA,EAAA,MAAA;WAAX,aAAA,EA2BkB,UA3BlB,CA2B6B,CA3B7B,CAAA;QAAe,CAAA,CAAA,EA6BX,UA7BW,CA6BA,CA7BA,CAAA;SAA8B,QAAA,CAAA,UAuCzB,SAvCyB,CAAA,CAAA,IAAA,EAuCR,UAvCQ,CAuCG,CAvCH,CAAA,CAAA,EAuCQ,MAvCR,CAuCe,CAvCf,CAAA;WAAX,EA+C7B,CA/C6B,CAAA,EAAA,IAAA;SAGlC,EAAA,IAAA;QACoB,CAAA,KAAA,EA6DZ,CA7DY,CAAA,EAAA,OAAA;WAAR,MAAA,EAsED,MAtEC,CAsEM,CAtEN,CAAA,GAAA,IAAA;SAuEX,MArEC,CAqEM,CArEN,CAAA,GAAA,IAAA;oBAIsB,EAkEV,SAlEU,EAAA,GAAA,IAAA;aAAT,CAAA,GAAA,EAAA,CAAA,KAAA,EAmEI,MAnEJ,CAmEW,CAnEX,CAAA,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA;YAiBc,UAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAmF5B,SAnF4B,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;WAAX,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAyFjB,iBAzFiB,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;aAEH,EA8FR,SA9FQ,CAAA,EAAA,IAAA;UAAX,MAAA;iBAUgB,CAAA,MAAA,EA6GF,iBA7GE,CAAA,EAAA,MAAA;WAA4B,EAkH3C,iBAlH2C,CAAA,EAAA,MAAA,GAAA,cAAA,GAAA,IAAA;UAAX,CAAA,MAAA,EA6J1B,SA7J0B,CAAA,EAAA,IAAA;aAAuB,EAsLrD,iBAtLqD,CAAA,EAAA,MAAA,GAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":[],"mappings":";;;;KAKY,aAAA;AAAA,KACA,SAAA,GADA,GACe,aADf,IAAA,MAAA,EAAA;AACA,KACA,iBAAA,GADe,GAAA,MAAA,IACkB,SADlB,EAAA;AACf,UAEK,UAFL,CAAA,UAE0B,SAFO,CAAA,SAEY,WAFZ,CAEwB,CAFxB,CAAA,CAAA;EAE7C,SAAiB,KAAA,EACA,aADA,CACc,iBADd,GAAA,IAAA,CAAA;EAAA,SAAA,UAAA,EAAA,MAAA;WAAqB,QAAA,EAAA,MAAA;WAA+B,iBAAA,EAAA,MAAA;;AACpD,UAMA,UANA,CAAA,UAMqB,SANrB,CAAA,SAMwC,IAAA,CAAK,MAN7C,CAAA;SADwC,EAQ/C,CAR+C,EAAA;UAShD;EAFT,UAAiB,EAAA,MAAA;EAAA,QAAA,EAAA,MAAA;mBAAqB,EAAA,MAAA;;AAE7B,cAKI,MALJ,CAAA,UAKqB,SALrB,CAAA,SAMA,GANA,CAMI,CANJ,CAAA,YAQP,WARO,CAQK,UARL,CAQgB,CARhB,CAAA,EAQoB,iBARpB,EAQuC,UARvC,CAQkD,CARlD,CAAA,CAAA,EASP,OATO,CAAA;QAWK,eAbgD;oBAcpC,QAAQ;EAPlC,UAAa,EAAA,MAAA;EAAA,KAAA,EAAA,CASG,iBATH,GAAA,IAAA,CAAA,EAAA;UAAiB,EAAA,MAAA;mBACjB,EAAA,MAAA;aAEY,CAAA,MAAA,CAAA,EAUI,QAVJ,CAUa,CAVb,CAAA,EAAA,UAAA,CAAA,EAAA,MAAA;WAAX,aAAA,EA2BkB,UA3BlB,CA2B6B,CA3B7B,CAAA;QAAe,CAAA,CAAA,EA6BX,UA7BW,CA6BA,CA7BA,CAAA;SAA8B,QAAA,CAAA,UAuCzB,SAvCyB,CAAA,CAAA,IAAA,EAuCR,UAvCQ,CAuCG,CAvCH,CAAA,CAAA,EAuCQ,MAvCR,CAuCe,CAvCf,CAAA;WAAX,EA+C7B,CA/C6B,CAAA,EAAA,IAAA;SAGlC,EAAA,IAAA;QACoB,CAAA,KAAA,EA6DZ,CA7DY,CAAA,EAAA,OAAA;WAAR,MAAA,EAsED,MAtEC,CAsEM,CAtEN,CAAA,GAAA,IAAA;SAuEX,MArEC,CAqEM,CArEN,CAAA,GAAA,IAAA;oBAIsB,EAkEV,SAlEU,EAAA,GAAA,IAAA;aAAT,CAAA,GAAA,EAAA,CAAA,KAAA,EAmEI,MAnEJ,CAmEW,CAnEX,CAAA,EAAA,GAAA,OAAA,CAAA,EAAA,IAAA;YAiBc,UAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAmF5B,SAnF4B,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;WAAX,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAyFjB,iBAzFiB,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;aAEH,EA8FR,SA9FQ,CAAA,EAAA,IAAA;UAAX,MAAA;iBAUgB,CAAA,MAAA,EA6GF,iBA7GE,CAAA,EAAA,MAAA;WAA4B,EAkH3C,iBAlH2C,CAAA,EAAA,MAAA,GAAA,cAAA,GAAA,IAAA;UAAX,CAAA,MAAA,EA6J1B,SA7J0B,CAAA,EAAA,IAAA;aAAuB,EAsLrD,iBAtLqD,CAAA,EAAA,MAAA,GAAA,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdateType = `add` | `clear` | `del` | `tx`\nexport type SetUpdate = `${SetUpdateType}:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXView<P extends primitive> extends ReadonlySet<P> {\n\treadonly cache: ReadonlyArray<NumberedSetUpdate | null>\n\treadonly cacheLimit: number\n\treadonly cacheIdx: number\n\treadonly cacheUpdateNumber: number\n}\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements\n\t\tTransceiver<SetRTXView<P>, NumberedSetUpdate, SetRTXJson<P>>,\n\t\tLineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<SetUpdate> = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: SetRTXView<P> = this\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null = null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\t/* eslint-disable-next-line no-console */\n\t\t\tconsole.warn(\n\t\t\t\t`Did not apply transaction to SetRTX; this error was thrown:`,\n\t\t\t\tthrown,\n\t\t\t)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) => {\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`)\n\t\t})\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as SetUpdateType\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const subUpdate of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(subUpdate as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdate): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst u = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!u) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(u)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as SetUpdateType\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/set-rtx/set-rtx.ts"],"sourcesContent":["import type { Lineage, Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdateType = `add` | `clear` | `del` | `tx`\nexport type SetUpdate = `${SetUpdateType}:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXView<P extends primitive> extends ReadonlySet<P> {\n\treadonly cache: ReadonlyArray<NumberedSetUpdate | null>\n\treadonly cacheLimit: number\n\treadonly cacheIdx: number\n\treadonly cacheUpdateNumber: number\n}\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements\n\t\tTransceiver<SetRTXView<P>, NumberedSetUpdate, SetRTXJson<P>>,\n\t\tLineage\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<SetUpdate> = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Iterable<P>, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: SetRTXView<P> = this\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tconst result = super.add(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic clear(): void {\n\t\tconst capturedContents = this.mode === `record` ? [...this] : null\n\t\tsuper.clear()\n\t\tif (capturedContents) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify(capturedContents)}`)\n\t\t}\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tconst result = super.delete(value)\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null = null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\t/* eslint-disable-next-line no-console */\n\t\t\tconsole.warn(\n\t\t\t\t`Did not apply transaction to SetRTX; this error was thrown:`,\n\t\t\t\tthrown,\n\t\t\t)\n\t\t\tthrow thrown\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) => {\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`)\n\t\t})\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as SetUpdateType\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const subUpdate of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(subUpdate as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic getUpdateNumber(update: NumberedSetUpdate): number {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\treturn Number(update.substring(0, breakpoint))\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t}\n\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\tif (cachedUpdate === update) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthis.mode = `playback`\n\t\t\tlet done = false\n\t\t\twhile (!done) {\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tconst u = this.cache[this.cacheIdx]\n\t\t\t\tthis.cacheIdx--\n\t\t\t\tif (!u) {\n\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t}\n\t\t\t\tthis.undo(u)\n\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t}\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.doStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\treturn null\n\t\t}\n\t\treturn `OUT_OF_RANGE`\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as SetUpdateType\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const v of values) this.add(v)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/web/persist-sync.ts"],"sourcesContent":["import type { AtomEffect, ViewOf } from \"atom.io\"\n\nexport type StringInterface<T> = {\n\tstringify: (t: ViewOf<T>) => string\n\tparse: (s: string) => T\n}\n\nexport const persistSync =\n\t<T>(\n\t\tstorage: Storage,\n\t\t{ stringify, parse }: StringInterface<T>,\n\t\tkey: string,\n\t): AtomEffect<T> =>\n\t({ setSelf, onSet }) => {\n\t\tconst savedValue = storage.getItem(key)\n\t\tif (savedValue != null) setSelf(parse(savedValue))\n\n\t\tonSet(({ newValue }) => {\n\t\t\tif (newValue == null) {\n\t\t\t\tstorage.removeItem(key)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tstorage.setItem(key, stringify(newValue))\n\t\t})\n\t}\n"],"mappings":";AAOA,MAAa,eAEX,SACA,EAAE,WAAW,OAA2B,EACxC,SAEA,EAAE,SAAS,OAAO,KAAK;CACvB,MAAM,aAAa,QAAQ,QAAQ;AACnC,KAAI,cAAc,KAAM,SAAQ,MAAM;AAEtC,QAAO,EAAE,UAAU,KAAK;AACvB,MAAI,YAAY,MAAM;AACrB,WAAQ,WAAW;AACnB;EACA;AACD,UAAQ,QAAQ,KAAK,UAAU;CAC/B;AACD"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/web/persist-sync.ts"],"sourcesContent":["import type { AtomEffect, ViewOf } from \"atom.io\"\n\nexport type StringInterface<T> = {\n\tstringify: (t: ViewOf<T>) => string\n\tparse: (s: string) => T\n}\n\nexport const persistSync =\n\t<T>(\n\t\tstorage: Storage,\n\t\t{ stringify, parse }: StringInterface<T>,\n\t\tkey: string,\n\t): AtomEffect<T> =>\n\t({ setSelf, onSet }) => {\n\t\tconst savedValue = storage.getItem(key)\n\t\tif (savedValue != null) setSelf(parse(savedValue))\n\n\t\tonSet(({ newValue }) => {\n\t\t\tif (newValue == null) {\n\t\t\t\tstorage.removeItem(key)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tstorage.setItem(key, stringify(newValue))\n\t\t})\n\t}\n"],"mappings":";AAOA,MAAa,eAEX,SACA,EAAE,WAAW,SACb,SAEA,EAAE,SAAS,YAAY;CACvB,MAAM,aAAa,QAAQ,QAAQ;AACnC,KAAI,cAAc,KAAM,SAAQ,MAAM;AAEtC,QAAO,EAAE,eAAe;AACvB,MAAI,YAAY,MAAM;AACrB,WAAQ,WAAW;AACnB;;AAED,UAAQ,QAAQ,KAAK,UAAU"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.38.2",
3
+ "version": "0.39.1",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -65,21 +65,21 @@
65
65
  "@storybook/addon-onboarding": "9.1.3",
66
66
  "@storybook/react-vite": "9.1.3",
67
67
  "@testing-library/react": "16.3.0",
68
- "@types/bun": "npm:bun-types@1.2.20",
68
+ "@types/bun": "npm:bun-types@1.2.21",
69
69
  "@types/eslint": "9.6.1",
70
70
  "@types/estree": "1.0.8",
71
71
  "@types/http-proxy": "1.17.16",
72
72
  "@types/npmlog": "7.0.0",
73
73
  "@types/react": "19.1.11",
74
74
  "@types/tmp": "0.2.6",
75
- "@typescript-eslint/parser": "8.40.0",
76
- "@typescript-eslint/rule-tester": "8.40.0",
77
- "@typescript-eslint/utils": "8.40.0",
75
+ "@typescript-eslint/parser": "8.41.0",
76
+ "@typescript-eslint/rule-tester": "8.41.0",
77
+ "@typescript-eslint/utils": "8.41.0",
78
78
  "@vitest/coverage-v8": "3.2.4",
79
79
  "@vitest/ui": "3.2.4",
80
- "concurrently": "9.2.0",
80
+ "concurrently": "9.2.1",
81
81
  "drizzle-kit": "0.31.4",
82
- "drizzle-orm": "0.44.4",
82
+ "drizzle-orm": "0.44.5",
83
83
  "eslint": "9.34.0",
84
84
  "happy-dom": "18.0.1",
85
85
  "http-proxy": "1.18.1",
@@ -96,8 +96,7 @@
96
96
  "socket.io-client": "4.8.1",
97
97
  "storybook": "9.1.3",
98
98
  "tmp": "0.2.5",
99
- "tsdown": "0.14.1",
100
- "tsx": "4.20.4",
99
+ "tsdown": "0.14.2",
101
100
  "typescript": "5.9.2",
102
101
  "vite": "7.1.3",
103
102
  "vite-tsconfig-paths": "5.1.4",
@@ -177,7 +176,7 @@
177
176
  }
178
177
  },
179
178
  "scripts": {
180
- "manifest": "tsx __scripts__/manifest-build.node.ts",
179
+ "manifest": "./__scripts__/manifest-build.node.ts",
181
180
  "build": "tsdown && bun ./__scripts__/build-sort.bun.ts",
182
181
  "lint:biome": "biome check -- .",
183
182
  "lint:eslint": "eslint -- .",
@@ -191,7 +190,7 @@
191
190
  "test:build": "bun run test:manifest && cross-env IMPORT=dist vitest run",
192
191
  "test:once": "echo tested built code",
193
192
  "test:once:public": "cross-env IMPORT=dist vitest run public",
194
- "test:manifest": "tsx __scripts__/manifest-test.node.ts",
193
+ "test:manifest": "./__scripts__/manifest-test.node.ts",
195
194
  "test:semver": "break-check --verbose",
196
195
  "postversion": "biome format --write package.json",
197
196
  "storybook": "storybook dev -p 6006",
@@ -21,12 +21,8 @@ export function createRegularAtom<T>(
21
21
  ): RegularAtomToken<T> {
22
22
  const type = `atom`
23
23
  const { key } = options
24
- store.logger.info(
25
- `🔨`,
26
- `atom`,
27
- key,
28
- `creating in store "${store.config.name}"`,
29
- )
24
+ store.logger.info(`🔨`, type, key, `is being created`)
25
+
30
26
  const target = newest(store)
31
27
  const existing = target.atoms.get(key)
32
28
  if (existing && existing.type === type) {
@@ -11,19 +11,16 @@ export function writeToCache<T>(
11
11
  target: Store,
12
12
  state: ReadableState<T>,
13
13
  value: T,
14
- // subject: Subject<StateUpdate<unknown>>,
15
14
  ): T
16
15
  export function writeToCache<T extends Promise<any>>(
17
16
  target: Store,
18
17
  state: ReadableState<T>,
19
18
  value: T,
20
- // subject: Subject<StateUpdate<unknown>>,
21
19
  ): Future<Awaited<T>>
22
20
  export function writeToCache<T>(
23
21
  target: Store,
24
22
  state: ReadableState<T>,
25
23
  value: T,
26
- // subject: Subject<StateUpdate<unknown>>,
27
24
  ): Future<T> | T {
28
25
  const { key, subject, type } = state
29
26
  const currentValue = target.valueMap.get(key)
@@ -55,7 +52,7 @@ export function writeToCache<T>(
55
52
  case `writable_pure_selector`:
56
53
  evictDownstreamFromSelector(target, key)
57
54
  break
58
- // held selectors, by definitions, don't become promises
55
+ // held selectors, by definition, don't become promises
59
56
  }
60
57
  closeOperation(target)
61
58
  subject.next({ newValue: resolved, oldValue: future })
@@ -66,6 +63,7 @@ export function writeToCache<T>(
66
63
  })
67
64
  return future
68
65
  }
66
+ target.logger.info(`📝`, state.type, state.key, `writing to cache`, value)
69
67
  target.valueMap.set(key, value)
70
68
  return value
71
69
  }
@@ -3,16 +3,15 @@ import type { AtomUpdateEvent } from "atom.io"
3
3
  import { setIntoStore } from "../set-state"
4
4
  import type { Store } from "../store"
5
5
 
6
- export function ingestAtomUpdate(
7
- applying: `newValue` | `oldValue`,
8
- atomUpdate: AtomUpdateEvent<any>,
6
+ export function ingestAtomUpdateEvent(
9
7
  store: Store,
8
+ event: AtomUpdateEvent<any>,
9
+ applying: `newValue` | `oldValue`,
10
10
  ): void {
11
11
  const {
12
12
  token,
13
13
  update: { newValue, oldValue },
14
- } = atomUpdate
14
+ } = event
15
15
  const value = applying === `newValue` ? newValue : oldValue
16
-
17
16
  setIntoStore(store, token, value)
18
17
  }