atom.io 0.21.1 → 0.23.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 (116) hide show
  1. package/data/dist/index.cjs +152 -63
  2. package/data/dist/index.d.ts +6 -0
  3. package/data/dist/index.js +3 -3
  4. package/data/src/join.ts +164 -51
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/chunk-6MLFYN32.js +18 -0
  7. package/dist/{chunk-HITX3MO4.js → chunk-7DT3PVS3.js} +151 -62
  8. package/dist/{chunk-RT43TVKP.js → chunk-GVHKIJ3G.js} +1 -1
  9. package/dist/chunk-OAYGID5B.js +27 -0
  10. package/dist/index.cjs +4 -18
  11. package/dist/index.d.ts +71 -28
  12. package/dist/index.js +6 -19
  13. package/ephemeral/dist/index.cjs +11 -0
  14. package/ephemeral/dist/index.js +9 -0
  15. package/ephemeral/package.json +16 -0
  16. package/ephemeral/src/index.ts +1 -0
  17. package/eslint-plugin/dist/index.cjs +155 -1
  18. package/eslint-plugin/dist/index.js +155 -1
  19. package/eslint-plugin/src/rules/index.ts +1 -0
  20. package/eslint-plugin/src/rules/lifespan.ts +203 -0
  21. package/eslint-plugin/src/rules/synchronous-selector-dependencies.ts +1 -65
  22. package/eslint-plugin/src/walk.ts +73 -0
  23. package/immortal/dist/index.cjs +260 -0
  24. package/immortal/dist/index.js +212 -0
  25. package/immortal/package.json +16 -0
  26. package/immortal/src/index.ts +3 -0
  27. package/immortal/src/make-molecule.ts +222 -0
  28. package/immortal/src/molecule.ts +167 -0
  29. package/immortal/src/seek-state.ts +73 -0
  30. package/internal/dist/index.cjs +1242 -837
  31. package/internal/dist/index.d.ts +135 -22
  32. package/internal/dist/index.js +1215 -838
  33. package/internal/src/atom/create-regular-atom.ts +0 -2
  34. package/internal/src/atom/create-standalone-atom.ts +6 -2
  35. package/internal/src/atom/dispose-atom.ts +26 -3
  36. package/internal/src/families/create-readonly-selector-family.ts +15 -10
  37. package/internal/src/families/create-regular-atom-family.ts +20 -21
  38. package/internal/src/families/create-writable-selector-family.ts +13 -9
  39. package/{src/dispose.ts → internal/src/families/dispose-from-store.ts} +7 -4
  40. package/internal/src/families/find-in-store.ts +11 -6
  41. package/internal/src/families/index.ts +3 -0
  42. package/internal/src/families/init-family-member.ts +112 -0
  43. package/internal/src/families/seek-in-store.ts +123 -0
  44. package/internal/src/get-state/get-from-store.ts +2 -2
  45. package/internal/src/ingest-updates/index.ts +1 -0
  46. package/internal/src/ingest-updates/ingest-creation-disposal.ts +104 -0
  47. package/internal/src/ingest-updates/ingest-transaction-update.ts +26 -4
  48. package/internal/src/mutable/create-mutable-atom-family.ts +22 -24
  49. package/internal/src/mutable/create-mutable-atom.ts +3 -3
  50. package/internal/src/mutable/get-json-family.ts +2 -2
  51. package/internal/src/mutable/get-json-token.ts +26 -12
  52. package/internal/src/mutable/tracker-family.ts +21 -19
  53. package/internal/src/not-found-error.ts +16 -3
  54. package/internal/src/selector/create-readonly-selector.ts +2 -3
  55. package/internal/src/selector/create-standalone-selector.ts +6 -2
  56. package/internal/src/selector/create-writable-selector.ts +2 -3
  57. package/internal/src/selector/dispose-selector.ts +68 -24
  58. package/internal/src/selector/register-selector.ts +10 -5
  59. package/internal/src/set-state/set-into-store.ts +2 -2
  60. package/internal/src/set-state/stow-update.ts +5 -1
  61. package/internal/src/store/deposit.ts +41 -7
  62. package/internal/src/store/index.ts +0 -1
  63. package/internal/src/store/store.ts +29 -5
  64. package/internal/src/store/withdraw.ts +28 -1
  65. package/internal/src/subscribe/subscribe-to-state.ts +2 -2
  66. package/internal/src/timeline/add-atom-to-timeline.ts +206 -182
  67. package/internal/src/timeline/create-timeline.ts +181 -60
  68. package/internal/src/timeline/time-travel.ts +20 -0
  69. package/internal/src/transaction/apply-transaction.ts +2 -12
  70. package/internal/src/transaction/build-transaction.ts +16 -2
  71. package/introspection/dist/index.cjs +40 -53
  72. package/introspection/dist/index.js +40 -53
  73. package/introspection/src/attach-atom-index.ts +38 -48
  74. package/introspection/src/attach-selector-index.ts +45 -50
  75. package/introspection/src/attach-timeline-family.ts +1 -0
  76. package/json/dist/index.cjs +40 -6
  77. package/json/dist/index.js +44 -9
  78. package/json/src/select-json-family.ts +47 -9
  79. package/package.json +30 -10
  80. package/react/dist/index.cjs +1 -1
  81. package/react/dist/index.js +1 -1
  82. package/react/src/use-json.ts +1 -1
  83. package/react-devtools/dist/index.cjs +69 -57
  84. package/react-devtools/dist/index.js +62 -49
  85. package/react-devtools/src/StateIndex.tsx +2 -1
  86. package/react-devtools/src/TimelineIndex.tsx +17 -14
  87. package/react-devtools/src/TransactionIndex.tsx +7 -7
  88. package/react-devtools/src/Updates.tsx +41 -32
  89. package/realtime-client/dist/index.cjs +3 -3
  90. package/realtime-client/dist/index.js +3 -3
  91. package/realtime-client/src/pull-mutable-atom-family-member.ts +1 -1
  92. package/realtime-client/src/pull-mutable-atom.ts +1 -1
  93. package/realtime-client/src/sync-continuity.ts +1 -2
  94. package/realtime-react/dist/index.cjs +1 -1
  95. package/realtime-react/dist/index.js +1 -1
  96. package/realtime-server/dist/index.cjs +39 -27
  97. package/realtime-server/dist/index.d.ts +1 -1
  98. package/realtime-server/dist/index.js +27 -16
  99. package/realtime-server/src/realtime-continuity-synchronizer.ts +5 -3
  100. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  101. package/realtime-server/src/realtime-mutable-provider.ts +1 -1
  102. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +21 -11
  103. package/realtime-testing/dist/index.cjs +7 -2
  104. package/realtime-testing/dist/index.js +8 -5
  105. package/realtime-testing/src/setup-realtime-test.tsx +5 -2
  106. package/src/atom.ts +19 -7
  107. package/src/dispose-state.ts +10 -0
  108. package/src/index.ts +5 -2
  109. package/src/selector.ts +13 -7
  110. package/src/silo.ts +3 -3
  111. package/src/subscribe.ts +8 -4
  112. package/src/timeline.ts +18 -1
  113. package/src/transaction.ts +59 -4
  114. package/dist/chunk-BF4MVQF6.js +0 -44
  115. package/internal/src/store/withdraw-new-family-member.ts +0 -69
  116. /package/{src → ephemeral/src}/find-state.ts +0 -0
@@ -1,7 +1,10 @@
1
1
  import { Junction } from '../../dist/chunk-FTONNX2R.js';
2
+ import { parseJson } from '../../dist/chunk-OAYGID5B.js';
2
3
  import { __spreadValues, __spreadProps } from '../../dist/chunk-F2X4B4VY.js';
3
- import { stringifyJson, selectJson, parseJson, selectJsonFamily } from 'atom.io/json';
4
+ import { stringifyJson, selectJson, parseJson as parseJson$1, selectJsonFamily } from 'atom.io/json';
4
5
  import { AtomIOLogger } from 'atom.io';
6
+ import { disposeMolecule, makeMoleculeInStore } from 'atom.io/immortal';
7
+ import * as Internal from 'atom.io/internal';
5
8
 
6
9
  // internal/src/arbitrary.ts
7
10
  function arbitrary(random = Math.random) {
@@ -60,14 +63,26 @@ function newest(scion) {
60
63
 
61
64
  // internal/src/store/deposit.ts
62
65
  function deposit(state) {
63
- const token = {
64
- key: state.key,
65
- type: state.type
66
- };
67
- if (`family` in state) {
68
- token.family = state.family;
66
+ const { type } = state;
67
+ switch (type) {
68
+ case `atom`:
69
+ case `molecule_family`:
70
+ case `mutable_atom`:
71
+ case `selector`:
72
+ case `readonly_selector`:
73
+ case `transaction`: {
74
+ const token = {
75
+ key: state.key,
76
+ type: state.type
77
+ };
78
+ if (`family` in state) {
79
+ token.family = state.family;
80
+ }
81
+ return token;
82
+ }
83
+ case `molecule`:
84
+ return state.token;
69
85
  }
70
- return token;
71
86
  }
72
87
 
73
88
  // internal/src/subject.ts
@@ -113,7 +128,7 @@ function isChildStore(store) {
113
128
 
114
129
  // internal/src/store/store.ts
115
130
  var Store = class {
116
- constructor(name, store = null) {
131
+ constructor(config, store = null) {
117
132
  this.parent = null;
118
133
  this.child = null;
119
134
  this.valueMap = /* @__PURE__ */ new Map();
@@ -142,6 +157,9 @@ var Store = class {
142
157
  makeContentKey: (...keys) => keys.sort().join(`:`)
143
158
  }
144
159
  );
160
+ this.molecules = /* @__PURE__ */ new Map();
161
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
162
+ this.miscResources = /* @__PURE__ */ new Map();
145
163
  this.on = {
146
164
  atomCreation: new Subject(),
147
165
  atomDisposal: new Subject(),
@@ -152,7 +170,10 @@ var Store = class {
152
170
  transactionApplying: new StatefulSubject(
153
171
  null
154
172
  ),
155
- operationClose: new Subject()
173
+ operationClose: new Subject(),
174
+ moleculeCreationStart: new Subject(),
175
+ moleculeCreationDone: new Subject(),
176
+ moleculeDisposal: new Subject()
156
177
  };
157
178
  this.operation = { open: false };
158
179
  this.transactionMeta = {
@@ -163,7 +184,8 @@ var Store = class {
163
184
  })
164
185
  };
165
186
  this.config = {
166
- name: `IMPLICIT_STORE`
187
+ name: `IMPLICIT_STORE`,
188
+ lifespan: `ephemeral`
167
189
  };
168
190
  this.loggers = [
169
191
  new AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
@@ -193,9 +215,7 @@ var Store = class {
193
215
  )
194
216
  };
195
217
  }
196
- this.config = __spreadProps(__spreadValues({}, store == null ? void 0 : store.config), {
197
- name
198
- });
218
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
199
219
  for (const [, family] of store.families) {
200
220
  family.install(this);
201
221
  }
@@ -206,7 +226,7 @@ var Store = class {
206
226
  }
207
227
  atom.install(this);
208
228
  if (atom.type === `mutable_atom`) {
209
- const originalJsonToken = getJsonToken(atom);
229
+ const originalJsonToken = getJsonToken(atom, store);
210
230
  const originalUpdateToken = getUpdateToken(atom);
211
231
  mutableHelpers.add(originalJsonToken.key);
212
232
  mutableHelpers.add(originalUpdateToken.key);
@@ -234,16 +254,20 @@ var IMPLICIT = {
234
254
  STORE_INTERNAL: void 0,
235
255
  get STORE() {
236
256
  var _a;
237
- return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store(`IMPLICIT_STORE`);
257
+ return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
258
+ name: `IMPLICIT_STORE`,
259
+ lifespan: `ephemeral`
260
+ });
238
261
  }
239
262
  };
240
263
  var clearStore = (store) => {
241
264
  const { config } = store;
242
- Object.assign(store, new Store(config.name));
265
+ for (const disposable of store.miscResources.values()) {
266
+ disposable[Symbol.dispose]();
267
+ }
268
+ Object.assign(store, new Store(config));
243
269
  store.config = config;
244
270
  };
245
-
246
- // internal/src/store/withdraw.ts
247
271
  function withdraw(token, store) {
248
272
  let withdrawn;
249
273
  let target = store;
@@ -271,6 +295,12 @@ function withdraw(token, store) {
271
295
  case `transaction`:
272
296
  withdrawn = target.transactions.get(token.key);
273
297
  break;
298
+ case `molecule`:
299
+ withdrawn = target.molecules.get(stringifyJson(token.key));
300
+ break;
301
+ case `molecule_family`:
302
+ withdrawn = target.moleculeFamilies.get(token.key);
303
+ break;
274
304
  }
275
305
  if (withdrawn) {
276
306
  return withdrawn;
@@ -280,36 +310,6 @@ function withdraw(token, store) {
280
310
  throw new NotFoundError(token, store);
281
311
  }
282
312
 
283
- // internal/src/store/withdraw-new-family-member.ts
284
- function withdrawOrCreate(token, store) {
285
- try {
286
- const state = withdraw(token, store);
287
- return state;
288
- } catch (notFoundError) {
289
- if (token.family) {
290
- store.logger.info(
291
- `\u{1F46A}`,
292
- token.type,
293
- token.key,
294
- `creating new family member in store "${store.config.name}"`
295
- );
296
- const target = newest(store);
297
- const family = target.families.get(token.family.key);
298
- if (family) {
299
- const jsonSubKey = JSON.parse(token.family.subKey);
300
- family(jsonSubKey);
301
- const state = withdraw(token, store);
302
- return state;
303
- }
304
- throw new NotFoundError(
305
- { key: token.family.key, type: `${token.type}_family` },
306
- store
307
- );
308
- }
309
- throw notFoundError;
310
- }
311
- }
312
-
313
313
  // internal/src/get-state/read-or-compute-value.ts
314
314
  var readOrComputeValue = (state, target) => {
315
315
  if (target.valueMap.has(state.key)) {
@@ -337,22 +337,17 @@ function createRegularAtomFamily(options, store) {
337
337
  const subKey = stringifyJson(key);
338
338
  const family = { key: options.key, subKey };
339
339
  const fullKey = `${options.key}(${subKey})`;
340
- const target2 = newest(store);
341
- const atomAlreadyCreated = target2.atoms.has(fullKey);
342
- let token;
343
- if (atomAlreadyCreated) {
344
- token = { type: `atom`, key: fullKey, family };
345
- } else {
346
- const individualOptions = {
347
- key: fullKey,
348
- default: options.default instanceof Function ? options.default(key) : options.default
349
- };
350
- if (options.effects) {
351
- individualOptions.effects = options.effects(key);
352
- }
353
- token = createRegularAtom(individualOptions, family, store);
354
- subject.next(token);
340
+ const target = newest(store);
341
+ const def = options.default;
342
+ const individualOptions = {
343
+ key: fullKey,
344
+ default: def instanceof Function ? def(key) : def
345
+ };
346
+ if (options.effects) {
347
+ individualOptions.effects = options.effects(key);
355
348
  }
349
+ const token = createRegularAtom(individualOptions, family, target);
350
+ subject.next({ type: `state_creation`, token });
356
351
  return token;
357
352
  },
358
353
  {
@@ -362,8 +357,7 @@ function createRegularAtomFamily(options, store) {
362
357
  install: (s) => createRegularAtomFamily(options, s)
363
358
  }
364
359
  );
365
- const target = newest(store);
366
- target.families.set(options.key, atomFamily);
360
+ store.families.set(options.key, atomFamily);
367
361
  return atomFamily;
368
362
  }
369
363
 
@@ -379,22 +373,20 @@ function createReadonlySelectorFamily(options, store) {
379
373
  const subject = new Subject();
380
374
  const readonlySelectorFamily = Object.assign(
381
375
  (key) => {
382
- const target = newest(store);
383
376
  const subKey = stringifyJson(key);
384
377
  const family = { key: options.key, subKey };
385
378
  const fullKey = `${options.key}(${subKey})`;
386
- const existing = target.readonlySelectors.get(fullKey);
387
- if (existing) {
388
- return deposit(existing);
389
- }
390
- return createReadonlySelector(
379
+ const target = newest(store);
380
+ const token = createReadonlySelector(
391
381
  {
392
382
  key: fullKey,
393
383
  get: options.get(key)
394
384
  },
395
385
  family,
396
- store
386
+ target
397
387
  );
388
+ subject.next({ type: `state_creation`, token });
389
+ return token;
398
390
  },
399
391
  {
400
392
  key: options.key,
@@ -413,10 +405,7 @@ function createWritableSelectorFamily(options, store) {
413
405
  const subKey = stringifyJson(key);
414
406
  const family = { key: options.key, subKey };
415
407
  const fullKey = `${options.key}(${subKey})`;
416
- const existing = store.selectors.get(fullKey);
417
- if (existing) {
418
- return deposit(existing);
419
- }
408
+ const target = newest(store);
420
409
  const token = createWritableSelector(
421
410
  {
422
411
  key: fullKey,
@@ -424,9 +413,9 @@ function createWritableSelectorFamily(options, store) {
424
413
  set: options.set(key)
425
414
  },
426
415
  family,
427
- store
416
+ target
428
417
  );
429
- subject.next(token);
418
+ subject.next({ type: `state_creation`, token });
430
419
  return token;
431
420
  },
432
421
  {
@@ -448,14 +437,39 @@ function createSelectorFamily(options, store) {
448
437
  }
449
438
  return createReadonlySelectorFamily(options, store);
450
439
  }
440
+ function disposeFromStore(token, store = Internal.IMPLICIT.STORE) {
441
+ switch (token.type) {
442
+ case `atom`:
443
+ case `mutable_atom`:
444
+ Internal.disposeAtom(token, store);
445
+ break;
446
+ case `selector`:
447
+ case `readonly_selector`:
448
+ Internal.disposeSelector(token, store);
449
+ break;
450
+ case `molecule`:
451
+ disposeMolecule(token, store);
452
+ break;
453
+ }
454
+ }
451
455
 
452
456
  // internal/src/not-found-error.ts
453
457
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
454
458
  function prettyPrintTokenType(token) {
455
- if (token.type === `readonly_selector`) {
456
- return `Readonly Selector`;
459
+ switch (token.type) {
460
+ case `atom_family`:
461
+ return `Atom Family`;
462
+ case `molecule_family`:
463
+ return `Molecule Family`;
464
+ case `readonly_selector`:
465
+ return `Readonly Selector`;
466
+ case `readonly_selector_family`:
467
+ return `Readonly Selector Family`;
468
+ case `selector_family`:
469
+ return `Selector Family`;
470
+ default:
471
+ return capitalize(token.type);
457
472
  }
458
- return capitalize(token.type);
459
473
  }
460
474
  var NotFoundError = class extends Error {
461
475
  constructor(token, store) {
@@ -465,15 +479,36 @@ var NotFoundError = class extends Error {
465
479
  }
466
480
  };
467
481
 
468
- // internal/src/families/find-in-store.ts
469
- function findInStore(token, key, store) {
470
- const familyKey = token.key;
471
- const family = store.families.get(familyKey);
472
- if (family === void 0) {
473
- throw new NotFoundError(token, store);
482
+ // internal/src/transaction/abort-transaction.ts
483
+ var abortTransaction = (store) => {
484
+ const target = newest(store);
485
+ if (!isChildStore(target)) {
486
+ store.logger.warn(
487
+ `\u{1F41E}`,
488
+ `transaction`,
489
+ `???`,
490
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
491
+ );
492
+ return;
474
493
  }
475
- const state = family(key);
476
- return state;
494
+ store.logger.info(
495
+ `\u{1FA82}`,
496
+ `transaction`,
497
+ target.transactionMeta.update.key,
498
+ `Aborting transaction`
499
+ );
500
+ target.parent.child = null;
501
+ };
502
+
503
+ // internal/src/transaction/act-upon-store.ts
504
+ function actUponStore(token, id, store) {
505
+ return (...parameters) => {
506
+ const tx = withdraw(token, store);
507
+ if (tx) {
508
+ return tx.run(parameters, id);
509
+ }
510
+ throw new NotFoundError(token, store);
511
+ };
477
512
  }
478
513
 
479
514
  // internal/src/set-state/become.ts
@@ -629,7 +664,10 @@ var stowUpdate = (state, update, store) => {
629
664
  if (!shouldStow) {
630
665
  return;
631
666
  }
632
- const atomUpdate = __spreadValues({ key }, update);
667
+ const atomUpdate = __spreadValues({
668
+ type: `atom_update`,
669
+ key
670
+ }, update);
633
671
  if (state.family) {
634
672
  atomUpdate.family = state.family;
635
673
  }
@@ -717,164 +755,616 @@ function setIntoStore(token, value, store) {
717
755
  );
718
756
  return;
719
757
  }
720
- const state = withdrawOrCreate(token, store);
758
+ const state = withdraw(token, store);
721
759
  setAtomOrSelector(state, value, store);
722
760
  closeOperation(store);
723
761
  }
724
762
 
725
- // internal/src/keys.ts
726
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
727
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
728
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
729
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
730
-
731
- // internal/src/selector/get-selector-dependency-keys.ts
732
- var getSelectorDependencyKeys = (key, store) => {
733
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
734
- return sources;
735
- };
736
-
737
- // internal/src/selector/trace-selector-atoms.ts
738
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
739
- const rootKeys = [];
740
- const indirectDependencyKeys = getSelectorDependencyKeys(
741
- directDependencyKey,
742
- store
743
- );
744
- let depth = 0;
745
- while (indirectDependencyKeys.length > 0) {
746
- const indirectDependencyKey = indirectDependencyKeys.shift();
747
- ++depth;
748
- if (depth > 99999) {
749
- throw new Error(
750
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
751
- );
763
+ // internal/src/ingest-updates/ingest-atom-update.ts
764
+ function ingestAtomUpdate(applying, atomUpdate, store) {
765
+ const { key, newValue, oldValue } = atomUpdate;
766
+ const value = applying === `newValue` ? newValue : oldValue;
767
+ const token = { key, type: `atom` };
768
+ if (atomUpdate.family) {
769
+ Object.assign(token, { family: atomUpdate.family });
770
+ }
771
+ setIntoStore(token, value, store);
772
+ }
773
+ function ingestCreationEvent(update, applying, store) {
774
+ switch (applying) {
775
+ case `newValue`: {
776
+ createInStore(update.token, store);
777
+ break;
752
778
  }
753
- if (!isAtomKey(indirectDependencyKey, store)) {
754
- indirectDependencyKeys.push(
755
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
756
- );
757
- } else if (!rootKeys.includes(indirectDependencyKey)) {
758
- rootKeys.push(indirectDependencyKey);
779
+ case `oldValue`: {
780
+ disposeFromStore(update.token, store);
781
+ break;
759
782
  }
760
783
  }
761
- return rootKeys;
762
- };
763
- var traceAllSelectorAtoms = (selector, store) => {
764
- const selectorKey = selector.key;
765
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
766
- return directDependencyKeys.flatMap(
767
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
768
- );
769
- };
770
-
771
- // internal/src/selector/update-selector-atoms.ts
772
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
773
- const target = newest(store);
774
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
775
- target.selectorAtoms.set({
776
- selectorKey,
777
- atomKey: dependency.key
778
- });
779
- store.logger.info(
780
- `\u{1F50D}`,
781
- `selector`,
782
- selectorKey,
783
- `discovers root atom "${dependency.key}"`
784
- );
785
- } else {
786
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
787
- store.logger.info(
788
- `\u{1F50D}`,
789
- `selector`,
790
- selectorKey,
791
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
792
- );
793
- for (const atomKey of rootKeys) {
794
- target.selectorAtoms = target.selectorAtoms.set({
795
- selectorKey,
796
- atomKey
797
- });
784
+ }
785
+ function ingestDisposalEvent(update, applying, store) {
786
+ switch (applying) {
787
+ case `newValue`: {
788
+ disposeFromStore(update.token, store);
789
+ break;
790
+ }
791
+ case `oldValue`: {
792
+ createInStore(update.token, store);
793
+ store.valueMap.set(update.token.key, update.value);
794
+ break;
798
795
  }
799
796
  }
800
- };
801
-
802
- // internal/src/selector/register-selector.ts
803
- var registerSelector = (selectorKey, store) => ({
804
- get: (dependency) => {
805
- const target = newest(store);
806
- const dependencyState = withdrawOrCreate(dependency, store);
807
- const dependencyValue = readOrComputeValue(dependencyState, store);
808
- store.logger.info(
809
- `\u{1F50C}`,
810
- `selector`,
811
- selectorKey,
812
- `registers dependency ( "${dependency.key}" =`,
813
- dependencyValue,
814
- `)`
815
- );
816
- target.selectorGraph.set(
817
- {
818
- upstreamSelectorKey: dependency.key,
819
- downstreamSelectorKey: selectorKey
820
- },
821
- {
822
- source: dependency.key
797
+ }
798
+ function createInStore(token, store) {
799
+ if (token.family) {
800
+ const family = store.families.get(token.family.key);
801
+ if (family) {
802
+ const molecule = store.molecules.get(token.family.subKey);
803
+ if (molecule) {
804
+ molecule.bond(family);
805
+ return;
823
806
  }
824
- );
825
- updateSelectorAtoms(selectorKey, dependency, store);
826
- return dependencyValue;
827
- },
828
- set: (WritableToken, newValue) => {
829
- const state = withdrawOrCreate(WritableToken, store);
830
- setAtomOrSelector(state, newValue, store);
831
- },
832
- find: (token, key) => findInStore(token, key, store)
833
- });
807
+ if (store.config.lifespan === `immortal`) {
808
+ throw new Error(`No molecule found for key "${token.family.subKey}"`);
809
+ }
810
+ initFamilyMember(family, parseJson(token.family.subKey), store);
811
+ }
812
+ }
813
+ }
814
+ function ingestMoleculeCreationEvent(update, applying, store) {
815
+ switch (applying) {
816
+ case `newValue`:
817
+ makeMoleculeInStore(
818
+ store,
819
+ update.context[0],
820
+ update.family,
821
+ update.token.key,
822
+ ...update.params
823
+ );
824
+ break;
825
+ case `oldValue`:
826
+ disposeMolecule(update.token, store);
827
+ break;
828
+ }
829
+ }
830
+ function ingestMoleculeDisposalEvent(update, applying, store) {
831
+ switch (applying) {
832
+ case `newValue`:
833
+ disposeMolecule(update.token, store);
834
+ break;
835
+ case `oldValue`:
836
+ makeMoleculeInStore(
837
+ store,
838
+ update.context[0],
839
+ update.family,
840
+ update.token.key
841
+ );
842
+ break;
843
+ }
844
+ }
834
845
 
835
- // internal/src/selector/create-readonly-selector.ts
836
- var createReadonlySelector = (options, family, store) => {
837
- const target = newest(store);
838
- const subject = new Subject();
839
- const { get, find } = registerSelector(options.key, target);
840
- const getSelf = () => {
841
- const value = options.get({ get, find });
842
- cacheValue(options.key, value, subject, newest(store));
843
- return value;
844
- };
845
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
846
- subject,
847
- install: (s) => createReadonlySelector(options, family, s),
848
- get: getSelf,
849
- type: `readonly_selector`
850
- }), family && { family });
851
- target.readonlySelectors.set(options.key, readonlySelector);
852
- const initialValue = getSelf();
853
- store.logger.info(
854
- `\u2728`,
855
- readonlySelector.type,
856
- readonlySelector.key,
857
- `=`,
858
- initialValue
859
- );
860
- const token = {
861
- key: options.key,
862
- type: `readonly_selector`
863
- };
864
- if (family) {
865
- token.family = family;
846
+ // internal/src/ingest-updates/ingest-selector-update.ts
847
+ function ingestSelectorUpdate(applying, selectorUpdate, store) {
848
+ const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
849
+ for (const atomUpdate of updates) {
850
+ ingestAtomUpdate(applying, atomUpdate, store);
866
851
  }
867
- store.on.selectorCreation.next(token);
868
- return token;
869
- };
852
+ }
870
853
 
871
- // internal/src/selector/create-writable-selector.ts
872
- var createWritableSelector = (options, family, store) => {
854
+ // internal/src/ingest-updates/ingest-transaction-update.ts
855
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
856
+ const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
857
+ for (const updateFromTransaction of updates) {
858
+ switch (updateFromTransaction.type) {
859
+ case `atom_update`:
860
+ case `selector_update`:
861
+ ingestAtomUpdate(applying, updateFromTransaction, store);
862
+ break;
863
+ case `state_creation`:
864
+ ingestCreationEvent(updateFromTransaction, applying, store);
865
+ break;
866
+ case `state_disposal`:
867
+ ingestDisposalEvent(updateFromTransaction, applying, store);
868
+ break;
869
+ case `molecule_creation`:
870
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
871
+ break;
872
+ case `molecule_disposal`:
873
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
874
+ break;
875
+ case `transaction_update`:
876
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
877
+ break;
878
+ }
879
+ }
880
+ }
881
+
882
+ // internal/src/transaction/set-epoch-number.ts
883
+ function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
884
+ const isRoot = isRootStore(store);
885
+ if (isRoot && continuityKey) {
886
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
887
+ }
888
+ }
889
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
890
+ const isRoot = isRootStore(store);
891
+ if (!isRoot) {
892
+ return;
893
+ }
894
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
895
+ if (continuityKey !== void 0) {
896
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
897
+ }
898
+ }
899
+
900
+ // internal/src/transaction/apply-transaction.ts
901
+ var applyTransaction = (output, store) => {
902
+ var _a;
903
+ const child = newest(store);
904
+ const { parent } = child;
905
+ if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
906
+ store.logger.warn(
907
+ `\u{1F41E}`,
908
+ `transaction`,
909
+ `???`,
910
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
911
+ );
912
+ return;
913
+ }
914
+ child.transactionMeta.phase = `applying`;
915
+ child.transactionMeta.update.output = output;
916
+ parent.child = null;
917
+ parent.on.transactionApplying.next(child.transactionMeta);
918
+ const { updates } = child.transactionMeta.update;
919
+ store.logger.info(
920
+ `\u{1F6C4}`,
921
+ `transaction`,
922
+ child.transactionMeta.update.key,
923
+ `Applying transaction with ${updates.length} updates:`,
924
+ updates
925
+ );
926
+ for (const tracker of child.trackers.values()) {
927
+ const mutableKey = tracker.mutableState.key;
928
+ if (!parent.atoms.has(mutableKey)) {
929
+ const atom = child.atoms.get(mutableKey);
930
+ atom == null ? void 0 : atom.install(parent);
931
+ }
932
+ tracker.dispose();
933
+ }
934
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
935
+ if (isRootStore(parent)) {
936
+ setEpochNumberOfAction(
937
+ child.transactionMeta.update.key,
938
+ child.transactionMeta.update.epoch,
939
+ parent
940
+ );
941
+ const myTransaction = withdraw(
942
+ { key: child.transactionMeta.update.key, type: `transaction` },
943
+ store
944
+ );
945
+ myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
946
+ store.logger.info(
947
+ `\u{1F6EC}`,
948
+ `transaction`,
949
+ child.transactionMeta.update.key,
950
+ `Finished applying transaction.`
951
+ );
952
+ } else if (isChildStore(parent)) {
953
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
954
+ }
955
+ parent.on.transactionApplying.next(null);
956
+ };
957
+
958
+ // internal/src/transaction/assign-transaction-to-continuity.ts
959
+ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
960
+ const isRoot = isRootStore(store);
961
+ if (!isRoot) {
962
+ return;
963
+ }
964
+ const { epoch, actionContinuities } = store.transactionMeta;
965
+ actionContinuities.set(continuityKey, transactionKey);
966
+ if (!epoch.has(continuityKey)) {
967
+ epoch.set(continuityKey, -1);
968
+ }
969
+ }
970
+
971
+ // internal/src/get-environment-data.ts
972
+ function getEnvironmentData(store) {
973
+ return {
974
+ window: typeof window === `undefined` ? void 0 : window,
975
+ global: typeof global === `undefined` ? void 0 : global,
976
+ store
977
+ };
978
+ }
979
+
980
+ // internal/src/get-state/get-from-store.ts
981
+ function getFromStore(token, store) {
982
+ const state = withdraw(token, store);
983
+ return readOrComputeValue(state, store);
984
+ }
985
+
986
+ // internal/src/lazy-map.ts
987
+ var LazyMap = class extends Map {
988
+ constructor(source) {
989
+ super();
990
+ this.source = source;
991
+ this.deleted = /* @__PURE__ */ new Set();
992
+ }
993
+ get(key) {
994
+ const has = super.has(key);
995
+ if (has) {
996
+ return super.get(key);
997
+ }
998
+ if (!this.deleted.has(key) && this.source.has(key)) {
999
+ const value = this.source.get(key);
1000
+ return value;
1001
+ }
1002
+ return void 0;
1003
+ }
1004
+ set(key, value) {
1005
+ this.deleted.delete(key);
1006
+ return super.set(key, value);
1007
+ }
1008
+ hasOwn(key) {
1009
+ return super.has(key);
1010
+ }
1011
+ has(key) {
1012
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1013
+ }
1014
+ delete(key) {
1015
+ this.deleted.add(key);
1016
+ return super.delete(key);
1017
+ }
1018
+ };
1019
+
1020
+ // internal/src/transaction/build-transaction.ts
1021
+ var buildTransaction = (key, params, store, id) => {
1022
+ const parent = newest(store);
1023
+ const childBase = {
1024
+ parent,
1025
+ child: null,
1026
+ on: parent.on,
1027
+ loggers: parent.loggers,
1028
+ logger: parent.logger,
1029
+ config: parent.config,
1030
+ atoms: new LazyMap(parent.atoms),
1031
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1032
+ families: new LazyMap(parent.families),
1033
+ operation: { open: false },
1034
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
1035
+ timelines: new LazyMap(parent.timelines),
1036
+ timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
1037
+ trackers: /* @__PURE__ */ new Map(),
1038
+ transactions: new LazyMap(parent.transactions),
1039
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1040
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1041
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1042
+ }),
1043
+ selectors: new LazyMap(parent.selectors),
1044
+ valueMap: new LazyMap(parent.valueMap),
1045
+ molecules: new LazyMap(parent.molecules),
1046
+ moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1047
+ miscResources: new LazyMap(parent.miscResources)
1048
+ };
1049
+ const epoch = getEpochNumberOfAction(key, store);
1050
+ const transactionMeta = {
1051
+ phase: `building`,
1052
+ update: {
1053
+ type: `transaction_update`,
1054
+ key,
1055
+ id,
1056
+ epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1057
+ updates: [],
1058
+ params,
1059
+ output: void 0
1060
+ },
1061
+ transactors: {
1062
+ get: (token) => getFromStore(token, child),
1063
+ set: (token, value) => {
1064
+ setIntoStore(token, value, child);
1065
+ },
1066
+ run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1067
+ find: (token, k) => findInStore(token, k, child),
1068
+ seek: (token, k) => seekInStore(token, k, child),
1069
+ json: (token) => getJsonToken(token, child),
1070
+ make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1071
+ dispose: (token) => {
1072
+ disposeFromStore(token, child);
1073
+ },
1074
+ env: () => getEnvironmentData(child)
1075
+ }
1076
+ };
1077
+ const child = Object.assign(childBase, {
1078
+ transactionMeta
1079
+ });
1080
+ parent.child = child;
1081
+ store.logger.info(
1082
+ `\u{1F6EB}`,
1083
+ `transaction`,
1084
+ key,
1085
+ `Building transaction with params:`,
1086
+ params
1087
+ );
1088
+ return child;
1089
+ };
1090
+
1091
+ // internal/src/transaction/create-transaction.ts
1092
+ function createTransaction(options, store) {
1093
+ const newTransaction = {
1094
+ key: options.key,
1095
+ type: `transaction`,
1096
+ run: (params, id) => {
1097
+ const childStore = buildTransaction(options.key, params, store, id);
1098
+ try {
1099
+ const target2 = newest(store);
1100
+ const { transactors } = childStore.transactionMeta;
1101
+ const output = options.do(transactors, ...params);
1102
+ applyTransaction(output, target2);
1103
+ return output;
1104
+ } catch (thrown) {
1105
+ abortTransaction(target);
1106
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1107
+ throw thrown;
1108
+ }
1109
+ },
1110
+ install: (s) => createTransaction(options, s),
1111
+ subject: new Subject()
1112
+ };
1113
+ const target = newest(store);
1114
+ target.transactions.set(newTransaction.key, newTransaction);
1115
+ const token = deposit(newTransaction);
1116
+ store.on.transactionCreation.next(token);
1117
+ return token;
1118
+ }
1119
+
1120
+ // internal/src/transaction/get-epoch-number.ts
1121
+ function getContinuityKey(transactionKey, store) {
1122
+ const isRoot = isRootStore(store);
1123
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1124
+ return continuity;
1125
+ }
1126
+ function getEpochNumberOfContinuity(continuityKey, store) {
1127
+ const isRoot = isRootStore(store);
1128
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1129
+ return epoch;
1130
+ }
1131
+ function getEpochNumberOfAction(transactionKey, store) {
1132
+ const isRoot = isRootStore(store);
1133
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1134
+ const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1135
+ return epoch;
1136
+ }
1137
+
1138
+ // internal/src/transaction/index.ts
1139
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1140
+
1141
+ // internal/src/families/init-family-member.ts
1142
+ function initFamilyMember(token, key, store) {
1143
+ const familyKey = token.key;
1144
+ const family = store.families.get(familyKey);
1145
+ if (family === void 0) {
1146
+ throw new NotFoundError(token, store);
1147
+ }
1148
+ const state = family(key);
1149
+ const target = newest(store);
1150
+ if (state.family) {
1151
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1152
+ target.transactionMeta.update.updates.push({
1153
+ type: `state_creation`,
1154
+ token: state
1155
+ });
1156
+ } else {
1157
+ switch (state.type) {
1158
+ case `atom`:
1159
+ case `mutable_atom`:
1160
+ store.on.atomCreation.next(state);
1161
+ break;
1162
+ case `selector`:
1163
+ case `readonly_selector`:
1164
+ store.on.selectorCreation.next(state);
1165
+ break;
1166
+ }
1167
+ }
1168
+ }
1169
+ return state;
1170
+ }
1171
+ function seekInStore(token, key, store) {
1172
+ const subKey = stringifyJson(key);
1173
+ const fullKey = `${token.key}(${subKey})`;
1174
+ const target = newest(store);
1175
+ let state;
1176
+ switch (token.type) {
1177
+ case `atom_family`:
1178
+ case `mutable_atom_family`:
1179
+ state = target.atoms.get(fullKey);
1180
+ break;
1181
+ case `selector_family`:
1182
+ state = target.selectors.get(fullKey);
1183
+ break;
1184
+ case `readonly_selector_family`:
1185
+ state = target.readonlySelectors.get(fullKey);
1186
+ break;
1187
+ case `molecule_family`:
1188
+ state = target.molecules.get(stringifyJson(key));
1189
+ if (state) {
1190
+ return deposit(state);
1191
+ }
1192
+ }
1193
+ if (state) {
1194
+ return deposit(state);
1195
+ }
1196
+ return state;
1197
+ }
1198
+
1199
+ // internal/src/families/find-in-store.ts
1200
+ function findInStore(token, key, store) {
1201
+ if (store.config.lifespan === `immortal`) {
1202
+ throw new Error(
1203
+ `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
1204
+ );
1205
+ }
1206
+ let state = seekInStore(token, key, store);
1207
+ if (state) {
1208
+ return state;
1209
+ }
1210
+ state = initFamilyMember(token, key, store);
1211
+ return state;
1212
+ }
1213
+
1214
+ // internal/src/keys.ts
1215
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
1216
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1217
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1218
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1219
+
1220
+ // internal/src/selector/get-selector-dependency-keys.ts
1221
+ var getSelectorDependencyKeys = (key, store) => {
1222
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1223
+ return sources;
1224
+ };
1225
+
1226
+ // internal/src/selector/trace-selector-atoms.ts
1227
+ var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1228
+ const rootKeys = [];
1229
+ const indirectDependencyKeys = getSelectorDependencyKeys(
1230
+ directDependencyKey,
1231
+ store
1232
+ );
1233
+ let depth = 0;
1234
+ while (indirectDependencyKeys.length > 0) {
1235
+ const indirectDependencyKey = indirectDependencyKeys.shift();
1236
+ ++depth;
1237
+ if (depth > 99999) {
1238
+ throw new Error(
1239
+ `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1240
+ );
1241
+ }
1242
+ if (!isAtomKey(indirectDependencyKey, store)) {
1243
+ indirectDependencyKeys.push(
1244
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
1245
+ );
1246
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
1247
+ rootKeys.push(indirectDependencyKey);
1248
+ }
1249
+ }
1250
+ return rootKeys;
1251
+ };
1252
+ var traceAllSelectorAtoms = (selector, store) => {
1253
+ const selectorKey = selector.key;
1254
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1255
+ return directDependencyKeys.flatMap(
1256
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1257
+ );
1258
+ };
1259
+
1260
+ // internal/src/selector/update-selector-atoms.ts
1261
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1262
+ const target = newest(store);
1263
+ if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1264
+ target.selectorAtoms.set({
1265
+ selectorKey,
1266
+ atomKey: dependency.key
1267
+ });
1268
+ store.logger.info(
1269
+ `\u{1F50D}`,
1270
+ `selector`,
1271
+ selectorKey,
1272
+ `discovers root atom "${dependency.key}"`
1273
+ );
1274
+ } else {
1275
+ const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1276
+ store.logger.info(
1277
+ `\u{1F50D}`,
1278
+ `selector`,
1279
+ selectorKey,
1280
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1281
+ );
1282
+ for (const atomKey of rootKeys) {
1283
+ target.selectorAtoms = target.selectorAtoms.set({
1284
+ selectorKey,
1285
+ atomKey
1286
+ });
1287
+ }
1288
+ }
1289
+ };
1290
+
1291
+ // internal/src/selector/register-selector.ts
1292
+ var registerSelector = (selectorKey, store) => ({
1293
+ get: (dependency) => {
1294
+ const target = newest(store);
1295
+ const dependencyState = withdraw(dependency, store);
1296
+ const dependencyValue = readOrComputeValue(dependencyState, store);
1297
+ store.logger.info(
1298
+ `\u{1F50C}`,
1299
+ `selector`,
1300
+ selectorKey,
1301
+ `registers dependency ( "${dependency.key}" =`,
1302
+ dependencyValue,
1303
+ `)`
1304
+ );
1305
+ target.selectorGraph.set(
1306
+ {
1307
+ upstreamSelectorKey: dependency.key,
1308
+ downstreamSelectorKey: selectorKey
1309
+ },
1310
+ {
1311
+ source: dependency.key
1312
+ }
1313
+ );
1314
+ updateSelectorAtoms(selectorKey, dependency, store);
1315
+ return dependencyValue;
1316
+ },
1317
+ set: (WritableToken, newValue) => {
1318
+ const state = withdraw(WritableToken, store);
1319
+ setAtomOrSelector(state, newValue, store);
1320
+ },
1321
+ find: (token, key) => findInStore(token, key, store),
1322
+ seek: (token, key) => seekInStore(token, key, store),
1323
+ json: (token) => getJsonToken(token, store)
1324
+ });
1325
+
1326
+ // internal/src/selector/create-readonly-selector.ts
1327
+ var createReadonlySelector = (options, family, store) => {
1328
+ const target = newest(store);
1329
+ const subject = new Subject();
1330
+ const { get, find, seek, json } = registerSelector(options.key, target);
1331
+ const getSelf = () => {
1332
+ const value = options.get({ get, find, seek, json });
1333
+ cacheValue(options.key, value, subject, newest(store));
1334
+ return value;
1335
+ };
1336
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1337
+ subject,
1338
+ install: (s) => createReadonlySelector(options, family, s),
1339
+ get: getSelf,
1340
+ type: `readonly_selector`
1341
+ }), family && { family });
1342
+ target.readonlySelectors.set(options.key, readonlySelector);
1343
+ const initialValue = getSelf();
1344
+ store.logger.info(
1345
+ `\u2728`,
1346
+ readonlySelector.type,
1347
+ readonlySelector.key,
1348
+ `=`,
1349
+ initialValue
1350
+ );
1351
+ const token = {
1352
+ key: options.key,
1353
+ type: `readonly_selector`
1354
+ };
1355
+ if (family) {
1356
+ token.family = family;
1357
+ }
1358
+ return token;
1359
+ };
1360
+
1361
+ // internal/src/selector/create-writable-selector.ts
1362
+ var createWritableSelector = (options, family, store) => {
873
1363
  const target = newest(store);
874
1364
  const subject = new Subject();
875
1365
  const transactors = registerSelector(options.key, target);
876
- const { find, get } = transactors;
877
- const readonlyTransactors = { find, get };
1366
+ const { find, get, seek, json } = transactors;
1367
+ const readonlyTransactors = { find, get, seek, json };
878
1368
  const getSelf = () => {
879
1369
  const value = options.get(readonlyTransactors);
880
1370
  cacheValue(options.key, value, subject, newest(store));
@@ -917,7 +1407,6 @@ var createWritableSelector = (options, family, store) => {
917
1407
  if (family) {
918
1408
  token.family = family;
919
1409
  }
920
- store.on.selectorCreation.next(token);
921
1410
  return token;
922
1411
  };
923
1412
 
@@ -925,39 +1414,88 @@ var createWritableSelector = (options, family, store) => {
925
1414
  function createStandaloneSelector(options, store) {
926
1415
  const isWritable = `set` in options;
927
1416
  if (isWritable) {
928
- return createWritableSelector(options, void 0, store);
1417
+ const state2 = createWritableSelector(options, void 0, store);
1418
+ store.on.selectorCreation.next(state2);
1419
+ return state2;
929
1420
  }
930
- return createReadonlySelector(options, void 0, store);
1421
+ const state = createReadonlySelector(options, void 0, store);
1422
+ store.on.selectorCreation.next(state);
1423
+ return state;
931
1424
  }
932
1425
 
933
1426
  // internal/src/selector/dispose-selector.ts
934
- function disposeSelector(selectorToken, store) {
1427
+ function disposeSelector2(selectorToken, store) {
1428
+ var _a;
935
1429
  const target = newest(store);
936
1430
  const { key } = selectorToken;
937
- switch (selectorToken.type) {
938
- case `selector`:
939
- target.selectors.delete(key);
940
- break;
941
- case `readonly_selector`:
942
- target.readonlySelectors.delete(key);
943
- break;
944
- }
945
- target.valueMap.delete(key);
946
- target.selectorAtoms.delete(key);
947
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
948
- ([downstreamSelectorKey]) => {
949
- var _a;
950
- return (_a = target.selectors.get(downstreamSelectorKey)) != null ? _a : target.readonlySelectors.get(downstreamSelectorKey);
1431
+ const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1432
+ if (!selector) {
1433
+ store.logger.info(
1434
+ `\u274C`,
1435
+ `selector`,
1436
+ key,
1437
+ `Tried to dispose selector, but it does not exist in the store.`
1438
+ );
1439
+ } else if (!selector.family) {
1440
+ store.logger.error(
1441
+ `\u274C`,
1442
+ `selector`,
1443
+ key,
1444
+ `Standalone selectors cannot be disposed.`
1445
+ );
1446
+ } else {
1447
+ switch (selectorToken.type) {
1448
+ case `selector`:
1449
+ {
1450
+ target.selectors.delete(key);
1451
+ const family = withdraw(
1452
+ { key: selector.family.key, type: `selector_family` },
1453
+ store
1454
+ );
1455
+ family.subject.next({
1456
+ type: `state_disposal`,
1457
+ token: selectorToken
1458
+ });
1459
+ }
1460
+ break;
1461
+ case `readonly_selector`:
1462
+ {
1463
+ target.readonlySelectors.delete(key);
1464
+ const family = withdraw(
1465
+ { key: selector.family.key, type: `readonly_selector_family` },
1466
+ store
1467
+ );
1468
+ family.subject.next({
1469
+ type: `state_disposal`,
1470
+ token: selectorToken
1471
+ });
1472
+ }
1473
+ break;
951
1474
  }
952
- );
953
- for (const downstreamToken of downstreamTokens) {
954
- if (downstreamToken) {
955
- disposeSelector(downstreamToken, store);
1475
+ target.valueMap.delete(key);
1476
+ target.selectorAtoms.delete(key);
1477
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1478
+ ([downstreamSelectorKey]) => {
1479
+ var _a2;
1480
+ return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1481
+ }
1482
+ );
1483
+ for (const downstreamToken of downstreamTokens) {
1484
+ if (downstreamToken) {
1485
+ disposeSelector2(downstreamToken, store);
1486
+ }
1487
+ }
1488
+ target.selectorGraph.delete(key);
1489
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1490
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1491
+ target.transactionMeta.update.updates.push({
1492
+ type: `state_disposal`,
1493
+ token: selectorToken
1494
+ });
1495
+ } else {
1496
+ store.on.selectorDisposal.next(selectorToken);
956
1497
  }
957
1498
  }
958
- target.selectorGraph.delete(key);
959
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
960
- store.on.selectorDisposal.next(selectorToken);
961
1499
  }
962
1500
 
963
1501
  // internal/src/subscribe/recall-state.ts
@@ -1028,7 +1566,7 @@ function subscribeToState(token, handleUpdate, key, store) {
1028
1566
  handleUpdate(update);
1029
1567
  }
1030
1568
  }
1031
- const state = withdrawOrCreate(token, store);
1569
+ const state = withdraw(token, store);
1032
1570
  store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
1033
1571
  const isSelector = state.type === `selector` || state.type === `readonly_selector`;
1034
1572
  let dependencyUnsubFunctions = null;
@@ -1289,37 +1827,40 @@ function createMutableAtom(options, family, store) {
1289
1827
  };
1290
1828
  }
1291
1829
  new Tracker(token, store);
1292
- selectJson(token, options, store);
1293
- store.on.atomCreation.next(token);
1830
+ if (!family) {
1831
+ selectJson(token, options, store);
1832
+ }
1294
1833
  return token;
1295
1834
  }
1296
1835
  var FamilyTracker = class {
1297
- constructor(findMutableState, store) {
1298
- this.findLatestUpdateState = createRegularAtomFamily(
1836
+ constructor(mutableAtoms, store) {
1837
+ this.latestUpdateAtoms = createRegularAtomFamily(
1299
1838
  {
1300
- key: `*${findMutableState.key}`,
1839
+ key: `*${mutableAtoms.key}`,
1301
1840
  default: null
1302
1841
  },
1303
1842
  store
1304
1843
  );
1305
- this.findMutableState = findMutableState;
1306
- this.findMutableState.subject.subscribe(
1844
+ this.mutableAtoms = mutableAtoms;
1845
+ this.mutableAtoms.subject.subscribe(
1307
1846
  `store=${store.config.name}::tracker-atom-family`,
1308
- (atomToken) => {
1309
- if (atomToken.family) {
1310
- const key = parseJson(atomToken.family.subKey);
1311
- this.findLatestUpdateState(key);
1312
- new Tracker(atomToken, store);
1847
+ (event) => {
1848
+ if (event.token.family) {
1849
+ const key = parseJson$1(event.token.family.subKey);
1850
+ seekInStore(this.latestUpdateAtoms, key, store);
1851
+ new Tracker(event.token, store);
1313
1852
  }
1314
1853
  }
1315
1854
  );
1316
- this.findLatestUpdateState.subject.subscribe(
1855
+ this.latestUpdateAtoms.subject.subscribe(
1317
1856
  `store=${store.config.name}::tracker-atom-family`,
1318
- (atomToken) => {
1319
- if (atomToken.family) {
1320
- const key = parseJson(atomToken.family.subKey);
1321
- const mutableAtomToken = this.findMutableState(key);
1322
- new Tracker(mutableAtomToken, store);
1857
+ (event) => {
1858
+ if (event.token.family) {
1859
+ const key = parseJson$1(event.token.family.subKey);
1860
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
1861
+ if (mutableAtomToken) {
1862
+ new Tracker(mutableAtomToken, store);
1863
+ }
1323
1864
  }
1324
1865
  }
1325
1866
  );
@@ -1334,25 +1875,19 @@ function createMutableAtomFamily(options, store) {
1334
1875
  const subKey = stringifyJson(key);
1335
1876
  const family = { key: options.key, subKey };
1336
1877
  const fullKey = `${options.key}(${subKey})`;
1337
- const target2 = newest(store);
1338
- const atomAlreadyCreated = target2.atoms.has(fullKey);
1339
- let token;
1340
- if (atomAlreadyCreated) {
1341
- token = { type: `mutable_atom`, key: fullKey, family };
1342
- } else {
1343
- const individualOptions = {
1344
- key: fullKey,
1345
- default: () => options.default(key),
1346
- toJson: options.toJson,
1347
- fromJson: options.fromJson,
1348
- mutable: true
1349
- };
1350
- if (options.effects) {
1351
- individualOptions.effects = options.effects(key);
1352
- }
1353
- token = createMutableAtom(individualOptions, family, store);
1354
- subject.next(token);
1878
+ const target = newest(store);
1879
+ const individualOptions = {
1880
+ key: fullKey,
1881
+ default: () => options.default(key),
1882
+ toJson: options.toJson,
1883
+ fromJson: options.fromJson,
1884
+ mutable: true
1885
+ };
1886
+ if (options.effects) {
1887
+ individualOptions.effects = options.effects(key);
1355
1888
  }
1889
+ const token = createMutableAtom(individualOptions, family, target);
1890
+ subject.next({ type: `state_creation`, token });
1356
1891
  return token;
1357
1892
  },
1358
1893
  {
@@ -1364,8 +1899,7 @@ function createMutableAtomFamily(options, store) {
1364
1899
  fromJson: options.fromJson
1365
1900
  }
1366
1901
  );
1367
- const target = newest(store);
1368
- target.families.set(options.key, atomFamily);
1902
+ store.families.set(options.key, atomFamily);
1369
1903
  selectJsonFamily(atomFamily, options, store);
1370
1904
  new FamilyTracker(atomFamily, store);
1371
1905
  return atomFamily;
@@ -1380,19 +1914,24 @@ var getJsonFamily = (mutableAtomFamily, store) => {
1380
1914
  };
1381
1915
 
1382
1916
  // internal/src/mutable/get-json-token.ts
1383
- var getJsonToken = (mutableAtomToken) => {
1384
- const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1385
- const jsonToken = {
1386
- type: `selector`,
1387
- key
1388
- };
1917
+ var getJsonToken = (mutableAtomToken, store) => {
1389
1918
  if (mutableAtomToken.family) {
1390
- jsonToken.family = {
1391
- key: `${mutableAtomToken.family.key}:JSON`,
1392
- subKey: mutableAtomToken.family.subKey
1919
+ const target = newest(store);
1920
+ const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
1921
+ const jsonFamilyToken = {
1922
+ key: jsonFamilyKey,
1923
+ type: `selector_family`
1393
1924
  };
1925
+ const family = withdraw(jsonFamilyToken, target);
1926
+ const subKey = JSON.parse(mutableAtomToken.family.subKey);
1927
+ const jsonToken = findInStore(family, subKey, store);
1928
+ return jsonToken;
1394
1929
  }
1395
- return jsonToken;
1930
+ const token = {
1931
+ type: `selector`,
1932
+ key: `${mutableAtomToken.key}:JSON`
1933
+ };
1934
+ return token;
1396
1935
  };
1397
1936
 
1398
1937
  // internal/src/mutable/get-update-token.ts
@@ -1564,7 +2103,6 @@ function createRegularAtom(options, family, store) {
1564
2103
  }
1565
2104
  };
1566
2105
  }
1567
- store.on.atomCreation.next(token);
1568
2106
  return token;
1569
2107
  }
1570
2108
 
@@ -1572,13 +2110,17 @@ function createRegularAtom(options, family, store) {
1572
2110
  function createStandaloneAtom(options, store) {
1573
2111
  const isMutable2 = `mutable` in options;
1574
2112
  if (isMutable2) {
1575
- return createMutableAtom(options, void 0, store);
2113
+ const state2 = createMutableAtom(options, void 0, store);
2114
+ store.on.atomCreation.next(state2);
2115
+ return state2;
1576
2116
  }
1577
- return createRegularAtom(options, void 0, store);
2117
+ const state = createRegularAtom(options, void 0, store);
2118
+ store.on.atomCreation.next(state);
2119
+ return state;
1578
2120
  }
1579
2121
 
1580
2122
  // internal/src/atom/dispose-atom.ts
1581
- function disposeAtom(atomToken, store) {
2123
+ function disposeAtom2(atomToken, store) {
1582
2124
  var _a, _b;
1583
2125
  const target = newest(store);
1584
2126
  const { key } = atomToken;
@@ -1588,10 +2130,19 @@ function disposeAtom(atomToken, store) {
1588
2130
  `\u274C`,
1589
2131
  `atom`,
1590
2132
  key,
1591
- `Tried to delete atom, but it does not exist in the store.`
2133
+ `Tried to dispose atom, but it does not exist in the store.`
1592
2134
  );
2135
+ } else if (!atom.family) {
2136
+ store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1593
2137
  } else {
1594
2138
  (_a = atom.cleanup) == null ? void 0 : _a.call(atom);
2139
+ const lastValue = store.valueMap.get(atom.key);
2140
+ const family = withdraw({ key: atom.family.key, type: `atom_family` }, store);
2141
+ family.subject.next({
2142
+ type: `state_disposal`,
2143
+ token: atomToken,
2144
+ value: lastValue
2145
+ });
1595
2146
  target.atoms.delete(key);
1596
2147
  target.valueMap.delete(key);
1597
2148
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -1599,7 +2150,7 @@ function disposeAtom(atomToken, store) {
1599
2150
  for (const selectorKey of selectorKeys) {
1600
2151
  const token = (_b = target.selectors.get(selectorKey)) != null ? _b : target.readonlySelectors.get(selectorKey);
1601
2152
  if (token) {
1602
- disposeSelector(token, store);
2153
+ disposeSelector2(token, store);
1603
2154
  }
1604
2155
  }
1605
2156
  }
@@ -1608,93 +2159,21 @@ function disposeAtom(atomToken, store) {
1608
2159
  target.timelineAtoms.delete(key);
1609
2160
  if (atomToken.type === `mutable_atom`) {
1610
2161
  const updateToken = getUpdateToken(atomToken);
1611
- disposeAtom(updateToken, store);
2162
+ disposeAtom2(updateToken, store);
2163
+ store.trackers.delete(key);
1612
2164
  }
1613
2165
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1614
- store.on.atomDisposal.next(atomToken);
1615
- }
1616
- }
1617
-
1618
- // internal/src/get-environment-data.ts
1619
- function getEnvironmentData(store) {
1620
- return {
1621
- window: typeof window === `undefined` ? void 0 : window,
1622
- global: typeof global === `undefined` ? void 0 : global,
1623
- store
1624
- };
1625
- }
1626
-
1627
- // internal/src/get-state/get-from-store.ts
1628
- function getFromStore(token, store) {
1629
- const state = withdrawOrCreate(token, store);
1630
- return readOrComputeValue(state, store);
1631
- }
1632
-
1633
- // internal/src/ingest-updates/ingest-atom-update.ts
1634
- function ingestAtomUpdate(applying, atomUpdate, store) {
1635
- const { key, newValue, oldValue } = atomUpdate;
1636
- const value = applying === `newValue` ? newValue : oldValue;
1637
- const token = { key, type: `atom` };
1638
- if (atomUpdate.family) {
1639
- Object.assign(token, { family: atomUpdate.family });
1640
- }
1641
- setIntoStore(token, value, store);
1642
- }
1643
-
1644
- // internal/src/ingest-updates/ingest-selector-update.ts
1645
- function ingestSelectorUpdate(applying, selectorUpdate, store) {
1646
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1647
- for (const atomUpdate of updates) {
1648
- ingestAtomUpdate(applying, atomUpdate, store);
1649
- }
1650
- }
1651
-
1652
- // internal/src/ingest-updates/ingest-transaction-update.ts
1653
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1654
- const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1655
- for (const updateFromTransaction of updates) {
1656
- if (`newValue` in updateFromTransaction) {
1657
- ingestAtomUpdate(applying, updateFromTransaction, store);
2166
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
2167
+ target.transactionMeta.update.updates.push({
2168
+ type: `state_disposal`,
2169
+ token: atomToken
2170
+ });
1658
2171
  } else {
1659
- ingestTransactionUpdate(applying, updateFromTransaction, store);
2172
+ store.on.atomDisposal.next(atomToken);
1660
2173
  }
1661
2174
  }
1662
2175
  }
1663
2176
 
1664
- // internal/src/lazy-map.ts
1665
- var LazyMap = class extends Map {
1666
- constructor(source) {
1667
- super();
1668
- this.source = source;
1669
- this.deleted = /* @__PURE__ */ new Set();
1670
- }
1671
- get(key) {
1672
- const has = super.has(key);
1673
- if (has) {
1674
- return super.get(key);
1675
- }
1676
- if (!this.deleted.has(key) && this.source.has(key)) {
1677
- const value = this.source.get(key);
1678
- return value;
1679
- }
1680
- return void 0;
1681
- }
1682
- set(key, value) {
1683
- this.deleted.delete(key);
1684
- return super.set(key, value);
1685
- }
1686
- hasOwn(key) {
1687
- return super.has(key);
1688
- }
1689
- has(key) {
1690
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1691
- }
1692
- delete(key) {
1693
- this.deleted.add(key);
1694
- return super.delete(key);
1695
- }
1696
- };
1697
-
1698
2177
  // internal/src/timeline/add-atom-to-timeline.ts
1699
2178
  var addAtomToTimeline = (atomToken, tl, store) => {
1700
2179
  let maybeAtom = withdraw(atomToken, store);
@@ -1704,188 +2183,212 @@ var addAtomToTimeline = (atomToken, tl, store) => {
1704
2183
  }
1705
2184
  const atom = maybeAtom;
1706
2185
  store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
1707
- atom.subject.subscribe(`timeline`, (update) => {
1708
- var _a, _b, _c, _d, _e, _f;
1709
- const target = newest(store);
1710
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1711
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1712
- const { transactionApplying } = target.on;
1713
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
1714
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
1715
- store.logger.info(
1716
- `\u23F3`,
1717
- `timeline`,
1718
- tl.key,
1719
- `atom`,
1720
- atomToken.key,
1721
- `went`,
1722
- update.oldValue,
1723
- `->`,
1724
- update.newValue,
1725
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
1726
- );
1727
- if (tl.timeTraveling === null) {
1728
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1729
- const mostRecentUpdate = tl.history.at(-1);
1730
- if (mostRecentUpdate === void 0) {
1731
- throw new Error(
1732
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
1733
- );
1734
- }
1735
- }
1736
- if (currentTransactionKey) {
1737
- const txToken = {
1738
- key: currentTransactionKey,
1739
- type: `transaction`
1740
- };
1741
- const currentTransaction = withdraw(txToken, store);
1742
- if (tl.transactionKey !== currentTransactionKey) {
1743
- if (tl.transactionKey) {
1744
- store.logger.error(
1745
- `\u{1F41E}`,
1746
- `timeline`,
1747
- tl.key,
1748
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2186
+ tl.subscriptions.set(
2187
+ atom.key,
2188
+ atom.subject.subscribe(`timeline`, (update) => {
2189
+ var _a, _b, _c, _d, _e, _f;
2190
+ const target = newest(store);
2191
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2192
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2193
+ const { transactionApplying } = target.on;
2194
+ const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
2195
+ const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
2196
+ store.logger.info(
2197
+ `\u23F3`,
2198
+ `timeline`,
2199
+ tl.key,
2200
+ `atom`,
2201
+ atomToken.key,
2202
+ `went`,
2203
+ update.oldValue,
2204
+ `->`,
2205
+ update.newValue,
2206
+ currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2207
+ );
2208
+ if (tl.timeTraveling === null) {
2209
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2210
+ const mostRecentUpdate = tl.history.at(-1);
2211
+ if (mostRecentUpdate === void 0) {
2212
+ throw new Error(
2213
+ `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
1749
2214
  );
1750
2215
  }
1751
- tl.transactionKey = currentTransactionKey;
1752
- const unsubscribe = currentTransaction.subject.subscribe(
1753
- `timeline:${tl.key}`,
1754
- (transactionUpdate) => {
1755
- var _a2, _b2;
1756
- unsubscribe();
1757
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
1758
- if (tl.at !== tl.history.length) {
1759
- tl.history.splice(tl.at);
1760
- }
1761
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
1762
- const newestStore = newest(store);
1763
- if (`updates` in updateFromTx) {
1764
- return true;
2216
+ }
2217
+ if (currentTransactionKey) {
2218
+ const txToken = {
2219
+ key: currentTransactionKey,
2220
+ type: `transaction`
2221
+ };
2222
+ const currentTransaction = withdraw(txToken, store);
2223
+ if (tl.transactionKey !== currentTransactionKey) {
2224
+ if (tl.transactionKey) {
2225
+ store.logger.error(
2226
+ `\u{1F41E}`,
2227
+ `timeline`,
2228
+ tl.key,
2229
+ `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2230
+ );
2231
+ }
2232
+ tl.transactionKey = currentTransactionKey;
2233
+ const unsubscribe = currentTransaction.subject.subscribe(
2234
+ `timeline:${tl.key}`,
2235
+ (transactionUpdate) => {
2236
+ var _a2, _b2;
2237
+ unsubscribe();
2238
+ if (tl.timeTraveling === null && currentTransactionInstanceId) {
2239
+ if (tl.at !== tl.history.length) {
2240
+ tl.history.splice(tl.at);
1765
2241
  }
1766
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
1767
- return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
1768
- (key) => {
1769
- var _a3;
1770
- return key === updateFromTx.key || key === ((_a3 = updateFromTx.family) == null ? void 0 : _a3.key);
2242
+ const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2243
+ var _a3, _b3;
2244
+ const newestStore = newest(store);
2245
+ if (`updates` in updateFromTx) {
2246
+ return true;
2247
+ }
2248
+ const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2249
+ if (!atomOrFamilyKeys) {
2250
+ return false;
2251
+ }
2252
+ let key;
2253
+ let familyKey;
2254
+ switch (updateFromTx.type) {
2255
+ case `state_creation`:
2256
+ case `state_disposal`:
2257
+ key = updateFromTx.token.key;
2258
+ familyKey = (_a3 = updateFromTx.token.family) == null ? void 0 : _a3.key;
2259
+ break;
2260
+ case `molecule_creation`:
2261
+ case `molecule_disposal`:
2262
+ break;
2263
+ default:
2264
+ key = updateFromTx.key;
2265
+ familyKey = (_b3 = updateFromTx.family) == null ? void 0 : _b3.key;
2266
+ break;
2267
+ }
2268
+ if (key === void 0) {
2269
+ return false;
1771
2270
  }
1772
- ) : false;
1773
- }).map((updateFromTx) => {
1774
- if (`updates` in updateFromTx) {
1775
- return __spreadProps(__spreadValues({}, updateFromTx), {
1776
- updates: filterUpdates(updateFromTx.updates)
1777
- });
2271
+ if (atomOrFamilyKeys.has(key)) {
2272
+ return true;
2273
+ }
2274
+ if (familyKey !== void 0) {
2275
+ return atomOrFamilyKeys.has(familyKey);
2276
+ }
2277
+ return false;
2278
+ }).map((updateFromTx) => {
2279
+ if (`updates` in updateFromTx) {
2280
+ return __spreadProps(__spreadValues({}, updateFromTx), {
2281
+ updates: filterUpdates(updateFromTx.updates)
2282
+ });
2283
+ }
2284
+ return updateFromTx;
2285
+ });
2286
+ const updates = filterUpdates(transactionUpdate.updates);
2287
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
2288
+ timestamp: Date.now()
2289
+ }, transactionUpdate), {
2290
+ updates
2291
+ });
2292
+ const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2293
+ if (willCapture) {
2294
+ tl.history.push(timelineTransactionUpdate);
2295
+ tl.at = tl.history.length;
2296
+ tl.subject.next(timelineTransactionUpdate);
1778
2297
  }
1779
- return updateFromTx;
1780
- });
1781
- const updates = filterUpdates(transactionUpdate.updates);
1782
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
1783
- type: `transaction_update`,
1784
- timestamp: Date.now()
1785
- }, transactionUpdate), {
1786
- updates
1787
- });
1788
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
1789
- if (willCapture) {
1790
- tl.history.push(timelineTransactionUpdate);
1791
- tl.at = tl.history.length;
1792
- tl.subject.next(timelineTransactionUpdate);
1793
2298
  }
2299
+ tl.transactionKey = null;
2300
+ store.logger.info(
2301
+ `\u231B`,
2302
+ `timeline`,
2303
+ tl.key,
2304
+ `got a transaction_update "${transactionUpdate.key}"`
2305
+ );
1794
2306
  }
1795
- tl.transactionKey = null;
2307
+ );
2308
+ }
2309
+ } else if (currentSelectorKey && currentSelectorTime) {
2310
+ let latestUpdate = tl.history.at(-1);
2311
+ if (currentSelectorTime !== tl.selectorTime) {
2312
+ latestUpdate = {
2313
+ type: `selector_update`,
2314
+ timestamp: currentSelectorTime,
2315
+ key: currentSelectorKey,
2316
+ atomUpdates: []
2317
+ };
2318
+ latestUpdate.atomUpdates.push(__spreadValues({
2319
+ key: atom.key,
2320
+ type: `atom_update`
2321
+ }, update));
2322
+ if (tl.at !== tl.history.length) {
2323
+ tl.history.splice(tl.at);
2324
+ }
2325
+ tl.history.push(latestUpdate);
2326
+ store.logger.info(
2327
+ `\u231B`,
2328
+ `timeline`,
2329
+ tl.key,
2330
+ `got a selector_update "${currentSelectorKey}" with`,
2331
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2332
+ );
2333
+ tl.at = tl.history.length;
2334
+ tl.selectorTime = currentSelectorTime;
2335
+ } else {
2336
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
2337
+ latestUpdate.atomUpdates.push(__spreadValues({
2338
+ key: atom.key,
2339
+ type: `atom_update`
2340
+ }, update));
1796
2341
  store.logger.info(
1797
2342
  `\u231B`,
1798
2343
  `timeline`,
1799
2344
  tl.key,
1800
- `got a transaction_update "${transactionUpdate.key}"`
2345
+ `set selector_update "${currentSelectorKey}" to`,
2346
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1801
2347
  );
1802
2348
  }
1803
- );
1804
- }
1805
- } else if (currentSelectorKey && currentSelectorTime) {
1806
- let latestUpdate = tl.history.at(-1);
1807
- if (currentSelectorTime !== tl.selectorTime) {
1808
- latestUpdate = {
1809
- type: `selector_update`,
1810
- timestamp: currentSelectorTime,
1811
- key: currentSelectorKey,
1812
- atomUpdates: []
1813
- };
1814
- latestUpdate.atomUpdates.push(__spreadValues({
1815
- key: atom.key,
1816
- type: `atom_update`
1817
- }, update));
2349
+ }
2350
+ if (latestUpdate) {
2351
+ const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2352
+ if (willCaptureSelectorUpdate) {
2353
+ tl.subject.next(latestUpdate);
2354
+ } else {
2355
+ tl.history.pop();
2356
+ tl.at = tl.history.length;
2357
+ }
2358
+ }
2359
+ } else {
2360
+ const timestamp = Date.now();
2361
+ tl.selectorTime = null;
1818
2362
  if (tl.at !== tl.history.length) {
1819
2363
  tl.history.splice(tl.at);
1820
2364
  }
1821
- tl.history.push(latestUpdate);
2365
+ const atomUpdate = {
2366
+ type: `atom_update`,
2367
+ timestamp,
2368
+ key: atom.key,
2369
+ oldValue: update.oldValue,
2370
+ newValue: update.newValue
2371
+ };
2372
+ if (atom.family) {
2373
+ atomUpdate.family = atom.family;
2374
+ }
2375
+ const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
1822
2376
  store.logger.info(
1823
2377
  `\u231B`,
1824
2378
  `timeline`,
1825
2379
  tl.key,
1826
- `got a selector_update "${currentSelectorKey}" with`,
1827
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2380
+ `got an atom_update to "${atom.key}"`
1828
2381
  );
1829
- tl.at = tl.history.length;
1830
- tl.selectorTime = currentSelectorTime;
1831
- } else {
1832
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1833
- latestUpdate.atomUpdates.push(__spreadValues({
1834
- key: atom.key,
1835
- type: `atom_update`
1836
- }, update));
1837
- store.logger.info(
1838
- `\u231B`,
1839
- `timeline`,
1840
- tl.key,
1841
- `set selector_update "${currentSelectorKey}" to`,
1842
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1843
- );
1844
- }
1845
- }
1846
- if (latestUpdate) {
1847
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
1848
- if (willCaptureSelectorUpdate) {
1849
- tl.subject.next(latestUpdate);
1850
- } else {
1851
- tl.history.pop();
2382
+ if (willCapture) {
2383
+ tl.history.push(atomUpdate);
1852
2384
  tl.at = tl.history.length;
2385
+ tl.subject.next(atomUpdate);
1853
2386
  }
1854
2387
  }
1855
- } else {
1856
- const timestamp = Date.now();
1857
- tl.selectorTime = null;
1858
- if (tl.at !== tl.history.length) {
1859
- tl.history.splice(tl.at);
1860
- }
1861
- const atomUpdate = {
1862
- type: `atom_update`,
1863
- timestamp,
1864
- key: atom.key,
1865
- oldValue: update.oldValue,
1866
- newValue: update.newValue
1867
- };
1868
- if (atom.family) {
1869
- atomUpdate.family = atom.family;
1870
- }
1871
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
1872
- store.logger.info(
1873
- `\u231B`,
1874
- `timeline`,
1875
- tl.key,
1876
- `got an atom_update to "${atom.key}"`
1877
- );
1878
- if (willCapture) {
1879
- tl.history.push(atomUpdate);
1880
- tl.at = tl.history.length;
1881
- tl.subject.next(atomUpdate);
1882
- }
1883
2388
  }
1884
- }
1885
- });
2389
+ })
2390
+ );
1886
2391
  };
1887
-
1888
- // internal/src/timeline/create-timeline.ts
1889
2392
  function createTimeline(options, store, data) {
1890
2393
  var _a, _b;
1891
2394
  const tl = __spreadProps(__spreadValues({
@@ -1898,60 +2401,141 @@ function createTimeline(options, store, data) {
1898
2401
  }, data), {
1899
2402
  history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1900
2403
  install: (s) => createTimeline(options, s, tl),
1901
- subject: new Subject()
2404
+ subject: new Subject(),
2405
+ subscriptions: /* @__PURE__ */ new Map()
1902
2406
  });
1903
2407
  if (options.shouldCapture) {
1904
2408
  tl.shouldCapture = options.shouldCapture;
1905
2409
  }
1906
2410
  const timelineKey = options.key;
1907
2411
  const target = newest(store);
1908
- for (const tokenOrFamily of options.atoms) {
2412
+ for (const tokenOrFamily of options.scope) {
1909
2413
  let atomKey = tokenOrFamily.key;
1910
- if (tokenOrFamily.type === `atom_family` || tokenOrFamily.type === `mutable_atom_family`) {
1911
- const familyToken = tokenOrFamily;
1912
- const family = withdraw(familyToken, store);
1913
- const familyKey = family.key;
1914
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
1915
- family.subject.subscribe(`timeline:${options.key}`, (token2) => {
1916
- addAtomToTimeline(token2, tl, store);
1917
- });
1918
- for (const atom of target.atoms.values()) {
1919
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2414
+ switch (tokenOrFamily.type) {
2415
+ case `atom_family`:
2416
+ case `mutable_atom_family`:
2417
+ {
2418
+ const familyToken = tokenOrFamily;
2419
+ const family = withdraw(familyToken, store);
2420
+ const familyKey = family.key;
2421
+ target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2422
+ tl.subscriptions.set(
2423
+ family.key,
2424
+ family.subject.subscribe(
2425
+ `timeline:${options.key}`,
2426
+ (creationOrDisposal) => {
2427
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
2428
+ }
2429
+ )
2430
+ );
2431
+ for (const atom of target.atoms.values()) {
2432
+ if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2433
+ addAtomToTimeline(atom, tl, store);
2434
+ }
2435
+ }
2436
+ }
2437
+ break;
2438
+ case `atom`:
2439
+ case `mutable_atom`:
2440
+ {
2441
+ let atom = withdraw(tokenOrFamily, store);
2442
+ if (isMutable(atom)) {
2443
+ const updateAtom = withdraw(getUpdateToken(atom), store);
2444
+ atom = updateAtom;
2445
+ atomKey = atom.key;
2446
+ }
2447
+ if (`family` in atom) {
2448
+ const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2449
+ atom.family.key
2450
+ );
2451
+ if (familyTimelineKey) {
2452
+ store.logger.error(
2453
+ `\u274C`,
2454
+ `timeline`,
2455
+ options.key,
2456
+ `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
2457
+ );
2458
+ continue;
2459
+ }
2460
+ }
2461
+ const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2462
+ if (existingTimelineKey) {
2463
+ store.logger.error(
2464
+ `\u274C`,
2465
+ `timeline`,
2466
+ options.key,
2467
+ `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2468
+ );
2469
+ continue;
2470
+ }
1920
2471
  addAtomToTimeline(atom, tl, store);
1921
2472
  }
1922
- }
1923
- } else {
1924
- let atom = withdraw(tokenOrFamily, store);
1925
- if (isMutable(atom)) {
1926
- const updateAtom = withdraw(getUpdateToken(atom), store);
1927
- atom = updateAtom;
1928
- atomKey = atom.key;
1929
- }
1930
- if (`family` in atom) {
1931
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
1932
- atom.family.key
1933
- );
1934
- if (familyTimelineKey) {
1935
- store.logger.error(
1936
- `\u274C`,
1937
- `timeline`,
1938
- options.key,
1939
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
1940
- );
1941
- continue;
2473
+ break;
2474
+ case `molecule_family`:
2475
+ {
2476
+ const family = store.moleculeFamilies.get(tokenOrFamily.key);
2477
+ if (family) {
2478
+ tl.subscriptions.set(
2479
+ tokenOrFamily.key,
2480
+ family.subject.subscribe(
2481
+ `timeline:${options.key}`,
2482
+ (creationOrDisposal) => {
2483
+ var _a2, _b2;
2484
+ switch (creationOrDisposal.type) {
2485
+ case `molecule_creation`:
2486
+ {
2487
+ const molecule = store.molecules.get(
2488
+ stringifyJson(creationOrDisposal.token.key)
2489
+ );
2490
+ if (molecule) {
2491
+ const event = Object.assign(creationOrDisposal, {
2492
+ timestamp: Date.now()
2493
+ });
2494
+ tl.history.push(event);
2495
+ tl.at = tl.history.length;
2496
+ tl.subject.next(event);
2497
+ for (const token2 of molecule.tokens) {
2498
+ switch (token2.type) {
2499
+ case `atom`:
2500
+ case `mutable_atom`:
2501
+ addAtomToTimeline(token2, tl, store);
2502
+ break;
2503
+ }
2504
+ }
2505
+ tl.subscriptions.set(
2506
+ molecule.key,
2507
+ molecule.subject.subscribe(
2508
+ `timeline:${options.key}`,
2509
+ (stateCreationOrDisposal) => {
2510
+ handleStateLifecycleEvent(
2511
+ stateCreationOrDisposal,
2512
+ tl,
2513
+ store
2514
+ );
2515
+ }
2516
+ )
2517
+ );
2518
+ }
2519
+ }
2520
+ break;
2521
+ case `molecule_disposal`:
2522
+ (_a2 = tl.subscriptions.get(creationOrDisposal.token.key)) == null ? void 0 : _a2();
2523
+ tl.subscriptions.delete(creationOrDisposal.token.key);
2524
+ for (const familyKey of creationOrDisposal.familyKeys) {
2525
+ const stateKey = `${familyKey}(${stringifyJson(
2526
+ creationOrDisposal.token.key
2527
+ )})`;
2528
+ (_b2 = tl.subscriptions.get(stateKey)) == null ? void 0 : _b2();
2529
+ tl.subscriptions.delete(stateKey);
2530
+ }
2531
+ break;
2532
+ }
2533
+ }
2534
+ )
2535
+ );
2536
+ }
1942
2537
  }
1943
- }
1944
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
1945
- if (existingTimelineKey) {
1946
- store.logger.error(
1947
- `\u274C`,
1948
- `timeline`,
1949
- options.key,
1950
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
1951
- );
1952
- continue;
1953
- }
1954
- addAtomToTimeline(atom, tl, store);
2538
+ break;
1955
2539
  }
1956
2540
  }
1957
2541
  store.timelines.set(options.key, tl);
@@ -1962,6 +2546,27 @@ function createTimeline(options, store, data) {
1962
2546
  store.on.timelineCreation.next(token);
1963
2547
  return token;
1964
2548
  }
2549
+ function handleStateLifecycleEvent(event, tl, store) {
2550
+ var _a;
2551
+ const timestamp = Date.now();
2552
+ const timelineEvent = Object.assign(event, {
2553
+ timestamp
2554
+ });
2555
+ if (!tl.timeTraveling) {
2556
+ tl.history.push(timelineEvent);
2557
+ tl.at = tl.history.length;
2558
+ tl.subject.next(timelineEvent);
2559
+ }
2560
+ switch (event.type) {
2561
+ case `state_creation`:
2562
+ addAtomToTimeline(event.token, tl, store);
2563
+ break;
2564
+ case `state_disposal`:
2565
+ (_a = tl.subscriptions.get(event.token.key)) == null ? void 0 : _a();
2566
+ tl.subscriptions.delete(event.token.key);
2567
+ break;
2568
+ }
2569
+ }
1965
2570
 
1966
2571
  // internal/src/timeline/time-travel.ts
1967
2572
  var timeTravel = (action, token, store) => {
@@ -2009,6 +2614,22 @@ var timeTravel = (action, token, store) => {
2009
2614
  ingestTransactionUpdate(applying, update, store);
2010
2615
  break;
2011
2616
  }
2617
+ case `state_creation`: {
2618
+ ingestCreationEvent(update, applying, store);
2619
+ break;
2620
+ }
2621
+ case `state_disposal`: {
2622
+ ingestDisposalEvent(update, applying, store);
2623
+ break;
2624
+ }
2625
+ case `molecule_creation`: {
2626
+ ingestMoleculeCreationEvent(update, applying, store);
2627
+ break;
2628
+ }
2629
+ case `molecule_disposal`: {
2630
+ ingestMoleculeDisposalEvent(update, applying, store);
2631
+ break;
2632
+ }
2012
2633
  }
2013
2634
  if (action === `redo`) {
2014
2635
  ++timelineData.at;
@@ -2023,248 +2644,4 @@ var timeTravel = (action, token, store) => {
2023
2644
  );
2024
2645
  };
2025
2646
 
2026
- // internal/src/transaction/abort-transaction.ts
2027
- var abortTransaction = (store) => {
2028
- const target = newest(store);
2029
- if (!isChildStore(target)) {
2030
- store.logger.warn(
2031
- `\u{1F41E}`,
2032
- `transaction`,
2033
- `???`,
2034
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2035
- );
2036
- return;
2037
- }
2038
- store.logger.info(
2039
- `\u{1FA82}`,
2040
- `transaction`,
2041
- target.transactionMeta.update.key,
2042
- `Aborting transaction`
2043
- );
2044
- target.parent.child = null;
2045
- };
2046
-
2047
- // internal/src/transaction/act-upon-store.ts
2048
- function actUponStore(token, id, store) {
2049
- return (...parameters) => {
2050
- const tx = withdraw(token, store);
2051
- if (tx) {
2052
- return tx.run(parameters, id);
2053
- }
2054
- throw new NotFoundError(token, store);
2055
- };
2056
- }
2057
-
2058
- // internal/src/transaction/set-epoch-number.ts
2059
- function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
2060
- const isRoot = isRootStore(store);
2061
- if (isRoot && continuityKey) {
2062
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2063
- }
2064
- }
2065
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
2066
- const isRoot = isRootStore(store);
2067
- if (!isRoot) {
2068
- return;
2069
- }
2070
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
2071
- if (continuityKey !== void 0) {
2072
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2073
- }
2074
- }
2075
-
2076
- // internal/src/transaction/apply-transaction.ts
2077
- var applyTransaction = (output, store) => {
2078
- var _a;
2079
- const child = newest(store);
2080
- const { parent } = child;
2081
- if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
2082
- store.logger.warn(
2083
- `\u{1F41E}`,
2084
- `transaction`,
2085
- `???`,
2086
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2087
- );
2088
- return;
2089
- }
2090
- child.transactionMeta.phase = `applying`;
2091
- child.transactionMeta.update.output = output;
2092
- parent.child = null;
2093
- parent.on.transactionApplying.next(child.transactionMeta);
2094
- const { updates } = child.transactionMeta.update;
2095
- store.logger.info(
2096
- `\u{1F6C4}`,
2097
- `transaction`,
2098
- child.transactionMeta.update.key,
2099
- `Applying transaction with ${updates.length} updates:`,
2100
- updates
2101
- );
2102
- for (const tracker of child.trackers.values()) {
2103
- const mutableKey = tracker.mutableState.key;
2104
- if (!parent.atoms.has(mutableKey)) {
2105
- const atom = child.atoms.get(mutableKey);
2106
- atom == null ? void 0 : atom.install(parent);
2107
- }
2108
- tracker.dispose();
2109
- }
2110
- for (const atom of child.atoms.values()) {
2111
- if (!parent.atoms.has(atom.key)) {
2112
- parent.atoms.set(atom.key, atom);
2113
- parent.valueMap.set(atom.key, atom.default);
2114
- parent.logger.info(
2115
- `\u{1F528}`,
2116
- `transaction`,
2117
- child.transactionMeta.update.key,
2118
- `Adding atom "${atom.key}"`
2119
- );
2120
- }
2121
- }
2122
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
2123
- if (isRootStore(parent)) {
2124
- setEpochNumberOfAction(
2125
- child.transactionMeta.update.key,
2126
- child.transactionMeta.update.epoch,
2127
- parent
2128
- );
2129
- const myTransaction = withdraw(
2130
- { key: child.transactionMeta.update.key, type: `transaction` },
2131
- store
2132
- );
2133
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
2134
- store.logger.info(
2135
- `\u{1F6EC}`,
2136
- `transaction`,
2137
- child.transactionMeta.update.key,
2138
- `Finished applying transaction.`
2139
- );
2140
- } else if (isChildStore(parent)) {
2141
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
2142
- }
2143
- parent.on.transactionApplying.next(null);
2144
- };
2145
-
2146
- // internal/src/transaction/assign-transaction-to-continuity.ts
2147
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2148
- const isRoot = isRootStore(store);
2149
- if (!isRoot) {
2150
- return;
2151
- }
2152
- const { epoch, actionContinuities } = store.transactionMeta;
2153
- actionContinuities.set(continuityKey, transactionKey);
2154
- if (!epoch.has(continuityKey)) {
2155
- epoch.set(continuityKey, -1);
2156
- }
2157
- }
2158
-
2159
- // internal/src/transaction/build-transaction.ts
2160
- var buildTransaction = (key, params, store, id) => {
2161
- const parent = newest(store);
2162
- const childBase = {
2163
- parent,
2164
- child: null,
2165
- on: parent.on,
2166
- loggers: parent.loggers,
2167
- logger: parent.logger,
2168
- config: parent.config,
2169
- atoms: new LazyMap(parent.atoms),
2170
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2171
- families: new LazyMap(parent.families),
2172
- operation: { open: false },
2173
- readonlySelectors: new LazyMap(parent.readonlySelectors),
2174
- timelines: new LazyMap(parent.timelines),
2175
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
2176
- trackers: /* @__PURE__ */ new Map(),
2177
- transactions: new LazyMap(parent.transactions),
2178
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
2179
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
2180
- makeContentKey: (...keys) => keys.sort().join(`:`)
2181
- }),
2182
- selectors: new LazyMap(parent.selectors),
2183
- valueMap: new LazyMap(parent.valueMap)
2184
- };
2185
- const epoch = getEpochNumberOfAction(key, store);
2186
- const transactionMeta = {
2187
- phase: `building`,
2188
- update: {
2189
- key,
2190
- id,
2191
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
2192
- updates: [],
2193
- params,
2194
- output: void 0
2195
- },
2196
- transactors: {
2197
- get: (token) => getFromStore(token, child),
2198
- set: (token, value) => {
2199
- setIntoStore(token, value, child);
2200
- },
2201
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2202
- find: (token, k) => findInStore(token, k, child),
2203
- env: () => getEnvironmentData(child)
2204
- }
2205
- };
2206
- const child = Object.assign(childBase, {
2207
- transactionMeta
2208
- });
2209
- parent.child = child;
2210
- store.logger.info(
2211
- `\u{1F6EB}`,
2212
- `transaction`,
2213
- key,
2214
- `Building transaction with params:`,
2215
- params
2216
- );
2217
- return child;
2218
- };
2219
-
2220
- // internal/src/transaction/create-transaction.ts
2221
- function createTransaction(options, store) {
2222
- const newTransaction = {
2223
- key: options.key,
2224
- type: `transaction`,
2225
- run: (params, id) => {
2226
- const childStore = buildTransaction(options.key, params, store, id);
2227
- try {
2228
- const target2 = newest(store);
2229
- const { transactors } = childStore.transactionMeta;
2230
- const output = options.do(transactors, ...params);
2231
- applyTransaction(output, target2);
2232
- return output;
2233
- } catch (thrown) {
2234
- abortTransaction(target);
2235
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
2236
- throw thrown;
2237
- }
2238
- },
2239
- install: (s) => createTransaction(options, s),
2240
- subject: new Subject()
2241
- };
2242
- const target = newest(store);
2243
- target.transactions.set(newTransaction.key, newTransaction);
2244
- const token = deposit(newTransaction);
2245
- store.on.transactionCreation.next(token);
2246
- return token;
2247
- }
2248
-
2249
- // internal/src/transaction/get-epoch-number.ts
2250
- function getContinuityKey(transactionKey, store) {
2251
- const isRoot = isRootStore(store);
2252
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2253
- return continuity;
2254
- }
2255
- function getEpochNumberOfContinuity(continuityKey, store) {
2256
- const isRoot = isRootStore(store);
2257
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
2258
- return epoch;
2259
- }
2260
- function getEpochNumberOfAction(transactionKey, store) {
2261
- const isRoot = isRootStore(store);
2262
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2263
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
2264
- return epoch;
2265
- }
2266
-
2267
- // internal/src/transaction/index.ts
2268
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2269
-
2270
- export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, addAtomToTimeline, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeSelector, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, ingestAtomUpdate, ingestSelectorUpdate, ingestTransactionUpdate, isAtomDefault, isAtomKey, isChildStore, isDone, isMutable, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, readCachedValue, readOrComputeValue, registerSelector, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw, withdrawOrCreate };
2647
+ export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, addAtomToTimeline, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom2 as disposeAtom, disposeFromStore, disposeSelector2 as disposeSelector, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMember, isAtomDefault, isAtomKey, isChildStore, isDone, isMutable, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, readCachedValue, readOrComputeValue, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };