atom.io 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/data/dist/index.cjs +17 -1
  2. package/data/dist/index.js +1 -1
  3. package/data/src/join.ts +30 -1
  4. package/dist/chunk-6MLFYN32.js +18 -0
  5. package/dist/{chunk-JA4V7TJY.js → chunk-7DT3PVS3.js} +18 -2
  6. package/dist/chunk-OAYGID5B.js +27 -0
  7. package/dist/index.cjs +2 -11
  8. package/dist/index.d.ts +51 -23
  9. package/dist/index.js +2 -11
  10. package/ephemeral/dist/index.d.ts +12 -0
  11. package/eslint-plugin/dist/index.cjs +0 -1
  12. package/eslint-plugin/dist/index.d.ts +73 -0
  13. package/eslint-plugin/dist/index.js +0 -1
  14. package/eslint-plugin/src/rules/lifespan.ts +0 -1
  15. package/immortal/dist/index.cjs +180 -20
  16. package/immortal/dist/index.d.ts +103 -0
  17. package/immortal/dist/index.js +134 -19
  18. package/immortal/src/index.ts +1 -0
  19. package/immortal/src/make-molecule.ts +222 -0
  20. package/immortal/src/molecule.ts +49 -16
  21. package/immortal/src/seek-state.ts +15 -2
  22. package/internal/dist/index.cjs +1119 -754
  23. package/internal/dist/index.d.ts +109 -12
  24. package/internal/dist/index.js +1098 -760
  25. package/internal/src/atom/create-regular-atom.ts +0 -2
  26. package/internal/src/atom/create-standalone-atom.ts +6 -2
  27. package/internal/src/atom/dispose-atom.ts +22 -2
  28. package/internal/src/families/create-readonly-selector-family.ts +7 -2
  29. package/internal/src/families/create-regular-atom-family.ts +6 -2
  30. package/internal/src/families/create-writable-selector-family.ts +7 -2
  31. package/internal/src/families/dispose-from-store.ts +22 -0
  32. package/internal/src/families/find-in-store.ts +0 -1
  33. package/internal/src/families/index.ts +1 -0
  34. package/internal/src/families/init-family-member.ts +22 -1
  35. package/internal/src/families/seek-in-store.ts +23 -6
  36. package/internal/src/ingest-updates/index.ts +1 -0
  37. package/internal/src/ingest-updates/ingest-creation-disposal.ts +104 -0
  38. package/internal/src/ingest-updates/ingest-transaction-update.ts +26 -4
  39. package/internal/src/mutable/create-mutable-atom-family.ts +6 -2
  40. package/internal/src/mutable/create-mutable-atom.ts +0 -2
  41. package/internal/src/mutable/get-json-token.ts +0 -1
  42. package/internal/src/mutable/tracker-family.ts +7 -7
  43. package/internal/src/not-found-error.ts +5 -0
  44. package/internal/src/selector/create-readonly-selector.ts +2 -3
  45. package/internal/src/selector/create-standalone-selector.ts +6 -2
  46. package/internal/src/selector/create-writable-selector.ts +2 -3
  47. package/internal/src/selector/dispose-selector.ts +32 -5
  48. package/internal/src/selector/register-selector.ts +2 -0
  49. package/internal/src/set-state/stow-update.ts +5 -1
  50. package/internal/src/store/deposit.ts +41 -7
  51. package/internal/src/store/store.ts +11 -0
  52. package/internal/src/store/withdraw.ts +28 -1
  53. package/internal/src/timeline/add-atom-to-timeline.ts +206 -182
  54. package/internal/src/timeline/create-timeline.ts +181 -60
  55. package/internal/src/timeline/time-travel.ts +20 -0
  56. package/internal/src/transaction/apply-transaction.ts +2 -12
  57. package/internal/src/transaction/build-transaction.ts +11 -2
  58. package/introspection/dist/index.cjs +2 -1
  59. package/introspection/dist/index.js +2 -1
  60. package/introspection/src/attach-timeline-family.ts +1 -0
  61. package/json/dist/index.cjs +3 -3
  62. package/json/dist/index.js +6 -5
  63. package/json/src/select-json-family.ts +3 -4
  64. package/package.json +8 -5
  65. package/react-devtools/dist/index.cjs +58 -47
  66. package/react-devtools/dist/index.js +60 -48
  67. package/react-devtools/src/TimelineIndex.tsx +15 -13
  68. package/react-devtools/src/Updates.tsx +41 -32
  69. package/realtime-server/dist/index.cjs +21 -10
  70. package/realtime-server/dist/index.d.ts +1 -1
  71. package/realtime-server/dist/index.js +21 -11
  72. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +21 -11
  73. package/realtime-testing/dist/index.cjs +1 -0
  74. package/realtime-testing/dist/index.js +1 -1
  75. package/src/atom.ts +9 -3
  76. package/src/dispose-state.ts +3 -12
  77. package/src/index.ts +4 -0
  78. package/src/selector.ts +3 -3
  79. package/src/subscribe.ts +8 -4
  80. package/src/timeline.ts +18 -1
  81. package/src/transaction.ts +56 -4
  82. package/dist/chunk-BF4MVQF6.js +0 -44
@@ -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
@@ -143,6 +158,7 @@ var Store = class {
143
158
  }
144
159
  );
145
160
  this.molecules = /* @__PURE__ */ new Map();
161
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
146
162
  this.miscResources = /* @__PURE__ */ new Map();
147
163
  this.on = {
148
164
  atomCreation: new Subject(),
@@ -154,7 +170,10 @@ var Store = class {
154
170
  transactionApplying: new StatefulSubject(
155
171
  null
156
172
  ),
157
- operationClose: new Subject()
173
+ operationClose: new Subject(),
174
+ moleculeCreationStart: new Subject(),
175
+ moleculeCreationDone: new Subject(),
176
+ moleculeDisposal: new Subject()
158
177
  };
159
178
  this.operation = { open: false };
160
179
  this.transactionMeta = {
@@ -249,8 +268,6 @@ var clearStore = (store) => {
249
268
  Object.assign(store, new Store(config));
250
269
  store.config = config;
251
270
  };
252
-
253
- // internal/src/store/withdraw.ts
254
271
  function withdraw(token, store) {
255
272
  let withdrawn;
256
273
  let target = store;
@@ -278,6 +295,12 @@ function withdraw(token, store) {
278
295
  case `transaction`:
279
296
  withdrawn = target.transactions.get(token.key);
280
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;
281
304
  }
282
305
  if (withdrawn) {
283
306
  return withdrawn;
@@ -324,7 +347,7 @@ function createRegularAtomFamily(options, store) {
324
347
  individualOptions.effects = options.effects(key);
325
348
  }
326
349
  const token = createRegularAtom(individualOptions, family, target);
327
- subject.next(token);
350
+ subject.next({ type: `state_creation`, token });
328
351
  return token;
329
352
  },
330
353
  {
@@ -362,7 +385,7 @@ function createReadonlySelectorFamily(options, store) {
362
385
  family,
363
386
  target
364
387
  );
365
- subject.next(token);
388
+ subject.next({ type: `state_creation`, token });
366
389
  return token;
367
390
  },
368
391
  {
@@ -392,7 +415,7 @@ function createWritableSelectorFamily(options, store) {
392
415
  family,
393
416
  target
394
417
  );
395
- subject.next(token);
418
+ subject.next({ type: `state_creation`, token });
396
419
  return token;
397
420
  },
398
421
  {
@@ -414,6 +437,21 @@ function createSelectorFamily(options, store) {
414
437
  }
415
438
  return createReadonlySelectorFamily(options, store);
416
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
+ }
417
455
 
418
456
  // internal/src/not-found-error.ts
419
457
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
@@ -421,6 +459,8 @@ function prettyPrintTokenType(token) {
421
459
  switch (token.type) {
422
460
  case `atom_family`:
423
461
  return `Atom Family`;
462
+ case `molecule_family`:
463
+ return `Molecule Family`;
424
464
  case `readonly_selector`:
425
465
  return `Readonly Selector`;
426
466
  case `readonly_selector_family`:
@@ -439,53 +479,36 @@ var NotFoundError = class extends Error {
439
479
  }
440
480
  };
441
481
 
442
- // internal/src/families/init-family-member.ts
443
- function initFamilyMember(token, key, store) {
444
- const familyKey = token.key;
445
- const family = store.families.get(familyKey);
446
- if (family === void 0) {
447
- throw new NotFoundError(token, store);
448
- }
449
- const state = family(key);
450
- return state;
451
- }
452
- function seekInStore(token, key, store) {
453
- const subKey = stringifyJson(key);
454
- const fullKey = `${token.key}(${subKey})`;
482
+ // internal/src/transaction/abort-transaction.ts
483
+ var abortTransaction = (store) => {
455
484
  const target = newest(store);
456
- let state;
457
- switch (token.type) {
458
- case `atom_family`:
459
- case `mutable_atom_family`:
460
- state = target.atoms.get(fullKey);
461
- break;
462
- case `selector_family`: {
463
- state = target.selectors.get(fullKey);
464
- break;
465
- }
466
- case `readonly_selector_family`:
467
- state = target.readonlySelectors.get(fullKey);
468
- break;
469
- }
470
- if (state) {
471
- return deposit(state);
472
- }
473
- return state;
474
- }
475
-
476
- // internal/src/families/find-in-store.ts
477
- function findInStore(token, key, store) {
478
- if (store.config.lifespan === `immortal`) {
479
- throw new Error(
480
- `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
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.`
481
491
  );
492
+ return;
482
493
  }
483
- let state = seekInStore(token, key, store);
484
- if (state) {
485
- return state;
486
- }
487
- state = initFamilyMember(token, key, store);
488
- 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
+ };
489
512
  }
490
513
 
491
514
  // internal/src/set-state/become.ts
@@ -641,7 +664,10 @@ var stowUpdate = (state, update, store) => {
641
664
  if (!shouldStow) {
642
665
  return;
643
666
  }
644
- const atomUpdate = __spreadValues({ key }, update);
667
+ const atomUpdate = __spreadValues({
668
+ type: `atom_update`,
669
+ key
670
+ }, update);
645
671
  if (state.family) {
646
672
  atomUpdate.family = state.family;
647
673
  }
@@ -734,162 +760,613 @@ function setIntoStore(token, value, store) {
734
760
  closeOperation(store);
735
761
  }
736
762
 
737
- // internal/src/keys.ts
738
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
739
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
740
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
741
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
742
-
743
- // internal/src/selector/get-selector-dependency-keys.ts
744
- var getSelectorDependencyKeys = (key, store) => {
745
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
746
- return sources;
747
- };
748
-
749
- // internal/src/selector/trace-selector-atoms.ts
750
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
751
- const rootKeys = [];
752
- const indirectDependencyKeys = getSelectorDependencyKeys(
753
- directDependencyKey,
754
- store
755
- );
756
- let depth = 0;
757
- while (indirectDependencyKeys.length > 0) {
758
- const indirectDependencyKey = indirectDependencyKeys.shift();
759
- ++depth;
760
- if (depth > 99999) {
761
- throw new Error(
762
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
763
- );
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;
764
778
  }
765
- if (!isAtomKey(indirectDependencyKey, store)) {
766
- indirectDependencyKeys.push(
767
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
768
- );
769
- } else if (!rootKeys.includes(indirectDependencyKey)) {
770
- rootKeys.push(indirectDependencyKey);
779
+ case `oldValue`: {
780
+ disposeFromStore(update.token, store);
781
+ break;
771
782
  }
772
783
  }
773
- return rootKeys;
774
- };
775
- var traceAllSelectorAtoms = (selector, store) => {
776
- const selectorKey = selector.key;
777
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
778
- return directDependencyKeys.flatMap(
779
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
780
- );
781
- };
782
-
783
- // internal/src/selector/update-selector-atoms.ts
784
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
785
- const target = newest(store);
786
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
787
- target.selectorAtoms.set({
788
- selectorKey,
789
- atomKey: dependency.key
790
- });
791
- store.logger.info(
792
- `\u{1F50D}`,
793
- `selector`,
794
- selectorKey,
795
- `discovers root atom "${dependency.key}"`
796
- );
797
- } else {
798
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
799
- store.logger.info(
800
- `\u{1F50D}`,
801
- `selector`,
802
- selectorKey,
803
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
804
- );
805
- for (const atomKey of rootKeys) {
806
- target.selectorAtoms = target.selectorAtoms.set({
807
- selectorKey,
808
- atomKey
809
- });
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;
810
795
  }
811
796
  }
812
- };
813
-
814
- // internal/src/selector/register-selector.ts
815
- var registerSelector = (selectorKey, store) => ({
816
- get: (dependency) => {
817
- const target = newest(store);
818
- const dependencyState = withdraw(dependency, store);
819
- const dependencyValue = readOrComputeValue(dependencyState, store);
820
- store.logger.info(
821
- `\u{1F50C}`,
822
- `selector`,
823
- selectorKey,
824
- `registers dependency ( "${dependency.key}" =`,
825
- dependencyValue,
826
- `)`
827
- );
828
- target.selectorGraph.set(
829
- {
830
- upstreamSelectorKey: dependency.key,
831
- downstreamSelectorKey: selectorKey
832
- },
833
- {
834
- 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;
835
806
  }
836
- );
837
- updateSelectorAtoms(selectorKey, dependency, store);
838
- return dependencyValue;
839
- },
840
- set: (WritableToken, newValue) => {
841
- const state = withdraw(WritableToken, store);
842
- setAtomOrSelector(state, newValue, store);
843
- },
844
- find: (token, key) => findInStore(token, key, store),
845
- seek: (token, key) => seekInStore(token, key, store)
846
- });
847
-
848
- // internal/src/selector/create-readonly-selector.ts
849
- var createReadonlySelector = (options, family, store) => {
850
- const target = newest(store);
851
- const subject = new Subject();
852
- const { get, find, seek } = registerSelector(options.key, target);
853
- const getSelf = () => {
854
- const value = options.get({ get, find, seek });
855
- cacheValue(options.key, value, subject, newest(store));
856
- return value;
857
- };
858
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
859
- subject,
860
- install: (s) => createReadonlySelector(options, family, s),
861
- get: getSelf,
862
- type: `readonly_selector`
863
- }), family && { family });
864
- target.readonlySelectors.set(options.key, readonlySelector);
865
- const initialValue = getSelf();
866
- store.logger.info(
867
- `\u2728`,
868
- readonlySelector.type,
869
- readonlySelector.key,
870
- `=`,
871
- initialValue
872
- );
873
- const token = {
874
- key: options.key,
875
- type: `readonly_selector`
876
- };
877
- if (family) {
878
- token.family = family;
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
+ }
879
812
  }
