atom.io 0.31.0 → 0.32.0

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 (171) hide show
  1. package/data/dist/index.d.ts +867 -101
  2. package/data/dist/index.js +10 -558
  3. package/data/src/index.ts +0 -2
  4. package/data/src/struct-family.ts +1 -1
  5. package/data/src/struct.ts +1 -2
  6. package/dist/chunk-354XQWHH.js +153 -0
  7. package/dist/chunk-4LWKCEW3.js +14 -0
  8. package/dist/chunk-5F2V7S3B.js +83 -0
  9. package/dist/chunk-ECOMOMUN.js +631 -0
  10. package/dist/{chunk-42UH5F5Q.js → chunk-GY2XQYZY.js} +2051 -755
  11. package/dist/chunk-NF7FJKJD.js +107 -0
  12. package/dist/chunk-R3ZUK5EH.js +1024 -0
  13. package/dist/chunk-Z2UJW4NQ.js +523 -0
  14. package/dist/index.d.ts +855 -127
  15. package/dist/index.js +1 -143
  16. package/eslint-plugin/dist/index.d.ts +1 -30
  17. package/eslint-plugin/dist/index.js +0 -146
  18. package/eslint-plugin/src/index.ts +0 -1
  19. package/eslint-plugin/src/rules/index.ts +0 -1
  20. package/internal/dist/index.d.ts +794 -70
  21. package/internal/dist/index.js +1 -2
  22. package/internal/src/atom/create-regular-atom.ts +3 -3
  23. package/internal/src/atom/dispose-atom.ts +4 -13
  24. package/internal/src/atom/is-default.ts +3 -3
  25. package/internal/src/caching.ts +5 -5
  26. package/internal/src/capitalize.ts +3 -0
  27. package/internal/src/families/create-readonly-selector-family.ts +5 -6
  28. package/internal/src/families/create-writable-selector-family.ts +1 -4
  29. package/internal/src/families/dispose-from-store.ts +3 -13
  30. package/internal/src/families/find-in-store.ts +1 -6
  31. package/internal/src/get-state/get-from-store.ts +2 -2
  32. package/internal/src/get-state/read-or-compute-value.ts +1 -1
  33. package/internal/src/index.ts +19 -9
  34. package/internal/src/ingest-updates/ingest-creation-disposal.ts +2 -3
  35. package/internal/src/install-into-store.ts +48 -0
  36. package/internal/src/join/edit-relations-in-store.ts +32 -0
  37. package/internal/src/join/find-relations-in-store.ts +124 -0
  38. package/internal/src/join/get-internal-relations-from-store.ts +14 -0
  39. package/internal/src/join/get-join.ts +31 -0
  40. package/internal/src/join/index.ts +5 -0
  41. package/{data/src/join.ts → internal/src/join/join-internal.ts} +20 -429
  42. package/internal/src/keys.ts +7 -7
  43. package/internal/src/molecule.ts +299 -0
  44. package/internal/src/mutable/create-mutable-atom-family.ts +1 -1
  45. package/internal/src/mutable/create-mutable-atom.ts +3 -3
  46. package/internal/src/mutable/get-json-token.ts +1 -1
  47. package/internal/src/mutable/tracker-family.ts +19 -17
  48. package/internal/src/mutable/tracker.ts +8 -8
  49. package/internal/src/not-found-error.ts +8 -30
  50. package/internal/src/pretty-print.ts +2 -13
  51. package/internal/src/selector/create-readonly-selector.ts +3 -7
  52. package/internal/src/selector/create-writable-selector.ts +4 -4
  53. package/internal/src/selector/dispose-selector.ts +20 -11
  54. package/internal/src/selector/get-selector-dependency-keys.ts +1 -1
  55. package/internal/src/selector/register-selector.ts +7 -17
  56. package/internal/src/selector/trace-selector-atoms.ts +2 -2
  57. package/internal/src/set-state/copy-mutable-if-needed.ts +1 -1
  58. package/internal/src/set-state/emit-update.ts +1 -1
  59. package/internal/src/set-state/evict-downstream.ts +1 -1
  60. package/internal/src/set-state/set-atom-or-selector.ts +1 -1
  61. package/internal/src/set-state/set-atom.ts +10 -10
  62. package/internal/src/set-state/set-into-store.ts +2 -2
  63. package/internal/src/set-state/stow-update.ts +1 -1
  64. package/internal/src/store/deposit.ts +10 -8
  65. package/internal/src/store/store.ts +1 -1
  66. package/internal/src/store/withdraw.ts +34 -53
  67. package/internal/src/subscribe/recall-state.ts +1 -1
  68. package/internal/src/subscribe/subscribe-in-store.ts +3 -3
  69. package/internal/src/subscribe/subscribe-to-root-atoms.ts +3 -3
  70. package/internal/src/subscribe/subscribe-to-state.ts +5 -5
  71. package/internal/src/subscribe/subscribe-to-timeline.ts +3 -3
  72. package/internal/src/subscribe/subscribe-to-transaction.ts +3 -3
  73. package/internal/src/timeline/create-timeline.ts +17 -37
  74. package/internal/src/transaction/act-upon-store.ts +2 -2
  75. package/internal/src/transaction/apply-transaction.ts +5 -5
  76. package/internal/src/transaction/assign-transaction-to-continuity.ts +1 -1
  77. package/internal/src/transaction/build-transaction.ts +5 -8
  78. package/internal/src/transaction/create-transaction.ts +3 -3
  79. package/internal/src/transaction/get-epoch-number.ts +3 -3
  80. package/internal/src/transaction/set-epoch-number.ts +2 -2
  81. package/introspection/dist/index.d.ts +922 -6
  82. package/introspection/dist/index.js +2 -620
  83. package/json/dist/index.d.ts +899 -5
  84. package/json/dist/index.js +1 -81
  85. package/json/src/select-json-family.ts +3 -14
  86. package/package.json +27 -45
  87. package/react/dist/index.d.ts +921 -3
  88. package/react/dist/index.js +2 -82
  89. package/react/src/use-o.ts +1 -1
  90. package/react/src/use-tl.ts +2 -2
  91. package/react-devtools/dist/index.css +16 -14
  92. package/react-devtools/dist/index.d.ts +26 -1
  93. package/react-devtools/dist/index.js +6 -6
  94. package/react-devtools/src/devtools.scss +16 -14
  95. package/realtime/dist/index.d.ts +202 -8
  96. package/realtime/dist/index.js +2 -107
  97. package/realtime/src/realtime-continuity.ts +2 -2
  98. package/realtime/src/shared-room-store.ts +1 -2
  99. package/realtime-client/dist/index.d.ts +960 -22
  100. package/realtime-client/dist/index.js +3 -509
  101. package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +3 -3
  102. package/realtime-client/src/continuity/use-conceal-state.ts +1 -1
  103. package/realtime-client/src/pull-atom-family-member.ts +2 -2
  104. package/realtime-client/src/pull-atom.ts +2 -2
  105. package/realtime-client/src/pull-mutable-atom-family-member.ts +2 -2
  106. package/realtime-client/src/pull-mutable-atom.ts +2 -2
  107. package/realtime-client/src/pull-selector-family-member.ts +4 -4
  108. package/realtime-client/src/pull-selector.ts +4 -4
  109. package/realtime-client/src/push-state.ts +5 -10
  110. package/realtime-client/src/server-action.ts +4 -4
  111. package/realtime-client/src/sync-continuity.ts +6 -6
  112. package/realtime-react/dist/index.d.ts +166 -12
  113. package/realtime-react/dist/index.js +5 -154
  114. package/realtime-react/src/use-pull-atom-family-member.ts +1 -1
  115. package/realtime-react/src/use-pull-atom.ts +1 -1
  116. package/realtime-react/src/use-pull-mutable-atom.ts +1 -1
  117. package/realtime-react/src/use-pull-mutable-family-member.ts +1 -1
  118. package/realtime-react/src/use-pull-selector-family-member.ts +1 -1
  119. package/realtime-react/src/use-pull-selector.ts +1 -1
  120. package/realtime-react/src/use-push.ts +1 -1
  121. package/realtime-react/src/use-server-action.ts +2 -2
  122. package/realtime-react/src/use-sync-continuity.ts +1 -1
  123. package/realtime-server/dist/index.d.ts +971 -28
  124. package/realtime-server/dist/index.js +3 -1001
  125. package/realtime-server/src/continuity/prepare-to-serve-transaction-request.ts +1 -1
  126. package/realtime-server/src/continuity/prepare-to-sync-realtime-continuity.ts +3 -3
  127. package/realtime-server/src/continuity/subscribe-to-continuity-actions.ts +2 -2
  128. package/realtime-server/src/continuity/subscribe-to-continuity-perpectives.ts +2 -2
  129. package/realtime-server/src/ipc-sockets/child-socket.ts +0 -1
  130. package/realtime-server/src/realtime-action-receiver.ts +1 -1
  131. package/realtime-server/src/realtime-family-provider.ts +2 -2
  132. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -2
  133. package/realtime-server/src/realtime-mutable-provider.ts +2 -2
  134. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +2 -1
  135. package/realtime-server/src/realtime-server-stores/server-room-external-store.ts +1 -1
  136. package/realtime-server/src/realtime-server-stores/server-user-store.ts +1 -2
  137. package/realtime-server/src/realtime-state-provider.ts +2 -2
  138. package/realtime-testing/dist/index.d.ts +1091 -3
  139. package/realtime-testing/dist/index.js +23 -26
  140. package/realtime-testing/src/setup-realtime-test.tsx +6 -5
  141. package/src/atom.ts +53 -29
  142. package/src/dispose-state.ts +12 -2
  143. package/{ephemeral/src → src}/find-state.ts +35 -25
  144. package/src/get-state.ts +16 -0
  145. package/src/index.ts +77 -3
  146. package/src/join.ts +218 -0
  147. package/src/realm.ts +169 -0
  148. package/src/selector.ts +20 -0
  149. package/src/set-state.ts +16 -8
  150. package/src/silo.ts +13 -7
  151. package/src/timeline.ts +1 -1
  152. package/src/transaction.ts +4 -8
  153. package/transceivers/set-rtx/dist/index.d.ts +37 -2
  154. package/transceivers/set-rtx/dist/index.js +1 -212
  155. package/transceivers/set-rtx/src/set-rtx.ts +4 -1
  156. package/web/dist/index.d.ts +30 -1
  157. package/web/dist/index.js +1 -15
  158. package/data/src/until.ts +0 -15
  159. package/dist/chunk-ICGFFQ3H.js +0 -272
  160. package/ephemeral/dist/index.d.ts +0 -57
  161. package/ephemeral/dist/index.js +0 -9
  162. package/ephemeral/package.json +0 -13
  163. package/ephemeral/src/index.ts +0 -1
  164. package/eslint-plugin/src/rules/lifespan.ts +0 -203
  165. package/immortal/dist/index.d.ts +0 -12
  166. package/immortal/dist/index.js +0 -9
  167. package/immortal/package.json +0 -13
  168. package/immortal/src/index.ts +0 -1
  169. package/immortal/src/seek-state.ts +0 -60
  170. package/src/allocate.ts +0 -443
  171. package/src/molecule.ts +0 -16
