atom.io 0.23.4 → 0.24.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 (72) hide show
  1. package/data/dist/index.cjs +51 -27
  2. package/data/dist/index.d.ts +5 -4
  3. package/data/dist/index.js +625 -9
  4. package/data/src/join.ts +74 -46
  5. package/dist/chunk-BF4MVQF6.js +44 -0
  6. package/dist/index.cjs +27 -0
  7. package/dist/index.d.ts +63 -18
  8. package/dist/index.js +27 -3
  9. package/immortal/dist/index.cjs +4 -262
  10. package/immortal/dist/index.d.ts +4 -94
  11. package/immortal/dist/index.js +3 -215
  12. package/immortal/src/index.ts +0 -2
  13. package/immortal/src/seek-state.ts +10 -11
  14. package/internal/dist/index.cjs +279 -111
  15. package/internal/dist/index.d.ts +63 -93
  16. package/internal/dist/index.js +273 -88
  17. package/internal/src/families/dispose-from-store.ts +11 -7
  18. package/internal/src/families/find-in-store.ts +2 -2
  19. package/internal/src/families/init-family-member.ts +37 -25
  20. package/internal/src/families/seek-in-store.ts +11 -15
  21. package/internal/src/get-environment-data.ts +0 -4
  22. package/internal/src/index.ts +1 -0
  23. package/internal/src/ingest-updates/ingest-creation-disposal.ts +8 -8
  24. package/internal/src/molecule/create-molecule-family.ts +30 -0
  25. package/internal/src/molecule/dispose-molecule.ts +76 -0
  26. package/internal/src/molecule/grow-molecule-in-store.ts +89 -0
  27. package/internal/src/molecule/index.ts +5 -0
  28. package/internal/src/molecule/make-molecule-in-store.ts +122 -0
  29. package/internal/src/molecule/molecule-internal.ts +48 -0
  30. package/internal/src/not-found-error.ts +4 -3
  31. package/internal/src/set-state/emit-update.ts +1 -2
  32. package/internal/src/store/deposit.ts +16 -30
  33. package/internal/src/store/store.ts +7 -12
  34. package/internal/src/store/withdraw.ts +30 -19
  35. package/internal/src/timeline/create-timeline.ts +7 -6
  36. package/internal/src/transaction/build-transaction.ts +2 -1
  37. package/introspection/dist/index.cjs +29 -33
  38. package/introspection/dist/index.js +1 -1
  39. package/introspection/src/auditor.ts +6 -6
  40. package/json/dist/index.cjs +4 -4
  41. package/json/dist/index.js +7 -8
  42. package/json/src/select-json-family.ts +6 -5
  43. package/package.json +2 -2
  44. package/react-devtools/dist/index.js +2 -3
  45. package/realtime-client/dist/index.js +362 -15
  46. package/realtime-react/dist/index.cjs +1 -326
  47. package/realtime-react/dist/index.d.ts +1 -14
  48. package/realtime-react/dist/index.js +1 -1
  49. package/realtime-react/src/use-sync-continuity.ts +2 -2
  50. package/realtime-server/dist/index.cjs +3 -151
  51. package/realtime-server/dist/index.d.ts +1 -3
  52. package/realtime-server/dist/index.js +2 -18
  53. package/realtime-server/src/index.ts +0 -2
  54. package/realtime-server/src/realtime-continuity-synchronizer.ts +1 -1
  55. package/realtime-testing/dist/index.cjs +4 -82
  56. package/realtime-testing/dist/index.js +2 -4
  57. package/realtime-testing/src/setup-realtime-test.tsx +2 -3
  58. package/src/dispose-state.ts +2 -2
  59. package/src/index.ts +1 -0
  60. package/src/logger.ts +2 -0
  61. package/src/molecule.ts +133 -0
  62. package/src/timeline.ts +3 -3
  63. package/src/transaction.ts +15 -13
  64. package/dist/chunk-6MLFYN32.js +0 -18
  65. package/dist/chunk-7DT3PVS3.js +0 -598
  66. package/dist/chunk-GVHKIJ3G.js +0 -329
  67. package/dist/chunk-O47EQUM6.js +0 -29
  68. package/dist/chunk-OAYGID5B.js +0 -27
  69. package/dist/chunk-PNIHPILQ.js +0 -8
  70. package/immortal/src/make-molecule.ts +0 -234
  71. package/immortal/src/molecule.ts +0 -167
  72. package/realtime-server/src/realtime-state-synchronizer.ts +0 -23
@@ -1,10 +1,10 @@
1
- export { syncContinuity } from '../../dist/chunk-GVHKIJ3G.js';
2
- export { confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue } from '../../dist/chunk-O47EQUM6.js';
3
- import '../../dist/chunk-BWWVY5O5.js';
1
+ import { lazyLocalStorageEffect } from '../../dist/chunk-BWWVY5O5.js';
4
2
  import '../../dist/chunk-F2X4B4VY.js';
5
3
  import * as Internal from 'atom.io/internal';
6
- import { setIntoStore, getJsonToken, getUpdateToken } from 'atom.io/internal';
4
+ import { setIntoStore, getJsonToken, getUpdateToken, getFromStore, assignTransactionToContinuity, subscribeToTransaction, disposeAtom, setEpochNumberOfContinuity, getEpochNumberOfContinuity, isRootStore, ingestTransactionUpdate, actUponStore } from 'atom.io/internal';
7
5
  import { parseJson } from 'atom.io/json';
6
+ import * as AtomIO from 'atom.io';
7
+ import { optimisticUpdateQueue as optimisticUpdateQueue$1, confirmedUpdateQueue as confirmedUpdateQueue$1 } from 'atom.io/realtime-client';
8
8
 
9
9
  function pullAtom(token, socket, store) {
10
10
  const setServedValue = (data) => {
@@ -85,17 +85,17 @@ function pullSelector(token, socket, store) {
85
85
  const unsubscribes = [];
86
86
  if (atomKeys) {
87
87
  for (const atomKey of atomKeys) {
88
- const atom = store.atoms.get(atomKey);
89
- if (!atom) {
88
+ const atom3 = store.atoms.get(atomKey);
89
+ if (!atom3) {
90
90
  continue;
91
91
  }
92
- switch (atom.type) {
92
+ switch (atom3.type) {
93
93
  case `atom`: {
94
- unsubscribes.push(pullAtom(atom, socket, store));
94
+ unsubscribes.push(pullAtom(atom3, socket, store));
95
95
  break;
96
96
  }
97
97
  case `mutable_atom`: {
98
- unsubscribes.push(pullMutableAtom(atom, socket, store));
98
+ unsubscribes.push(pullMutableAtom(atom3, socket, store));
99
99
  break;
100
100
  }
101
101
  }
@@ -119,17 +119,17 @@ function pullSelectorFamilyMember(token, socket, store) {
119
119
  const unsubscribes = [];
120
120
  if (atomKeys) {
121
121
  for (const atomKey of atomKeys) {
122
- const atom = store.atoms.get(atomKey);
123
- if (!atom) {
122
+ const atom3 = store.atoms.get(atomKey);
123
+ if (!atom3) {
124
124
  continue;
125
125
  }
126
- switch (atom.type) {
126
+ switch (atom3.type) {
127
127
  case `atom`: {
128
- unsubscribes.push(pullAtomFamilyMember(atom, socket, store));
128
+ unsubscribes.push(pullAtomFamilyMember(atom3, socket, store));
129
129
  break;
130
130
  }
131
131
  case `mutable_atom`: {
132
- unsubscribes.push(pullMutableAtomFamilyMember(atom, socket, store));
132
+ unsubscribes.push(pullMutableAtomFamilyMember(atom3, socket, store));
133
133
  break;
134
134
  }
135
135
  }
@@ -156,6 +156,30 @@ function pushState(token, socket, store) {
156
156
  socket.emit(`unclaim:${token.key}`);
157
157
  };
158
158
  }
159
+ var myIdState__INTERNAL = AtomIO.atom({
160
+ key: `mySocketId__INTERNAL`,
161
+ default: void 0
162
+ });
163
+ var myIdState = AtomIO.selector({
164
+ key: `mySocketId`,
165
+ get: ({ get }) => get(myIdState__INTERNAL)
166
+ });
167
+ var usernameEffects = typeof window === `undefined` ? [] : [lazyLocalStorageEffect(`myUsername`)];
168
+ var myUsernameState = AtomIO.atom({
169
+ key: `myUsername`,
170
+ default: null,
171
+ effects: usernameEffects
172
+ });
173
+ var optimisticUpdateQueue = AtomIO.atom({
174
+ key: `updateQueue`,
175
+ default: []
176
+ });
177
+ var confirmedUpdateQueue = AtomIO.atom(
178
+ {
179
+ key: `serverConfirmedUpdateQueue`,
180
+ default: []
181
+ }
182
+ );
159
183
  function serverAction(token, socket, store) {
160
184
  const unsubscribeFromLocalUpdates = Internal.subscribeToTransaction(
161
185
  token,
@@ -169,5 +193,328 @@ function serverAction(token, socket, store) {
169
193
  unsubscribeFromLocalUpdates();
170
194
  };
171
195
  }
196
+ function syncContinuity(continuity, socket, store) {
197
+ const continuityKey = continuity.key;
198
+ const optimisticUpdates = getFromStore(optimisticUpdateQueue$1, store);
199
+ const confirmedUpdates = getFromStore(confirmedUpdateQueue$1, store);
200
+ const initializeContinuity = (epoch, payload) => {
201
+ socket.off(`continuity-init:${continuityKey}`, initializeContinuity);
202
+ let i = 0;
203
+ let k = ``;
204
+ let v = null;
205
+ for (const x of payload) {
206
+ if (i % 2 === 0) {
207
+ k = x;
208
+ } else {
209
+ v = x;
210
+ if (`type` in k && k.type === `mutable_atom`) {
211
+ k = getJsonToken(k, store);
212
+ }
213
+ setIntoStore(k, v, store);
214
+ }
215
+ i++;
216
+ }
217
+ setEpochNumberOfContinuity(continuityKey, epoch, store);
218
+ };
219
+ socket.off(`continuity-init:${continuityKey}`);
220
+ socket.on(`continuity-init:${continuityKey}`, initializeContinuity);
221
+ const registerAndAttemptConfirmedUpdate = (confirmed) => {
222
+ function reconcileEpoch(optimisticUpdate, confirmedUpdate) {
223
+ store.logger.info(
224
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
225
+ `continuity`,
226
+ continuityKey,
227
+ `reconciling updates`
228
+ );
229
+ setIntoStore(
230
+ optimisticUpdateQueue$1,
231
+ (queue) => {
232
+ queue.shift();
233
+ return queue;
234
+ },
235
+ store
236
+ );
237
+ if (optimisticUpdate.id === confirmedUpdate.id) {
238
+ const clientResult = JSON.stringify(optimisticUpdate.updates);
239
+ const serverResult = JSON.stringify(confirmedUpdate.updates);
240
+ if (clientResult === serverResult) {
241
+ store.logger.info(
242
+ `\u2705`,
243
+ `continuity`,
244
+ continuityKey,
245
+ `results for ${optimisticUpdate.id} match between client and server`
246
+ );
247
+ socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
248
+ return;
249
+ }
250
+ } else {
251
+ store.logger.info(
252
+ `\u274C`,
253
+ `continuity`,
254
+ continuityKey,
255
+ `thought update #${confirmedUpdate.epoch} was ${optimisticUpdate.key}:${optimisticUpdate.id}, but it was actually ${confirmedUpdate.key}:${confirmedUpdate.id}`
256
+ );
257
+ }
258
+ store.logger.info(
259
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
260
+ `continuity`,
261
+ continuityKey,
262
+ `updates do not match`,
263
+ optimisticUpdate,
264
+ confirmedUpdate
265
+ );
266
+ const reversedOptimisticUpdates = optimisticUpdates.toReversed();
267
+ for (const subsequentOptimistic of reversedOptimisticUpdates) {
268
+ ingestTransactionUpdate(`oldValue`, subsequentOptimistic, store);
269
+ }
270
+ store.logger.info(
271
+ `\u23EA`,
272
+ `continuity`,
273
+ continuityKey,
274
+ `undid optimistic updates:`,
275
+ reversedOptimisticUpdates
276
+ );
277
+ ingestTransactionUpdate(`oldValue`, optimisticUpdate, store);
278
+ store.logger.info(
279
+ `\u23EA`,
280
+ `continuity`,
281
+ continuityKey,
282
+ `undid zeroth optimistic update`,
283
+ optimisticUpdate
284
+ );
285
+ ingestTransactionUpdate(`newValue`, confirmedUpdate, store);
286
+ store.logger.info(
287
+ `\u23E9`,
288
+ `continuity`,
289
+ continuityKey,
290
+ `applied confirmed update`,
291
+ confirmedUpdate
292
+ );
293
+ socket.emit(`ack:${continuityKey}`, confirmedUpdate.epoch);
294
+ for (const subsequentOptimistic of optimisticUpdates) {
295
+ const token = {
296
+ type: `transaction`,
297
+ key: subsequentOptimistic.key
298
+ };
299
+ const { id, params } = subsequentOptimistic;
300
+ actUponStore(token, id, store)(...params);
301
+ }
302
+ store.logger.info(
303
+ `\u23E9`,
304
+ `continuity`,
305
+ continuityKey,
306
+ `reapplied subsequent optimistic updates:`,
307
+ optimisticUpdates
308
+ );
309
+ }
310
+ store.logger.info(
311
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
312
+ `continuity`,
313
+ continuityKey,
314
+ `integrating confirmed update`,
315
+ { confirmedUpdate: confirmed, confirmedUpdates, optimisticUpdates }
316
+ );
317
+ const zerothOptimisticUpdate = optimisticUpdates[0];
318
+ if (zerothOptimisticUpdate) {
319
+ store.logger.info(
320
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
321
+ `continuity`,
322
+ continuityKey,
323
+ `has optimistic updates to reconcile`
324
+ );
325
+ if (confirmed.epoch === zerothOptimisticUpdate.epoch) {
326
+ store.logger.info(
327
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
328
+ `continuity`,
329
+ continuityKey,
330
+ `epoch of confirmed update #${confirmed.epoch} matches zeroth optimistic update`
331
+ );
332
+ reconcileEpoch(zerothOptimisticUpdate, confirmed);
333
+ for (const nextConfirmed of confirmedUpdates) {
334
+ const nextOptimistic = optimisticUpdates[0];
335
+ if (nextConfirmed.epoch === (nextOptimistic == null ? void 0 : nextOptimistic.epoch)) {
336
+ reconcileEpoch(nextOptimistic, nextConfirmed);
337
+ } else {
338
+ break;
339
+ }
340
+ }
341
+ } else {
342
+ store.logger.info(
343
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
344
+ `continuity`,
345
+ continuityKey,
346
+ `epoch of confirmed update #${confirmed.epoch} does not match zeroth optimistic update #${zerothOptimisticUpdate.epoch}`
347
+ );
348
+ const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
349
+ (update) => update.epoch === confirmed.epoch
350
+ );
351
+ if (!confirmedUpdateIsAlreadyEnqueued) {
352
+ store.logger.info(
353
+ `\u{1F448}`,
354
+ `continuity`,
355
+ continuityKey,
356
+ `pushing confirmed update to queue`,
357
+ confirmed
358
+ );
359
+ setIntoStore(
360
+ confirmedUpdateQueue$1,
361
+ (queue) => {
362
+ queue.push(confirmed);
363
+ queue.sort((a, b) => a.epoch - b.epoch);
364
+ return queue;
365
+ },
366
+ store
367
+ );
368
+ }
369
+ }
370
+ } else {
371
+ store.logger.info(
372
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
373
+ `continuity`,
374
+ continuityKey,
375
+ `has no optimistic updates to deal with`
376
+ );
377
+ const continuityEpoch = getEpochNumberOfContinuity(continuityKey, store);
378
+ const isRoot = isRootStore(store);
379
+ if (isRoot && continuityEpoch === confirmed.epoch - 1) {
380
+ store.logger.info(
381
+ `\u2705`,
382
+ `continuity`,
383
+ continuityKey,
384
+ `integrating update #${confirmed.epoch} (${confirmed.key} ${confirmed.id})`
385
+ );
386
+ ingestTransactionUpdate(`newValue`, confirmed, store);
387
+ socket.emit(`ack:${continuityKey}`, confirmed.epoch);
388
+ setEpochNumberOfContinuity(continuityKey, confirmed.epoch, store);
389
+ } else if (isRoot && continuityEpoch !== void 0) {
390
+ store.logger.info(
391
+ `\u{1F9D1}\u200D\u2696\uFE0F`,
392
+ `continuity`,
393
+ continuityKey,
394
+ `received update #${confirmed.epoch} but still waiting for update #${continuityEpoch + 1}`,
395
+ {
396
+ clientEpoch: continuityEpoch,
397
+ serverEpoch: confirmed.epoch
398
+ }
399
+ );
400
+ const confirmedUpdateIsAlreadyEnqueued = confirmedUpdates.some(
401
+ (update) => update.epoch === confirmed.epoch
402
+ );
403
+ if (confirmedUpdateIsAlreadyEnqueued) {
404
+ store.logger.info(
405
+ `\u{1F44D}`,
406
+ `continuity`,
407
+ continuityKey,
408
+ `confirmed update #${confirmed.epoch} is already enqueued`
409
+ );
410
+ } else {
411
+ store.logger.info(
412
+ `\u{1F448}`,
413
+ `continuity`,
414
+ continuityKey,
415
+ `pushing confirmed update #${confirmed.epoch} to queue`
416
+ );
417
+ setIntoStore(
418
+ confirmedUpdateQueue$1,
419
+ (queue) => {
420
+ queue.push(confirmed);
421
+ queue.sort((a, b) => a.epoch - b.epoch);
422
+ return queue;
423
+ },
424
+ store
425
+ );
426
+ }
427
+ }
428
+ }
429
+ };
430
+ socket.off(`tx-new:${continuityKey}`);
431
+ socket.on(`tx-new:${continuityKey}`, registerAndAttemptConfirmedUpdate);
432
+ const unsubscribeFunctions = continuity.actions.map((transaction) => {
433
+ assignTransactionToContinuity(continuityKey, transaction.key, store);
434
+ const unsubscribeFromTransactionUpdates = subscribeToTransaction(
435
+ transaction,
436
+ (clientUpdate) => {
437
+ store.logger.info(
438
+ `\u{1F91E}`,
439
+ `continuity`,
440
+ continuityKey,
441
+ `enqueuing optimistic update`
442
+ );
443
+ const optimisticUpdateIndex = optimisticUpdates.findIndex(
444
+ (update) => update.id === clientUpdate.id
445
+ );
446
+ if (optimisticUpdateIndex === -1) {
447
+ store.logger.info(
448
+ `\u{1F91E}`,
449
+ `continuity`,
450
+ continuityKey,
451
+ `enqueuing new optimistic update`
452
+ );
453
+ setIntoStore(
454
+ optimisticUpdateQueue$1,
455
+ (queue) => {
456
+ queue.push(clientUpdate);
457
+ queue.sort((a, b) => a.epoch - b.epoch);
458
+ return queue;
459
+ },
460
+ store
461
+ );
462
+ } else {
463
+ store.logger.info(
464
+ `\u{1F91E}`,
465
+ `continuity`,
466
+ continuityKey,
467
+ `replacing existing optimistic update at index ${optimisticUpdateIndex}`
468
+ );
469
+ setIntoStore(
470
+ optimisticUpdateQueue$1,
471
+ (queue) => {
472
+ queue[optimisticUpdateIndex] = clientUpdate;
473
+ return queue;
474
+ },
475
+ store
476
+ );
477
+ }
478
+ socket.emit(`tx-run:${continuityKey}`, {
479
+ id: clientUpdate.id,
480
+ key: transaction.key,
481
+ params: clientUpdate.params
482
+ });
483
+ },
484
+ `tx-run:${continuityKey}`,
485
+ store
486
+ );
487
+ return unsubscribeFromTransactionUpdates;
488
+ });
489
+ socket.on(`reveal:${continuityKey}`, (revealed) => {
490
+ let i = 0;
491
+ let k = ``;
492
+ let v = null;
493
+ for (const x of revealed) {
494
+ if (i % 2 === 0) {
495
+ k = x;
496
+ } else {
497
+ v = x;
498
+ setIntoStore(k, v, store);
499
+ }
500
+ i++;
501
+ }
502
+ });
503
+ socket.on(
504
+ `conceal:${continuityKey}`,
505
+ (concealed) => {
506
+ for (const token of concealed) {
507
+ disposeAtom(token, store);
508
+ }
509
+ }
510
+ );
511
+ socket.emit(`get:${continuityKey}`);
512
+ return () => {
513
+ socket.off(`continuity-init:${continuityKey}`);
514
+ socket.off(`tx-new:${continuityKey}`);
515
+ for (const unsubscribe of unsubscribeFunctions)
516
+ unsubscribe();
517
+ };
518
+ }
172
519
 
173
- export { pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction };
520
+ export { confirmedUpdateQueue, myIdState, myIdState__INTERNAL, myUsernameState, optimisticUpdateQueue, pullAtom, pullAtomFamilyMember, pullMutableAtom, pullMutableAtomFamilyMember, pullSelector, pullSelectorFamilyMember, pushState, serverAction, syncContinuity };