880
- store.on.selectorCreation.next(token);
881
- return token;
882
- };
883
-
884
- // internal/src/selector/create-writable-selector.ts
885
- var createWritableSelector = (options, family, store) => {
886
- const target = newest(store);
887
- const subject = new Subject();
888
- const transactors = registerSelector(options.key, target);
889
- const { find, get, seek } = transactors;
890
- const readonlyTransactors = { find, get, seek };
891
- const getSelf = () => {
892
- const value = options.get(readonlyTransactors);
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
+ }
845
+
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);
851
+ }
852
+ }
853
+
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) => {
1363
+ const target = newest(store);
1364
+ const subject = new Subject();
1365
+ const transactors = registerSelector(options.key, target);
1366
+ const { find, get, seek, json } = transactors;
1367
+ const readonlyTransactors = { find, get, seek, json };
1368
+ const getSelf = () => {
1369
+ const value = options.get(readonlyTransactors);
893
1370
  cacheValue(options.key, value, subject, newest(store));
894
1371
  return value;
895
1372
  };
@@ -930,7 +1407,6 @@ var createWritableSelector = (options, family, store) => {
930
1407
  if (family) {
931
1408
  token.family = family;
932
1409
  }
933
- store.on.selectorCreation.next(token);
934
1410
  return token;
935
1411
  };
936
1412
 
@@ -938,19 +1414,23 @@ var createWritableSelector = (options, family, store) => {
938
1414
  function createStandaloneSelector(options, store) {
939
1415
  const isWritable = `set` in options;
940
1416
  if (isWritable) {
941
- return createWritableSelector(options, void 0, store);
1417
+ const state2 = createWritableSelector(options, void 0, store);
1418
+ store.on.selectorCreation.next(state2);
1419
+ return state2;
942
1420
  }
943
- return createReadonlySelector(options, void 0, store);
1421
+ const state = createReadonlySelector(options, void 0, store);
1422
+ store.on.selectorCreation.next(state);
1423
+ return state;
944
1424
  }
945
1425
 
946
1426
  // internal/src/selector/dispose-selector.ts
947
- function disposeSelector(selectorToken, store) {
1427
+ function disposeSelector2(selectorToken, store) {
948
1428
  var _a;
949
1429
  const target = newest(store);
950
1430
  const { key } = selectorToken;
951
1431
  const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
952
1432
  if (!selector) {
953
- store.logger.error(
1433
+ store.logger.info(
954
1434
  `\u274C`,
955
1435
  `selector`,
956
1436
  key,
@@ -966,10 +1446,30 @@ function disposeSelector(selectorToken, store) {
966
1446
  } else {
967
1447
  switch (selectorToken.type) {
968
1448
  case `selector`:
969
- target.selectors.delete(key);
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
+ }
970
1460
  break;
971
1461
  case `readonly_selector`:
972
- target.readonlySelectors.delete(key);
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
+ }
973
1473
  break;
974
1474
  }
975
1475
  target.valueMap.delete(key);
@@ -982,12 +1482,19 @@ function disposeSelector(selectorToken, store) {
982
1482
  );
983
1483
  for (const downstreamToken of downstreamTokens) {
984
1484
  if (downstreamToken) {
985
- disposeSelector(downstreamToken, store);
1485
+ disposeSelector2(downstreamToken, store);
986
1486
  }
987
1487
  }
988
1488
  target.selectorGraph.delete(key);
989
1489
  store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
990
- store.on.selectorDisposal.next(selectorToken);
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);
1497
+ }
991
1498
  }
992
1499
  }
993
1500
 
@@ -1323,7 +1830,6 @@ function createMutableAtom(options, family, store) {
1323
1830
  if (!family) {
1324
1831
  selectJson(token, options, store);
1325
1832
  }
1326
- store.on.atomCreation.next(token);
1327
1833
  return token;
1328
1834
  }
1329
1835
  var FamilyTracker = class {
@@ -1338,19 +1844,19 @@ var FamilyTracker = class {
1338
1844
  this.mutableAtoms = mutableAtoms;
1339
1845
  this.mutableAtoms.subject.subscribe(
1340
1846
  `store=${store.config.name}::tracker-atom-family`,
1341
- (atomToken) => {
1342
- if (atomToken.family) {
1343
- const key = parseJson(atomToken.family.subKey);
1847
+ (event) => {
1848
+ if (event.token.family) {
1849
+ const key = parseJson$1(event.token.family.subKey);
1344
1850
  seekInStore(this.latestUpdateAtoms, key, store);
1345
- new Tracker(atomToken, store);
1851
+ new Tracker(event.token, store);
1346
1852
  }
1347
1853
  }
1348
1854
  );
1349
1855
  this.latestUpdateAtoms.subject.subscribe(
1350
1856
  `store=${store.config.name}::tracker-atom-family`,
1351
- (atomToken) => {
1352
- if (atomToken.family) {
1353
- const key = parseJson(atomToken.family.subKey);
1857
+ (event) => {
1858
+ if (event.token.family) {
1859
+ const key = parseJson$1(event.token.family.subKey);
1354
1860
  const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
1355
1861
  if (mutableAtomToken) {
1356
1862
  new Tracker(mutableAtomToken, store);
@@ -1381,7 +1887,7 @@ function createMutableAtomFamily(options, store) {
1381
1887
  individualOptions.effects = options.effects(key);
1382
1888
  }
1383
1889
  const token = createMutableAtom(individualOptions, family, target);
1384
- subject.next(token);
1890
+ subject.next({ type: `state_creation`, token });
1385
1891
  return token;
1386
1892
  },
1387
1893
  {
@@ -1597,7 +2103,6 @@ function createRegularAtom(options, family, store) {
1597
2103
  }
1598
2104
  };
1599
2105
  }
1600
- store.on.atomCreation.next(token);
1601
2106
  return token;
1602
2107
  }
1603
2108
 
@@ -1605,13 +2110,17 @@ function createRegularAtom(options, family, store) {
1605
2110
  function createStandaloneAtom(options, store) {
1606
2111
  const isMutable2 = `mutable` in options;
1607
2112
  if (isMutable2) {
1608
- return createMutableAtom(options, void 0, store);
2113
+ const state2 = createMutableAtom(options, void 0, store);
2114
+ store.on.atomCreation.next(state2);
2115
+ return state2;
1609
2116
  }
1610
- return createRegularAtom(options, void 0, store);
2117
+ const state = createRegularAtom(options, void 0, store);
2118
+ store.on.atomCreation.next(state);
2119
+ return state;
1611
2120
  }
1612
2121
 
1613
2122
  // internal/src/atom/dispose-atom.ts
1614
- function disposeAtom(atomToken, store) {
2123
+ function disposeAtom2(atomToken, store) {
1615
2124
  var _a, _b;
1616
2125
  const target = newest(store);
1617
2126
  const { key } = atomToken;
@@ -1627,6 +2136,13 @@ function disposeAtom(atomToken, store) {
1627
2136
  store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1628
2137
  } else {
1629
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
+ });
1630
2146
  target.atoms.delete(key);
1631
2147
  target.valueMap.delete(key);
1632
2148
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -1634,7 +2150,7 @@ function disposeAtom(atomToken, store) {
1634
2150
  for (const selectorKey of selectorKeys) {
1635
2151
  const token = (_b = target.selectors.get(selectorKey)) != null ? _b : target.readonlySelectors.get(selectorKey);
1636
2152
  if (token) {
1637
- disposeSelector(token, store);
2153
+ disposeSelector2(token, store);
1638
2154
  }
1639
2155
  }
1640
2156
  }
@@ -1643,94 +2159,21 @@ function disposeAtom(atomToken, store) {
1643
2159
  target.timelineAtoms.delete(key);
1644
2160
  if (atomToken.type === `mutable_atom`) {
1645
2161
  const updateToken = getUpdateToken(atomToken);
1646
- disposeAtom(updateToken, store);
2162
+ disposeAtom2(updateToken, store);
1647
2163
  store.trackers.delete(key);
1648
2164
  }
1649
2165
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1650
- store.on.atomDisposal.next(atomToken);
1651
- }
1652
- }
1653
-
1654
- // internal/src/get-environment-data.ts
1655
- function getEnvironmentData(store) {
1656
- return {
1657
- window: typeof window === `undefined` ? void 0 : window,
1658
- global: typeof global === `undefined` ? void 0 : global,
1659
- store
1660
- };
1661
- }
1662
-
1663
- // internal/src/get-state/get-from-store.ts
1664
- function getFromStore(token, store) {
1665
- const state = withdraw(token, store);
1666
- return readOrComputeValue(state, store);
1667
- }
1668
-
1669
- // internal/src/ingest-updates/ingest-atom-update.ts
1670
- function ingestAtomUpdate(applying, atomUpdate, store) {
1671
- const { key, newValue, oldValue } = atomUpdate;
1672
- const value = applying === `newValue` ? newValue : oldValue;
1673
- const token = { key, type: `atom` };
1674
- if (atomUpdate.family) {
1675
- Object.assign(token, { family: atomUpdate.family });
1676
- }
1677
- setIntoStore(token, value, store);
1678
- }
1679
-
1680
- // internal/src/ingest-updates/ingest-selector-update.ts
1681
- function ingestSelectorUpdate(applying, selectorUpdate, store) {
1682
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1683
- for (const atomUpdate of updates) {
1684
- ingestAtomUpdate(applying, atomUpdate, store);
1685
- }
1686
- }
1687
-
1688
- // internal/src/ingest-updates/ingest-transaction-update.ts
1689
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1690
- const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1691
- for (const updateFromTransaction of updates) {
1692
- if (`newValue` in updateFromTransaction) {
1693
- 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
+ });
1694
2171
  } else {
1695
- ingestTransactionUpdate(applying, updateFromTransaction, store);
2172
+ store.on.atomDisposal.next(atomToken);
1696
2173
  }
1697
2174
  }
1698
2175
  }
1699
2176
 
1700
- // internal/src/lazy-map.ts
1701
- var LazyMap = class extends Map {
1702
- constructor(source) {
1703
- super();
1704
- this.source = source;
1705
- this.deleted = /* @__PURE__ */ new Set();
1706
- }
1707
- get(key) {
1708
- const has = super.has(key);
1709
- if (has) {
1710
- return super.get(key);
1711
- }
1712
- if (!this.deleted.has(key) && this.source.has(key)) {
1713
- const value = this.source.get(key);
1714
- return value;
1715
- }
1716
- return void 0;
1717
- }
1718
- set(key, value) {
1719
- this.deleted.delete(key);
1720
- return super.set(key, value);
1721
- }
1722
- hasOwn(key) {
1723
- return super.has(key);
1724
- }
1725
- has(key) {
1726
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1727
- }
1728
- delete(key) {
1729
- this.deleted.add(key);
1730
- return super.delete(key);
1731
- }
1732
- };
1733
-
1734
2177
  // internal/src/timeline/add-atom-to-timeline.ts
1735
2178
  var addAtomToTimeline = (atomToken, tl, store) => {
1736
2179
  let maybeAtom = withdraw(atomToken, store);
@@ -1740,188 +2183,212 @@ var addAtomToTimeline = (atomToken, tl, store) => {
1740
2183
  }
1741
2184
  const atom = maybeAtom;
1742
2185
  store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
1743
- atom.subject.subscribe(`timeline`, (update) => {
1744
- var _a, _b, _c, _d, _e, _f;
1745
- const target = newest(store);
1746
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1747
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1748
- const { transactionApplying } = target.on;
1749
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
1750
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
1751
- store.logger.info(
1752
- `\u23F3`,
1753
- `timeline`,
1754
- tl.key,
1755
- `atom`,
1756
- atomToken.key,
1757
- `went`,
1758
- update.oldValue,
1759
- `->`,
1760
- update.newValue,
1761
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
1762
- );
1763
- if (tl.timeTraveling === null) {
1764
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1765
- const mostRecentUpdate = tl.history.at(-1);
1766
- if (mostRecentUpdate === void 0) {
1767
- throw new Error(
1768
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
1769
- );
1770
- }
1771
- }
1772
- if (currentTransactionKey) {
1773
- const txToken = {
1774
- key: currentTransactionKey,
1775
- type: `transaction`
1776
- };
1777
- const currentTransaction = withdraw(txToken, store);
1778
- if (tl.transactionKey !== currentTransactionKey) {
1779
- if (tl.transactionKey) {
1780
- store.logger.error(
1781
- `\u{1F41E}`,
1782
- `timeline`,
1783
- tl.key,
1784
- `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.`
1785
2214
  );
1786
2215
  }
1787
- tl.transactionKey = currentTransactionKey;
1788
- const unsubscribe = currentTransaction.subject.subscribe(
1789
- `timeline:${tl.key}`,
1790
- (transactionUpdate) => {
1791
- var _a2, _b2;
1792
- unsubscribe();
1793
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
1794
- if (tl.at !== tl.history.length) {
1795
- tl.history.splice(tl.at);
1796
- }
1797
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
1798
- const newestStore = newest(store);
1799
- if (`updates` in updateFromTx) {
1800
- 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);
1801
2241
  }
1802
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
1803
- return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
1804
- (key) => {
1805
- var _a3;
1806
- 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;
1807
2251
  }
1808
- ) : false;
1809
- }).map((updateFromTx) => {
1810
- if (`updates` in updateFromTx) {
1811
- return __spreadProps(__spreadValues({}, updateFromTx), {
1812
- updates: filterUpdates(updateFromTx.updates)
1813
- });
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;
2270
+ }
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);
1814
2297
  }
1815
- return updateFromTx;
1816
- });
1817
- const updates = filterUpdates(transactionUpdate.updates);
1818
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
1819
- type: `transaction_update`,
1820
- timestamp: Date.now()
1821
- }, transactionUpdate), {
1822
- updates
1823
- });
1824
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
1825
- if (willCapture) {
1826
- tl.history.push(timelineTransactionUpdate);
1827
- tl.at = tl.history.length;
1828
- tl.subject.next(timelineTransactionUpdate);
1829
2298
  }
2299
+ tl.transactionKey = null;
2300
+ store.logger.info(
2301
+ `\u231B`,
2302
+ `timeline`,
2303
+ tl.key,
2304
+ `got a transaction_update "${transactionUpdate.key}"`
2305
+ );
1830
2306
  }
1831
- 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));
1832
2341
  store.logger.info(
1833
2342
  `\u231B`,
1834
2343
  `timeline`,
1835
2344
  tl.key,
1836
- `got a transaction_update "${transactionUpdate.key}"`
2345
+ `set selector_update "${currentSelectorKey}" to`,
2346
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1837
2347
  );
1838
2348
  }
1839
- );
1840
- }
1841
- } else if (currentSelectorKey && currentSelectorTime) {
1842
- let latestUpdate = tl.history.at(-1);
1843
- if (currentSelectorTime !== tl.selectorTime) {
1844
- latestUpdate = {
1845
- type: `selector_update`,
1846
- timestamp: currentSelectorTime,
1847
- key: currentSelectorKey,
1848
- atomUpdates: []
1849
- };
1850
- latestUpdate.atomUpdates.push(__spreadValues({
1851
- key: atom.key,
1852
- type: `atom_update`
1853
- }, 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;
1854
2362
  if (tl.at !== tl.history.length) {
1855
2363
  tl.history.splice(tl.at);
1856
2364
  }
1857
- 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;
1858
2376
  store.logger.info(
1859
2377
  `\u231B`,
1860
2378
  `timeline`,
1861
2379
  tl.key,
1862
- `got a selector_update "${currentSelectorKey}" with`,
1863
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2380
+ `got an atom_update to "${atom.key}"`
1864
2381
  );
1865
- tl.at = tl.history.length;
1866
- tl.selectorTime = currentSelectorTime;
1867
- } else {
1868
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1869
- latestUpdate.atomUpdates.push(__spreadValues({
1870
- key: atom.key,
1871
- type: `atom_update`
1872
- }, update));
1873
- store.logger.info(
1874
- `\u231B`,
1875
- `timeline`,
1876
- tl.key,
1877
- `set selector_update "${currentSelectorKey}" to`,
1878
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1879
- );
1880
- }
1881
- }
1882
- if (latestUpdate) {
1883
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
1884
- if (willCaptureSelectorUpdate) {
1885
- tl.subject.next(latestUpdate);
1886
- } else {
1887
- tl.history.pop();
2382
+ if (willCapture) {
2383
+ tl.history.push(atomUpdate);
1888
2384
  tl.at = tl.history.length;
2385
+ tl.subject.next(atomUpdate);
1889
2386
  }
1890
2387
  }
1891
- } else {
1892
- const timestamp = Date.now();
1893
- tl.selectorTime = null;
1894
- if (tl.at !== tl.history.length) {
1895
- tl.history.splice(tl.at);
1896
- }
1897
- const atomUpdate = {
1898
- type: `atom_update`,
1899
- timestamp,
1900
- key: atom.key,
1901
- oldValue: update.oldValue,
1902
- newValue: update.newValue
1903
- };
1904
- if (atom.family) {
1905
- atomUpdate.family = atom.family;
1906
- }
1907
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
1908
- store.logger.info(
1909
- `\u231B`,
1910
- `timeline`,
1911
- tl.key,
1912
- `got an atom_update to "${atom.key}"`
1913
- );
1914
- if (willCapture) {
1915
- tl.history.push(atomUpdate);
1916
- tl.at = tl.history.length;
1917
- tl.subject.next(atomUpdate);
1918
- }
1919
2388
  }
1920
- }
1921
- });
2389
+ })
2390
+ );
1922
2391
  };
1923
-
1924
- // internal/src/timeline/create-timeline.ts
1925
2392
  function createTimeline(options, store, data) {
1926
2393
  var _a, _b;
1927
2394
  const tl = __spreadProps(__spreadValues({
@@ -1934,60 +2401,141 @@ function createTimeline(options, store, data) {
1934
2401
  }, data), {
1935
2402
  history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1936
2403
  install: (s) => createTimeline(options, s, tl),
1937
- subject: new Subject()
2404
+ subject: new Subject(),
2405
+ subscriptions: /* @__PURE__ */ new Map()
1938
2406
  });
1939
2407
  if (options.shouldCapture) {
1940
2408
  tl.shouldCapture = options.shouldCapture;
1941
2409
  }
1942
2410
  const timelineKey = options.key;
1943
2411
  const target = newest(store);
1944
- for (const tokenOrFamily of options.atoms) {
2412
+ for (const tokenOrFamily of options.scope) {
1945
2413
  let atomKey = tokenOrFamily.key;
1946
- if (tokenOrFamily.type === `atom_family` || tokenOrFamily.type === `mutable_atom_family`) {
1947
- const familyToken = tokenOrFamily;
1948
- const family = withdraw(familyToken, store);
1949
- const familyKey = family.key;
1950
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
1951
- family.subject.subscribe(`timeline:${options.key}`, (token2) => {
1952
- addAtomToTimeline(token2, tl, store);
1953
- });
1954
- for (const atom of target.atoms.values()) {
1955
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
1956
- addAtomToTimeline(atom, tl, store);
1957
- }
1958
- }
1959
- } else {
1960
- let atom = withdraw(tokenOrFamily, store);
1961
- if (isMutable(atom)) {
1962
- const updateAtom = withdraw(getUpdateToken(atom), store);
1963
- atom = updateAtom;
1964
- atomKey = atom.key;
1965
- }
1966
- if (`family` in atom) {
1967
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
1968
- atom.family.key
1969
- );
1970
- if (familyTimelineKey) {
1971
- store.logger.error(
1972
- `\u274C`,
1973
- `timeline`,
1974
- options.key,
1975
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
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
+ )
1976
2430
  );
1977
- continue;
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
+ }
1978
2436
  }
1979
- }
1980
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
1981
- if (existingTimelineKey) {
1982
- store.logger.error(
1983
- `\u274C`,
1984
- `timeline`,
1985
- options.key,
1986
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
1987
- );
1988
- continue;
1989
- }
1990
- addAtomToTimeline(atom, tl, store);
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
+ }
2471
+ addAtomToTimeline(atom, tl, store);
2472
+ }
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
+ }
2537
+ }
2538
+ break;
1991
2539
  }
1992
2540
  }
1993
2541
  store.timelines.set(options.key, tl);
@@ -1998,6 +2546,27 @@ function createTimeline(options, store, data) {
1998
2546
  store.on.timelineCreation.next(token);
1999
2547
  return token;
2000
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
+ }
2001
2570
 
2002
2571
  // internal/src/timeline/time-travel.ts
2003
2572
  var timeTravel = (action, token, store) => {
@@ -2045,6 +2614,22 @@ var timeTravel = (action, token, store) => {
2045
2614
  ingestTransactionUpdate(applying, update, store);
2046
2615
  break;
2047
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
+ }
2048
2633
  }
2049
2634
  if (action === `redo`) {
2050
2635
  ++timelineData.at;
@@ -2059,251 +2644,4 @@ var timeTravel = (action, token, store) => {
2059
2644
  );
2060
2645
  };
2061
2646
 
2062
- // internal/src/transaction/abort-transaction.ts
2063
- var abortTransaction = (store) => {
2064
- const target = newest(store);
2065
- if (!isChildStore(target)) {
2066
- store.logger.warn(
2067
- `\u{1F41E}`,
2068
- `transaction`,
2069
- `???`,
2070
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2071
- );
2072
- return;
2073
- }
2074
- store.logger.info(
2075
- `\u{1FA82}`,
2076
- `transaction`,
2077
- target.transactionMeta.update.key,
2078
- `Aborting transaction`
2079
- );
2080
- target.parent.child = null;
2081
- };
2082
-
2083
- // internal/src/transaction/act-upon-store.ts
2084
- function actUponStore(token, id, store) {
2085
- return (...parameters) => {
2086
- const tx = withdraw(token, store);
2087
- if (tx) {
2088
- return tx.run(parameters, id);
2089
- }
2090
- throw new NotFoundError(token, store);
2091
- };
2092
- }
2093
-
2094
- // internal/src/transaction/set-epoch-number.ts
2095
- function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
2096
- const isRoot = isRootStore(store);
2097
- if (isRoot && continuityKey) {
2098
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2099
- }
2100
- }
2101
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
2102
- const isRoot = isRootStore(store);
2103
- if (!isRoot) {
2104
- return;
2105
- }
2106
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
2107
- if (continuityKey !== void 0) {
2108
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2109
- }
2110
- }
2111
-
2112
- // internal/src/transaction/apply-transaction.ts
2113
- var applyTransaction = (output, store) => {
2114
- var _a;
2115
- const child = newest(store);
2116
- const { parent } = child;
2117
- if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
2118
- store.logger.warn(
2119
- `\u{1F41E}`,
2120
- `transaction`,
2121
- `???`,
2122
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2123
- );
2124
- return;
2125
- }
2126
- child.transactionMeta.phase = `applying`;
2127
- child.transactionMeta.update.output = output;
2128
- parent.child = null;
2129
- parent.on.transactionApplying.next(child.transactionMeta);
2130
- const { updates } = child.transactionMeta.update;
2131
- store.logger.info(
2132
- `\u{1F6C4}`,
2133
- `transaction`,
2134
- child.transactionMeta.update.key,
2135
- `Applying transaction with ${updates.length} updates:`,
2136
- updates
2137
- );
2138
- for (const tracker of child.trackers.values()) {
2139
- const mutableKey = tracker.mutableState.key;
2140
- if (!parent.atoms.has(mutableKey)) {
2141
- const atom = child.atoms.get(mutableKey);
2142
- atom == null ? void 0 : atom.install(parent);
2143
- }
2144
- tracker.dispose();
2145
- }
2146
- for (const atom of child.atoms.values()) {
2147
- if (!parent.atoms.has(atom.key)) {
2148
- parent.atoms.set(atom.key, atom);
2149
- parent.valueMap.set(atom.key, atom.default);
2150
- parent.logger.info(
2151
- `\u{1F528}`,
2152
- `transaction`,
2153
- child.transactionMeta.update.key,
2154
- `Adding atom "${atom.key}"`
2155
- );
2156
- }
2157
- }
2158
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
2159
- if (isRootStore(parent)) {
2160
- setEpochNumberOfAction(
2161
- child.transactionMeta.update.key,
2162
- child.transactionMeta.update.epoch,
2163
- parent
2164
- );
2165
- const myTransaction = withdraw(
2166
- { key: child.transactionMeta.update.key, type: `transaction` },
2167
- store
2168
- );
2169
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
2170
- store.logger.info(
2171
- `\u{1F6EC}`,
2172
- `transaction`,
2173
- child.transactionMeta.update.key,
2174
- `Finished applying transaction.`
2175
- );
2176
- } else if (isChildStore(parent)) {
2177
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
2178
- }
2179
- parent.on.transactionApplying.next(null);
2180
- };
2181
-
2182
- // internal/src/transaction/assign-transaction-to-continuity.ts
2183
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2184
- const isRoot = isRootStore(store);
2185
- if (!isRoot) {
2186
- return;
2187
- }
2188
- const { epoch, actionContinuities } = store.transactionMeta;
2189
- actionContinuities.set(continuityKey, transactionKey);
2190
- if (!epoch.has(continuityKey)) {
2191
- epoch.set(continuityKey, -1);
2192
- }
2193
- }
2194
-
2195
- // internal/src/transaction/build-transaction.ts
2196
- var buildTransaction = (key, params, store, id) => {
2197
- const parent = newest(store);
2198
- const childBase = {
2199
- parent,
2200
- child: null,
2201
- on: parent.on,
2202
- loggers: parent.loggers,
2203
- logger: parent.logger,
2204
- config: parent.config,
2205
- atoms: new LazyMap(parent.atoms),
2206
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2207
- families: new LazyMap(parent.families),
2208
- operation: { open: false },
2209
- readonlySelectors: new LazyMap(parent.readonlySelectors),
2210
- timelines: new LazyMap(parent.timelines),
2211
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
2212
- trackers: /* @__PURE__ */ new Map(),
2213
- transactions: new LazyMap(parent.transactions),
2214
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
2215
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
2216
- makeContentKey: (...keys) => keys.sort().join(`:`)
2217
- }),
2218
- selectors: new LazyMap(parent.selectors),
2219
- valueMap: new LazyMap(parent.valueMap),
2220
- molecules: new LazyMap(parent.molecules),
2221
- miscResources: new LazyMap(parent.miscResources)
2222
- };
2223
- const epoch = getEpochNumberOfAction(key, store);
2224
- const transactionMeta = {
2225
- phase: `building`,
2226
- update: {
2227
- key,
2228
- id,
2229
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
2230
- updates: [],
2231
- params,
2232
- output: void 0
2233
- },
2234
- transactors: {
2235
- get: (token) => getFromStore(token, child),
2236
- set: (token, value) => {
2237
- setIntoStore(token, value, child);
2238
- },
2239
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2240
- find: (token, k) => findInStore(token, k, child),
2241
- seek: (token, k) => seekInStore(token, k, child),
2242
- env: () => getEnvironmentData(child)
2243
- }
2244
- };
2245
- const child = Object.assign(childBase, {
2246
- transactionMeta
2247
- });
2248
- parent.child = child;
2249
- store.logger.info(
2250
- `\u{1F6EB}`,
2251
- `transaction`,
2252
- key,
2253
- `Building transaction with params:`,
2254
- params
2255
- );
2256
- return child;
2257
- };
2258
-
2259
- // internal/src/transaction/create-transaction.ts
2260
- function createTransaction(options, store) {
2261
- const newTransaction = {
2262
- key: options.key,
2263
- type: `transaction`,
2264
- run: (params, id) => {
2265
- const childStore = buildTransaction(options.key, params, store, id);
2266
- try {
2267
- const target2 = newest(store);
2268
- const { transactors } = childStore.transactionMeta;
2269
- const output = options.do(transactors, ...params);
2270
- applyTransaction(output, target2);
2271
- return output;
2272
- } catch (thrown) {
2273
- abortTransaction(target);
2274
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
2275
- throw thrown;
2276
- }
2277
- },
2278
- install: (s) => createTransaction(options, s),
2279
- subject: new Subject()
2280
- };
2281
- const target = newest(store);
2282
- target.transactions.set(newTransaction.key, newTransaction);
2283
- const token = deposit(newTransaction);
2284
- store.on.transactionCreation.next(token);
2285
- return token;
2286
- }
2287
-
2288
- // internal/src/transaction/get-epoch-number.ts
2289
- function getContinuityKey(transactionKey, store) {
2290
- const isRoot = isRootStore(store);
2291
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2292
- return continuity;
2293
- }
2294
- function getEpochNumberOfContinuity(continuityKey, store) {
2295
- const isRoot = isRootStore(store);
2296
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
2297
- return epoch;
2298
- }
2299
- function getEpochNumberOfAction(transactionKey, store) {
2300
- const isRoot = isRootStore(store);
2301
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2302
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
2303
- return epoch;
2304
- }
2305
-
2306
- // internal/src/transaction/index.ts
2307
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2308
-
2309
- 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, 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 };
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 };