@@ -1,1002 +1,4 @@
1
+ export { ChildSocket, CustomSocket, ParentSocket, SubjectSocket, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, prepareToExposeRealtimeContinuity, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, redactTransactionUpdateContent, redactorAtoms, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets } from '../../dist/chunk-R3ZUK5EH.js';
2
+ import '../../dist/chunk-NF7FJKJD.js';
3
+ import '../../dist/chunk-GY2XQYZY.js';
1
4
  import '../../dist/chunk-XWL6SNVU.js';
2
- import { editRelationsInStore, join, findRelationsInStore } from 'atom.io/data';
3
- import { Subject, getFromStore, subscribeToState, findInStore, IMPLICIT, getJsonToken, getUpdateToken, isRootStore, actUponStore, setIntoStore, subscribeToTransaction } from 'atom.io/internal';
4
- import * as AtomIO from 'atom.io';
5
- import { atomFamily, selectorFamily, atom } from 'atom.io';
6
- import { roomIndex, usersInRooms } from 'atom.io/realtime';
7
- import { spawn } from 'node:child_process';
8
- import { parseJson, stringifyJson } from 'atom.io/json';
9
- import { SetRTX } from 'atom.io/transceivers/set-rtx';
10
-
11
- // realtime-server/src/ipc-sockets/custom-socket.ts
12
- var CustomSocket = class {
13
- constructor(emit) {
14
- this.emit = emit;
15
- this.listeners = /* @__PURE__ */ new Map();
16
- this.globalListeners = /* @__PURE__ */ new Set();
17
- }
18
- listeners;
19
- globalListeners;
20
- handleEvent(event, ...args) {
21
- for (const listener of this.globalListeners) {
22
- listener(event, ...args);
23
- }
24
- const listeners = this.listeners.get(event);
25
- if (listeners) {
26
- for (const listener of listeners) {
27
- listener(...args);
28
- }
29
- }
30
- }
31
- id = `no_id_retrieved`;
32
- on(event, listener) {
33
- const listeners = this.listeners.get(event);
34
- if (listeners) {
35
- listeners.add(listener);
36
- } else {
37
- this.listeners.set(event, /* @__PURE__ */ new Set([listener]));
38
- }
39
- return this;
40
- }
41
- onAny(listener) {
42
- this.globalListeners.add(listener);
43
- return this;
44
- }
45
- off(event, listener) {
46
- const listeners = this.listeners.get(event);
47
- if (listeners) {
48
- if (listener) {
49
- listeners.delete(listener);
50
- } else {
51
- this.listeners.delete(event);
52
- }
53
- }
54
- return this;
55
- }
56
- offAny(listener) {
57
- this.globalListeners.delete(listener);
58
- return this;
59
- }
60
- };
61
-
62
- // realtime-server/src/ipc-sockets/child-socket.ts
63
- var ChildSocket = class extends CustomSocket {
64
- incompleteData = ``;
65
- unprocessedEvents = [];
66
- incompleteLog = ``;
67
- unprocessedLogs = [];
68
- id = `#####`;
69
- process;
70
- key;
71
- logger;
72
- handleLog(arg) {
73
- if (Array.isArray(arg)) {
74
- const [level, ...rest] = arg;
75
- switch (level) {
76
- case `i`:
77
- this.logger.info(...rest);
78
- break;
79
- case `w`:
80
- this.logger.warn(...rest);
81
- break;
82
- case `e`:
83
- this.logger.error(...rest);
84
- break;
85
- }
86
- }
87
- }
88
- constructor(process2, key, logger) {
89
- super((event, ...args) => {
90
- const stringifiedEvent = JSON.stringify([event, ...args]) + ``;
91
- const errorHandler = (err) => {
92
- if (err.code === `EPIPE`) {
93
- console.error(`EPIPE error during write`, this.process.stdin);
94
- }
95
- this.process.stdin.removeListener(`error`, errorHandler);
96
- };
97
- this.process.stdin.once(`error`, errorHandler);
98
- this.process.stdin.write(stringifiedEvent);
99
- return this;
100
- });
101
- this.process = process2;
102
- this.key = key;
103
- this.logger = logger ?? {
104
- info: (...args) => {
105
- console.info(this.id, this.key, ...args);
106
- },
107
- warn: (...args) => {
108
- console.warn(this.id, this.key, ...args);
109
- },
110
- error: (...args) => {
111
- console.error(this.id, this.key, ...args);
112
- }
113
- };
114
- this.process.stdout.on(
115
- `data`,
116
- (buffer) => {
117
- const chunk = buffer.toString();
118
- if (chunk === `ALIVE`) {
119
- return;
120
- }
121
- this.unprocessedEvents.push(...chunk.split(``));
122
- const newInput = this.unprocessedEvents.shift();
123
- this.incompleteData += newInput ?? ``;
124
- try {
125
- if (this.incompleteData.startsWith(`error`)) {
126
- console.log(`\u2757`, this.incompleteData);
127
- }
128
- let parsedEvent = parseJson(this.incompleteData);
129
- this.handleEvent(...parsedEvent);
130
- while (this.unprocessedEvents.length > 0) {
131
- const event = this.unprocessedEvents.shift();
132
- if (event) {
133
- if (this.unprocessedEvents.length === 0) {
134
- this.incompleteData = event;
135
- }
136
- parsedEvent = parseJson(event);
137
- this.handleEvent(...parsedEvent);
138
- }
139
- }
140
- this.incompleteData = ``;
141
- } catch (error) {
142
- console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
143
- console.warn(this.incompleteData);
144
- console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
145
- console.error(error);
146
- }
147
- }
148
- );
149
- this.process.stderr.on(`data`, (buf) => {
150
- const chunk = buf.toString();
151
- this.unprocessedLogs.push(...chunk.split(``));
152
- const newInput = this.unprocessedLogs.shift();
153
- this.incompleteLog += newInput ?? ``;
154
- try {
155
- let parsedLog = parseJson(this.incompleteLog);
156
- this.handleLog(parsedLog);
157
- while (this.unprocessedLogs.length > 0) {
158
- this.incompleteLog = this.unprocessedLogs.shift() ?? ``;
159
- if (this.incompleteLog) {
160
- parsedLog = parseJson(this.incompleteLog);
161
- this.handleLog(parsedLog);
162
- }
163
- }
164
- } catch (error) {
165
- console.error(`\u274C\u274C\u274C`);
166
- console.error(this.incompleteLog);
167
- console.error(error);
168
- console.error(`\u274C\u274C\u274C\uFE0F`);
169
- }
170
- });
171
- if (process2.pid) {
172
- this.id = process2.pid.toString();
173
- }
174
- }
175
- };
176
- var SubjectSocket = class extends CustomSocket {
177
- in;
178
- out;
179
- id = `no_id_retrieved`;
180
- disposalFunctions = [];
181
- constructor(id) {
182
- super((...args) => {
183
- this.out.next(args);
184
- return this;
185
- });
186
- this.id = id;
187
- this.in = new Subject();
188
- this.out = new Subject();
189
- this.in.subscribe(`socket`, (event) => {
190
- this.handleEvent(...event);
191
- });
192
- }
193
- dispose() {
194
- for (const dispose of this.disposalFunctions) {
195
- dispose();
196
- }
197
- }
198
- };
199
- var ParentSocket = class extends CustomSocket {
200
- incompleteData = ``;
201
- unprocessedEvents = [];
202
- relays;
203
- relayServices;
204
- process;
205
- id = `#####`;
206
- log(...args) {
207
- this.process.stderr.write(
208
- stringifyJson(
209
- args.map(
210
- (arg) => arg instanceof SetRTX ? `{ ${arg.toJSON().members.join(` | `)} }` : arg
211
- )
212
- ) + ``
213
- );
214
- }
215
- logger = {
216
- info: (...args) => {
217
- this.log(`i`, ...args);
218
- },
219
- warn: (...args) => {
220
- this.log(`w`, ...args);
221
- },
222
- error: (...args) => {
223
- this.log(`e`, ...args);
224
- }
225
- };
226
- constructor() {
227
- super((event, ...args) => {
228
- const stringifiedEvent = JSON.stringify([event, ...args]);
229
- this.process.stdout.write(stringifiedEvent + ``);
230
- return this;
231
- });
232
- this.process = process;
233
- this.process.stdin.resume();
234
- this.relays = /* @__PURE__ */ new Map();
235
- this.relayServices = [];
236
- this.process.stdin.on(
237
- `data`,
238
- (buffer) => {
239
- const chunk = buffer.toString();
240
- this.unprocessedEvents.push(...chunk.split(``));
241
- const newInput = this.unprocessedEvents.shift();
242
- this.incompleteData += newInput ?? ``;
243
- try {
244
- const parsedData = parseJson(this.incompleteData);
245
- this.logger.info(`\u{1F3B0}`, `received`, parsedData);
246
- this.handleEvent(...parsedData);
247
- while (this.unprocessedEvents.length > 0) {
248
- const event = this.unprocessedEvents.shift();
249
- if (event) {
250
- if (this.unprocessedEvents.length === 0) {
251
- this.incompleteData = event;
252
- }
253
- const parsedEvent = parseJson(event);
254
- this.handleEvent(...parsedEvent);
255
- }
256
- }
257
- this.incompleteData = ``;
258
- } catch (thrown) {
259
- if (thrown instanceof Error) {
260
- this.logger.error(`\u2757`, thrown.message, thrown.cause, thrown.stack);
261
- }
262
- }
263
- }
264
- );
265
- this.on(`exit`, () => {
266
- this.logger.info(`\u{1F525}`, this.id, `received "exit"`);
267
- process.exit(0);
268
- });
269
- process.on(`exit`, (code) => {
270
- this.logger.info(`\u{1F525}`, this.id, `exited with code ${code}`);
271
- });
272
- process.on(`end`, () => {
273
- this.logger.info(`\u{1F525}`, this.id, `ended`);
274
- process.exit(0);
275
- });
276
- process.on(`SIGTERM`, () => {
277
- this.logger.error(`\u{1F525}`, this.id, `terminated`);
278
- process.exit(0);
279
- });
280
- process.on(`SIGINT`, () => {
281
- this.logger.error(`\u{1F525}`, this.id, `interrupted`);
282
- process.exit(0);
283
- });
284
- if (process.pid) {
285
- this.id = process.pid?.toString();
286
- }
287
- this.on(`user-joins`, (username) => {
288
- this.logger.info(`\u{1F464}`, `user`, username, `joined`);
289
- const relay = new SubjectSocket(`user:${username}`);
290
- this.relays.set(username, relay);
291
- this.logger.info(
292
- `\u{1F517}`,
293
- `attaching services:`,
294
- `[${[...this.relayServices.keys()].join(`, `)}]`
295
- );
296
- for (const attachServices of this.relayServices) {
297
- const cleanup = attachServices(relay);
298
- if (cleanup) {
299
- relay.disposalFunctions.push(cleanup);
300
- }
301
- }
302
- this.on(`user:${username}`, (...data) => {
303
- relay.in.next(data);
304
- });
305
- relay.out.subscribe(`socket`, (data) => {
306
- this.emit(...data);
307
- });
308
- });
309
- this.on(`user-leaves`, (username) => {
310
- const relay = this.relays.get(username);
311
- this.off(`relay:${username}`);
312
- if (relay) {
313
- relay.dispose();
314
- this.relays.delete(username);
315
- }
316
- });
317
- process.stdout.write(`ALIVE`);
318
- }
319
- relay(attachServices) {
320
- this.logger.info(`\u{1F517}`, `running relay method`);
321
- this.relayServices.push(attachServices);
322
- }
323
- };
324
-
325
- // realtime-server/src/realtime-server-stores/server-room-external-store.ts
326
- var roomArgumentsAtoms = atomFamily({
327
- key: `roomArguments`,
328
- default: [`echo`, [`Hello World!`]]
329
- });
330
- var roomSelectors = selectorFamily({
331
- key: `room`,
332
- get: (roomId) => async ({ get, find }) => {
333
- const argumentsState = find(roomArgumentsAtoms, roomId);
334
- const args = get(argumentsState);
335
- const [script, options] = args;
336
- const child = await new Promise(
337
- (resolve) => {
338
- const room = spawn(script, options, { env: process.env });
339
- const resolver = (data) => {
340
- if (data.toString() === `ALIVE`) {
341
- room.stdout.off(`data`, resolver);
342
- resolve(room);
343
- }
344
- };
345
- room.stdout.on(`data`, resolver);
346
- }
347
- );
348
- return new ChildSocket(child, roomId);
349
- }
350
- });
351
-
352
- // realtime-server/src/realtime-server-stores/server-room-external-actions.ts
353
- var createRoomTX = AtomIO.transaction({
354
- key: `createRoom`,
355
- do: ({ get, set, find }, roomId, script, options) => {
356
- const args = options ? [script, options] : [script];
357
- const roomArgumentsState = find(roomArgumentsAtoms, roomId);
358
- set(roomArgumentsState, args);
359
- set(roomIndex, (s) => s.add(roomId));
360
- const roomState = find(roomSelectors, roomId);
361
- const room = get(roomState);
362
- return room;
363
- }
364
- });
365
- var joinRoomTX = AtomIO.transaction({
366
- key: `joinRoom`,
367
- do: (tools, roomId, userId, enteredAtEpoch) => {
368
- const meta = { enteredAtEpoch };
369
- editRelationsInStore(
370
- usersInRooms,
371
- (relations) => {
372
- relations.set({ room: roomId, user: userId }, meta);
373
- },
374
- tools.env().store
375
- );
376
- return meta;
377
- }
378
- });
379
- var leaveRoomTX = AtomIO.transaction({
380
- key: `leaveRoom`,
381
- do: (tools, roomId, userId) => {
382
- editRelationsInStore(
383
- usersInRooms,
384
- (relations) => {
385
- relations.delete({ room: roomId, user: userId });
386
- },
387
- tools.env().store
388
- );
389
- }
390
- });
391
- var destroyRoomTX = AtomIO.transaction({
392
- key: `destroyRoom`,
393
- do: (tools, roomId) => {
394
- editRelationsInStore(
395
- usersInRooms,
396
- (relations) => {
397
- relations.delete({ room: roomId });
398
- },
399
- tools.env().store
400
- );
401
- tools.set(roomIndex, (s) => (s.delete(roomId), s));
402
- }
403
- });
404
- function redactTransactionUpdateContent(visibleStateKeys, updates) {
405
- return updates.map((update) => {
406
- switch (update.type) {
407
- case `transaction_update`: {
408
- const redacted = redactTransactionUpdateContent(
409
- visibleStateKeys,
410
- update.updates
411
- );
412
- return { ...update, updates: redacted };
413
- }
414
- default:
415
- return update;
416
- }
417
- }).filter((update) => {
418
- switch (update.type) {
419
- case `atom_update`:
420
- case `selector_update`:
421
- return visibleStateKeys.includes(update.key);
422
- case `state_creation`:
423
- return visibleStateKeys.includes(update.token.key);
424
- case `molecule_creation`:
425
- return true;
426
- case `transaction_update`:
427
- return true;
428
- }
429
- });
430
- }
431
- var redactorAtoms = atomFamily({
432
- key: `redactor`,
433
- default: { occlude: (updates) => updates }
434
- });
435
- var userUnacknowledgedQueues = atomFamily({
436
- key: `unacknowledgedUpdates`,
437
- default: () => []
438
- });
439
- var socketAtoms = atomFamily({
440
- key: `sockets`,
441
- default: null
442
- });
443
- var socketIndex = atom({
444
- key: `socketsIndex`,
445
- mutable: true,
446
- default: () => new SetRTX(),
447
- toJson: (set) => set.toJSON(),
448
- fromJson: (json) => SetRTX.fromJSON(json)
449
- });
450
- var userIndex = atom({
451
- key: `usersIndex`,
452
- mutable: true,
453
- default: () => new SetRTX(),
454
- toJson: (set) => set.toJSON(),
455
- fromJson: (json) => SetRTX.fromJSON(json)
456
- });
457
- var usersOfSockets = join({
458
- key: `usersOfSockets`,
459
- between: [`user`, `socket`],
460
- cardinality: `1:1`,
461
- isAType: (s) => s.startsWith(`user::`),
462
- isBType: (s) => s.startsWith(`socket::`)
463
- });
464
- function prepareToSendInitialPayload(store, continuity, userKey, socket) {
465
- const continuityKey = continuity.key;
466
- return function sendInitialPayload() {
467
- const initialPayload = [];
468
- for (const atom2 of continuity.globals) {
469
- const resourceToken = atom2.type === `mutable_atom` ? getJsonToken(store, atom2) : atom2;
470
- const resource = getFromStore(store, resourceToken);
471
- initialPayload.push(resourceToken, resource);
472
- }
473
- for (const perspective of continuity.perspectives) {
474
- const { viewAtoms, resourceAtoms } = perspective;
475
- const userViewState = findInStore(store, viewAtoms, userKey);
476
- const userView = getFromStore(store, userViewState);
477
- store.logger.info(`\u{1F441}`, `atom`, resourceAtoms.key, `${userKey} can see`, {
478
- viewAtoms,
479
- resourceAtoms,
480
- userView
481
- });
482
- for (const visibleToken of userView) {
483
- const resourceToken = visibleToken.type === `mutable_atom` ? getJsonToken(store, visibleToken) : visibleToken;
484
- const resource = getFromStore(store, resourceToken);
485
- initialPayload.push(resourceToken, resource);
486
- }
487
- }
488
- const epoch = isRootStore(store) ? store.transactionMeta.epoch.get(continuityKey) ?? null : null;
489
- socket?.emit(`continuity-init:${continuityKey}`, epoch, initialPayload);
490
- };
491
- }
492
- function prepareToServeTransactionRequest(store, continuity, userKey) {
493
- const continuityKey = continuity.key;
494
- return function serveTransactionRequest(update) {
495
- store.logger.info(`\u{1F6CE}\uFE0F`, `continuity`, continuityKey, `received`, update);
496
- const transactionKey = update.key;
497
- const updateId = update.id;
498
- const performanceKey = `tx-run:${transactionKey}:${updateId}`;
499
- const performanceKeyStart = `${performanceKey}:start`;
500
- const performanceKeyEnd = `${performanceKey}:end`;
501
- performance.mark(performanceKeyStart);
502
- try {
503
- actUponStore(
504
- { type: `transaction`, key: transactionKey },
505
- updateId,
506
- store
507
- )(...update.params);
508
- } catch (thrown) {
509
- if (thrown instanceof Error) {
510
- store.logger.error(
511
- `\u274C`,
512
- `continuity`,
513
- continuityKey,
514
- `failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,
515
- thrown.message
516
- );
517
- }
518
- }
519
- performance.mark(performanceKeyEnd);
520
- const metric = performance.measure(
521
- performanceKey,
522
- performanceKeyStart,
523
- performanceKeyEnd
524
- );
525
- store?.logger.info(
526
- `\u{1F680}`,
527
- `transaction`,
528
- transactionKey,
529
- updateId,
530
- userKey,
531
- metric.duration
532
- );
533
- };
534
- }
535
- function prepareToTrackClientAcknowledgement(store, continuity, userKey, userUnacknowledgedUpdates) {
536
- const continuityKey = continuity.key;
537
- return function trackClientAcknowledgement(epoch) {
538
- store.logger.info(
539
- `\u{1F44D}`,
540
- `continuity`,
541
- continuityKey,
542
- `${userKey} acknowledged epoch ${epoch}`
543
- );
544
- const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch;
545
- if (isUnacknowledged) {
546
- setIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {
547
- updates.shift();
548
- store.logger.info(
549
- `\u{1F44D}`,
550
- `continuity`,
551
- continuityKey,
552
- `${userKey} unacknowledged update queue now has`,
553
- updates.length,
554
- `items`
555
- );
556
- return updates;
557
- });
558
- }
559
- };
560
- }
561
- function subscribeToContinuityActions(store, continuity, userKey, socket) {
562
- const continuityKey = continuity.key;
563
- const unsubscribeFunctions = [];
564
- for (const transaction2 of continuity.actions) {
565
- const unsubscribeFromTransaction = subscribeToTransaction(
566
- transaction2,
567
- (update) => {
568
- try {
569
- const visibleKeys = continuity.globals.map((atom2) => {
570
- if (atom2.type === `atom`) {
571
- return atom2.key;
572
- }
573
- return getUpdateToken(atom2).key;
574
- }).concat(
575
- continuity.perspectives.flatMap((perspective) => {
576
- const { viewAtoms } = perspective;
577
- const userPerspectiveTokenState = findInStore(
578
- store,
579
- viewAtoms,
580
- userKey
581
- );
582
- const visibleTokens = getFromStore(
583
- store,
584
- userPerspectiveTokenState
585
- );
586
- return visibleTokens.map((token) => {
587
- const key = token.type === `mutable_atom` ? `*` + token.key : token.key;
588
- return key;
589
- });
590
- })
591
- );
592
- const redactedUpdates = redactTransactionUpdateContent(
593
- visibleKeys,
594
- update.updates
595
- );
596
- const redactedUpdate = {
597
- ...update,
598
- updates: redactedUpdates
599
- };
600
- setIntoStore(store, userUnacknowledgedQueues, userKey, (updates) => {
601
- if (redactedUpdate) {
602
- updates.push(redactedUpdate);
603
- updates.sort((a, b) => a.epoch - b.epoch);
604
- store.logger.info(
605
- `\u{1F44D}`,
606
- `continuity`,
607
- continuityKey,
608
- `${userKey} unacknowledged update queue now has`,
609
- updates.length,
610
- `items`
611
- );
612
- }
613
- return updates;
614
- });
615
- socket?.emit(
616
- `tx-new:${continuityKey}`,
617
- redactedUpdate
618
- );
619
- } catch (thrown) {
620
- if (thrown instanceof Error) {
621
- store.logger.error(
622
- `\u274C`,
623
- `continuity`,
624
- continuityKey,
625
- `${userKey} failed to send update from transaction ${transaction2.key} to ${userKey}`,
626
- thrown.message
627
- );
628
- }
629
- }
630
- },
631
- `sync-continuity:${continuityKey}:${userKey}`,
632
- store
633
- );
634
- unsubscribeFunctions.push(unsubscribeFromTransaction);
635
- }
636
- return unsubscribeFunctions;
637
- }
638
- function subscribeToContinuityPerspectives(store, continuity, userKey, socket) {
639
- const continuityKey = continuity.key;
640
- const unsubFns = [];
641
- for (const perspective of continuity.perspectives) {
642
- const { viewAtoms } = perspective;
643
- const userViewState = findInStore(store, viewAtoms, userKey);
644
- const unsubscribeFromUserView = subscribeToState(
645
- userViewState,
646
- ({ oldValue, newValue }) => {
647
- const oldKeys = oldValue.map((token) => token.key);
648
- const newKeys = newValue.map((token) => token.key);
649
- const concealed = oldValue.filter(
650
- (token) => !newKeys.includes(token.key)
651
- );
652
- const revealed = newValue.filter((token) => !oldKeys.includes(token.key)).flatMap((token) => {
653
- const resourceToken = token.type === `mutable_atom` ? getJsonToken(store, token) : token;
654
- const resource = getFromStore(store, resourceToken);
655
- return [resourceToken, resource];
656
- });
657
- store.logger.info(
658
- `\u{1F441}`,
659
- `atom`,
660
- perspective.resourceAtoms.key,
661
- `${userKey} has a new perspective`,
662
- { oldKeys, newKeys, revealed, concealed }
663
- );
664
- if (revealed.length > 0) {
665
- socket?.emit(`reveal:${continuityKey}`, revealed);
666
- }
667
- if (concealed.length > 0) {
668
- socket?.emit(`conceal:${continuityKey}`, concealed);
669
- }
670
- },
671
- `sync-continuity:${continuityKey}:${userKey}:perspective:${perspective.resourceAtoms.key}`,
672
- store
673
- );
674
- unsubFns.push(unsubscribeFromUserView);
675
- }
676
- return unsubFns;
677
- }
678
-
679
- // realtime-server/src/continuity/prepare-to-sync-realtime-continuity.ts
680
- function prepareToExposeRealtimeContinuity({
681
- socket: initialSocket,
682
- store = IMPLICIT.STORE
683
- }) {
684
- return function syncRealtimeContinuity(continuity) {
685
- let socket = initialSocket;
686
- const continuityKey = continuity.key;
687
- const userKeyState = findRelationsInStore(
688
- usersOfSockets,
689
- `socket::${socket.id}`,
690
- store
691
- ).userKeyOfSocket;
692
- const userKey = getFromStore(store, userKeyState);
693
- if (!userKey) {
694
- store.logger.error(
695
- `\u274C`,
696
- `continuity`,
697
- continuityKey,
698
- `Tried to create a synchronizer for a socket (${socket.id}) that is not connected to a user.`
699
- );
700
- return () => {
701
- };
702
- }
703
- const socketKeyState = findRelationsInStore(
704
- usersOfSockets,
705
- userKey,
706
- store
707
- ).socketKeyOfUser;
708
- subscribeToState(
709
- socketKeyState,
710
- ({ newValue: newSocketKey }) => {
711
- store.logger.info(
712
- `\u{1F44B}`,
713
- `continuity`,
714
- continuityKey,
715
- `seeing ${userKey} on new socket ${newSocketKey}`
716
- );
717
- if (newSocketKey === null) {
718
- store.logger.warn(
719
- `\u274C`,
720
- `continuity`,
721
- continuityKey,
722
- `User (${userKey}) is not connected to a socket, waiting for them to reappear.`
723
- );
724
- return;
725
- }
726
- const newSocketState = findInStore(store, socketAtoms, newSocketKey);
727
- const newSocket = getFromStore(store, newSocketState);
728
- socket = newSocket;
729
- for (const unacknowledgedUpdate of userUnacknowledgedUpdates) {
730
- socket?.emit(
731
- `tx-new:${continuityKey}`,
732
- unacknowledgedUpdate
733
- );
734
- }
735
- },
736
- `sync-continuity:${continuityKey}:${userKey}`,
737
- store
738
- );
739
- const userUnacknowledgedUpdates = getFromStore(
740
- store,
741
- userUnacknowledgedQueues,
742
- userKey
743
- );
744
- const unsubscribeFunctions = [];
745
- const unsubscribeFromPerspectives = subscribeToContinuityPerspectives(
746
- store,
747
- continuity,
748
- userKey,
749
- socket
750
- );
751
- const unsubscribeFromTransactions = subscribeToContinuityActions(
752
- store,
753
- continuity,
754
- userKey,
755
- socket
756
- );
757
- unsubscribeFunctions.push(
758
- ...unsubscribeFromPerspectives,
759
- ...unsubscribeFromTransactions
760
- );
761
- const sendInitialPayload = prepareToSendInitialPayload(
762
- store,
763
- continuity,
764
- userKey,
765
- initialSocket
766
- );
767
- socket.off(`get:${continuityKey}`, sendInitialPayload);
768
- socket.on(`get:${continuityKey}`, sendInitialPayload);
769
- const fillTransactionRequest = prepareToServeTransactionRequest(
770
- store,
771
- continuity,
772
- userKey
773
- );
774
- socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
775
- socket.on(`tx-run:${continuityKey}`, fillTransactionRequest);
776
- const trackClientAcknowledgement = prepareToTrackClientAcknowledgement(
777
- store,
778
- continuity,
779
- userKey,
780
- userUnacknowledgedUpdates
781
- );
782
- socket?.on(`ack:${continuityKey}`, trackClientAcknowledgement);
783
- return () => {
784
- for (const unsubscribe of unsubscribeFunctions) unsubscribe();
785
- socket?.off(`ack:${continuityKey}`, trackClientAcknowledgement);
786
- socket?.off(`get:${continuityKey}`, sendInitialPayload);
787
- socket?.off(`tx-run:${continuityKey}`, fillTransactionRequest);
788
- };
789
- };
790
- }
791
- function realtimeActionReceiver({
792
- socket,
793
- store = IMPLICIT.STORE
794
- }) {
795
- return function actionReceiver(tx) {
796
- const fillTransactionRequest = (update) => {
797
- const performanceKey = `tx-run:${tx.key}:${update.id}`;
798
- const performanceKeyStart = `${performanceKey}:start`;
799
- const performanceKeyEnd = `${performanceKey}:end`;
800
- performance.mark(performanceKeyStart);
801
- actUponStore(tx, update.id, store)(...update.params);
802
- performance.mark(performanceKeyEnd);
803
- const metric = performance.measure(
804
- performanceKey,
805
- performanceKeyStart,
806
- performanceKeyEnd
807
- );
808
- store?.logger.info(`\u{1F680}`, `transaction`, tx.key, update.id, metric.duration);
809
- };
810
- socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
811
- return () => {
812
- socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
813
- };
814
- };
815
- }
816
- function realtimeAtomFamilyProvider({
817
- socket,
818
- store = IMPLICIT.STORE
819
- }) {
820
- return function familyProvider(family, index) {
821
- const unsubCallbacksByKey = /* @__PURE__ */ new Map();
822
- const fillUnsubRequest = (key) => {
823
- socket.off(`unsub:${key}`, fillUnsubRequest);
824
- const unsub = unsubCallbacksByKey.get(key);
825
- if (unsub) {
826
- unsub();
827
- unsubCallbacksByKey.delete(key);
828
- }
829
- };
830
- const fillSubRequest = (subKey) => {
831
- const exposedSubKeys = getFromStore(store, index);
832
- for (const exposedSubKey of exposedSubKeys) {
833
- if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
834
- const token = findInStore(store, family, subKey);
835
- socket.emit(`serve:${token.key}`, getFromStore(store, token));
836
- const unsubscribe = subscribeToState(
837
- token,
838
- ({ newValue }) => {
839
- socket.emit(`serve:${token.key}`, newValue);
840
- },
841
- `expose-family:${family.key}:${socket.id}`,
842
- store
843
- );
844
- unsubCallbacksByKey.set(token.key, unsubscribe);
845
- socket.on(`unsub:${token.key}`, () => {
846
- fillUnsubRequest(token.key);
847
- });
848
- break;
849
- }
850
- }
851
- };
852
- socket.on(`sub:${family.key}`, fillSubRequest);
853
- return () => {
854
- socket.off(`sub:${family.key}`, fillSubRequest);
855
- for (const [, unsub] of unsubCallbacksByKey) {
856
- unsub();
857
- }
858
- unsubCallbacksByKey.clear();
859
- };
860
- };
861
- }
862
- function realtimeMutableFamilyProvider({
863
- socket,
864
- store = IMPLICIT.STORE
865
- }) {
866
- return function mutableFamilyProvider(family, index) {
867
- const unsubCallbacksByKey = /* @__PURE__ */ new Map();
868
- const fillUnsubRequest = (key) => {
869
- socket.off(`unsub:${key}`, fillUnsubRequest);
870
- const unsub = unsubCallbacksByKey.get(key);
871
- if (unsub) {
872
- unsub();
873
- unsubCallbacksByKey.delete(key);
874
- }
875
- };
876
- const fillSubRequest = (subKey) => {
877
- const exposedSubKeys = getFromStore(store, index);
878
- for (const exposedSubKey of exposedSubKeys) {
879
- if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
880
- const token = findInStore(store, family, subKey);
881
- getFromStore(store, token);
882
- const jsonToken = getJsonToken(store, token);
883
- const updateToken = getUpdateToken(token);
884
- socket.emit(`init:${token.key}`, getFromStore(store, jsonToken));
885
- const unsubscribe = subscribeToState(
886
- updateToken,
887
- ({ newValue }) => {
888
- socket.emit(`next:${token.key}`, newValue);
889
- },
890
- `expose-family:${family.key}:${socket.id}`,
891
- store
892
- );
893
- unsubCallbacksByKey.set(token.key, unsubscribe);
894
- socket.on(`unsub:${token.key}`, () => {
895
- fillUnsubRequest(token.key);
896
- });
897
- break;
898
- }
899
- }
900
- };
901
- socket.on(`sub:${family.key}`, fillSubRequest);
902
- return () => {
903
- socket.off(`sub:${family.key}`, fillSubRequest);
904
- for (const [, unsub] of unsubCallbacksByKey) {
905
- unsub();
906
- }
907
- unsubCallbacksByKey.clear();
908
- };
909
- };
910
- }
911
- function realtimeMutableProvider({
912
- socket,
913
- store = IMPLICIT.STORE
914
- }) {
915
- return function mutableProvider(token) {
916
- let unsubscribeFromStateUpdates = null;
917
- const jsonToken = getJsonToken(store, token);
918
- const trackerToken = getUpdateToken(token);
919
- const fillUnsubRequest = () => {
920
- socket.off(`unsub:${token.key}`, fillUnsubRequest);
921
- unsubscribeFromStateUpdates?.();
922
- unsubscribeFromStateUpdates = null;
923
- };
924
- const fillSubRequest = () => {
925
- socket.emit(`init:${token.key}`, getFromStore(store, jsonToken));
926
- unsubscribeFromStateUpdates = subscribeToState(
927
- trackerToken,
928
- ({ newValue }) => {
929
- socket.emit(`next:${token.key}`, newValue);
930
- },
931
- `expose-single:${socket.id}`,
932
- store
933
- );
934
- socket.on(`unsub:${token.key}`, fillUnsubRequest);
935
- };
936
- socket.on(`sub:${token.key}`, fillSubRequest);
937
- return () => {
938
- socket.off(`sub:${token.key}`, fillSubRequest);
939
- unsubscribeFromStateUpdates?.();
940
- };
941
- };
942
- }
943
- function realtimeStateProvider({
944
- socket,
945
- store = IMPLICIT.STORE
946
- }) {
947
- return function stateProvider(token) {
948
- let unsubscribeFromStateUpdates;
949
- const fillSubRequest = () => {
950
- socket.emit(`serve:${token.key}`, getFromStore(store, token));
951
- unsubscribeFromStateUpdates = subscribeToState(
952
- token,
953
- ({ newValue }) => {
954
- socket.emit(`serve:${token.key}`, newValue);
955
- },
956
- `expose-single:${socket.id}`,
957
- store
958
- );
959
- const fillUnsubRequest = () => {
960
- socket.off(`unsub:${token.key}`, fillUnsubRequest);
961
- if (unsubscribeFromStateUpdates) {
962
- unsubscribeFromStateUpdates();
963
- unsubscribeFromStateUpdates = undefined;
964
- }
965
- };
966
- socket.on(`unsub:${token.key}`, fillUnsubRequest);
967
- };
968
- socket.on(`sub:${token.key}`, fillSubRequest);
969
- return () => {
970
- socket.off(`sub:${token.key}`, fillSubRequest);
971
- if (unsubscribeFromStateUpdates) {
972
- unsubscribeFromStateUpdates();
973
- unsubscribeFromStateUpdates = undefined;
974
- }
975
- };
976
- };
977
- }
978
- function realtimeStateReceiver({
979
- socket,
980
- store = IMPLICIT.STORE
981
- }) {
982
- return function stateReceiver(token) {
983
- const publish = (newValue) => {
984
- setIntoStore(store, token, newValue);
985
- };
986
- const fillPubUnclaim = () => {
987
- socket.off(`pub:${token.key}`, publish);
988
- socket.off(`unclaim:${token.key}`, fillPubUnclaim);
989
- };
990
- const fillPubClaim = () => {
991
- socket.on(`pub:${token.key}`, publish);
992
- socket.on(`unclaim:${token.key}`, fillPubUnclaim);
993
- };
994
- socket.on(`claim:${token.key}`, fillPubClaim);
995
- return () => {
996
- socket.off(`claim:${token.key}`, fillPubClaim);
997
- socket.off(`pub:${token.key}`, publish);
998
- };
999
- };
1000
- }
1001
-
1002
- export { ChildSocket, CustomSocket, ParentSocket, SubjectSocket, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, prepareToExposeRealtimeContinuity, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, redactTransactionUpdateContent, redactorAtoms, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets };