atom.io 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/data/dist/index.cjs +62 -40
  2. package/data/dist/index.cjs.map +1 -1
  3. package/data/dist/index.d.ts +8 -2
  4. package/data/dist/index.js +64 -42
  5. package/data/dist/index.js.map +1 -1
  6. package/data/src/dict.ts +8 -4
  7. package/data/src/join.ts +74 -33
  8. package/data/src/struct-family.ts +18 -17
  9. package/dist/chunk-IZHOMSXA.js +331 -0
  10. package/dist/chunk-IZHOMSXA.js.map +1 -0
  11. package/dist/chunk-JDUNWJFB.js +18 -0
  12. package/dist/chunk-JDUNWJFB.js.map +1 -0
  13. package/dist/index.cjs +4 -10
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.ts +66 -51
  16. package/dist/index.js +5 -11
  17. package/dist/index.js.map +1 -1
  18. package/internal/dist/index.cjs +187 -58
  19. package/internal/dist/index.cjs.map +1 -1
  20. package/internal/dist/index.d.ts +95 -71
  21. package/internal/dist/index.js +179 -53
  22. package/internal/dist/index.js.map +1 -1
  23. package/internal/src/arbitrary.ts +3 -0
  24. package/internal/src/atom/delete-atom.ts +7 -6
  25. package/internal/src/caching.ts +6 -4
  26. package/internal/src/families/find-in-store.ts +16 -0
  27. package/internal/src/get-environment-data.ts +4 -7
  28. package/internal/src/index.ts +6 -5
  29. package/internal/src/ingest-updates/ingest-atom-update.ts +6 -2
  30. package/internal/src/ingest-updates/ingest-transaction-update.ts +0 -1
  31. package/internal/src/selector/create-standalone-selector.ts +0 -2
  32. package/internal/src/set-state/copy-mutable-if-needed.ts +5 -0
  33. package/internal/src/set-state/emit-update.ts +25 -11
  34. package/internal/src/set-state/set-atom.ts +15 -18
  35. package/internal/src/store/store.ts +14 -2
  36. package/internal/src/store/withdraw.ts +72 -2
  37. package/internal/src/subscribe/subscribe-to-timeline.ts +2 -2
  38. package/internal/src/subscribe/subscribe-to-transaction.ts +2 -2
  39. package/internal/src/timeline/create-timeline.ts +12 -1
  40. package/internal/src/transaction/act-upon-store.ts +19 -0
  41. package/internal/src/transaction/apply-transaction.ts +6 -1
  42. package/internal/src/transaction/assign-transaction-to-continuity.ts +18 -0
  43. package/internal/src/transaction/build-transaction.ts +7 -6
  44. package/internal/src/transaction/create-transaction.ts +1 -1
  45. package/internal/src/transaction/get-epoch-number.ts +40 -0
  46. package/internal/src/transaction/index.ts +10 -1
  47. package/internal/src/transaction/set-epoch-number.ts +30 -0
  48. package/introspection/dist/index.cjs.map +1 -1
  49. package/introspection/dist/index.d.ts +3 -3
  50. package/introspection/dist/index.js.map +1 -1
  51. package/introspection/src/attach-introspection-states.ts +6 -2
  52. package/introspection/src/attach-timeline-family.ts +5 -2
  53. package/introspection/src/attach-transaction-logs.ts +2 -2
  54. package/json/dist/index.d.ts +3 -1
  55. package/json/src/index.ts +4 -0
  56. package/package.json +241 -230
  57. package/react/dist/index.cjs.map +1 -1
  58. package/react/dist/index.d.ts +1 -1
  59. package/react/dist/index.js.map +1 -1
  60. package/react/src/use-json.ts +1 -1
  61. package/react-devtools/dist/index.cjs +131 -134
  62. package/react-devtools/dist/index.cjs.map +1 -1
  63. package/react-devtools/dist/index.css +2 -2
  64. package/react-devtools/dist/index.css.map +1 -1
  65. package/react-devtools/dist/index.d.ts +3 -3
  66. package/react-devtools/dist/index.js +91 -108
  67. package/react-devtools/dist/index.js.map +1 -1
  68. package/react-devtools/src/StateEditor.tsx +4 -4
  69. package/react-devtools/src/StateIndex.tsx +1 -4
  70. package/react-devtools/src/TimelineIndex.tsx +3 -3
  71. package/react-devtools/src/TransactionIndex.tsx +9 -8
  72. package/react-devtools/src/index.ts +2 -2
  73. package/realtime/dist/index.cjs +120 -0
  74. package/realtime/dist/index.cjs.map +1 -0
  75. package/realtime/dist/index.d.ts +146 -0
  76. package/realtime/dist/index.js +111 -0
  77. package/realtime/dist/index.js.map +1 -0
  78. package/realtime/package.json +16 -0
  79. package/realtime/src/index.ts +2 -0
  80. package/realtime/src/realtime-continuity.ts +162 -0
  81. package/realtime/src/shared-room-store.ts +48 -0
  82. package/realtime-client/dist/index.cjs +424 -170
  83. package/realtime-client/dist/index.cjs.map +1 -1
  84. package/realtime-client/dist/index.d.ts +15 -11
  85. package/realtime-client/dist/index.js +96 -177
  86. package/realtime-client/dist/index.js.map +1 -1
  87. package/realtime-client/src/index.ts +8 -7
  88. package/realtime-client/src/{pull-family-member.ts → pull-atom-family-member.ts} +2 -2
  89. package/realtime-client/src/{pull-state.ts → pull-atom.ts} +2 -2
  90. package/realtime-client/src/{pull-mutable-family-member.ts → pull-mutable-atom-family-member.ts} +6 -6
  91. package/realtime-client/src/{pull-mutable.ts → pull-mutable-atom.ts} +1 -1
  92. package/realtime-client/src/pull-selector-family-member.ts +42 -0
  93. package/realtime-client/src/pull-selector.ts +38 -0
  94. package/realtime-client/src/realtime-client-stores/client-main-store.ts +12 -2
  95. package/realtime-client/src/realtime-client-stores/client-sync-store.ts +7 -7
  96. package/realtime-client/src/sync-continuity.ts +368 -0
  97. package/realtime-react/dist/index.cjs +367 -27
  98. package/realtime-react/dist/index.cjs.map +1 -1
  99. package/realtime-react/dist/index.d.ts +24 -8
  100. package/realtime-react/dist/index.js +38 -22
  101. package/realtime-react/dist/index.js.map +1 -1
  102. package/realtime-react/src/index.ts +6 -5
  103. package/realtime-react/src/use-pull-atom-family-member.ts +21 -0
  104. package/realtime-react/src/{use-sync.ts → use-pull-atom.ts} +4 -4
  105. package/realtime-react/src/{use-pull-mutable.ts → use-pull-mutable-atom.ts} +4 -3
  106. package/realtime-react/src/use-pull-mutable-family-member.ts +9 -4
  107. package/realtime-react/src/use-pull-selector-family-member.ts +21 -0
  108. package/realtime-react/src/{use-pull.ts → use-pull-selector.ts} +7 -5
  109. package/realtime-react/src/use-push.ts +3 -2
  110. package/realtime-react/src/use-server-action.ts +3 -2
  111. package/realtime-react/src/use-sync-continuity.ts +12 -0
  112. package/realtime-server/dist/index.cjs +769 -371
  113. package/realtime-server/dist/index.cjs.map +1 -1
  114. package/realtime-server/dist/index.d.ts +130 -60
  115. package/realtime-server/dist/index.js +753 -361
  116. package/realtime-server/dist/index.js.map +1 -1
  117. package/realtime-server/src/index.ts +17 -3
  118. package/realtime-server/src/ipc-sockets/child-socket.ts +135 -0
  119. package/realtime-server/src/ipc-sockets/custom-socket.ts +90 -0
  120. package/realtime-server/src/ipc-sockets/index.ts +3 -0
  121. package/realtime-server/src/ipc-sockets/parent-socket.ts +185 -0
  122. package/realtime-server/src/realtime-action-receiver.ts +8 -5
  123. package/realtime-server/src/realtime-continuity-synchronizer.ts +376 -0
  124. package/realtime-server/src/realtime-family-provider.ts +30 -71
  125. package/realtime-server/src/realtime-mutable-family-provider.ts +24 -86
  126. package/realtime-server/src/realtime-server-stores/index.ts +4 -1
  127. package/realtime-server/src/realtime-server-stores/realtime-continuity-store.ts +109 -0
  128. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +64 -0
  129. package/realtime-server/src/realtime-server-stores/server-room-external-store.ts +42 -0
  130. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +51 -98
  131. package/realtime-server/src/realtime-server-stores/server-user-store.ts +14 -29
  132. package/realtime-server/src/realtime-state-receiver.ts +0 -1
  133. package/realtime-testing/dist/index.cjs +34 -32
  134. package/realtime-testing/dist/index.cjs.map +1 -1
  135. package/realtime-testing/dist/index.d.ts +1 -0
  136. package/realtime-testing/dist/index.js +33 -31
  137. package/realtime-testing/dist/index.js.map +1 -1
  138. package/realtime-testing/src/setup-realtime-test.tsx +44 -32
  139. package/src/atom.ts +49 -31
  140. package/src/logger.ts +14 -5
  141. package/src/selector.ts +44 -25
  142. package/src/subscribe.ts +2 -1
  143. package/src/timeline.ts +4 -4
  144. package/src/transaction.ts +13 -17
  145. package/src/validators.ts +15 -9
  146. package/dist/chunk-H4Q5FTPZ.js +0 -11
  147. package/dist/chunk-H4Q5FTPZ.js.map +0 -1
  148. package/internal/src/set-state/copy-mutable-in-transaction.ts +0 -19
  149. package/realtime-client/src/sync-server-action.ts +0 -170
  150. package/realtime-client/src/sync-state.ts +0 -19
  151. package/realtime-react/src/use-pull-family-member.ts +0 -16
  152. package/realtime-react/src/use-sync-server-action.ts +0 -16
  153. package/realtime-server/src/realtime-action-synchronizer.ts +0 -152
@@ -1,118 +1,728 @@
1
1
  import { __spreadProps, __spreadValues } from '../../dist/chunk-PZLG2HP3.js';
2
+ import { parseJson, stringifyJson } from 'atom.io/json';
3
+ import { getUpdateToken, IMPLICIT, Subject, findInStore, getFromStore, subscribeToState, getJsonToken, isRootStore, subscribeToTransaction, actUponStore, setIntoStore } from 'atom.io/internal';
4
+ import { SetRTX } from 'atom.io/transceivers/set-rtx';
2
5
  import * as AtomIO from 'atom.io';
3
- import { atom, atomFamily, selectorFamily } from 'atom.io';
6
+ import { selectorFamily, atomFamily, atom } from 'atom.io';
7
+ import { SyncGroup, roomIndex, usersInRooms } from 'atom.io/realtime';
8
+ import { spawn } from 'child_process';
4
9
  import { join } from 'atom.io/data';
5
- import { SetRTX } from 'atom.io/transceivers/set-rtx';
6
- import { IMPLICIT, getJsonToken, getUpdateToken, findInStore, getFromStore, setIntoStore, subscribeToState, subscribeToTransaction } from 'atom.io/internal';
7
- import { parseJson } from 'atom.io/json';
8
10
 
9
- var userIndex = atom({
10
- key: `usersIndex`,
11
- mutable: true,
12
- default: () => new SetRTX(),
13
- toJson: (set) => set.toJSON(),
14
- fromJson: (json) => SetRTX.fromJSON(json)
11
+ // realtime-server/src/ipc-sockets/custom-socket.ts
12
+ var CustomSocket = class {
13
+ constructor(emit) {
14
+ this.emit = emit;
15
+ this.id = `no_id_retrieved`;
16
+ this.listeners = /* @__PURE__ */ new Map();
17
+ this.globalListeners = /* @__PURE__ */ new Set();
18
+ }
19
+ handleEvent(event, ...args) {
20
+ for (const listener of this.globalListeners) {
21
+ listener(event, ...args);
22
+ }
23
+ const listeners = this.listeners.get(event);
24
+ if (listeners) {
25
+ for (const listener of listeners) {
26
+ listener(...args);
27
+ }
28
+ }
29
+ }
30
+ on(event, listener) {
31
+ const listeners = this.listeners.get(event);
32
+ if (listeners) {
33
+ listeners.add(listener);
34
+ } else {
35
+ this.listeners.set(event, /* @__PURE__ */ new Set([listener]));
36
+ }
37
+ return this;
38
+ }
39
+ onAny(listener) {
40
+ this.globalListeners.add(listener);
41
+ return this;
42
+ }
43
+ off(event, listener) {
44
+ const listeners = this.listeners.get(event);
45
+ if (listeners) {
46
+ if (listener) {
47
+ listeners.delete(listener);
48
+ } else {
49
+ this.listeners.delete(event);
50
+ }
51
+ }
52
+ return this;
53
+ }
54
+ offAny(listener) {
55
+ this.globalListeners.delete(listener);
56
+ return this;
57
+ }
58
+ };
59
+
60
+ // realtime-server/src/ipc-sockets/child-socket.ts
61
+ var ChildSocket = class extends CustomSocket {
62
+ constructor(process2, key, logger = console) {
63
+ super((event, ...args) => {
64
+ const stringifiedEvent = JSON.stringify([event, ...args]) + ``;
65
+ const errorHandler = (err) => {
66
+ if (err.code === `EPIPE`) {
67
+ console.error(`EPIPE error during write`, this.process.stdin);
68
+ }
69
+ this.process.stdin.removeListener(`error`, errorHandler);
70
+ };
71
+ this.process.stdin.once(`error`, errorHandler);
72
+ this.process.stdin.write(stringifiedEvent);
73
+ return this;
74
+ });
75
+ this.process = process2;
76
+ this.key = key;
77
+ this.logger = logger;
78
+ this.incompleteData = ``;
79
+ this.unprocessedEvents = [];
80
+ this.incompleteLog = ``;
81
+ this.unprocessedLogs = [];
82
+ this.id = `#####`;
83
+ this.process = process2;
84
+ this.process.stdout.on(
85
+ `data`,
86
+ (buffer) => {
87
+ const chunk = buffer.toString();
88
+ if (chunk === `\u2728`) {
89
+ return;
90
+ }
91
+ this.unprocessedEvents.push(...chunk.split(``));
92
+ const newInput = this.unprocessedEvents.shift();
93
+ this.incompleteData += newInput || ``;
94
+ try {
95
+ if (this.incompleteData.startsWith(`error`)) {
96
+ console.log(`\u2757`, this.incompleteData);
97
+ }
98
+ const parsedEvent = parseJson(this.incompleteData);
99
+ this.handleEvent(...parsedEvent);
100
+ while (this.unprocessedEvents.length > 0) {
101
+ const event = this.unprocessedEvents.shift();
102
+ if (event) {
103
+ if (this.unprocessedEvents.length === 0) {
104
+ this.incompleteData = event;
105
+ }
106
+ const parsedEvent2 = parseJson(event);
107
+ this.handleEvent(...parsedEvent2);
108
+ }
109
+ }
110
+ this.incompleteData = ``;
111
+ } catch (error) {
112
+ console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
113
+ console.warn(this.incompleteData);
114
+ console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
115
+ console.error(error);
116
+ }
117
+ }
118
+ );
119
+ this.process.stderr.on(`data`, (buf) => {
120
+ var _a;
121
+ const chunk = buf.toString();
122
+ this.unprocessedLogs.push(...chunk.split(``));
123
+ const newInput = this.unprocessedLogs.shift();
124
+ this.incompleteLog += newInput || ``;
125
+ try {
126
+ const parsedLog = parseJson(this.incompleteLog);
127
+ this.handleLog(parsedLog);
128
+ while (this.unprocessedLogs.length > 0) {
129
+ this.incompleteLog = (_a = this.unprocessedLogs.shift()) != null ? _a : ``;
130
+ if (this.incompleteLog) {
131
+ const parsedLog2 = parseJson(this.incompleteLog);
132
+ this.handleLog(parsedLog2);
133
+ }
134
+ }
135
+ } catch (error) {
136
+ console.error(`\u274C\u274C\u274C`);
137
+ console.error(this.incompleteLog);
138
+ console.error(error);
139
+ console.error(`\u274C\u274C\u274C\uFE0F`);
140
+ }
141
+ });
142
+ if (process2.pid) {
143
+ this.id = process2.pid.toString();
144
+ }
145
+ }
146
+ handleLog(arg) {
147
+ if (Array.isArray(arg)) {
148
+ const [level, ...rest] = arg;
149
+ switch (level) {
150
+ case `i`:
151
+ this.logger.info(this.id, this.key, ...rest);
152
+ break;
153
+ case `w`:
154
+ this.logger.warn(this.id, this.key, ...rest);
155
+ break;
156
+ case `e`:
157
+ this.logger.error(this.id, this.key, ...rest);
158
+ break;
159
+ }
160
+ }
161
+ }
162
+ };
163
+ var SubjectSocket = class extends CustomSocket {
164
+ constructor(id) {
165
+ super((...args) => {
166
+ this.out.next(args);
167
+ return this;
168
+ });
169
+ this.id = `no_id_retrieved`;
170
+ this.disposalFunctions = [];
171
+ this.id = id;
172
+ this.in = new Subject();
173
+ this.out = new Subject();
174
+ this.in.subscribe(`socket`, (event) => {
175
+ this.handleEvent(...event);
176
+ });
177
+ }
178
+ dispose() {
179
+ for (const dispose of this.disposalFunctions) {
180
+ dispose();
181
+ }
182
+ }
183
+ };
184
+ var ParentSocket = class extends CustomSocket {
185
+ constructor() {
186
+ var _a;
187
+ super((event, ...args) => {
188
+ const stringifiedEvent = JSON.stringify([event, ...args]);
189
+ this.process.stdout.write(stringifiedEvent + ``);
190
+ return this;
191
+ });
192
+ this.incompleteData = ``;
193
+ this.unprocessedEvents = [];
194
+ this.id = `#####`;
195
+ this.logger = {
196
+ info: (...args) => this.log(`i`, ...args),
197
+ warn: (...args) => this.log(`w`, ...args),
198
+ error: (...args) => this.log(`e`, ...args)
199
+ };
200
+ this.process = process;
201
+ this.process.stdin.resume();
202
+ this.relays = /* @__PURE__ */ new Map();
203
+ this.relayServices = [];
204
+ this.process.stdin.on(
205
+ `data`,
206
+ (buffer) => {
207
+ const chunk = buffer.toString();
208
+ this.unprocessedEvents.push(...chunk.split(``));
209
+ const newInput = this.unprocessedEvents.shift();
210
+ this.incompleteData += newInput || ``;
211
+ try {
212
+ const parsedEvent = parseJson(this.incompleteData);
213
+ this.logger.info(`\u{1F3B0}`, `received`, parsedEvent);
214
+ this.handleEvent(...parsedEvent);
215
+ while (this.unprocessedEvents.length > 0) {
216
+ const event = this.unprocessedEvents.shift();
217
+ if (event) {
218
+ if (this.unprocessedEvents.length === 0) {
219
+ this.incompleteData = event;
220
+ }
221
+ const parsedEvent2 = parseJson(event);
222
+ this.handleEvent(...parsedEvent2);
223
+ }
224
+ }
225
+ this.incompleteData = ``;
226
+ } catch (thrown) {
227
+ if (thrown instanceof Error) {
228
+ this.logger.error(`\u2757`, thrown.message, thrown.cause, thrown.stack);
229
+ }
230
+ }
231
+ }
232
+ );
233
+ this.on(`exit`, () => {
234
+ process.exit(0);
235
+ });
236
+ process.on(`exit`, () => {
237
+ this.logger.info(`\u{1F525}`, this.id, `exited`);
238
+ process.exit(0);
239
+ });
240
+ process.on(`end`, () => {
241
+ this.logger.info(`\u{1F525}`, this.id, `ended`);
242
+ process.exit(0);
243
+ });
244
+ process.on(`SIGTERM`, () => {
245
+ this.logger.error(`\u{1F525}`, this.id, `terminated`);
246
+ process.exit(0);
247
+ });
248
+ process.on(`SIGINT`, () => {
249
+ this.logger.error(`\u{1F525}`, this.id, `interrupted`);
250
+ process.exit(0);
251
+ });
252
+ if (process.pid) {
253
+ this.id = (_a = process.pid) == null ? void 0 : _a.toString();
254
+ }
255
+ this.on(`user-joins`, (username) => {
256
+ this.logger.info(`\u{1F464}`, `user`, username, `joined`);
257
+ const relay = new SubjectSocket(`user:${username}`);
258
+ this.relays.set(username, relay);
259
+ this.logger.info(
260
+ `\u{1F517}`,
261
+ `attaching services:`,
262
+ `[${[...this.relayServices.keys()].join(`, `)}]`
263
+ );
264
+ for (const attachServices of this.relayServices) {
265
+ const cleanup = attachServices(relay);
266
+ if (cleanup) {
267
+ relay.disposalFunctions.push(cleanup);
268
+ }
269
+ }
270
+ this.on(`user:${username}`, (...data) => {
271
+ relay.in.next(data);
272
+ });
273
+ relay.out.subscribe(`socket`, (data) => {
274
+ this.emit(...data);
275
+ });
276
+ });
277
+ this.on(`user-leaves`, (username) => {
278
+ const relay = this.relays.get(username);
279
+ this.off(`relay:${username}`);
280
+ if (relay) {
281
+ relay.dispose();
282
+ this.relays.delete(username);
283
+ }
284
+ });
285
+ process.stdout.write(`\u2728`);
286
+ }
287
+ log(...args) {
288
+ this.process.stderr.write(
289
+ stringifyJson(
290
+ args.map(
291
+ (arg) => arg instanceof SetRTX ? `{ ${arg.toJSON().members.join(` | `)} }` : arg
292
+ )
293
+ ) + ``
294
+ );
295
+ }
296
+ relay(attachServices) {
297
+ this.logger.info(`\u{1F517}`, `running relay method`);
298
+ this.relayServices.push(attachServices);
299
+ }
300
+ };
301
+ selectorFamily({
302
+ key: `perspectiveRedactor`,
303
+ get: ({ userId, syncGroupKey }) => ({ get, find }) => {
304
+ const syncGroup = SyncGroup.existing.get(syncGroupKey);
305
+ if (!syncGroup) {
306
+ throw new Error(
307
+ `Tried to create a synchronizer for a sync group that does not exist.`
308
+ );
309
+ }
310
+ const userPerspectiveTokens = syncGroup.perspectives.flatMap(
311
+ ({ viewAtoms }) => {
312
+ const userPerspectiveToken = find(viewAtoms, userId);
313
+ const userPerspective = get(userPerspectiveToken);
314
+ const visibleTokens = [...userPerspective].map((token) => {
315
+ return token.type === `mutable_atom` ? getUpdateToken(token).key : token.key;
316
+ });
317
+ IMPLICIT.STORE.logger.info(
318
+ `\u{1F52D}`,
319
+ `continuity`,
320
+ syncGroupKey,
321
+ `${userId} can see ${visibleTokens.length} tokens in ${viewAtoms.key}`,
322
+ visibleTokens
323
+ );
324
+ return visibleTokens;
325
+ }
326
+ );
327
+ const filterTransactionUpdate = (visible, transactionUpdate) => {
328
+ IMPLICIT.STORE.logger.info(
329
+ `\u{1F58C}`,
330
+ `continuity`,
331
+ syncGroupKey,
332
+ `redacting updates from ${transactionUpdate.epoch}:${transactionUpdate.key}:${transactionUpdate.id}`,
333
+ visible,
334
+ transactionUpdate.updates
335
+ );
336
+ const updates = transactionUpdate.updates.filter((update) => {
337
+ if (`newValue` in update) {
338
+ return visible.includes(update.key);
339
+ }
340
+ return true;
341
+ }).map((update) => {
342
+ if (`updates` in update) {
343
+ return filterTransactionUpdate(visible, update);
344
+ }
345
+ return update;
346
+ });
347
+ const filtered = __spreadProps(__spreadValues({}, transactionUpdate), {
348
+ updates
349
+ });
350
+ return filtered;
351
+ };
352
+ const filter = (update) => {
353
+ const visibleKeys = syncGroup.globals.map(
354
+ (atomToken) => atomToken.type === `mutable_atom` ? getUpdateToken(atomToken).key : atomToken.key
355
+ );
356
+ visibleKeys.push(...userPerspectiveTokens);
357
+ return filterTransactionUpdate(visibleKeys, update);
358
+ };
359
+ return filter;
360
+ }
15
361
  });
16
- var usersOfSockets = join({
17
- key: `usersOfSockets`,
18
- between: [`user`, `socket`],
19
- cardinality: `1:1`
362
+ var roomArgumentsAtoms = atomFamily({
363
+ key: `roomArguments`,
364
+ default: [`echo`, [`Hello World!`]]
20
365
  });
21
- var roomIndex = atom({
22
- key: `conclaveIndex`,
23
- default: () => new SetRTX(),
24
- mutable: true,
25
- toJson: (set) => set.toJSON(),
26
- fromJson: (json) => SetRTX.fromJSON(json)
366
+ var roomSelectors = selectorFamily({
367
+ key: `room`,
368
+ get: (roomId) => async ({ get, find }) => {
369
+ const argumentsState = find(roomArgumentsAtoms, roomId);
370
+ const args = get(argumentsState);
371
+ const [script, options] = args;
372
+ const child = await new Promise(
373
+ (resolve) => {
374
+ const room = spawn(script, options, { env: process.env });
375
+ const resolver = (data) => {
376
+ if (data.toString() === `\u2728`) {
377
+ room.stdout.off(`data`, resolver);
378
+ resolve(room);
379
+ }
380
+ };
381
+ room.stdout.on(`data`, resolver);
382
+ }
383
+ );
384
+ return new ChildSocket(child, roomId);
385
+ }
27
386
  });
28
- var DEFAULT_USER_IN_ROOM_META = {
29
- enteredAtEpoch: 0
30
- };
31
- var usersInRooms = join(
32
- {
33
- key: `usersInRooms`,
34
- between: [`room`, `user`],
35
- cardinality: `1:n`
36
- },
37
- DEFAULT_USER_IN_ROOM_META
38
- );
39
- var completeUpdateAtoms = atomFamily({
40
- key: `completeUpdate`,
41
- default: null
387
+
388
+ // realtime-server/src/realtime-server-stores/server-room-external-actions.ts
389
+ var createRoomTX = AtomIO.transaction({
390
+ key: `createRoom`,
391
+ do: ({ get, set, find }, roomId, script, options) => {
392
+ const args = options ? [script, options] : [script];
393
+ const roomArgumentsState = find(roomArgumentsAtoms, roomId);
394
+ set(roomArgumentsState, args);
395
+ set(roomIndex, (s) => s.add(roomId));
396
+ const roomState = find(roomSelectors, roomId);
397
+ const room = get(roomState);
398
+ return room;
399
+ }
42
400
  });
43
- var transactionRedactorAtoms = atomFamily({
44
- key: `transactionRedactor`,
45
- default: { filter: (updates) => updates }
401
+ var joinRoomTX = AtomIO.transaction({
402
+ key: `joinRoom`,
403
+ do: (transactors, roomId, userId, enteredAtEpoch) => {
404
+ const meta = { enteredAtEpoch };
405
+ usersInRooms.transact(transactors, ({ relations }) => {
406
+ relations.set(roomId, userId, meta);
407
+ });
408
+ return meta;
409
+ }
46
410
  });
47
- var redactedUpdateSelectors = selectorFamily({
48
- key: `redactedUpdate`,
49
- get: ([transactionKey, updateId]) => ({ get, find }) => {
50
- const update = get(find(completeUpdateAtoms, updateId));
51
- const { filter } = get(find(transactionRedactorAtoms, transactionKey));
52
- if (update && filter) {
53
- return __spreadProps(__spreadValues({}, update), { updates: filter(update.updates) });
54
- }
55
- return null;
411
+ var leaveRoomTX = AtomIO.transaction({
412
+ key: `leaveRoom`,
413
+ do: (transactors, roomId, userId) => {
414
+ usersInRooms.transact(transactors, ({ relations }) => {
415
+ relations.delete({ room: roomId, user: userId });
416
+ });
56
417
  }
57
418
  });
58
- var userUnacknowledgedUpdatesAtoms = atomFamily({
59
- key: `unacknowledgedUpdates`,
60
- default: () => []
419
+ var destroyRoomTX = AtomIO.transaction({
420
+ key: `destroyRoom`,
421
+ do: (transactors, roomId) => {
422
+ usersInRooms.transact(transactors, ({ relations }) => {
423
+ relations.delete({ room: roomId });
424
+ });
425
+ transactors.set(roomIndex, (s) => (s.delete(roomId), s));
426
+ }
61
427
  });
62
- var socketUnacknowledgedUpdatesSelectors = selectorFamily({
63
- key: `socketUnacknowledgedUpdates`,
64
- get: (socketId) => ({ get, find }) => {
65
- const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
66
- const userKey = get(userKeyState);
67
- if (!userKey) {
68
- return [];
428
+ function redactTransactionUpdateContent(visibleStateKeys, updates) {
429
+ return updates.map((update) => {
430
+ if (`newValue` in update) {
431
+ return update;
69
432
  }
70
- const unacknowledgedUpdatesState = find(
71
- userUnacknowledgedUpdatesAtoms,
72
- userKey
433
+ const redacted = redactTransactionUpdateContent(
434
+ visibleStateKeys,
435
+ update.updates
73
436
  );
74
- const unacknowledgedUpdates = get(unacknowledgedUpdatesState);
75
- return unacknowledgedUpdates;
76
- },
77
- set: (socketId) => ({ set, get, find }, newUpdates) => {
78
- const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
79
- const userKey = get(userKeyState);
80
- if (!userKey) {
81
- return;
437
+ return __spreadProps(__spreadValues({}, update), { updates: redacted });
438
+ }).filter((update) => {
439
+ if (`newValue` in update) {
440
+ return visibleStateKeys.includes(update.key);
82
441
  }
83
- const unacknowledgedUpdatesState = find(
84
- userUnacknowledgedUpdatesAtoms,
85
- userKey
86
- );
87
- set(unacknowledgedUpdatesState, newUpdates);
88
- }
442
+ return true;
443
+ });
444
+ }
445
+ var actionOcclusionAtoms = atomFamily({
446
+ key: `transactionRedactor`,
447
+ default: { occlude: (updates) => updates }
89
448
  });
90
- var userEpochAtoms = atomFamily({
91
- key: `clientEpoch`,
449
+ var userUnacknowledgedQueues = atomFamily({
450
+ key: `unacknowledgedUpdates`,
451
+ default: () => []
452
+ });
453
+ var socketAtoms = atomFamily({
454
+ key: `sockets`,
92
455
  default: null
93
456
  });
94
- var socketEpochSelectors = selectorFamily({
95
- key: `socketEpoch`,
96
- get: (socketId) => ({ get, find }) => {
97
- const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
98
- const userKey = get(userKeyState);
99
- if (!userKey) {
100
- return null;
101
- }
102
- const userEpochState = find(userEpochAtoms, userKey);
103
- const userEpoch = get(userEpochState);
104
- return userEpoch;
105
- },
106
- set: (socketId) => ({ set, get, find }, newEpoch) => {
107
- const userKeyState = find(usersOfSockets.states.userKeyOfSocket, socketId);
108
- const userKey = get(userKeyState);
457
+ var socketIndex = atom({
458
+ key: `socketsIndex`,
459
+ mutable: true,
460
+ default: () => new SetRTX(),
461
+ toJson: (set) => set.toJSON(),
462
+ fromJson: (json) => SetRTX.fromJSON(json)
463
+ });
464
+ var userIndex = atom({
465
+ key: `usersIndex`,
466
+ mutable: true,
467
+ default: () => new SetRTX(),
468
+ toJson: (set) => set.toJSON(),
469
+ fromJson: (json) => SetRTX.fromJSON(json)
470
+ });
471
+ var usersOfSockets = join({
472
+ key: `usersOfSockets`,
473
+ between: [`user`, `socket`],
474
+ cardinality: `1:1`
475
+ });
476
+
477
+ // realtime-server/src/realtime-continuity-synchronizer.ts
478
+ function realtimeContinuitySynchronizer({
479
+ socket: initialSocket,
480
+ store = IMPLICIT.STORE
481
+ }) {
482
+ return function synchronizer(continuity) {
483
+ let socket = initialSocket;
484
+ const continuityKey = continuity.key;
485
+ const userKeyState = findInStore(
486
+ usersOfSockets.states.userKeyOfSocket,
487
+ socket.id,
488
+ store
489
+ );
490
+ const userKey = getFromStore(userKeyState, store);
109
491
  if (!userKey) {
110
- return;
492
+ store.logger.error(
493
+ `\u274C`,
494
+ `continuity`,
495
+ continuityKey,
496
+ `Tried to create a synchronizer for a socket (${socket.id}) that is not connected to a user.`
497
+ );
498
+ return () => {
499
+ };
111
500
  }
112
- const userEpochState = find(userEpochAtoms, userKey);
113
- set(userEpochState, newEpoch);
114
- }
115
- });
501
+ const socketKeyState = findInStore(
502
+ usersOfSockets.states.socketKeyOfUser,
503
+ userKey,
504
+ store
505
+ );
506
+ subscribeToState(
507
+ socketKeyState,
508
+ ({ newValue: newSocketKey }) => {
509
+ store.logger.info(
510
+ `\u{1F44B}`,
511
+ `continuity`,
512
+ continuityKey,
513
+ `seeing ${userKey} on new socket ${newSocketKey}`
514
+ );
515
+ if (newSocketKey === null) {
516
+ store.logger.error(
517
+ `\u274C`,
518
+ `continuity`,
519
+ continuityKey,
520
+ `Tried to create a synchronizer for a user (${userKey}) that is not connected to a socket.`
521
+ );
522
+ return;
523
+ }
524
+ const newSocketState = findInStore(socketAtoms, newSocketKey, store);
525
+ const newSocket = getFromStore(newSocketState, store);
526
+ socket = newSocket;
527
+ },
528
+ `sync-continuity:${continuityKey}:${userKey}`,
529
+ store
530
+ );
531
+ const userUnacknowledgedQueue = findInStore(
532
+ userUnacknowledgedQueues,
533
+ userKey,
534
+ store
535
+ );
536
+ getFromStore(
537
+ userUnacknowledgedQueue,
538
+ store
539
+ );
540
+ const unsubscribeFunctions = [];
541
+ const revealPerspectives = () => {
542
+ const unsubscribeFunctions2 = [];
543
+ for (const perspective of continuity.perspectives) {
544
+ const { viewAtoms } = perspective;
545
+ const userViewState = findInStore(viewAtoms, userKey, store);
546
+ const unsubscribe = subscribeToState(
547
+ userViewState,
548
+ ({ oldValue, newValue }) => {
549
+ const oldKeys = oldValue.map((token) => token.key);
550
+ const newKeys = newValue.map((token) => token.key);
551
+ const concealed = oldValue.filter(
552
+ (token) => !newKeys.includes(token.key)
553
+ );
554
+ const revealed = newValue.filter((token) => !oldKeys.includes(token.key)).flatMap((token) => {
555
+ const resourceToken = token.type === `mutable_atom` ? getJsonToken(token) : token;
556
+ const resource = getFromStore(resourceToken, store);
557
+ return [resourceToken, resource];
558
+ });
559
+ store.logger.info(
560
+ `\u{1F441}`,
561
+ `atom`,
562
+ perspective.resourceAtoms.key,
563
+ `${userKey} has a new perspective`,
564
+ { oldKeys, newKeys, revealed, concealed }
565
+ );
566
+ if (revealed.length > 0) {
567
+ socket == null ? void 0 : socket.emit(`reveal:${continuityKey}`, revealed);
568
+ }
569
+ if (concealed.length > 0) {
570
+ socket == null ? void 0 : socket.emit(`conceal:${continuityKey}`, concealed);
571
+ }
572
+ },
573
+ `sync-continuity:${continuityKey}:${userKey}:perspective:${perspective.resourceAtoms.key}`,
574
+ store
575
+ );
576
+ unsubscribeFunctions2.push(unsubscribe);
577
+ }
578
+ return () => {
579
+ for (const unsubscribe of unsubscribeFunctions2)
580
+ unsubscribe();
581
+ };
582
+ };
583
+ const unsubscribeFromPerspectives = revealPerspectives();
584
+ const sendInitialPayload = () => {
585
+ var _a;
586
+ const initialPayload = [];
587
+ for (const atom2 of continuity.globals) {
588
+ const resourceToken = atom2.type === `mutable_atom` ? getJsonToken(atom2) : atom2;
589
+ initialPayload.push(resourceToken, getFromStore(atom2, store));
590
+ }
591
+ for (const perspective of continuity.perspectives) {
592
+ const { viewAtoms, resourceAtoms } = perspective;
593
+ const userViewState = findInStore(viewAtoms, userKey, store);
594
+ const userView = getFromStore(userViewState, store);
595
+ store.logger.info(`\u{1F441}`, `atom`, resourceAtoms.key, `${userKey} can see`, {
596
+ viewAtoms,
597
+ resourceAtoms,
598
+ userView
599
+ });
600
+ for (const visibleToken of userView) {
601
+ const resourceToken = visibleToken.type === `mutable_atom` ? getJsonToken(visibleToken) : visibleToken;
602
+ const resource = getFromStore(resourceToken, store);
603
+ initialPayload.push(resourceToken, resource);
604
+ }
605
+ }
606
+ const epoch = isRootStore(store) ? (_a = store.transactionMeta.epoch.get(continuityKey)) != null ? _a : null : null;
607
+ socket == null ? void 0 : socket.emit(`continuity-init:${continuityKey}`, epoch, initialPayload);
608
+ for (const transaction2 of continuity.actions) {
609
+ const unsubscribeFromTransaction = subscribeToTransaction(
610
+ transaction2,
611
+ (update) => {
612
+ try {
613
+ const visibleKeys = continuity.globals.map((atom2) => atom2.key).concat(
614
+ continuity.perspectives.flatMap((perspective) => {
615
+ const { viewAtoms } = perspective;
616
+ const userPerspectiveTokenState = findInStore(
617
+ viewAtoms,
618
+ userKey,
619
+ store
620
+ );
621
+ const visibleTokens = getFromStore(
622
+ userPerspectiveTokenState,
623
+ store
624
+ );
625
+ return visibleTokens.map((token) => {
626
+ const key = token.type === `mutable_atom` ? `*` + token.key : token.key;
627
+ return key;
628
+ });
629
+ })
630
+ );
631
+ const redactedUpdates = redactTransactionUpdateContent(
632
+ visibleKeys,
633
+ update.updates
634
+ );
635
+ const redactedUpdate = __spreadProps(__spreadValues({}, update), {
636
+ updates: redactedUpdates
637
+ });
638
+ socket == null ? void 0 : socket.emit(
639
+ `tx-new:${continuityKey}`,
640
+ redactedUpdate
641
+ );
642
+ } catch (thrown) {
643
+ if (thrown instanceof Error) {
644
+ store.logger.error(
645
+ `\u274C`,
646
+ `continuity`,
647
+ continuityKey,
648
+ `failed to send update from transaction ${transaction2.key} to ${userKey}`,
649
+ thrown.message
650
+ );
651
+ }
652
+ }
653
+ },
654
+ `sync-continuity:${continuityKey}:${userKey}`,
655
+ store
656
+ );
657
+ unsubscribeFunctions.push(unsubscribeFromTransaction);
658
+ }
659
+ };
660
+ socket.off(`get:${continuityKey}`, sendInitialPayload);
661
+ socket.on(`get:${continuityKey}`, sendInitialPayload);
662
+ const fillTransactionRequest = (update) => {
663
+ store.logger.info(`\u{1F6CE}\uFE0F`, `continuity`, continuityKey, `received`, update);
664
+ const transactionKey = update.key;
665
+ const updateId = update.id;
666
+ const performanceKey = `tx-run:${transactionKey}:${updateId}`;
667
+ const performanceKeyStart = `${performanceKey}:start`;
668
+ const performanceKeyEnd = `${performanceKey}:end`;
669
+ performance.mark(performanceKeyStart);
670
+ try {
671
+ actUponStore(
672
+ { type: `transaction`, key: transactionKey },
673
+ updateId,
674
+ store
675
+ )(...update.params);
676
+ } catch (thrown) {
677
+ if (thrown instanceof Error) {
678
+ store.logger.error(
679
+ `\u274C`,
680
+ `continuity`,
681
+ continuityKey,
682
+ `failed to run transaction ${transactionKey} with update ${updateId}`,
683
+ thrown.message
684
+ );
685
+ }
686
+ }
687
+ performance.mark(performanceKeyEnd);
688
+ const metric = performance.measure(
689
+ performanceKey,
690
+ performanceKeyStart,
691
+ performanceKeyEnd
692
+ );
693
+ store == null ? void 0 : store.logger.info(
694
+ `\u{1F680}`,
695
+ `transaction`,
696
+ transactionKey,
697
+ updateId,
698
+ metric.duration
699
+ );
700
+ const valuesOfCardsViewKey = `valuesOfCardsView("${userKey}")`;
701
+ const rootsOfCardValueView = store.selectorAtoms.getRelatedKeys(valuesOfCardsViewKey);
702
+ const myCardValueView = store.valueMap.get(valuesOfCardsViewKey);
703
+ store.logger.info(
704
+ `\u{1F441}`,
705
+ `continuity`,
706
+ continuityKey,
707
+ `seeing ${userKey} card values`,
708
+ {
709
+ valuesOfCardsViewKey,
710
+ rootsOfCardValueView,
711
+ myCardValueView
712
+ }
713
+ );
714
+ };
715
+ socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
716
+ socket.on(`tx-run:${continuityKey}`, fillTransactionRequest);
717
+ return () => {
718
+ for (const unsubscribe of unsubscribeFunctions)
719
+ unsubscribe();
720
+ unsubscribeFromPerspectives();
721
+ socket == null ? void 0 : socket.off(`get:${continuityKey}`, sendInitialPayload);
722
+ socket == null ? void 0 : socket.off(`tx-run:${continuityKey}`, fillTransactionRequest);
723
+ };
724
+ };
725
+ }
116
726
  function realtimeStateProvider({
117
727
  socket,
118
728
  store = IMPLICIT.STORE
@@ -162,89 +772,49 @@ function realtimeStateSynchronizer({
162
772
  };
163
773
  };
164
774
  }
165
- function realtimeFamilyProvider({
775
+ function realtimeAtomFamilyProvider({
166
776
  socket,
167
777
  store = IMPLICIT.STORE
168
778
  }) {
169
779
  return function familyProvider(family, index) {
170
- const unsubSingleCallbacksByKey = /* @__PURE__ */ new Map();
171
- const unsubFamilyCallbacksByKey = /* @__PURE__ */ new Map();
172
- const fillFamilyUnsubRequest = () => {
173
- for (const [, unsub] of unsubFamilyCallbacksByKey) {
174
- unsub();
175
- }
176
- unsubFamilyCallbacksByKey.clear();
177
- socket.off(`unsub:${family.key}`, fillFamilyUnsubRequest);
178
- };
179
- const fillSingleUnsubRequest = (key) => {
180
- socket.off(`unsub:${key}`, fillSingleUnsubRequest);
181
- const unsub = unsubSingleCallbacksByKey.get(key);
780
+ const unsubCallbacksByKey = /* @__PURE__ */ new Map();
781
+ const fillUnsubRequest = (key) => {
782
+ socket.off(`unsub:${key}`, fillUnsubRequest);
783
+ const unsub = unsubCallbacksByKey.get(key);
182
784
  if (unsub) {
183
785
  unsub();
184
- unsubSingleCallbacksByKey.delete(key);
786
+ unsubCallbacksByKey.delete(key);
185
787
  }
186
788
  };
187
789
  const fillSubRequest = (subKey) => {
188
- var _a;
189
- if (subKey === void 0) {
190
- const keys = getFromStore(index, store);
191
- for (const key of keys) {
192
- const token = findInStore(family, key, store);
193
- socket.emit(
194
- `serve:${family.key}`,
195
- parseJson(((_a = token.family) == null ? void 0 : _a.subKey) || `null`),
196
- getFromStore(token, store)
790
+ const exposedSubKeys = getFromStore(index, store);
791
+ for (const exposedSubKey of exposedSubKeys) {
792
+ if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
793
+ const token = findInStore(family, subKey, store);
794
+ socket.emit(`serve:${token.key}`, getFromStore(token, store));
795
+ const unsubscribe = subscribeToState(
796
+ token,
797
+ ({ newValue }) => {
798
+ socket.emit(`serve:${token.key}`, newValue);
799
+ },
800
+ `expose-family:${family.key}:${socket.id}`,
801
+ store
197
802
  );
803
+ unsubCallbacksByKey.set(token.key, unsubscribe);
804
+ socket.on(`unsub:${token.key}`, () => {
805
+ fillUnsubRequest(token.key);
806
+ });
807
+ break;
198
808
  }
199
- const unsubscribeFromTokenCreation = family.subject.subscribe(
200
- `expose-family:${socket.id}`,
201
- (token) => {
202
- const unsub = subscribeToState(
203
- token,
204
- ({ newValue }) => {
205
- var _a2;
206
- socket.emit(
207
- `serve:${family.key}`,
208
- parseJson(((_a2 = token.family) == null ? void 0 : _a2.subKey) || `null`),
209
- newValue
210
- );
211
- },
212
- `expose-family:${family.key}:${socket.id}`,
213
- store
214
- );
215
- unsubFamilyCallbacksByKey.set(token.key, unsub);
216
- }
217
- );
218
- unsubFamilyCallbacksByKey.set(family.key, unsubscribeFromTokenCreation);
219
- socket.on(`unsub:${family.key}`, fillFamilyUnsubRequest);
220
- } else {
221
- const token = family(subKey);
222
- socket.emit(`serve:${token.key}`, getFromStore(token, store));
223
- const unsubscribe = subscribeToState(
224
- token,
225
- ({ newValue }) => {
226
- socket.emit(`serve:${token.key}`, newValue);
227
- },
228
- `expose-family:${family.key}:${socket.id}`,
229
- store
230
- );
231
- unsubSingleCallbacksByKey.set(token.key, unsubscribe);
232
- socket.on(`unsub:${token.key}`, () => {
233
- fillSingleUnsubRequest(token.key);
234
- });
235
809
  }
236
810
  };
237
811
  socket.on(`sub:${family.key}`, fillSubRequest);
238
812
  return () => {
239
813
  socket.off(`sub:${family.key}`, fillSubRequest);
240
- for (const [, unsub] of unsubFamilyCallbacksByKey) {
241
- unsub();
242
- }
243
- for (const [, unsub] of unsubSingleCallbacksByKey) {
814
+ for (const [, unsub] of unsubCallbacksByKey) {
244
815
  unsub();
245
816
  }
246
- unsubFamilyCallbacksByKey.clear();
247
- unsubSingleCallbacksByKey.clear();
817
+ unsubCallbacksByKey.clear();
248
818
  };
249
819
  };
250
820
  }
@@ -285,110 +855,46 @@ function realtimeMutableFamilyProvider({
285
855
  store = IMPLICIT.STORE
286
856
  }) {
287
857
  return function mutableFamilyProvider(family, index) {
288
- const unsubSingleCallbacksByKey = /* @__PURE__ */ new Map();
289
- const unsubFamilyCallbacksByKey = /* @__PURE__ */ new Map();
290
- const fillFamilyUnsubRequest = () => {
291
- for (const [, unsub] of unsubFamilyCallbacksByKey) {
292
- unsub();
293
- }
294
- unsubFamilyCallbacksByKey.clear();
295
- socket.off(`unsub:${family.key}`, fillFamilyUnsubRequest);
296
- };
297
- const fillSingleUnsubRequest = (key) => {
298
- socket.off(`unsub:${key}`, fillSingleUnsubRequest);
299
- const unsub = unsubSingleCallbacksByKey.get(key);
858
+ const unsubCallbacksByKey = /* @__PURE__ */ new Map();
859
+ const fillUnsubRequest = (key) => {
860
+ socket.off(`unsub:${key}`, fillUnsubRequest);
861
+ const unsub = unsubCallbacksByKey.get(key);
300
862
  if (unsub) {
301
863
  unsub();
302
- unsubSingleCallbacksByKey.delete(key);
864
+ unsubCallbacksByKey.delete(key);
303
865
  }
304
866
  };
305
867
  const fillSubRequest = (subKey) => {
306
- var _a;
307
- if (subKey === void 0) {
308
- const keys = getFromStore(index, store);
309
- for (const key of keys) {
310
- const token = findInStore(family, key, store);
868
+ const exposedSubKeys = getFromStore(index, store);
869
+ for (const exposedSubKey of exposedSubKeys) {
870
+ if (stringifyJson(exposedSubKey) === stringifyJson(subKey)) {
871
+ const token = findInStore(family, subKey, store);
311
872
  const jsonToken = getJsonToken(token);
312
- const trackerToken = getUpdateToken(token);
313
- socket.emit(
314
- `init:${family.key}`,
315
- parseJson(((_a = jsonToken.family) == null ? void 0 : _a.subKey) || `null`),
316
- getFromStore(jsonToken, store)
317
- );
318
- const unsubFromUpdates = subscribeToState(
319
- trackerToken,
873
+ const updateToken = getUpdateToken(token);
874
+ socket.emit(`init:${token.key}`, getFromStore(jsonToken, store));
875
+ const unsubscribe = subscribeToState(
876
+ updateToken,
320
877
  ({ newValue }) => {
321
- var _a2;
322
- socket.emit(
323
- `next:${token.key}`,
324
- parseJson(((_a2 = jsonToken.family) == null ? void 0 : _a2.subKey) || `null`),
325
- newValue
326
- );
878
+ socket.emit(`next:${token.key}`, newValue);
327
879
  },
328
880
  `expose-family:${family.key}:${socket.id}`,
329
881
  store
330
882
  );
331
- unsubFamilyCallbacksByKey.set(token.key, unsubFromUpdates);
883
+ unsubCallbacksByKey.set(token.key, unsubscribe);
884
+ socket.on(`unsub:${token.key}`, () => {
885
+ fillUnsubRequest(token.key);
886
+ });
887
+ break;
332
888
  }
333
- const unsubscribeFromTokenCreation = family.subject.subscribe(
334
- `expose-family:${socket.id}`,
335
- (token) => {
336
- var _a2;
337
- const jsonToken = getJsonToken(token);
338
- const trackerToken = getUpdateToken(token);
339
- socket.emit(
340
- `init:${family.key}`,
341
- parseJson(((_a2 = jsonToken.family) == null ? void 0 : _a2.subKey) || `null`),
342
- getFromStore(jsonToken, store)
343
- );
344
- const unsubFromUpdates = subscribeToState(
345
- trackerToken,
346
- ({ newValue }) => {
347
- var _a3;
348
- socket.emit(
349
- `next:${token.key}`,
350
- parseJson(((_a3 = jsonToken.family) == null ? void 0 : _a3.subKey) || `null`),
351
- newValue
352
- );
353
- },
354
- `expose-family:${family.key}:${socket.id}`,
355
- store
356
- );
357
- unsubFamilyCallbacksByKey.set(token.key, unsubFromUpdates);
358
- }
359
- );
360
- unsubFamilyCallbacksByKey.set(family.key, unsubscribeFromTokenCreation);
361
- socket.on(`unsub:${family.key}`, fillFamilyUnsubRequest);
362
- } else {
363
- const token = family(subKey);
364
- const jsonToken = getJsonToken(token);
365
- const updateToken = getUpdateToken(token);
366
- socket.emit(`init:${token.key}`, getFromStore(jsonToken, store));
367
- const unsubscribe = subscribeToState(
368
- updateToken,
369
- ({ newValue }) => {
370
- socket.emit(`next:${token.key}`, newValue);
371
- },
372
- `expose-family:${family.key}:${socket.id}`,
373
- store
374
- );
375
- unsubSingleCallbacksByKey.set(token.key, unsubscribe);
376
- socket.on(`unsub:${token.key}`, () => {
377
- fillSingleUnsubRequest(token.key);
378
- });
379
889
  }
380
890
  };
381
891
  socket.on(`sub:${family.key}`, fillSubRequest);
382
892
  return () => {
383
893
  socket.off(`sub:${family.key}`, fillSubRequest);
384
- for (const [, unsub] of unsubFamilyCallbacksByKey) {
385
- unsub();
386
- }
387
- for (const [, unsub] of unsubSingleCallbacksByKey) {
894
+ for (const [, unsub] of unsubCallbacksByKey) {
388
895
  unsub();
389
896
  }
390
- unsubFamilyCallbacksByKey.clear();
391
- unsubSingleCallbacksByKey.clear();
897
+ unsubCallbacksByKey.clear();
392
898
  };
393
899
  };
394
900
  }
@@ -423,7 +929,7 @@ function realtimeActionReceiver({
423
929
  const performanceKeyStart = `${performanceKey}:start`;
424
930
  const performanceKeyEnd = `${performanceKey}:end`;
425
931
  performance.mark(performanceKeyStart);
426
- AtomIO.runTransaction(tx, update.id, store)(...update.params);
932
+ actUponStore(tx, update.id, store)(...update.params);
427
933
  performance.mark(performanceKeyEnd);
428
934
  const metric = performance.measure(
429
935
  performanceKey,
@@ -436,121 +942,7 @@ function realtimeActionReceiver({
436
942
  return () => socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
437
943
  };
438
944
  }
439
- function realtimeActionSynchronizer({
440
- socket,
441
- store = IMPLICIT.STORE
442
- }) {
443
- return function actionSynchronizer(tx, filter) {
444
- const userKeyState = findInStore(
445
- usersOfSockets.states.userKeyOfSocket,
446
- socket.id,
447
- store
448
- );
449
- const userKey = getFromStore(userKeyState, store);
450
- const socketUnacknowledgedUpdatesState = findInStore(
451
- socketUnacknowledgedUpdatesSelectors,
452
- socket.id,
453
- store
454
- );
455
- const socketUnacknowledgedUpdates = getFromStore(
456
- socketUnacknowledgedUpdatesState,
457
- store
458
- );
459
- if (filter) {
460
- const redactorState = findInStore(transactionRedactorAtoms, tx.key, store);
461
- setIntoStore(redactorState, { filter }, store);
462
- }
463
- const fillTransactionRequest = (update) => {
464
- const performanceKey = `tx-run:${tx.key}:${update.id}`;
465
- const performanceKeyStart = `${performanceKey}:start`;
466
- const performanceKeyEnd = `${performanceKey}:end`;
467
- performance.mark(performanceKeyStart);
468
- AtomIO.runTransaction(tx, update.id, store)(...update.params);
469
- performance.mark(performanceKeyEnd);
470
- const metric = performance.measure(
471
- performanceKey,
472
- performanceKeyStart,
473
- performanceKeyEnd
474
- );
475
- store == null ? void 0 : store.logger.info(`\u{1F680}`, `transaction`, tx.key, update.id, metric.duration);
476
- };
477
- socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
478
- socket.on(`tx-run:${tx.key}`, fillTransactionRequest);
479
- let unsubscribeFromTransaction;
480
- const fillTransactionSubscriptionRequest = () => {
481
- unsubscribeFromTransaction = subscribeToTransaction(
482
- tx,
483
- (update) => {
484
- const updateState = findInStore(completeUpdateAtoms, update.id, store);
485
- setIntoStore(updateState, update, store);
486
- const toEmit = filter ? getFromStore(
487
- findInStore(redactedUpdateSelectors, [tx.key, update.id], store),
488
- store
489
- ) : update;
490
- setIntoStore(
491
- socketUnacknowledgedUpdatesState,
492
- (updates) => {
493
- if (toEmit) {
494
- updates.push(toEmit);
495
- updates.sort((a, b) => a.epoch - b.epoch);
496
- }
497
- return updates;
498
- },
499
- store
500
- );
501
- socket.emit(`tx-new:${tx.key}`, toEmit);
502
- },
503
- `tx-sub:${tx.key}:${socket.id}`,
504
- store
505
- );
506
- socket.on(`tx-unsub:${tx.key}`, unsubscribeFromTransaction);
507
- };
508
- socket.on(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
509
- let i = 1;
510
- let next = 1;
511
- const retry = setInterval(() => {
512
- const toEmit = socketUnacknowledgedUpdates[0];
513
- console.log(userKey, socketUnacknowledgedUpdates);
514
- if (toEmit && i === next) {
515
- socket.emit(`tx-new:${tx.key}`, toEmit);
516
- next *= 2;
517
- }
518
- i++;
519
- }, 250);
520
- const trackClientAcknowledgement = (epoch) => {
521
- var _a;
522
- i = 1;
523
- next = 1;
524
- const socketEpochState = findInStore(
525
- socketEpochSelectors,
526
- socket.id,
527
- store
528
- );
529
- setIntoStore(socketEpochState, epoch, store);
530
- if (((_a = socketUnacknowledgedUpdates[0]) == null ? void 0 : _a.epoch) === epoch) {
531
- setIntoStore(
532
- socketUnacknowledgedUpdatesState,
533
- (updates) => {
534
- updates.shift();
535
- return updates;
536
- },
537
- store
538
- );
539
- }
540
- };
541
- socket.on(`tx-ack:${tx.key}`, trackClientAcknowledgement);
542
- return () => {
543
- if (unsubscribeFromTransaction) {
544
- unsubscribeFromTransaction();
545
- unsubscribeFromTransaction = void 0;
546
- }
547
- clearInterval(retry);
548
- socket.off(`tx-run:${tx.key}`, fillTransactionRequest);
549
- socket.off(`tx-sub:${tx.key}`, fillTransactionSubscriptionRequest);
550
- };
551
- };
552
- }
553
945
 
554
- export { DEFAULT_USER_IN_ROOM_META, completeUpdateAtoms, realtimeActionReceiver, realtimeActionSynchronizer, realtimeFamilyProvider, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, realtimeStateSynchronizer, redactedUpdateSelectors, roomIndex, socketEpochSelectors, socketUnacknowledgedUpdatesSelectors, transactionRedactorAtoms, userEpochAtoms, userIndex, userUnacknowledgedUpdatesAtoms, usersInRooms, usersOfSockets };
946
+ export { ChildSocket, CustomSocket, ParentSocket, SubjectSocket, actionOcclusionAtoms, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeContinuitySynchronizer, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, realtimeStateSynchronizer, redactTransactionUpdateContent, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets };
555
947
  //# sourceMappingURL=out.js.map
556
948
  //# sourceMappingURL=index.js.map