atom.io 0.40.7 → 0.40.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
  2. package/dist/data/index.js +1 -2
  3. package/dist/data/index.js.map +1 -1
  4. package/dist/eslint-plugin/index.js +2 -3
  5. package/dist/eslint-plugin/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +4 -3
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +1231 -176
  9. package/dist/internal/index.js.map +1 -1
  10. package/dist/introspection/index.d.ts.map +1 -1
  11. package/dist/introspection/index.js +13 -32
  12. package/dist/introspection/index.js.map +1 -1
  13. package/dist/json/index.d.ts.map +1 -1
  14. package/dist/json/index.js.map +1 -1
  15. package/dist/main/index.d.ts.map +1 -1
  16. package/dist/main/index.js +1 -2
  17. package/dist/main/index.js.map +1 -1
  18. package/dist/react/index.d.ts.map +1 -1
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/react-devtools/index.d.ts.map +1 -1
  21. package/dist/react-devtools/index.js +2 -4
  22. package/dist/react-devtools/index.js.map +1 -1
  23. package/dist/realtime/index.d.ts +29 -5
  24. package/dist/realtime/index.d.ts.map +1 -1
  25. package/dist/realtime/index.js +47 -5
  26. package/dist/realtime/index.js.map +1 -1
  27. package/dist/realtime-client/index.d.ts +2 -6
  28. package/dist/realtime-client/index.d.ts.map +1 -1
  29. package/dist/realtime-client/index.js +6 -22
  30. package/dist/realtime-client/index.js.map +1 -1
  31. package/dist/realtime-react/index.d.ts +6 -9
  32. package/dist/realtime-react/index.d.ts.map +1 -1
  33. package/dist/realtime-react/index.js +4 -16
  34. package/dist/realtime-react/index.js.map +1 -1
  35. package/dist/realtime-server/index.d.ts +38 -57
  36. package/dist/realtime-server/index.d.ts.map +1 -1
  37. package/dist/realtime-server/index.js +128 -178
  38. package/dist/realtime-server/index.js.map +1 -1
  39. package/dist/realtime-testing/index.d.ts +2 -0
  40. package/dist/realtime-testing/index.d.ts.map +1 -1
  41. package/dist/realtime-testing/index.js +15 -9
  42. package/dist/realtime-testing/index.js.map +1 -1
  43. package/dist/transceivers/set-rtx/index.d.ts +1 -1
  44. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  45. package/dist/transceivers/set-rtx/index.js +5 -9
  46. package/dist/transceivers/set-rtx/index.js.map +1 -1
  47. package/dist/transceivers/u-list/index.d.ts +29 -0
  48. package/dist/transceivers/u-list/index.d.ts.map +1 -0
  49. package/dist/transceivers/u-list/index.js +87 -0
  50. package/dist/transceivers/u-list/index.js.map +1 -0
  51. package/dist/web/index.js.map +1 -1
  52. package/package.json +17 -13
  53. package/src/internal/mutable/tracker.ts +61 -46
  54. package/src/internal/mutable/transceiver.ts +4 -4
  55. package/src/internal/set-state/index.ts +1 -0
  56. package/src/internal/subscribe/subscribe-to-state.ts +9 -0
  57. package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
  58. package/src/realtime/index.ts +2 -0
  59. package/src/realtime/shared-room-store.ts +12 -11
  60. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
  61. package/src/realtime-client/index.ts +0 -1
  62. package/src/realtime-client/push-state.ts +1 -2
  63. package/src/realtime-react/index.ts +0 -1
  64. package/src/realtime-react/use-single-effect.ts +1 -1
  65. package/src/realtime-server/continuity/continuity-store.ts +2 -27
  66. package/src/realtime-server/continuity/provide-continuity.ts +50 -0
  67. package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +16 -14
  68. package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +11 -10
  69. package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +8 -6
  70. package/src/realtime-server/continuity/receive-action-requests.ts +66 -0
  71. package/src/realtime-server/continuity/{prepare-to-track-client-acknowledgement.ts → track-acknowledgements.ts} +15 -9
  72. package/src/realtime-server/index.ts +1 -3
  73. package/src/realtime-server/ipc-sockets/custom-socket.ts +4 -5
  74. package/src/realtime-server/ipc-sockets/parent-socket.ts +21 -17
  75. package/src/realtime-server/realtime-family-provider.ts +1 -1
  76. package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
  77. package/src/realtime-server/realtime-mutable-provider.ts +1 -1
  78. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
  79. package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
  80. package/src/realtime-server/realtime-state-provider.ts +1 -1
  81. package/src/realtime-server/realtime-state-receiver.ts +3 -6
  82. package/src/realtime-server/server-config.ts +1 -3
  83. package/src/realtime-testing/setup-realtime-test.tsx +23 -18
  84. package/src/transceivers/set-rtx/set-rtx.ts +3 -3
  85. package/src/transceivers/u-list/index.ts +1 -0
  86. package/src/transceivers/u-list/u-list.ts +123 -0
  87. package/dist/employ-socket-D6wgByWh.js +0 -12
  88. package/dist/employ-socket-D6wgByWh.js.map +0 -1
  89. package/dist/has-role-hv4-hJMw.js +0 -1149
  90. package/dist/has-role-hv4-hJMw.js.map +0 -1
  91. package/dist/is-fn-DY1wZ-md.js +0 -10
  92. package/dist/is-fn-DY1wZ-md.js.map +0 -1
  93. package/dist/mutex-store-CSvxY9i3.js +0 -11
  94. package/dist/mutex-store-CSvxY9i3.js.map +0 -1
  95. package/dist/shared-room-store-COGGKqes.js +0 -32
  96. package/dist/shared-room-store-COGGKqes.js.map +0 -1
  97. package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
  98. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
  99. package/src/realtime-client/server-action.ts +0 -23
  100. package/src/realtime-react/use-server-action.ts +0 -19
  101. package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
  102. package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
  103. package/src/realtime-server/realtime-action-receiver.ts +0 -40
  104. /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
@@ -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 || Number.isNaN(eventOffset)) {\n\t\t\tif (eventOffset === 1 || Number.isNaN(eventOffset)) {\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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"}
@@ -0,0 +1,29 @@
1
+ import { Subject, Transceiver, TransceiverMode } from "atom.io/internal";
2
+ import { Json, primitive, stringified } from "atom.io/json";
3
+
4
+ //#region src/transceivers/u-list/u-list.d.ts
5
+ type UListUpdateType = `add` | `clear` | `del`;
6
+ type UListUpdate<P extends primitive> = `${`add` | `del`}:${stringified<P>}` | `clear:${stringified<P[]>}`;
7
+ interface UListJson<P extends primitive> extends Json.Object {
8
+ members: P[];
9
+ }
10
+ declare class UList<P extends primitive> extends Set<P> implements Transceiver<ReadonlySet<P>, UListUpdate<P>, UListJson<P>> {
11
+ mode: TransceiverMode;
12
+ readonly subject: Subject<UListUpdate<P>>;
13
+ constructor(values?: Iterable<P>);
14
+ readonly READONLY_VIEW: ReadonlySet<P>;
15
+ toJSON(): UListJson<P>;
16
+ static fromJSON<P extends primitive>(json: UListJson<P>): UList<P>;
17
+ add(value: P): this;
18
+ clear(): void;
19
+ delete(value: P): boolean;
20
+ subscribe(key: string, fn: (update: UListUpdate<P>) => void): () => void;
21
+ emit(update: UListUpdate<P>): void;
22
+ private doStep;
23
+ do(update: UListUpdate<P>): null;
24
+ undoStep(update: UListUpdate<P>): void;
25
+ undo(update: UListUpdate<P>): number | null;
26
+ }
27
+ //#endregion
28
+ export { UList, UListJson, UListUpdate, UListUpdateType };
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":[],"mappings":";;;;KAKY,eAAA;AAAA,KACA,WADA,CAAA,UACsB,SADtB,CAAA,GAAA,GAAA,KAAA,GAAA,KAAA,IAEW,WAFX,CAEuB,CAFvB,CAAA,EAAA,GAAA,SAGA,WAHA,CAGY,CAHZ,EAAA,CAAA,EAAA;AACA,UAIK,SAJL,CAAA,UAIyB,SAJzB,CAAA,SAI4C,IAAA,CAAK,MAJjD,CAAA;EAAA,OAAA,EAKF,CALE,EAAA;;AACuB,cAMtB,KANsB,CAAA,UAMN,SANM,CAAA,SAO1B,GAP0B,CAOtB,CAPsB,CAAA,YAQvB,WARuB,CAQX,WARW,CAQC,CARD,CAAA,EAQK,WARL,CAQiB,CARjB,CAAA,EAQqB,SARrB,CAQ+B,CAR/B,CAAA,CAAA,CAAA;QAUrB,eAVS;WACC,OAAA,EAUE,OAVF,CAUU,WAVV,CAUsB,CAVtB,CAAA,CAAA;aAAZ,CAAA,MAAA,CAAA,EAciB,QAdjB,CAc0B,CAd1B,CAAA;EAAA,SAAA,aAAA,EAoBoB,WApBpB,CAoBgC,CApBhC,CAAA;EAEZ,MAAiB,CAAA,CAAA,EAoBC,SApBD,CAoBW,CApBX,CAAA;EAAA,OAAA,QAAA,CAAA,UA0BiB,SA1BjB,CAAA,CAAA,IAAA,EA0BkC,SA1BlC,CA0B4C,CA1B5C,CAAA,CAAA,EA0BiD,KA1BjD,CA0BuD,CA1BvD,CAAA;WAAoB,EA8BlB,CA9BkB,CAAA,EAAA,IAAA;SAC3B,EAAA,IAAA;QAD8C,CAAA,KAAK,EA8CvC,CA9CuC,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,MAAA,EAwD9C,WAxD8C,CAwDlC,CAxDkC,CAAA,EAAA,GAAA,IAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAG7D,IAAa,CAAA,MAAA,EA0DQ,WA1DR,CA0DoB,CA1DpB,CAAA,CAAA,EAAA,IAAA;EAAA,QAAA,MAAA;WAAgB,EA8EV,WA9EU,CA8EE,CA9EF,CAAA,CAAA,EAAA,IAAA;UAChB,CAAA,MAAA,EAoFY,WApFZ,CAoFwB,CApFxB,CAAA,CAAA,EAAA,IAAA;aACuB,EAqGf,WArGe,CAqGH,CArGG,CAAA,CAAA,EAAA,MAAA,GAAA,IAAA"}
@@ -0,0 +1,87 @@
1
+ import { Subject } from "atom.io/internal";
2
+ import { stringifyJson } from "atom.io/json";
3
+
4
+ //#region src/transceivers/u-list/u-list.ts
5
+ var UList = class UList extends Set {
6
+ mode = `record`;
7
+ subject = new Subject();
8
+ constructor(values) {
9
+ super(values);
10
+ if (values instanceof UList) {}
11
+ }
12
+ READONLY_VIEW = this;
13
+ toJSON() {
14
+ return { members: [...this] };
15
+ }
16
+ static fromJSON(json) {
17
+ return new UList(json.members);
18
+ }
19
+ add(value) {
20
+ const result = super.add(value);
21
+ if (this.mode === `record`) this.emit(`add:${stringifyJson(value)}`);
22
+ return result;
23
+ }
24
+ clear() {
25
+ const capturedContents = this.mode === `record` ? [...this] : null;
26
+ super.clear();
27
+ if (capturedContents) this.emit(`clear:${stringifyJson(capturedContents)}`);
28
+ }
29
+ delete(value) {
30
+ const result = super.delete(value);
31
+ if (this.mode === `record`) this.emit(`del:${stringifyJson(value)}`);
32
+ return result;
33
+ }
34
+ subscribe(key, fn) {
35
+ return this.subject.subscribe(key, fn);
36
+ }
37
+ emit(update) {
38
+ this.subject.next(update);
39
+ }
40
+ doStep(update) {
41
+ const typeValueBreak = update.indexOf(`:`);
42
+ const type = update.substring(0, typeValueBreak);
43
+ const value = update.substring(typeValueBreak + 1);
44
+ switch (type) {
45
+ case `add`:
46
+ this.add(JSON.parse(value));
47
+ break;
48
+ case `del`:
49
+ this.delete(JSON.parse(value));
50
+ break;
51
+ case `clear`: this.clear();
52
+ }
53
+ }
54
+ do(update) {
55
+ this.mode = `playback`;
56
+ this.doStep(update);
57
+ this.mode = `record`;
58
+ return null;
59
+ }
60
+ undoStep(update) {
61
+ const breakpoint = update.indexOf(`:`);
62
+ const type = update.substring(0, breakpoint);
63
+ const value = update.substring(breakpoint + 1);
64
+ switch (type) {
65
+ case `add`:
66
+ this.delete(JSON.parse(value));
67
+ break;
68
+ case `del`:
69
+ this.add(JSON.parse(value));
70
+ break;
71
+ case `clear`: {
72
+ const values = JSON.parse(value);
73
+ for (const v of values) this.add(v);
74
+ }
75
+ }
76
+ }
77
+ undo(update) {
78
+ this.mode = `playback`;
79
+ this.undoStep(update);
80
+ this.mode = `record`;
81
+ return null;
82
+ }
83
+ };
84
+
85
+ //#endregion
86
+ export { UList };
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/transceivers/u-list/u-list.ts"],"sourcesContent":["import type { Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, primitive, stringified } from \"atom.io/json\"\nimport { stringifyJson } from \"atom.io/json\"\n\nexport type UListUpdateType = `add` | `clear` | `del`\nexport type UListUpdate<P extends primitive> =\n\t| `${`add` | `del`}:${stringified<P>}`\n\t| `clear:${stringified<P[]>}`\n\nexport interface UListJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n}\nexport class UList<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<ReadonlySet<P>, UListUpdate<P>, UListJson<P>>\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject: Subject<UListUpdate<P>> = new Subject<\n\t\tUListUpdate<P>\n\t>()\n\n\tpublic constructor(values?: Iterable<P>) {\n\t\tsuper(values)\n\t\tif (values instanceof UList) {\n\t\t}\n\t}\n\n\tpublic readonly READONLY_VIEW: ReadonlySet<P> = this\n\n\tpublic toJSON(): UListJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: UListJson<P>): UList<P> {\n\t\treturn new UList<P>(json.members)\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.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.emit(`clear:${stringifyJson(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.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn result\n\t}\n\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: UListUpdate<P>) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\n\tpublic emit(update: UListUpdate<P>): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: UListUpdate<P>): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak) as UListUpdateType\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 `del`:\n\t\t\t\tthis.delete(JSON.parse(value))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t}\n\t}\n\n\tpublic do(update: UListUpdate<P>): null {\n\t\tthis.mode = `playback`\n\t\tthis.doStep(update)\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n\n\tpublic undoStep(update: UListUpdate<P>): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint) as UListUpdateType\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}\n\t\t}\n\t}\n\n\tpublic undo(update: UListUpdate<P>): number | null {\n\t\tthis.mode = `playback`\n\t\tthis.undoStep(update)\n\t\tthis.mode = `record`\n\t\treturn null\n\t}\n}\n"],"mappings":";;;;AAaA,IAAa,QAAb,MAAa,cACJ,IAET;CACC,AAAO,OAAwB;CAC/B,AAAgB,UAAmC,IAAI,SAEpD;CAEH,AAAO,YAAY,QAAsB;AACxC,QAAM,OAAO;AACb,MAAI,kBAAkB,OAAO;;CAI9B,AAAgB,gBAAgC;CAEhD,AAAO,SAAuB;AAC7B,SAAO,EACN,SAAS,CAAC,GAAG,KAAK,EAClB;;CAGF,OAAc,SAA8B,MAA8B;AACzE,SAAO,IAAI,MAAS,KAAK,QAAQ;;CAGlC,AAAO,IAAI,OAAgB;EAC1B,MAAM,SAAS,MAAM,IAAI,MAAM;AAC/B,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK,OAAO,cAAiB,MAAM,GAAG;AAE5C,SAAO;;CAGR,AAAO,QAAc;EACpB,MAAM,mBAAmB,KAAK,SAAS,WAAW,CAAC,GAAG,KAAK,GAAG;AAC9D,QAAM,OAAO;AACb,MAAI,iBACH,MAAK,KAAK,SAAS,cAAc,iBAAiB,GAAG;;CAIvD,AAAO,OAAO,OAAmB;EAChC,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,MAAI,KAAK,SAAS,SACjB,MAAK,KAAK,OAAO,cAAiB,MAAM,GAAG;AAE5C,SAAO;;CAGR,AAAO,UACN,KACA,IACa;AACb,SAAO,KAAK,QAAQ,UAAU,KAAK,GAAG;;CAGvC,AAAO,KAAK,QAA8B;AACzC,OAAK,QAAQ,KAAK,OAAO;;CAG1B,AAAQ,OAAO,QAA8B;EAC5C,MAAM,iBAAiB,OAAO,QAAQ,IAAI;EAC1C,MAAM,OAAO,OAAO,UAAU,GAAG,eAAe;EAChD,MAAM,QAAQ,OAAO,UAAU,iBAAiB,EAAE;AAClD,UAAQ,MAAR;GACC,KAAK;AACJ,SAAK,IAAI,KAAK,MAAM,MAAM,CAAC;AAC3B;GACD,KAAK;AACJ,SAAK,OAAO,KAAK,MAAM,MAAM,CAAC;AAC9B;GACD,KAAK,QACJ,MAAK,OAAO;;;CAIf,AAAO,GAAG,QAA8B;AACvC,OAAK,OAAO;AACZ,OAAK,OAAO,OAAO;AACnB,OAAK,OAAO;AACZ,SAAO;;CAGR,AAAO,SAAS,QAA8B;EAC7C,MAAM,aAAa,OAAO,QAAQ,IAAI;EACtC,MAAM,OAAO,OAAO,UAAU,GAAG,WAAW;EAC5C,MAAM,QAAQ,OAAO,UAAU,aAAa,EAAE;AAC9C,UAAQ,MAAR;GACC,KAAK;AACJ,SAAK,OAAO,KAAK,MAAM,MAAM,CAAC;AAC9B;GACD,KAAK;AACJ,SAAK,IAAI,KAAK,MAAM,MAAM,CAAC;AAC3B;GACD,KAAK,SAAS;IACb,MAAM,SAAS,KAAK,MAAM,MAAM;AAChC,SAAK,MAAM,KAAK,OAAQ,MAAK,IAAI,EAAE;;;;CAKtC,AAAO,KAAK,QAAuC;AAClD,OAAK,OAAO;AACZ,OAAK,SAAS,OAAO;AACrB,OAAK,OAAO;AACZ,SAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/web/storage-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 storageSync =\n\t<T>(\n\t\tstorage: Storage | undefined,\n\t\t{ stringify, parse }: StringInterface<T>,\n\t\tkey: string,\n\t): AtomEffect<T> =>\n\t({ setSelf, onSet }) => {\n\t\tif (!storage) {\n\t\t\treturn\n\t\t}\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;AACvB,KAAI,CAAC,QACJ;CAED,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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/web/storage-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 storageSync =\n\t<T>(\n\t\tstorage: Storage | undefined,\n\t\t{ stringify, parse }: StringInterface<T>,\n\t\tkey: string,\n\t): AtomEffect<T> =>\n\t({ setSelf, onSet }) => {\n\t\tif (!storage) {\n\t\t\treturn\n\t\t}\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;AACvB,KAAI,CAAC,QACJ;CAED,MAAM,aAAa,QAAQ,QAAQ,IAAI;AACvC,KAAI,cAAc,KAAM,SAAQ,MAAM,WAAW,CAAC;AAElD,QAAO,EAAE,eAAe;AACvB,MAAI,YAAY,MAAM;AACrB,WAAQ,WAAW,IAAI;AACvB;;AAED,UAAQ,QAAQ,KAAK,UAAU,SAAS,CAAC;GACxC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.40.7",
3
+ "version": "0.40.9",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -61,20 +61,20 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint/core": "0.15.2",
64
- "@storybook/addon-docs": "9.1.4",
65
- "@storybook/addon-onboarding": "9.1.4",
66
- "@storybook/react-vite": "9.1.4",
64
+ "@storybook/addon-docs": "9.1.5",
65
+ "@storybook/addon-onboarding": "9.1.5",
66
+ "@storybook/react-vite": "9.1.5",
67
67
  "@testing-library/react": "16.3.0",
68
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
- "@types/react": "19.1.12",
73
+ "@types/react": "19.1.13",
74
74
  "@types/tmp": "0.2.6",
75
- "@typescript-eslint/parser": "8.42.0",
76
- "@typescript-eslint/rule-tester": "8.42.0",
77
- "@typescript-eslint/utils": "8.42.0",
75
+ "@typescript-eslint/parser": "8.43.0",
76
+ "@typescript-eslint/rule-tester": "8.43.0",
77
+ "@typescript-eslint/utils": "8.43.0",
78
78
  "@vitest/coverage-v8": "3.2.4",
79
79
  "@vitest/ui": "3.2.4",
80
80
  "concurrently": "9.2.1",
@@ -90,19 +90,19 @@
90
90
  "preact": "10.27.1",
91
91
  "react": "19.1.1",
92
92
  "react-dom": "19.1.1",
93
- "react-router-dom": "7.8.2",
93
+ "react-router-dom": "7.9.0",
94
94
  "recoverage": "0.1.11",
95
95
  "socket.io": "4.8.1",
96
96
  "socket.io-client": "4.8.1",
97
- "storybook": "9.1.4",
97
+ "storybook": "9.1.5",
98
98
  "tmp": "0.2.5",
99
- "tsdown": "0.14.2",
99
+ "tsdown": "0.15.1",
100
100
  "typescript": "5.9.2",
101
- "vite": "7.1.4",
101
+ "vite": "7.1.5",
102
102
  "vite-tsconfig-paths": "5.1.4",
103
103
  "vitest": "3.2.4",
104
104
  "zod": "3.25.76",
105
- "break-check": "0.6.15"
105
+ "break-check": "0.6.16"
106
106
  },
107
107
  "main": "./dist/main/index.js",
108
108
  "files": [
@@ -170,6 +170,10 @@
170
170
  "import": "./dist/transceivers/set-rtx/index.js",
171
171
  "types": "./dist/transceivers/set-rtx/index.d.ts"
172
172
  },
173
+ "./transceivers/u-list": {
174
+ "import": "./dist/transceivers/u-list/index.js",
175
+ "types": "./dist/transceivers/u-list/index.d.ts"
176
+ },
173
177
  "./web": {
174
178
  "import": "./dist/web/index.js",
175
179
  "types": "./dist/web/index.d.ts"
@@ -1,9 +1,15 @@
1
- import type { FamilyMetadata, MutableAtomToken, RegularAtomToken } from "atom.io"
1
+ import type {
2
+ FamilyMetadata,
3
+ MutableAtomToken,
4
+ RegularAtomToken,
5
+ StateUpdate,
6
+ } from "atom.io"
2
7
 
3
8
  import { createRegularAtom } from "../atom"
4
9
  import { getFromStore } from "../get-state"
5
10
  import { newest } from "../lineage"
6
11
  import { setIntoStore } from "../set-state"
12
+ import { JOIN_OP, operateOnStore } from "../set-state/operate-on-store"
7
13
  import type { Store } from "../store"
8
14
  import { subscribeToState, subscribeToTimeline } from "../subscribe"
9
15
  import { isChildStore } from "../transaction/is-root-store"
@@ -61,9 +67,9 @@ export class Tracker<T extends Transceiver<any, any, any>> {
61
67
  const storeStatus = isChildStore(target)
62
68
  ? target.transactionMeta.update.token.key
63
69
  : `main`
64
- const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`
70
+ const subscriptionKey = `tracker-from-core:${storeName}:${storeStatus}:${stateKey}`
65
71
  const trackerCapturesOutboundSignal = (update: SignalFrom<T>) => {
66
- setIntoStore(target, latestSignalState, update)
72
+ operateOnStore(JOIN_OP, target, latestSignalState, update)
67
73
  }
68
74
  const originalInnerValue = getFromStore(target, mutableState)
69
75
  this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
@@ -91,60 +97,69 @@ export class Tracker<T extends Transceiver<any, any, any>> {
91
97
  latestSignalState: RegularAtomToken<SignalFrom<T> | null>,
92
98
  target: Store,
93
99
  ): void {
94
- const subscriptionKey = `tracker:${target.config.name}:${
95
- isChildStore(target) ? target.transactionMeta.update.token.key : `main`
96
- }:${mutableState.key}`
100
+ const stateKey = mutableState.key
101
+ const storeName = target.config.name
102
+ const storeStatus = isChildStore(target)
103
+ ? target.transactionMeta.update.token.key
104
+ : `main`
105
+ const subscriptionKey = `tracker-to-core:${storeName}:${storeStatus}:${stateKey}`
97
106
  subscribeToState(
98
107
  target,
99
108
  latestSignalState,
100
109
  subscriptionKey,
101
- function trackerCapturesInboundSignal({ newValue, oldValue }) {
102
- const timelineId = target.timelineTopics.getRelatedKey(
103
- latestSignalState.key,
104
- )
105
-
106
- if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
107
- const unsubscribe = subscribeToTimeline(
108
- target,
109
- { key: timelineId, type: `timeline` },
110
- subscriptionKey,
111
- function trackerWaitsForTimeTravelToFinish(update) {
112
- unsubscribe()
113
- setIntoStore(target, mutableState, (transceiver) => {
114
- if (update === `redo` && newValue) {
115
- transceiver.do(newValue)
116
- } else if (update === `undo` && oldValue) {
117
- transceiver.undo(oldValue)
118
- }
119
- return transceiver
120
- })
121
- },
110
+ Object.assign(
111
+ function trackerCapturesInboundSignal({
112
+ newValue,
113
+ oldValue,
114
+ }: StateUpdate<SignalFrom<T> | null>) {
115
+ const timelineId = target.timelineTopics.getRelatedKey(
116
+ latestSignalState.key,
122
117
  )
123
- return
124
- }
125
118
 
126
- const mutable = getFromStore(target, mutableState)
127
- const updateNumber = mutable.getUpdateNumber(newValue)
128
- const eventOffset = updateNumber - mutable.cacheUpdateNumber
129
- if (newValue && eventOffset === 1) {
119
+ if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
120
+ const unsubscribe = subscribeToTimeline(
121
+ target,
122
+ { key: timelineId, type: `timeline` },
123
+ subscriptionKey,
124
+ function trackerWaitsForTimeTravelToFinish(update) {
125
+ unsubscribe()
126
+ setIntoStore(target, mutableState, (transceiver) => {
127
+ if (update === `redo` && newValue) {
128
+ transceiver.do(newValue)
129
+ } else if (update === `undo` && oldValue) {
130
+ transceiver.undo(oldValue)
131
+ }
132
+ return transceiver
133
+ })
134
+ },
135
+ )
136
+ return
137
+ }
138
+
139
+ // const mutable = getFromStore(target, mutableState)
140
+ // const updateNumber = mutable.getUpdateNumber(newValue)
141
+ // const eventOffset = updateNumber - mutable.cacheUpdateNumber
142
+ // if (newValue && eventOffset === 1) {
130
143
  setIntoStore(
131
144
  target,
132
145
  mutableState,
133
146
  (transceiver) => (transceiver.do(newValue), transceiver),
134
147
  )
135
- } else {
136
- const expected = mutable.cacheUpdateNumber + 1
137
- target.logger.info(
138
- `❌`,
139
- `mutable_atom`,
140
- mutableState.key,
141
- `could not be updated. Expected update number`,
142
- expected,
143
- `but got`,
144
- updateNumber,
145
- )
146
- }
147
- },
148
+ // } else {
149
+ // const expected = mutable.cacheUpdateNumber + 1
150
+ // target.logger.info(
151
+ // `❌`,
152
+ // `mutable_atom`,
153
+ // mutableState.key,
154
+ // `could not be updated. Expected update number`,
155
+ // expected,
156
+ // `but got`,
157
+ // updateNumber,
158
+ // )
159
+ // }
160
+ },
161
+ { inboundTracker: true },
162
+ ),
148
163
  )
149
164
  }
150
165
 
@@ -9,8 +9,8 @@ export interface Transceiver<
9
9
  do: (update: S) => number | `OUT_OF_RANGE` | null
10
10
  undo: (update: S) => void
11
11
  subscribe: (key: string, fn: (update: S) => void) => () => void
12
- cacheUpdateNumber: number
13
- getUpdateNumber: (update: S) => number
12
+ // cacheUpdateNumber: number
13
+ // getUpdateNumber: (update: S) => number
14
14
  toJSON: () => J
15
15
  }
16
16
 
@@ -31,8 +31,8 @@ export function isTransceiver(
31
31
  `do` in value &&
32
32
  `undo` in value &&
33
33
  `subscribe` in value &&
34
- `cacheUpdateNumber` in value &&
35
- `getUpdateNumber` in value &&
34
+ // `cacheUpdateNumber` in value &&
35
+ // `getUpdateNumber` in value &&
36
36
  `READONLY_VIEW` in value &&
37
37
  `toJSON` in value
38
38
  )
@@ -1,5 +1,6 @@
1
1
  export * from "./become"
2
2
  export * from "./evict-downstream"
3
+ export * from "./operate-on-store"
3
4
  export * from "./reset-atom-or-selector"
4
5
  export * from "./reset-in-store"
5
6
  export * from "./set-atom-or-selector"
@@ -1,5 +1,6 @@
1
1
  import type { ReadableToken, StateUpdate, UpdateHandler } from "atom.io"
2
2
 
3
+ import { hasRole } from "../atom"
3
4
  import { readOrComputeValue } from "../get-state"
4
5
  import { reduceReference } from "../get-state/reduce-reference"
5
6
  import { traceRootSelectorAtoms } from "../selector"
@@ -15,6 +16,14 @@ export function subscribeToState<T, E>(
15
16
  ): () => void {
16
17
  function safelyHandleUpdate(update: StateUpdate<any>): void {
17
18
  if (store.operation.open) {
19
+ if (
20
+ state?.type === `atom` &&
21
+ hasRole(state, `tracker:signal`) &&
22
+ `*` + store.operation.token.key === token.key &&
23
+ `inboundTracker` in handleUpdate
24
+ ) {
25
+ return
26
+ }
18
27
  const unsubscribe = store.on.operationClose.subscribe(
19
28
  `state subscription ${key}`,
20
29
  () => {
@@ -1,5 +1,5 @@
1
- import type { Events } from "./ipc-sockets"
2
- import type { Socket } from "./socket-interface"
1
+ import type { Socket } from "atom.io/realtime"
2
+ import type { Events } from "atom.io/realtime-server"
3
3
 
4
4
  export function employSocket<I extends Events, K extends string & keyof I>(
5
5
  socket: Socket,
@@ -1,3 +1,5 @@
1
+ export * from "./employ-socket"
1
2
  export * from "./mutex-store"
2
3
  export * from "./realtime-continuity"
3
4
  export * from "./shared-room-store"
5
+ export type * from "./socket-interface"
@@ -4,19 +4,20 @@ import type {
4
4
  ReadonlyPureSelectorFamilyToken,
5
5
  } from "atom.io"
6
6
  import { getInternalRelations, join, mutableAtom, selectorFamily } from "atom.io"
7
- import { SetRTX } from "atom.io/transceivers/set-rtx"
7
+ import { UList } from "atom.io/transceivers/u-list"
8
8
 
9
- export const usersInThisRoomIndex: MutableAtomToken<SetRTX<string>> =
10
- mutableAtom<SetRTX<string>>({
11
- key: `usersInRoomIndex`,
12
- class: SetRTX,
13
- })
9
+ export const usersInThisRoomIndex: MutableAtomToken<UList<string>> = mutableAtom<
10
+ UList<string>
11
+ >({
12
+ key: `usersInRoomIndex`,
13
+ class: UList,
14
+ })
14
15
 
15
- export const roomIndex: MutableAtomToken<SetRTX<string>> = mutableAtom<
16
- SetRTX<string>
16
+ export const roomIndex: MutableAtomToken<UList<string>> = mutableAtom<
17
+ UList<string>
17
18
  >({
18
19
  key: `roomIndex`,
19
- class: SetRTX,
20
+ class: UList,
20
21
  })
21
22
 
22
23
  export type UserInRoomMeta = {
@@ -44,9 +45,9 @@ export const usersInRooms: JoinToken<
44
45
  )
45
46
 
46
47
  export const usersInMyRoomView: ReadonlyPureSelectorFamilyToken<
47
- MutableAtomToken<SetRTX<string>>[],
48
+ MutableAtomToken<UList<string>>[],
48
49
  string
49
- > = selectorFamily<MutableAtomToken<SetRTX<string>>[], string>({
50
+ > = selectorFamily<MutableAtomToken<UList<string>>[], string>({
50
51
  key: `usersInMyRoomView`,
51
52
  get:
52
53
  (myUsername) =>
@@ -7,11 +7,11 @@ import {
7
7
  setEpochNumberOfContinuity,
8
8
  setIntoStore,
9
9
  } from "atom.io/internal"
10
+ import type { Socket } from "atom.io/realtime"
10
11
  import {
11
12
  confirmedUpdateQueue,
12
13
  optimisticUpdateQueue,
13
14
  } from "atom.io/realtime-client"
14
- import type { Socket } from "atom.io/realtime-server"
15
15
 
16
16
  export const useRegisterAndAttemptConfirmedUpdate =
17
17
  (
@@ -7,5 +7,4 @@ export * from "./pull-selector"
7
7
  export * from "./pull-selector-family-member"
8
8
  export * from "./push-state"
9
9
  export * from "./realtime-client-stores"
10
- export * from "./server-action"
11
10
  export * from "./sync-continuity"
@@ -2,8 +2,7 @@ import type { WritableToken } from "atom.io"
2
2
  import type { Store } from "atom.io/internal"
3
3
  import { setIntoStore, subscribeToState } from "atom.io/internal"
4
4
  import type { Json } from "atom.io/json"
5
- import { mutexAtoms } from "atom.io/realtime/mutex-store"
6
- import { employSocket } from "atom.io/realtime-server/employ-socket"
5
+ import { employSocket, mutexAtoms } from "atom.io/realtime"
7
6
  import type { Socket } from "socket.io-client"
8
7
 
9
8
  export function pushState<J extends Json.Serializable>(
@@ -7,6 +7,5 @@ export * from "./use-pull-selector"
7
7
  export * from "./use-pull-selector-family-member"
8
8
  export * from "./use-push"
9
9
  export * from "./use-realtime-service"
10
- export * from "./use-server-action"
11
10
  export * from "./use-single-effect"
12
11
  export * from "./use-sync-continuity"
@@ -1,6 +1,6 @@
1
1
  /** biome-ignore-all lint/correctness/useHookAtTopLevel: intentional */
2
2
 
3
- import { isFn } from "atom.io/internal/is-fn"
3
+ import { isFn } from "atom.io/internal"
4
4
  import * as React from "react"
5
5
 
6
6
  export function useSingleEffect(
@@ -5,15 +5,7 @@ import type {
5
5
  } from "atom.io"
6
6
  import { atomFamily } from "atom.io"
7
7
 
8
- import type { UserKey } from "../realtime-server-stores/server-user-store"
9
-
10
- // export const completeUpdateAtoms = atomFamily<
11
- // TransactionUpdate<any> | null,
12
- // string
13
- // >({
14
- // key: `completeUpdate`,
15
- // default: null,
16
- // })
8
+ import type { UserKey } from "../realtime-server-stores"
17
9
 
18
10
  export function redactTransactionUpdateContent(
19
11
  visibleStateKeys: string[],
@@ -67,29 +59,12 @@ export const redactorAtoms: RegularAtomFamilyToken<
67
59
  key: `redactor`,
68
60
  default: { occlude: (updates) => updates },
69
61
  })
70
- // export const redactedUpdateSelectors = selectorFamily<
71
- // TransactionUpdate<any> | null,
72
- // [transactionKey: string, updateId: string]
73
- // >({
74
- // key: `redactedUpdate`,
75
- // get:
76
- // ([transactionKey, updateId]) =>
77
- // ({ get, find }) => {
78
- // const update = get(find(completeUpdateAtoms, updateId))
79
- // const { filter } = get(find(transactionRedactorAtoms, transactionKey))
80
-
81
- // if (update && filter) {
82
- // return { ...update, updates: filter(update.updates) }
83
- // }
84
- // return null
85
- // },
86
- // })
87
62
 
88
63
  export type ContinuitySyncTransactionUpdate = Pick<
89
64
  TransactionOutcomeEvent<any>,
90
65
  `epoch` | `id` | `output` | `subEvents` | `token`
91
66
  >
92
- export const userUnacknowledgedQueues: RegularAtomFamilyToken<
67
+ export const unacknowledgedUpdatesAtoms: RegularAtomFamilyToken<
93
68
  ContinuitySyncTransactionUpdate[],
94
69
  UserKey
95
70
  > = atomFamily<ContinuitySyncTransactionUpdate[], UserKey>({