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
@@ -2,6 +2,28 @@
2
2
 
3
3
  var json = require('atom.io/json');
4
4
  var atom_io = require('atom.io');
5
+ var immortal = require('atom.io/immortal');
6
+ var Internal = require('atom.io/internal');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var Internal__namespace = /*#__PURE__*/_interopNamespace(Internal);
5
27
 
6
28
  var __defProp = Object.defineProperty;
7
29
  var __defProps = Object.defineProperties;
@@ -80,14 +102,26 @@ function newest(scion) {
80
102
 
81
103
  // internal/src/store/deposit.ts
82
104
  function deposit(state) {
83
- const token = {
84
- key: state.key,
85
- type: state.type
86
- };
87
- if (`family` in state) {
88
- token.family = state.family;
105
+ const { type } = state;
106
+ switch (type) {
107
+ case `atom`:
108
+ case `molecule_family`:
109
+ case `mutable_atom`:
110
+ case `selector`:
111
+ case `readonly_selector`:
112
+ case `transaction`: {
113
+ const token = {
114
+ key: state.key,
115
+ type: state.type
116
+ };
117
+ if (`family` in state) {
118
+ token.family = state.family;
119
+ }
120
+ return token;
121
+ }
122
+ case `molecule`:
123
+ return state.token;
89
124
  }
90
- return token;
91
125
  }
92
126
 
93
127
  // ../rel8/junction/src/junction.ts
@@ -391,7 +425,7 @@ function isChildStore(store) {
391
425
 
392
426
  // internal/src/store/store.ts
393
427
  var Store = class {
394
- constructor(name, store = null) {
428
+ constructor(config, store = null) {
395
429
  this.parent = null;
396
430
  this.child = null;
397
431
  this.valueMap = /* @__PURE__ */ new Map();
@@ -420,6 +454,9 @@ var Store = class {
420
454
  makeContentKey: (...keys) => keys.sort().join(`:`)
421
455
  }
422
456
  );
457
+ this.molecules = /* @__PURE__ */ new Map();
458
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
459
+ this.miscResources = /* @__PURE__ */ new Map();
423
460
  this.on = {
424
461
  atomCreation: new Subject(),
425
462
  atomDisposal: new Subject(),
@@ -430,7 +467,10 @@ var Store = class {
430
467
  transactionApplying: new StatefulSubject(
431
468
  null
432
469
  ),
433
- operationClose: new Subject()
470
+ operationClose: new Subject(),
471
+ moleculeCreationStart: new Subject(),
472
+ moleculeCreationDone: new Subject(),
473
+ moleculeDisposal: new Subject()
434
474
  };
435
475
  this.operation = { open: false };
436
476
  this.transactionMeta = {
@@ -441,7 +481,8 @@ var Store = class {
441
481
  })
442
482
  };
443
483
  this.config = {
444
- name: `IMPLICIT_STORE`
484
+ name: `IMPLICIT_STORE`,
485
+ lifespan: `ephemeral`
445
486
  };
446
487
  this.loggers = [
447
488
  new atom_io.AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
@@ -471,9 +512,7 @@ var Store = class {
471
512
  )
472
513
  };
473
514
  }
474
- this.config = __spreadProps(__spreadValues({}, store == null ? void 0 : store.config), {
475
- name
476
- });
515
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
477
516
  for (const [, family] of store.families) {
478
517
  family.install(this);
479
518
  }
@@ -484,7 +523,7 @@ var Store = class {
484
523
  }
485
524
  atom.install(this);
486
525
  if (atom.type === `mutable_atom`) {
487
- const originalJsonToken = getJsonToken(atom);
526
+ const originalJsonToken = getJsonToken(atom, store);
488
527
  const originalUpdateToken = getUpdateToken(atom);
489
528
  mutableHelpers.add(originalJsonToken.key);
490
529
  mutableHelpers.add(originalUpdateToken.key);
@@ -512,16 +551,20 @@ var IMPLICIT = {
512
551
  STORE_INTERNAL: void 0,
513
552
  get STORE() {
514
553
  var _a;
515
- return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store(`IMPLICIT_STORE`);
554
+ return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
555
+ name: `IMPLICIT_STORE`,
556
+ lifespan: `ephemeral`
557
+ });
516
558
  }
517
559
  };
518
560
  var clearStore = (store) => {
519
561
  const { config } = store;
520
- Object.assign(store, new Store(config.name));
562
+ for (const disposable of store.miscResources.values()) {
563
+ disposable[Symbol.dispose]();
564
+ }
565
+ Object.assign(store, new Store(config));
521
566
  store.config = config;
522
567
  };
523
-
524
- // internal/src/store/withdraw.ts
525
568
  function withdraw(token, store) {
526
569
  let withdrawn;
527
570
  let target = store;
@@ -549,6 +592,12 @@ function withdraw(token, store) {
549
592
  case `transaction`:
550
593
  withdrawn = target.transactions.get(token.key);
551
594
  break;
595
+ case `molecule`:
596
+ withdrawn = target.molecules.get(json.stringifyJson(token.key));
597
+ break;
598
+ case `molecule_family`:
599
+ withdrawn = target.moleculeFamilies.get(token.key);
600
+ break;
552
601
  }
553
602
  if (withdrawn) {
554
603
  return withdrawn;
@@ -558,36 +607,6 @@ function withdraw(token, store) {
558
607
  throw new NotFoundError(token, store);
559
608
  }
560
609
 
561
- // internal/src/store/withdraw-new-family-member.ts
562
- function withdrawOrCreate(token, store) {
563
- try {
564
- const state = withdraw(token, store);
565
- return state;
566
- } catch (notFoundError) {
567
- if (token.family) {
568
- store.logger.info(
569
- `\u{1F46A}`,
570
- token.type,
571
- token.key,
572
- `creating new family member in store "${store.config.name}"`
573
- );
574
- const target = newest(store);
575
- const family = target.families.get(token.family.key);
576
- if (family) {
577
- const jsonSubKey = JSON.parse(token.family.subKey);
578
- family(jsonSubKey);
579
- const state = withdraw(token, store);
580
- return state;
581
- }
582
- throw new NotFoundError(
583
- { key: token.family.key, type: `${token.type}_family` },
584
- store
585
- );
586
- }
587
- throw notFoundError;
588
- }
589
- }
590
-
591
610
  // internal/src/get-state/read-or-compute-value.ts
592
611
  var readOrComputeValue = (state, target) => {
593
612
  if (target.valueMap.has(state.key)) {
@@ -615,22 +634,17 @@ function createRegularAtomFamily(options, store) {
615
634
  const subKey = json.stringifyJson(key);
616
635
  const family = { key: options.key, subKey };
617
636
  const fullKey = `${options.key}(${subKey})`;
618
- const target2 = newest(store);
619
- const atomAlreadyCreated = target2.atoms.has(fullKey);
620
- let token;
621
- if (atomAlreadyCreated) {
622
- token = { type: `atom`, key: fullKey, family };
623
- } else {
624
- const individualOptions = {
625
- key: fullKey,
626
- default: options.default instanceof Function ? options.default(key) : options.default
627
- };
628
- if (options.effects) {
629
- individualOptions.effects = options.effects(key);
630
- }
631
- token = createRegularAtom(individualOptions, family, store);
632
- subject.next(token);
637
+ const target = newest(store);
638
+ const def = options.default;
639
+ const individualOptions = {
640
+ key: fullKey,
641
+ default: def instanceof Function ? def(key) : def
642
+ };
643
+ if (options.effects) {
644
+ individualOptions.effects = options.effects(key);
633
645
  }
646
+ const token = createRegularAtom(individualOptions, family, target);
647
+ subject.next({ type: `state_creation`, token });
634
648
  return token;
635
649
  },
636
650
  {
@@ -640,8 +654,7 @@ function createRegularAtomFamily(options, store) {
640
654
  install: (s) => createRegularAtomFamily(options, s)
641
655
  }
642
656
  );
643
- const target = newest(store);
644
- target.families.set(options.key, atomFamily);
657
+ store.families.set(options.key, atomFamily);
645
658
  return atomFamily;
646
659
  }
647
660
 
@@ -657,22 +670,20 @@ function createReadonlySelectorFamily(options, store) {
657
670
  const subject = new Subject();
658
671
  const readonlySelectorFamily = Object.assign(
659
672
  (key) => {
660
- const target = newest(store);
661
673
  const subKey = json.stringifyJson(key);
662
674
  const family = { key: options.key, subKey };
663
675
  const fullKey = `${options.key}(${subKey})`;
664
- const existing = target.readonlySelectors.get(fullKey);
665
- if (existing) {
666
- return deposit(existing);
667
- }
668
- return createReadonlySelector(
676
+ const target = newest(store);
677
+ const token = createReadonlySelector(
669
678
  {
670
679
  key: fullKey,
671
680
  get: options.get(key)
672
681
  },
673
682
  family,
674
- store
683
+ target
675
684
  );
685
+ subject.next({ type: `state_creation`, token });
686
+ return token;
676
687
  },
677
688
  {
678
689
  key: options.key,
@@ -691,10 +702,7 @@ function createWritableSelectorFamily(options, store) {
691
702
  const subKey = json.stringifyJson(key);
692
703
  const family = { key: options.key, subKey };
693
704
  const fullKey = `${options.key}(${subKey})`;
694
- const existing = store.selectors.get(fullKey);
695
- if (existing) {
696
- return deposit(existing);
697
- }
705
+ const target = newest(store);
698
706
  const token = createWritableSelector(
699
707
  {
700
708
  key: fullKey,
@@ -702,9 +710,9 @@ function createWritableSelectorFamily(options, store) {
702
710
  set: options.set(key)
703
711
  },
704
712
  family,
705
- store
713
+ target
706
714
  );
707
- subject.next(token);
715
+ subject.next({ type: `state_creation`, token });
708
716
  return token;
709
717
  },
710
718
  {
@@ -726,14 +734,39 @@ function createSelectorFamily(options, store) {
726
734
  }
727
735
  return createReadonlySelectorFamily(options, store);
728
736
  }
737
+ function disposeFromStore(token, store = Internal__namespace.IMPLICIT.STORE) {
738
+ switch (token.type) {
739
+ case `atom`:
740
+ case `mutable_atom`:
741
+ Internal__namespace.disposeAtom(token, store);
742
+ break;
743
+ case `selector`:
744
+ case `readonly_selector`:
745
+ Internal__namespace.disposeSelector(token, store);
746
+ break;
747
+ case `molecule`:
748
+ immortal.disposeMolecule(token, store);
749
+ break;
750
+ }
751
+ }
729
752
 
730
753
  // internal/src/not-found-error.ts
731
754
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
732
755
  function prettyPrintTokenType(token) {
733
- if (token.type === `readonly_selector`) {
734
- return `Readonly Selector`;
756
+ switch (token.type) {
757
+ case `atom_family`:
758
+ return `Atom Family`;
759
+ case `molecule_family`:
760
+ return `Molecule Family`;
761
+ case `readonly_selector`:
762
+ return `Readonly Selector`;
763
+ case `readonly_selector_family`:
764
+ return `Readonly Selector Family`;
765
+ case `selector_family`:
766
+ return `Selector Family`;
767
+ default:
768
+ return capitalize(token.type);
735
769
  }
736
- return capitalize(token.type);
737
770
  }
738
771
  var NotFoundError = class extends Error {
739
772
  constructor(token, store) {
@@ -743,15 +776,36 @@ var NotFoundError = class extends Error {
743
776
  }
744
777
  };
745
778
 
746
- // internal/src/families/find-in-store.ts
747
- function findInStore(token, key, store) {
748
- const familyKey = token.key;
749
- const family = store.families.get(familyKey);
750
- if (family === void 0) {
751
- throw new NotFoundError(token, store);
779
+ // internal/src/transaction/abort-transaction.ts
780
+ var abortTransaction = (store) => {
781
+ const target = newest(store);
782
+ if (!isChildStore(target)) {
783
+ store.logger.warn(
784
+ `\u{1F41E}`,
785
+ `transaction`,
786
+ `???`,
787
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
788
+ );
789
+ return;
752
790
  }
753
- const state = family(key);
754
- return state;
791
+ store.logger.info(
792
+ `\u{1FA82}`,
793
+ `transaction`,
794
+ target.transactionMeta.update.key,
795
+ `Aborting transaction`
796
+ );
797
+ target.parent.child = null;
798
+ };
799
+
800
+ // internal/src/transaction/act-upon-store.ts
801
+ function actUponStore(token, id, store) {
802
+ return (...parameters) => {
803
+ const tx = withdraw(token, store);
804
+ if (tx) {
805
+ return tx.run(parameters, id);
806
+ }
807
+ throw new NotFoundError(token, store);
808
+ };
755
809
  }
756
810
 
757
811
  // internal/src/set-state/become.ts
@@ -907,7 +961,10 @@ var stowUpdate = (state, update, store) => {
907
961
  if (!shouldStow) {
908
962
  return;
909
963
  }
910
- const atomUpdate = __spreadValues({ key }, update);
964
+ const atomUpdate = __spreadValues({
965
+ type: `atom_update`,
966
+ key
967
+ }, update);
911
968
  if (state.family) {
912
969
  atomUpdate.family = state.family;
913
970
  }
@@ -995,164 +1052,619 @@ function setIntoStore(token, value, store) {
995
1052
  );
996
1053
  return;
997
1054
  }
998
- const state = withdrawOrCreate(token, store);
1055
+ const state = withdraw(token, store);
999
1056
  setAtomOrSelector(state, value, store);
1000
1057
  closeOperation(store);
1001
1058
  }
1002
1059
 
1003
- // internal/src/keys.ts
1004
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
1005
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1006
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1007
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1008
-
1009
- // internal/src/selector/get-selector-dependency-keys.ts
1010
- var getSelectorDependencyKeys = (key, store) => {
1011
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1012
- return sources;
1013
- };
1060
+ // internal/src/ingest-updates/ingest-atom-update.ts
1061
+ function ingestAtomUpdate(applying, atomUpdate, store) {
1062
+ const { key, newValue, oldValue } = atomUpdate;
1063
+ const value = applying === `newValue` ? newValue : oldValue;
1064
+ const token = { key, type: `atom` };
1065
+ if (atomUpdate.family) {
1066
+ Object.assign(token, { family: atomUpdate.family });
1067
+ }
1068
+ setIntoStore(token, value, store);
1069
+ }
1014
1070
 
1015
- // internal/src/selector/trace-selector-atoms.ts
1016
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1017
- const rootKeys = [];
1018
- const indirectDependencyKeys = getSelectorDependencyKeys(
1019
- directDependencyKey,
1020
- store
1021
- );
1022
- let depth = 0;
1023
- while (indirectDependencyKeys.length > 0) {
1024
- const indirectDependencyKey = indirectDependencyKeys.shift();
1025
- ++depth;
1026
- if (depth > 99999) {
1027
- throw new Error(
1028
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1029
- );
1071
+ // ../anvl/src/json/index.ts
1072
+ var parseJson = (str) => JSON.parse(str);
1073
+ function ingestCreationEvent(update, applying, store) {
1074
+ switch (applying) {
1075
+ case `newValue`: {
1076
+ createInStore(update.token, store);
1077
+ break;
1030
1078
  }
1031
- if (!isAtomKey(indirectDependencyKey, store)) {
1032
- indirectDependencyKeys.push(
1033
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
1034
- );
1035
- } else if (!rootKeys.includes(indirectDependencyKey)) {
1036
- rootKeys.push(indirectDependencyKey);
1079
+ case `oldValue`: {
1080
+ disposeFromStore(update.token, store);
1081
+ break;
1037
1082
  }
1038
1083
  }
1039
- return rootKeys;
1040
- };
1041
- var traceAllSelectorAtoms = (selector, store) => {
1042
- const selectorKey = selector.key;
1043
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1044
- return directDependencyKeys.flatMap(
1045
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1046
- );
1047
- };
1048
-
1049
- // internal/src/selector/update-selector-atoms.ts
1050
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
1051
- const target = newest(store);
1052
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1053
- target.selectorAtoms.set({
1054
- selectorKey,
1055
- atomKey: dependency.key
1056
- });
1057
- store.logger.info(
1058
- `\u{1F50D}`,
1059
- `selector`,
1060
- selectorKey,
1061
- `discovers root atom "${dependency.key}"`
1062
- );
1063
- } else {
1064
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1065
- store.logger.info(
1066
- `\u{1F50D}`,
1067
- `selector`,
1068
- selectorKey,
1069
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1070
- );
1071
- for (const atomKey of rootKeys) {
1072
- target.selectorAtoms = target.selectorAtoms.set({
1073
- selectorKey,
1074
- atomKey
1075
- });
1084
+ }
1085
+ function ingestDisposalEvent(update, applying, store) {
1086
+ switch (applying) {
1087
+ case `newValue`: {
1088
+ disposeFromStore(update.token, store);
1089
+ break;
1090
+ }
1091
+ case `oldValue`: {
1092
+ createInStore(update.token, store);
1093
+ store.valueMap.set(update.token.key, update.value);
1094
+ break;
1076
1095
  }
1077
1096
  }
1078
- };
1079
-
1080
- // internal/src/selector/register-selector.ts
1081
- var registerSelector = (selectorKey, store) => ({
1082
- get: (dependency) => {
1083
- const target = newest(store);
1084
- const dependencyState = withdrawOrCreate(dependency, store);
1085
- const dependencyValue = readOrComputeValue(dependencyState, store);
1086
- store.logger.info(
1087
- `\u{1F50C}`,
1088
- `selector`,
1089
- selectorKey,
1090
- `registers dependency ( "${dependency.key}" =`,
1091
- dependencyValue,
1092
- `)`
1093
- );
1094
- target.selectorGraph.set(
1095
- {
1096
- upstreamSelectorKey: dependency.key,
1097
- downstreamSelectorKey: selectorKey
1098
- },
1099
- {
1100
- source: dependency.key
1097
+ }
1098
+ function createInStore(token, store) {
1099
+ if (token.family) {
1100
+ const family = store.families.get(token.family.key);
1101
+ if (family) {
1102
+ const molecule = store.molecules.get(token.family.subKey);
1103
+ if (molecule) {
1104
+ molecule.bond(family);
1105
+ return;
1101
1106
  }
1102
- );
1103
- updateSelectorAtoms(selectorKey, dependency, store);
1104
- return dependencyValue;
1105
- },
1106
- set: (WritableToken, newValue) => {
1107
- const state = withdrawOrCreate(WritableToken, store);
1108
- setAtomOrSelector(state, newValue, store);
1109
- },
1110
- find: (token, key) => findInStore(token, key, store)
1111
- });
1112
-
1113
- // internal/src/selector/create-readonly-selector.ts
1114
- var createReadonlySelector = (options, family, store) => {
1115
- const target = newest(store);
1116
- const subject = new Subject();
1117
- const { get, find } = registerSelector(options.key, target);
1118
- const getSelf = () => {
1119
- const value = options.get({ get, find });
1120
- cacheValue(options.key, value, subject, newest(store));
1121
- return value;
1122
- };
1123
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1124
- subject,
1125
- install: (s) => createReadonlySelector(options, family, s),
1126
- get: getSelf,
1127
- type: `readonly_selector`
1128
- }), family && { family });
1129
- target.readonlySelectors.set(options.key, readonlySelector);
1130
- const initialValue = getSelf();
1131
- store.logger.info(
1132
- `\u2728`,
1133
- readonlySelector.type,
1134
- readonlySelector.key,
1135
- `=`,
1136
- initialValue
1137
- );
1138
- const token = {
1139
- key: options.key,
1140
- type: `readonly_selector`
1141
- };
1142
- if (family) {
1143
- token.family = family;
1107
+ if (store.config.lifespan === `immortal`) {
1108
+ throw new Error(`No molecule found for key "${token.family.subKey}"`);
1109
+ }
1110
+ initFamilyMember(family, parseJson(token.family.subKey), store);
1111
+ }
1144
1112
  }
1145
- store.on.selectorCreation.next(token);
1146
- return token;
1147
- };
1113
+ }
1114
+ function ingestMoleculeCreationEvent(update, applying, store) {
1115
+ switch (applying) {
1116
+ case `newValue`:
1117
+ immortal.makeMoleculeInStore(
1118
+ store,
1119
+ update.context[0],
1120
+ update.family,
1121
+ update.token.key,
1122
+ ...update.params
1123
+ );
1124
+ break;
1125
+ case `oldValue`:
1126
+ immortal.disposeMolecule(update.token, store);
1127
+ break;
1128
+ }
1129
+ }
1130
+ function ingestMoleculeDisposalEvent(update, applying, store) {
1131
+ switch (applying) {
1132
+ case `newValue`:
1133
+ immortal.disposeMolecule(update.token, store);
1134
+ break;
1135
+ case `oldValue`:
1136
+ immortal.makeMoleculeInStore(
1137
+ store,
1138
+ update.context[0],
1139
+ update.family,
1140
+ update.token.key
1141
+ );
1142
+ break;
1143
+ }
1144
+ }
1145
+
1146
+ // internal/src/ingest-updates/ingest-selector-update.ts
1147
+ function ingestSelectorUpdate(applying, selectorUpdate, store) {
1148
+ const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1149
+ for (const atomUpdate of updates) {
1150
+ ingestAtomUpdate(applying, atomUpdate, store);
1151
+ }
1152
+ }
1153
+
1154
+ // internal/src/ingest-updates/ingest-transaction-update.ts
1155
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1156
+ const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1157
+ for (const updateFromTransaction of updates) {
1158
+ switch (updateFromTransaction.type) {
1159
+ case `atom_update`:
1160
+ case `selector_update`:
1161
+ ingestAtomUpdate(applying, updateFromTransaction, store);
1162
+ break;
1163
+ case `state_creation`:
1164
+ ingestCreationEvent(updateFromTransaction, applying, store);
1165
+ break;
1166
+ case `state_disposal`:
1167
+ ingestDisposalEvent(updateFromTransaction, applying, store);
1168
+ break;
1169
+ case `molecule_creation`:
1170
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1171
+ break;
1172
+ case `molecule_disposal`:
1173
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1174
+ break;
1175
+ case `transaction_update`:
1176
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
1177
+ break;
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ // internal/src/transaction/set-epoch-number.ts
1183
+ function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
1184
+ const isRoot = isRootStore(store);
1185
+ if (isRoot && continuityKey) {
1186
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1187
+ }
1188
+ }
1189
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1190
+ const isRoot = isRootStore(store);
1191
+ if (!isRoot) {
1192
+ return;
1193
+ }
1194
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1195
+ if (continuityKey !== void 0) {
1196
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1197
+ }
1198
+ }
1199
+
1200
+ // internal/src/transaction/apply-transaction.ts
1201
+ var applyTransaction = (output, store) => {
1202
+ var _a;
1203
+ const child = newest(store);
1204
+ const { parent } = child;
1205
+ if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
1206
+ store.logger.warn(
1207
+ `\u{1F41E}`,
1208
+ `transaction`,
1209
+ `???`,
1210
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1211
+ );
1212
+ return;
1213
+ }
1214
+ child.transactionMeta.phase = `applying`;
1215
+ child.transactionMeta.update.output = output;
1216
+ parent.child = null;
1217
+ parent.on.transactionApplying.next(child.transactionMeta);
1218
+ const { updates } = child.transactionMeta.update;
1219
+ store.logger.info(
1220
+ `\u{1F6C4}`,
1221
+ `transaction`,
1222
+ child.transactionMeta.update.key,
1223
+ `Applying transaction with ${updates.length} updates:`,
1224
+ updates
1225
+ );
1226
+ for (const tracker of child.trackers.values()) {
1227
+ const mutableKey = tracker.mutableState.key;
1228
+ if (!parent.atoms.has(mutableKey)) {
1229
+ const atom = child.atoms.get(mutableKey);
1230
+ atom == null ? void 0 : atom.install(parent);
1231
+ }
1232
+ tracker.dispose();
1233
+ }
1234
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1235
+ if (isRootStore(parent)) {
1236
+ setEpochNumberOfAction(
1237
+ child.transactionMeta.update.key,
1238
+ child.transactionMeta.update.epoch,
1239
+ parent
1240
+ );
1241
+ const myTransaction = withdraw(
1242
+ { key: child.transactionMeta.update.key, type: `transaction` },
1243
+ store
1244
+ );
1245
+ myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
1246
+ store.logger.info(
1247
+ `\u{1F6EC}`,
1248
+ `transaction`,
1249
+ child.transactionMeta.update.key,
1250
+ `Finished applying transaction.`
1251
+ );
1252
+ } else if (isChildStore(parent)) {
1253
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1254
+ }
1255
+ parent.on.transactionApplying.next(null);
1256
+ };
1257
+
1258
+ // internal/src/transaction/assign-transaction-to-continuity.ts
1259
+ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1260
+ const isRoot = isRootStore(store);
1261
+ if (!isRoot) {
1262
+ return;
1263
+ }
1264
+ const { epoch, actionContinuities } = store.transactionMeta;
1265
+ actionContinuities.set(continuityKey, transactionKey);
1266
+ if (!epoch.has(continuityKey)) {
1267
+ epoch.set(continuityKey, -1);
1268
+ }
1269
+ }
1270
+
1271
+ // internal/src/get-environment-data.ts
1272
+ function getEnvironmentData(store) {
1273
+ return {
1274
+ window: typeof window === `undefined` ? void 0 : window,
1275
+ global: typeof global === `undefined` ? void 0 : global,
1276
+ store
1277
+ };
1278
+ }
1279
+
1280
+ // internal/src/get-state/get-from-store.ts
1281
+ function getFromStore(token, store) {
1282
+ const state = withdraw(token, store);
1283
+ return readOrComputeValue(state, store);
1284
+ }
1285
+
1286
+ // internal/src/lazy-map.ts
1287
+ var LazyMap = class extends Map {
1288
+ constructor(source) {
1289
+ super();
1290
+ this.source = source;
1291
+ this.deleted = /* @__PURE__ */ new Set();
1292
+ }
1293
+ get(key) {
1294
+ const has = super.has(key);
1295
+ if (has) {
1296
+ return super.get(key);
1297
+ }
1298
+ if (!this.deleted.has(key) && this.source.has(key)) {
1299
+ const value = this.source.get(key);
1300
+ return value;
1301
+ }
1302
+ return void 0;
1303
+ }
1304
+ set(key, value) {
1305
+ this.deleted.delete(key);
1306
+ return super.set(key, value);
1307
+ }
1308
+ hasOwn(key) {
1309
+ return super.has(key);
1310
+ }
1311
+ has(key) {
1312
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1313
+ }
1314
+ delete(key) {
1315
+ this.deleted.add(key);
1316
+ return super.delete(key);
1317
+ }
1318
+ };
1319
+
1320
+ // internal/src/transaction/build-transaction.ts
1321
+ var buildTransaction = (key, params, store, id) => {
1322
+ const parent = newest(store);
1323
+ const childBase = {
1324
+ parent,
1325
+ child: null,
1326
+ on: parent.on,
1327
+ loggers: parent.loggers,
1328
+ logger: parent.logger,
1329
+ config: parent.config,
1330
+ atoms: new LazyMap(parent.atoms),
1331
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1332
+ families: new LazyMap(parent.families),
1333
+ operation: { open: false },
1334
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
1335
+ timelines: new LazyMap(parent.timelines),
1336
+ timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
1337
+ trackers: /* @__PURE__ */ new Map(),
1338
+ transactions: new LazyMap(parent.transactions),
1339
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1340
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1341
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1342
+ }),
1343
+ selectors: new LazyMap(parent.selectors),
1344
+ valueMap: new LazyMap(parent.valueMap),
1345
+ molecules: new LazyMap(parent.molecules),
1346
+ moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1347
+ miscResources: new LazyMap(parent.miscResources)
1348
+ };
1349
+ const epoch = getEpochNumberOfAction(key, store);
1350
+ const transactionMeta = {
1351
+ phase: `building`,
1352
+ update: {
1353
+ type: `transaction_update`,
1354
+ key,
1355
+ id,
1356
+ epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1357
+ updates: [],
1358
+ params,
1359
+ output: void 0
1360
+ },
1361
+ transactors: {
1362
+ get: (token) => getFromStore(token, child),
1363
+ set: (token, value) => {
1364
+ setIntoStore(token, value, child);
1365
+ },
1366
+ run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1367
+ find: (token, k) => findInStore(token, k, child),
1368
+ seek: (token, k) => seekInStore(token, k, child),
1369
+ json: (token) => getJsonToken(token, child),
1370
+ make: (context, family, k, ...args) => immortal.makeMoleculeInStore(child, context, family, k, ...args),
1371
+ dispose: (token) => {
1372
+ disposeFromStore(token, child);
1373
+ },
1374
+ env: () => getEnvironmentData(child)
1375
+ }
1376
+ };
1377
+ const child = Object.assign(childBase, {
1378
+ transactionMeta
1379
+ });
1380
+ parent.child = child;
1381
+ store.logger.info(
1382
+ `\u{1F6EB}`,
1383
+ `transaction`,
1384
+ key,
1385
+ `Building transaction with params:`,
1386
+ params
1387
+ );
1388
+ return child;
1389
+ };
1390
+
1391
+ // internal/src/transaction/create-transaction.ts
1392
+ function createTransaction(options, store) {
1393
+ const newTransaction = {
1394
+ key: options.key,
1395
+ type: `transaction`,
1396
+ run: (params, id) => {
1397
+ const childStore = buildTransaction(options.key, params, store, id);
1398
+ try {
1399
+ const target2 = newest(store);
1400
+ const { transactors } = childStore.transactionMeta;
1401
+ const output = options.do(transactors, ...params);
1402
+ applyTransaction(output, target2);
1403
+ return output;
1404
+ } catch (thrown) {
1405
+ abortTransaction(target);
1406
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1407
+ throw thrown;
1408
+ }
1409
+ },
1410
+ install: (s) => createTransaction(options, s),
1411
+ subject: new Subject()
1412
+ };
1413
+ const target = newest(store);
1414
+ target.transactions.set(newTransaction.key, newTransaction);
1415
+ const token = deposit(newTransaction);
1416
+ store.on.transactionCreation.next(token);
1417
+ return token;
1418
+ }
1419
+
1420
+ // internal/src/transaction/get-epoch-number.ts
1421
+ function getContinuityKey(transactionKey, store) {
1422
+ const isRoot = isRootStore(store);
1423
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1424
+ return continuity;
1425
+ }
1426
+ function getEpochNumberOfContinuity(continuityKey, store) {
1427
+ const isRoot = isRootStore(store);
1428
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1429
+ return epoch;
1430
+ }
1431
+ function getEpochNumberOfAction(transactionKey, store) {
1432
+ const isRoot = isRootStore(store);
1433
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1434
+ const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1435
+ return epoch;
1436
+ }
1437
+
1438
+ // internal/src/transaction/index.ts
1439
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1440
+
1441
+ // internal/src/families/init-family-member.ts
1442
+ function initFamilyMember(token, key, store) {
1443
+ const familyKey = token.key;
1444
+ const family = store.families.get(familyKey);
1445
+ if (family === void 0) {
1446
+ throw new NotFoundError(token, store);
1447
+ }
1448
+ const state = family(key);
1449
+ const target = newest(store);
1450
+ if (state.family) {
1451
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1452
+ target.transactionMeta.update.updates.push({
1453
+ type: `state_creation`,
1454
+ token: state
1455
+ });
1456
+ } else {
1457
+ switch (state.type) {
1458
+ case `atom`:
1459
+ case `mutable_atom`:
1460
+ store.on.atomCreation.next(state);
1461
+ break;
1462
+ case `selector`:
1463
+ case `readonly_selector`:
1464
+ store.on.selectorCreation.next(state);
1465
+ break;
1466
+ }
1467
+ }
1468
+ }
1469
+ return state;
1470
+ }
1471
+ function seekInStore(token, key, store) {
1472
+ const subKey = json.stringifyJson(key);
1473
+ const fullKey = `${token.key}(${subKey})`;
1474
+ const target = newest(store);
1475
+ let state;
1476
+ switch (token.type) {
1477
+ case `atom_family`:
1478
+ case `mutable_atom_family`:
1479
+ state = target.atoms.get(fullKey);
1480
+ break;
1481
+ case `selector_family`:
1482
+ state = target.selectors.get(fullKey);
1483
+ break;
1484
+ case `readonly_selector_family`:
1485
+ state = target.readonlySelectors.get(fullKey);
1486
+ break;
1487
+ case `molecule_family`:
1488
+ state = target.molecules.get(json.stringifyJson(key));
1489
+ if (state) {
1490
+ return deposit(state);
1491
+ }
1492
+ }
1493
+ if (state) {
1494
+ return deposit(state);
1495
+ }
1496
+ return state;
1497
+ }
1498
+
1499
+ // internal/src/families/find-in-store.ts
1500
+ function findInStore(token, key, store) {
1501
+ if (store.config.lifespan === `immortal`) {
1502
+ throw new Error(
1503
+ `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
1504
+ );
1505
+ }
1506
+ let state = seekInStore(token, key, store);
1507
+ if (state) {
1508
+ return state;
1509
+ }
1510
+ state = initFamilyMember(token, key, store);
1511
+ return state;
1512
+ }
1513
+
1514
+ // internal/src/keys.ts
1515
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
1516
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1517
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1518
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1519
+
1520
+ // internal/src/selector/get-selector-dependency-keys.ts
1521
+ var getSelectorDependencyKeys = (key, store) => {
1522
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1523
+ return sources;
1524
+ };
1525
+
1526
+ // internal/src/selector/trace-selector-atoms.ts
1527
+ var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1528
+ const rootKeys = [];
1529
+ const indirectDependencyKeys = getSelectorDependencyKeys(
1530
+ directDependencyKey,
1531
+ store
1532
+ );
1533
+ let depth = 0;
1534
+ while (indirectDependencyKeys.length > 0) {
1535
+ const indirectDependencyKey = indirectDependencyKeys.shift();
1536
+ ++depth;
1537
+ if (depth > 99999) {
1538
+ throw new Error(
1539
+ `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1540
+ );
1541
+ }
1542
+ if (!isAtomKey(indirectDependencyKey, store)) {
1543
+ indirectDependencyKeys.push(
1544
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
1545
+ );
1546
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
1547
+ rootKeys.push(indirectDependencyKey);
1548
+ }
1549
+ }
1550
+ return rootKeys;
1551
+ };
1552
+ var traceAllSelectorAtoms = (selector, store) => {
1553
+ const selectorKey = selector.key;
1554
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1555
+ return directDependencyKeys.flatMap(
1556
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1557
+ );
1558
+ };
1559
+
1560
+ // internal/src/selector/update-selector-atoms.ts
1561
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1562
+ const target = newest(store);
1563
+ if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1564
+ target.selectorAtoms.set({
1565
+ selectorKey,
1566
+ atomKey: dependency.key
1567
+ });
1568
+ store.logger.info(
1569
+ `\u{1F50D}`,
1570
+ `selector`,
1571
+ selectorKey,
1572
+ `discovers root atom "${dependency.key}"`
1573
+ );
1574
+ } else {
1575
+ const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1576
+ store.logger.info(
1577
+ `\u{1F50D}`,
1578
+ `selector`,
1579
+ selectorKey,
1580
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1581
+ );
1582
+ for (const atomKey of rootKeys) {
1583
+ target.selectorAtoms = target.selectorAtoms.set({
1584
+ selectorKey,
1585
+ atomKey
1586
+ });
1587
+ }
1588
+ }
1589
+ };
1590
+
1591
+ // internal/src/selector/register-selector.ts
1592
+ var registerSelector = (selectorKey, store) => ({
1593
+ get: (dependency) => {
1594
+ const target = newest(store);
1595
+ const dependencyState = withdraw(dependency, store);
1596
+ const dependencyValue = readOrComputeValue(dependencyState, store);
1597
+ store.logger.info(
1598
+ `\u{1F50C}`,
1599
+ `selector`,
1600
+ selectorKey,
1601
+ `registers dependency ( "${dependency.key}" =`,
1602
+ dependencyValue,
1603
+ `)`
1604
+ );
1605
+ target.selectorGraph.set(
1606
+ {
1607
+ upstreamSelectorKey: dependency.key,
1608
+ downstreamSelectorKey: selectorKey
1609
+ },
1610
+ {
1611
+ source: dependency.key
1612
+ }
1613
+ );
1614
+ updateSelectorAtoms(selectorKey, dependency, store);
1615
+ return dependencyValue;
1616
+ },
1617
+ set: (WritableToken, newValue) => {
1618
+ const state = withdraw(WritableToken, store);
1619
+ setAtomOrSelector(state, newValue, store);
1620
+ },
1621
+ find: (token, key) => findInStore(token, key, store),
1622
+ seek: (token, key) => seekInStore(token, key, store),
1623
+ json: (token) => getJsonToken(token, store)
1624
+ });
1625
+
1626
+ // internal/src/selector/create-readonly-selector.ts
1627
+ var createReadonlySelector = (options, family, store) => {
1628
+ const target = newest(store);
1629
+ const subject = new Subject();
1630
+ const { get, find, seek, json } = registerSelector(options.key, target);
1631
+ const getSelf = () => {
1632
+ const value = options.get({ get, find, seek, json });
1633
+ cacheValue(options.key, value, subject, newest(store));
1634
+ return value;
1635
+ };
1636
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1637
+ subject,
1638
+ install: (s) => createReadonlySelector(options, family, s),
1639
+ get: getSelf,
1640
+ type: `readonly_selector`
1641
+ }), family && { family });
1642
+ target.readonlySelectors.set(options.key, readonlySelector);
1643
+ const initialValue = getSelf();
1644
+ store.logger.info(
1645
+ `\u2728`,
1646
+ readonlySelector.type,
1647
+ readonlySelector.key,
1648
+ `=`,
1649
+ initialValue
1650
+ );
1651
+ const token = {
1652
+ key: options.key,
1653
+ type: `readonly_selector`
1654
+ };
1655
+ if (family) {
1656
+ token.family = family;
1657
+ }
1658
+ return token;
1659
+ };
1148
1660
 
1149
1661
  // internal/src/selector/create-writable-selector.ts
1150
1662
  var createWritableSelector = (options, family, store) => {
1151
1663
  const target = newest(store);
1152
1664
  const subject = new Subject();
1153
1665
  const transactors = registerSelector(options.key, target);
1154
- const { find, get } = transactors;
1155
- const readonlyTransactors = { find, get };
1666
+ const { find, get, seek, json } = transactors;
1667
+ const readonlyTransactors = { find, get, seek, json };
1156
1668
  const getSelf = () => {
1157
1669
  const value = options.get(readonlyTransactors);
1158
1670
  cacheValue(options.key, value, subject, newest(store));
@@ -1195,7 +1707,6 @@ var createWritableSelector = (options, family, store) => {
1195
1707
  if (family) {
1196
1708
  token.family = family;
1197
1709
  }
1198
- store.on.selectorCreation.next(token);
1199
1710
  return token;
1200
1711
  };
1201
1712
 
@@ -1203,39 +1714,88 @@ var createWritableSelector = (options, family, store) => {
1203
1714
  function createStandaloneSelector(options, store) {
1204
1715
  const isWritable = `set` in options;
1205
1716
  if (isWritable) {
1206
- return createWritableSelector(options, void 0, store);
1717
+ const state2 = createWritableSelector(options, void 0, store);
1718
+ store.on.selectorCreation.next(state2);
1719
+ return state2;
1207
1720
  }
1208
- return createReadonlySelector(options, void 0, store);
1721
+ const state = createReadonlySelector(options, void 0, store);
1722
+ store.on.selectorCreation.next(state);
1723
+ return state;
1209
1724
  }
1210
1725
 
1211
1726
  // internal/src/selector/dispose-selector.ts
1212
- function disposeSelector(selectorToken, store) {
1727
+ function disposeSelector2(selectorToken, store) {
1728
+ var _a;
1213
1729
  const target = newest(store);
1214
1730
  const { key } = selectorToken;
1215
- switch (selectorToken.type) {
1216
- case `selector`:
1217
- target.selectors.delete(key);
1218
- break;
1219
- case `readonly_selector`:
1220
- target.readonlySelectors.delete(key);
1221
- break;
1222
- }
1223
- target.valueMap.delete(key);
1224
- target.selectorAtoms.delete(key);
1225
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1226
- ([downstreamSelectorKey]) => {
1227
- var _a;
1228
- return (_a = target.selectors.get(downstreamSelectorKey)) != null ? _a : target.readonlySelectors.get(downstreamSelectorKey);
1731
+ const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1732
+ if (!selector) {
1733
+ store.logger.info(
1734
+ `\u274C`,
1735
+ `selector`,
1736
+ key,
1737
+ `Tried to dispose selector, but it does not exist in the store.`
1738
+ );
1739
+ } else if (!selector.family) {
1740
+ store.logger.error(
1741
+ `\u274C`,
1742
+ `selector`,
1743
+ key,
1744
+ `Standalone selectors cannot be disposed.`
1745
+ );
1746
+ } else {
1747
+ switch (selectorToken.type) {
1748
+ case `selector`:
1749
+ {
1750
+ target.selectors.delete(key);
1751
+ const family = withdraw(
1752
+ { key: selector.family.key, type: `selector_family` },
1753
+ store
1754
+ );
1755
+ family.subject.next({
1756
+ type: `state_disposal`,
1757
+ token: selectorToken
1758
+ });
1759
+ }
1760
+ break;
1761
+ case `readonly_selector`:
1762
+ {
1763
+ target.readonlySelectors.delete(key);
1764
+ const family = withdraw(
1765
+ { key: selector.family.key, type: `readonly_selector_family` },
1766
+ store
1767
+ );
1768
+ family.subject.next({
1769
+ type: `state_disposal`,
1770
+ token: selectorToken
1771
+ });
1772
+ }
1773
+ break;
1229
1774
  }
1230
- );
1231
- for (const downstreamToken of downstreamTokens) {
1232
- if (downstreamToken) {
1233
- disposeSelector(downstreamToken, store);
1775
+ target.valueMap.delete(key);
1776
+ target.selectorAtoms.delete(key);
1777
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1778
+ ([downstreamSelectorKey]) => {
1779
+ var _a2;
1780
+ return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
1781
+ }
1782
+ );
1783
+ for (const downstreamToken of downstreamTokens) {
1784
+ if (downstreamToken) {
1785
+ disposeSelector2(downstreamToken, store);
1786
+ }
1787
+ }
1788
+ target.selectorGraph.delete(key);
1789
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1790
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1791
+ target.transactionMeta.update.updates.push({
1792
+ type: `state_disposal`,
1793
+ token: selectorToken
1794
+ });
1795
+ } else {
1796
+ store.on.selectorDisposal.next(selectorToken);
1234
1797
  }
1235
1798
  }
1236
- target.selectorGraph.delete(key);
1237
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1238
- store.on.selectorDisposal.next(selectorToken);
1239
1799
  }
1240
1800
 
1241
1801
  // internal/src/subscribe/recall-state.ts
@@ -1306,7 +1866,7 @@ function subscribeToState(token, handleUpdate, key, store) {
1306
1866
  handleUpdate(update);
1307
1867
  }
1308
1868
  }
1309
- const state = withdrawOrCreate(token, store);
1869
+ const state = withdraw(token, store);
1310
1870
  store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
1311
1871
  const isSelector = state.type === `selector` || state.type === `readonly_selector`;
1312
1872
  let dependencyUnsubFunctions = null;
@@ -1567,37 +2127,40 @@ function createMutableAtom(options, family, store) {
1567
2127
  };
1568
2128
  }
1569
2129
  new Tracker(token, store);
1570
- json.selectJson(token, options, store);
1571
- store.on.atomCreation.next(token);
2130
+ if (!family) {
2131
+ json.selectJson(token, options, store);
2132
+ }
1572
2133
  return token;
1573
2134
  }
1574
2135
  var FamilyTracker = class {
1575
- constructor(findMutableState, store) {
1576
- this.findLatestUpdateState = createRegularAtomFamily(
2136
+ constructor(mutableAtoms, store) {
2137
+ this.latestUpdateAtoms = createRegularAtomFamily(
1577
2138
  {
1578
- key: `*${findMutableState.key}`,
2139
+ key: `*${mutableAtoms.key}`,
1579
2140
  default: null
1580
2141
  },
1581
2142
  store
1582
2143
  );
1583
- this.findMutableState = findMutableState;
1584
- this.findMutableState.subject.subscribe(
2144
+ this.mutableAtoms = mutableAtoms;
2145
+ this.mutableAtoms.subject.subscribe(
1585
2146
  `store=${store.config.name}::tracker-atom-family`,
1586
- (atomToken) => {
1587
- if (atomToken.family) {
1588
- const key = json.parseJson(atomToken.family.subKey);
1589
- this.findLatestUpdateState(key);
1590
- new Tracker(atomToken, store);
2147
+ (event) => {
2148
+ if (event.token.family) {
2149
+ const key = json.parseJson(event.token.family.subKey);
2150
+ seekInStore(this.latestUpdateAtoms, key, store);
2151
+ new Tracker(event.token, store);
1591
2152
  }
1592
2153
  }
1593
2154
  );
1594
- this.findLatestUpdateState.subject.subscribe(
2155
+ this.latestUpdateAtoms.subject.subscribe(
1595
2156
  `store=${store.config.name}::tracker-atom-family`,
1596
- (atomToken) => {
1597
- if (atomToken.family) {
1598
- const key = json.parseJson(atomToken.family.subKey);
1599
- const mutableAtomToken = this.findMutableState(key);
1600
- new Tracker(mutableAtomToken, store);
2157
+ (event) => {
2158
+ if (event.token.family) {
2159
+ const key = json.parseJson(event.token.family.subKey);
2160
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
2161
+ if (mutableAtomToken) {
2162
+ new Tracker(mutableAtomToken, store);
2163
+ }
1601
2164
  }
1602
2165
  }
1603
2166
  );
@@ -1612,25 +2175,19 @@ function createMutableAtomFamily(options, store) {
1612
2175
  const subKey = json.stringifyJson(key);
1613
2176
  const family = { key: options.key, subKey };
1614
2177
  const fullKey = `${options.key}(${subKey})`;
1615
- const target2 = newest(store);
1616
- const atomAlreadyCreated = target2.atoms.has(fullKey);
1617
- let token;
1618
- if (atomAlreadyCreated) {
1619
- token = { type: `mutable_atom`, key: fullKey, family };
1620
- } else {
1621
- const individualOptions = {
1622
- key: fullKey,
1623
- default: () => options.default(key),
1624
- toJson: options.toJson,
1625
- fromJson: options.fromJson,
1626
- mutable: true
1627
- };
1628
- if (options.effects) {
1629
- individualOptions.effects = options.effects(key);
1630
- }
1631
- token = createMutableAtom(individualOptions, family, store);
1632
- subject.next(token);
2178
+ const target = newest(store);
2179
+ const individualOptions = {
2180
+ key: fullKey,
2181
+ default: () => options.default(key),
2182
+ toJson: options.toJson,
2183
+ fromJson: options.fromJson,
2184
+ mutable: true
2185
+ };
2186
+ if (options.effects) {
2187
+ individualOptions.effects = options.effects(key);
1633
2188
  }
2189
+ const token = createMutableAtom(individualOptions, family, target);
2190
+ subject.next({ type: `state_creation`, token });
1634
2191
  return token;
1635
2192
  },
1636
2193
  {
@@ -1642,8 +2199,7 @@ function createMutableAtomFamily(options, store) {
1642
2199
  fromJson: options.fromJson
1643
2200
  }
1644
2201
  );
1645
- const target = newest(store);
1646
- target.families.set(options.key, atomFamily);
2202
+ store.families.set(options.key, atomFamily);
1647
2203
  json.selectJsonFamily(atomFamily, options, store);
1648
2204
  new FamilyTracker(atomFamily, store);
1649
2205
  return atomFamily;
@@ -1658,19 +2214,24 @@ var getJsonFamily = (mutableAtomFamily, store) => {
1658
2214
  };
1659
2215
 
1660
2216
  // internal/src/mutable/get-json-token.ts
1661
- var getJsonToken = (mutableAtomToken) => {
1662
- const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1663
- const jsonToken = {
1664
- type: `selector`,
1665
- key
1666
- };
2217
+ var getJsonToken = (mutableAtomToken, store) => {
1667
2218
  if (mutableAtomToken.family) {
1668
- jsonToken.family = {
1669
- key: `${mutableAtomToken.family.key}:JSON`,
1670
- subKey: mutableAtomToken.family.subKey
2219
+ const target = newest(store);
2220
+ const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
2221
+ const jsonFamilyToken = {
2222
+ key: jsonFamilyKey,
2223
+ type: `selector_family`
1671
2224
  };
2225
+ const family = withdraw(jsonFamilyToken, target);
2226
+ const subKey = JSON.parse(mutableAtomToken.family.subKey);
2227
+ const jsonToken = findInStore(family, subKey, store);
2228
+ return jsonToken;
1672
2229
  }
1673
- return jsonToken;
2230
+ const token = {
2231
+ type: `selector`,
2232
+ key: `${mutableAtomToken.key}:JSON`
2233
+ };
2234
+ return token;
1674
2235
  };
1675
2236
 
1676
2237
  // internal/src/mutable/get-update-token.ts
@@ -1842,7 +2403,6 @@ function createRegularAtom(options, family, store) {
1842
2403
  }
1843
2404
  };
1844
2405
  }
1845
- store.on.atomCreation.next(token);
1846
2406
  return token;
1847
2407
  }
1848
2408
 
@@ -1850,13 +2410,17 @@ function createRegularAtom(options, family, store) {
1850
2410
  function createStandaloneAtom(options, store) {
1851
2411
  const isMutable2 = `mutable` in options;
1852
2412
  if (isMutable2) {
1853
- return createMutableAtom(options, void 0, store);
2413
+ const state2 = createMutableAtom(options, void 0, store);
2414
+ store.on.atomCreation.next(state2);
2415
+ return state2;
1854
2416
  }
1855
- return createRegularAtom(options, void 0, store);
2417
+ const state = createRegularAtom(options, void 0, store);
2418
+ store.on.atomCreation.next(state);
2419
+ return state;
1856
2420
  }
1857
2421
 
1858
2422
  // internal/src/atom/dispose-atom.ts
1859
- function disposeAtom(atomToken, store) {
2423
+ function disposeAtom2(atomToken, store) {
1860
2424
  var _a, _b;
1861
2425
  const target = newest(store);
1862
2426
  const { key } = atomToken;
@@ -1866,10 +2430,19 @@ function disposeAtom(atomToken, store) {
1866
2430
  `\u274C`,
1867
2431
  `atom`,
1868
2432
  key,
1869
- `Tried to delete atom, but it does not exist in the store.`
2433
+ `Tried to dispose atom, but it does not exist in the store.`
1870
2434
  );
2435
+ } else if (!atom.family) {
2436
+ store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1871
2437
  } else {
1872
2438
  (_a = atom.cleanup) == null ? void 0 : _a.call(atom);
2439
+ const lastValue = store.valueMap.get(atom.key);
2440
+ const family = withdraw({ key: atom.family.key, type: `atom_family` }, store);
2441
+ family.subject.next({
2442
+ type: `state_disposal`,
2443
+ token: atomToken,
2444
+ value: lastValue
2445
+ });
1873
2446
  target.atoms.delete(key);
1874
2447
  target.valueMap.delete(key);
1875
2448
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -1877,7 +2450,7 @@ function disposeAtom(atomToken, store) {
1877
2450
  for (const selectorKey of selectorKeys) {
1878
2451
  const token = (_b = target.selectors.get(selectorKey)) != null ? _b : target.readonlySelectors.get(selectorKey);
1879
2452
  if (token) {
1880
- disposeSelector(token, store);
2453
+ disposeSelector2(token, store);
1881
2454
  }
1882
2455
  }
1883
2456
  }
@@ -1886,93 +2459,21 @@ function disposeAtom(atomToken, store) {
1886
2459
  target.timelineAtoms.delete(key);
1887
2460
  if (atomToken.type === `mutable_atom`) {
1888
2461
  const updateToken = getUpdateToken(atomToken);
1889
- disposeAtom(updateToken, store);
2462
+ disposeAtom2(updateToken, store);
2463
+ store.trackers.delete(key);
1890
2464
  }
1891
2465
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1892
- store.on.atomDisposal.next(atomToken);
1893
- }
1894
- }
1895
-
1896
- // internal/src/get-environment-data.ts
1897
- function getEnvironmentData(store) {
1898
- return {
1899
- window: typeof window === `undefined` ? void 0 : window,
1900
- global: typeof global === `undefined` ? void 0 : global,
1901
- store
1902
- };
1903
- }
1904
-
1905
- // internal/src/get-state/get-from-store.ts
1906
- function getFromStore(token, store) {
1907
- const state = withdrawOrCreate(token, store);
1908
- return readOrComputeValue(state, store);
1909
- }
1910
-
1911
- // internal/src/ingest-updates/ingest-atom-update.ts
1912
- function ingestAtomUpdate(applying, atomUpdate, store) {
1913
- const { key, newValue, oldValue } = atomUpdate;
1914
- const value = applying === `newValue` ? newValue : oldValue;
1915
- const token = { key, type: `atom` };
1916
- if (atomUpdate.family) {
1917
- Object.assign(token, { family: atomUpdate.family });
1918
- }
1919
- setIntoStore(token, value, store);
1920
- }
1921
-
1922
- // internal/src/ingest-updates/ingest-selector-update.ts
1923
- function ingestSelectorUpdate(applying, selectorUpdate, store) {
1924
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1925
- for (const atomUpdate of updates) {
1926
- ingestAtomUpdate(applying, atomUpdate, store);
1927
- }
1928
- }
1929
-
1930
- // internal/src/ingest-updates/ingest-transaction-update.ts
1931
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1932
- const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1933
- for (const updateFromTransaction of updates) {
1934
- if (`newValue` in updateFromTransaction) {
1935
- ingestAtomUpdate(applying, updateFromTransaction, store);
2466
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
2467
+ target.transactionMeta.update.updates.push({
2468
+ type: `state_disposal`,
2469
+ token: atomToken
2470
+ });
1936
2471
  } else {
1937
- ingestTransactionUpdate(applying, updateFromTransaction, store);
2472
+ store.on.atomDisposal.next(atomToken);
1938
2473
  }
1939
2474
  }
1940
2475
  }
1941
2476
 
1942
- // internal/src/lazy-map.ts
1943
- var LazyMap = class extends Map {
1944
- constructor(source) {
1945
- super();
1946
- this.source = source;
1947
- this.deleted = /* @__PURE__ */ new Set();
1948
- }
1949
- get(key) {
1950
- const has = super.has(key);
1951
- if (has) {
1952
- return super.get(key);
1953
- }
1954
- if (!this.deleted.has(key) && this.source.has(key)) {
1955
- const value = this.source.get(key);
1956
- return value;
1957
- }
1958
- return void 0;
1959
- }
1960
- set(key, value) {
1961
- this.deleted.delete(key);
1962
- return super.set(key, value);
1963
- }
1964
- hasOwn(key) {
1965
- return super.has(key);
1966
- }
1967
- has(key) {
1968
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1969
- }
1970
- delete(key) {
1971
- this.deleted.add(key);
1972
- return super.delete(key);
1973
- }
1974
- };
1975
-
1976
2477
  // internal/src/timeline/add-atom-to-timeline.ts
1977
2478
  var addAtomToTimeline = (atomToken, tl, store) => {
1978
2479
  let maybeAtom = withdraw(atomToken, store);
@@ -1982,188 +2483,212 @@ var addAtomToTimeline = (atomToken, tl, store) => {
1982
2483
  }
1983
2484
  const atom = maybeAtom;
1984
2485
  store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
1985
- atom.subject.subscribe(`timeline`, (update) => {
1986
- var _a, _b, _c, _d, _e, _f;
1987
- const target = newest(store);
1988
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1989
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1990
- const { transactionApplying } = target.on;
1991
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
1992
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
1993
- store.logger.info(
1994
- `\u23F3`,
1995
- `timeline`,
1996
- tl.key,
1997
- `atom`,
1998
- atomToken.key,
1999
- `went`,
2000
- update.oldValue,
2001
- `->`,
2002
- update.newValue,
2003
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2004
- );
2005
- if (tl.timeTraveling === null) {
2006
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2007
- const mostRecentUpdate = tl.history.at(-1);
2008
- if (mostRecentUpdate === void 0) {
2009
- throw new Error(
2010
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
2011
- );
2012
- }
2013
- }
2014
- if (currentTransactionKey) {
2015
- const txToken = {
2016
- key: currentTransactionKey,
2017
- type: `transaction`
2018
- };
2019
- const currentTransaction = withdraw(txToken, store);
2020
- if (tl.transactionKey !== currentTransactionKey) {
2021
- if (tl.transactionKey) {
2022
- store.logger.error(
2023
- `\u{1F41E}`,
2024
- `timeline`,
2025
- tl.key,
2026
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2486
+ tl.subscriptions.set(
2487
+ atom.key,
2488
+ atom.subject.subscribe(`timeline`, (update) => {
2489
+ var _a, _b, _c, _d, _e, _f;
2490
+ const target = newest(store);
2491
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2492
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2493
+ const { transactionApplying } = target.on;
2494
+ const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
2495
+ const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
2496
+ store.logger.info(
2497
+ `\u23F3`,
2498
+ `timeline`,
2499
+ tl.key,
2500
+ `atom`,
2501
+ atomToken.key,
2502
+ `went`,
2503
+ update.oldValue,
2504
+ `->`,
2505
+ update.newValue,
2506
+ currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2507
+ );
2508
+ if (tl.timeTraveling === null) {
2509
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2510
+ const mostRecentUpdate = tl.history.at(-1);
2511
+ if (mostRecentUpdate === void 0) {
2512
+ throw new Error(
2513
+ `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
2027
2514
  );
2028
2515
  }
2029
- tl.transactionKey = currentTransactionKey;
2030
- const unsubscribe = currentTransaction.subject.subscribe(
2031
- `timeline:${tl.key}`,
2032
- (transactionUpdate) => {
2033
- var _a2, _b2;
2034
- unsubscribe();
2035
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
2036
- if (tl.at !== tl.history.length) {
2037
- tl.history.splice(tl.at);
2038
- }
2039
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2040
- const newestStore = newest(store);
2041
- if (`updates` in updateFromTx) {
2042
- return true;
2516
+ }
2517
+ if (currentTransactionKey) {
2518
+ const txToken = {
2519
+ key: currentTransactionKey,
2520
+ type: `transaction`
2521
+ };
2522
+ const currentTransaction = withdraw(txToken, store);
2523
+ if (tl.transactionKey !== currentTransactionKey) {
2524
+ if (tl.transactionKey) {
2525
+ store.logger.error(
2526
+ `\u{1F41E}`,
2527
+ `timeline`,
2528
+ tl.key,
2529
+ `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
2530
+ );
2531
+ }
2532
+ tl.transactionKey = currentTransactionKey;
2533
+ const unsubscribe = currentTransaction.subject.subscribe(
2534
+ `timeline:${tl.key}`,
2535
+ (transactionUpdate) => {
2536
+ var _a2, _b2;
2537
+ unsubscribe();
2538
+ if (tl.timeTraveling === null && currentTransactionInstanceId) {
2539
+ if (tl.at !== tl.history.length) {
2540
+ tl.history.splice(tl.at);
2043
2541
  }
2044
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2045
- return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
2046
- (key) => {
2047
- var _a3;
2048
- return key === updateFromTx.key || key === ((_a3 = updateFromTx.family) == null ? void 0 : _a3.key);
2542
+ const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2543
+ var _a3, _b3;
2544
+ const newestStore = newest(store);
2545
+ if (`updates` in updateFromTx) {
2546
+ return true;
2547
+ }
2548
+ const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2549
+ if (!atomOrFamilyKeys) {
2550
+ return false;
2551
+ }
2552
+ let key;
2553
+ let familyKey;
2554
+ switch (updateFromTx.type) {
2555
+ case `state_creation`:
2556
+ case `state_disposal`:
2557
+ key = updateFromTx.token.key;
2558
+ familyKey = (_a3 = updateFromTx.token.family) == null ? void 0 : _a3.key;
2559
+ break;
2560
+ case `molecule_creation`:
2561
+ case `molecule_disposal`:
2562
+ break;
2563
+ default:
2564
+ key = updateFromTx.key;
2565
+ familyKey = (_b3 = updateFromTx.family) == null ? void 0 : _b3.key;
2566
+ break;
2567
+ }
2568
+ if (key === void 0) {
2569
+ return false;
2570
+ }
2571
+ if (atomOrFamilyKeys.has(key)) {
2572
+ return true;
2049
2573
  }
2050
- ) : false;
2051
- }).map((updateFromTx) => {
2052
- if (`updates` in updateFromTx) {
2053
- return __spreadProps(__spreadValues({}, updateFromTx), {
2054
- updates: filterUpdates(updateFromTx.updates)
2055
- });
2574
+ if (familyKey !== void 0) {
2575
+ return atomOrFamilyKeys.has(familyKey);
2576
+ }
2577
+ return false;
2578
+ }).map((updateFromTx) => {
2579
+ if (`updates` in updateFromTx) {
2580
+ return __spreadProps(__spreadValues({}, updateFromTx), {
2581
+ updates: filterUpdates(updateFromTx.updates)
2582
+ });
2583
+ }
2584
+ return updateFromTx;
2585
+ });
2586
+ const updates = filterUpdates(transactionUpdate.updates);
2587
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
2588
+ timestamp: Date.now()
2589
+ }, transactionUpdate), {
2590
+ updates
2591
+ });
2592
+ const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2593
+ if (willCapture) {
2594
+ tl.history.push(timelineTransactionUpdate);
2595
+ tl.at = tl.history.length;
2596
+ tl.subject.next(timelineTransactionUpdate);
2056
2597
  }
2057
- return updateFromTx;
2058
- });
2059
- const updates = filterUpdates(transactionUpdate.updates);
2060
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
2061
- type: `transaction_update`,
2062
- timestamp: Date.now()
2063
- }, transactionUpdate), {
2064
- updates
2065
- });
2066
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2067
- if (willCapture) {
2068
- tl.history.push(timelineTransactionUpdate);
2069
- tl.at = tl.history.length;
2070
- tl.subject.next(timelineTransactionUpdate);
2071
2598
  }
2599
+ tl.transactionKey = null;
2600
+ store.logger.info(
2601
+ `\u231B`,
2602
+ `timeline`,
2603
+ tl.key,
2604
+ `got a transaction_update "${transactionUpdate.key}"`
2605
+ );
2072
2606
  }
2073
- tl.transactionKey = null;
2607
+ );
2608
+ }
2609
+ } else if (currentSelectorKey && currentSelectorTime) {
2610
+ let latestUpdate = tl.history.at(-1);
2611
+ if (currentSelectorTime !== tl.selectorTime) {
2612
+ latestUpdate = {
2613
+ type: `selector_update`,
2614
+ timestamp: currentSelectorTime,
2615
+ key: currentSelectorKey,
2616
+ atomUpdates: []
2617
+ };
2618
+ latestUpdate.atomUpdates.push(__spreadValues({
2619
+ key: atom.key,
2620
+ type: `atom_update`
2621
+ }, update));
2622
+ if (tl.at !== tl.history.length) {
2623
+ tl.history.splice(tl.at);
2624
+ }
2625
+ tl.history.push(latestUpdate);
2626
+ store.logger.info(
2627
+ `\u231B`,
2628
+ `timeline`,
2629
+ tl.key,
2630
+ `got a selector_update "${currentSelectorKey}" with`,
2631
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2632
+ );
2633
+ tl.at = tl.history.length;
2634
+ tl.selectorTime = currentSelectorTime;
2635
+ } else {
2636
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
2637
+ latestUpdate.atomUpdates.push(__spreadValues({
2638
+ key: atom.key,
2639
+ type: `atom_update`
2640
+ }, update));
2074
2641
  store.logger.info(
2075
2642
  `\u231B`,
2076
2643
  `timeline`,
2077
2644
  tl.key,
2078
- `got a transaction_update "${transactionUpdate.key}"`
2645
+ `set selector_update "${currentSelectorKey}" to`,
2646
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2079
2647
  );
2080
2648
  }
2081
- );
2082
- }
2083
- } else if (currentSelectorKey && currentSelectorTime) {
2084
- let latestUpdate = tl.history.at(-1);
2085
- if (currentSelectorTime !== tl.selectorTime) {
2086
- latestUpdate = {
2087
- type: `selector_update`,
2088
- timestamp: currentSelectorTime,
2089
- key: currentSelectorKey,
2090
- atomUpdates: []
2091
- };
2092
- latestUpdate.atomUpdates.push(__spreadValues({
2093
- key: atom.key,
2094
- type: `atom_update`
2095
- }, update));
2649
+ }
2650
+ if (latestUpdate) {
2651
+ const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2652
+ if (willCaptureSelectorUpdate) {
2653
+ tl.subject.next(latestUpdate);
2654
+ } else {
2655
+ tl.history.pop();
2656
+ tl.at = tl.history.length;
2657
+ }
2658
+ }
2659
+ } else {
2660
+ const timestamp = Date.now();
2661
+ tl.selectorTime = null;
2096
2662
  if (tl.at !== tl.history.length) {
2097
2663
  tl.history.splice(tl.at);
2098
2664
  }
2099
- tl.history.push(latestUpdate);
2665
+ const atomUpdate = {
2666
+ type: `atom_update`,
2667
+ timestamp,
2668
+ key: atom.key,
2669
+ oldValue: update.oldValue,
2670
+ newValue: update.newValue
2671
+ };
2672
+ if (atom.family) {
2673
+ atomUpdate.family = atom.family;
2674
+ }
2675
+ const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
2100
2676
  store.logger.info(
2101
2677
  `\u231B`,
2102
2678
  `timeline`,
2103
2679
  tl.key,
2104
- `got a selector_update "${currentSelectorKey}" with`,
2105
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2680
+ `got an atom_update to "${atom.key}"`
2106
2681
  );
2107
- tl.at = tl.history.length;
2108
- tl.selectorTime = currentSelectorTime;
2109
- } else {
2110
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
2111
- latestUpdate.atomUpdates.push(__spreadValues({
2112
- key: atom.key,
2113
- type: `atom_update`
2114
- }, update));
2115
- store.logger.info(
2116
- `\u231B`,
2117
- `timeline`,
2118
- tl.key,
2119
- `set selector_update "${currentSelectorKey}" to`,
2120
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2121
- );
2122
- }
2123
- }
2124
- if (latestUpdate) {
2125
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2126
- if (willCaptureSelectorUpdate) {
2127
- tl.subject.next(latestUpdate);
2128
- } else {
2129
- tl.history.pop();
2682
+ if (willCapture) {
2683
+ tl.history.push(atomUpdate);
2130
2684
  tl.at = tl.history.length;
2685
+ tl.subject.next(atomUpdate);
2131
2686
  }
2132
2687
  }
2133
- } else {
2134
- const timestamp = Date.now();
2135
- tl.selectorTime = null;
2136
- if (tl.at !== tl.history.length) {
2137
- tl.history.splice(tl.at);
2138
- }
2139
- const atomUpdate = {
2140
- type: `atom_update`,
2141
- timestamp,
2142
- key: atom.key,
2143
- oldValue: update.oldValue,
2144
- newValue: update.newValue
2145
- };
2146
- if (atom.family) {
2147
- atomUpdate.family = atom.family;
2148
- }
2149
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
2150
- store.logger.info(
2151
- `\u231B`,
2152
- `timeline`,
2153
- tl.key,
2154
- `got an atom_update to "${atom.key}"`
2155
- );
2156
- if (willCapture) {
2157
- tl.history.push(atomUpdate);
2158
- tl.at = tl.history.length;
2159
- tl.subject.next(atomUpdate);
2160
- }
2161
2688
  }
2162
- }
2163
- });
2689
+ })
2690
+ );
2164
2691
  };
2165
-
2166
- // internal/src/timeline/create-timeline.ts
2167
2692
  function createTimeline(options, store, data) {
2168
2693
  var _a, _b;
2169
2694
  const tl = __spreadProps(__spreadValues({
@@ -2176,60 +2701,141 @@ function createTimeline(options, store, data) {
2176
2701
  }, data), {
2177
2702
  history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2178
2703
  install: (s) => createTimeline(options, s, tl),
2179
- subject: new Subject()
2704
+ subject: new Subject(),
2705
+ subscriptions: /* @__PURE__ */ new Map()
2180
2706
  });
2181
2707
  if (options.shouldCapture) {
2182
2708
  tl.shouldCapture = options.shouldCapture;
2183
2709
  }
2184
2710
  const timelineKey = options.key;
2185
2711
  const target = newest(store);
2186
- for (const tokenOrFamily of options.atoms) {
2712
+ for (const tokenOrFamily of options.scope) {
2187
2713
  let atomKey = tokenOrFamily.key;
2188
- if (tokenOrFamily.type === `atom_family` || tokenOrFamily.type === `mutable_atom_family`) {
2189
- const familyToken = tokenOrFamily;
2190
- const family = withdraw(familyToken, store);
2191
- const familyKey = family.key;
2192
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2193
- family.subject.subscribe(`timeline:${options.key}`, (token2) => {
2194
- addAtomToTimeline(token2, tl, store);
2195
- });
2196
- for (const atom of target.atoms.values()) {
2197
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2714
+ switch (tokenOrFamily.type) {
2715
+ case `atom_family`:
2716
+ case `mutable_atom_family`:
2717
+ {
2718
+ const familyToken = tokenOrFamily;
2719
+ const family = withdraw(familyToken, store);
2720
+ const familyKey = family.key;
2721
+ target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2722
+ tl.subscriptions.set(
2723
+ family.key,
2724
+ family.subject.subscribe(
2725
+ `timeline:${options.key}`,
2726
+ (creationOrDisposal) => {
2727
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
2728
+ }
2729
+ )
2730
+ );
2731
+ for (const atom of target.atoms.values()) {
2732
+ if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2733
+ addAtomToTimeline(atom, tl, store);
2734
+ }
2735
+ }
2736
+ }
2737
+ break;
2738
+ case `atom`:
2739
+ case `mutable_atom`:
2740
+ {
2741
+ let atom = withdraw(tokenOrFamily, store);
2742
+ if (isMutable(atom)) {
2743
+ const updateAtom = withdraw(getUpdateToken(atom), store);
2744
+ atom = updateAtom;
2745
+ atomKey = atom.key;
2746
+ }
2747
+ if (`family` in atom) {
2748
+ const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2749
+ atom.family.key
2750
+ );
2751
+ if (familyTimelineKey) {
2752
+ store.logger.error(
2753
+ `\u274C`,
2754
+ `timeline`,
2755
+ options.key,
2756
+ `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
2757
+ );
2758
+ continue;
2759
+ }
2760
+ }
2761
+ const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2762
+ if (existingTimelineKey) {
2763
+ store.logger.error(
2764
+ `\u274C`,
2765
+ `timeline`,
2766
+ options.key,
2767
+ `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2768
+ );
2769
+ continue;
2770
+ }
2198
2771
  addAtomToTimeline(atom, tl, store);
2199
2772
  }
2200
- }
2201
- } else {
2202
- let atom = withdraw(tokenOrFamily, store);
2203
- if (isMutable(atom)) {
2204
- const updateAtom = withdraw(getUpdateToken(atom), store);
2205
- atom = updateAtom;
2206
- atomKey = atom.key;
2207
- }
2208
- if (`family` in atom) {
2209
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2210
- atom.family.key
2211
- );
2212
- if (familyTimelineKey) {
2213
- store.logger.error(
2214
- `\u274C`,
2215
- `timeline`,
2216
- options.key,
2217
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
2218
- );
2219
- continue;
2773
+ break;
2774
+ case `molecule_family`:
2775
+ {
2776
+ const family = store.moleculeFamilies.get(tokenOrFamily.key);
2777
+ if (family) {
2778
+ tl.subscriptions.set(
2779
+ tokenOrFamily.key,
2780
+ family.subject.subscribe(
2781
+ `timeline:${options.key}`,
2782
+ (creationOrDisposal) => {
2783
+ var _a2, _b2;
2784
+ switch (creationOrDisposal.type) {
2785
+ case `molecule_creation`:
2786
+ {
2787
+ const molecule = store.molecules.get(
2788
+ json.stringifyJson(creationOrDisposal.token.key)
2789
+ );
2790
+ if (molecule) {
2791
+ const event = Object.assign(creationOrDisposal, {
2792
+ timestamp: Date.now()
2793
+ });
2794
+ tl.history.push(event);
2795
+ tl.at = tl.history.length;
2796
+ tl.subject.next(event);
2797
+ for (const token2 of molecule.tokens) {
2798
+ switch (token2.type) {
2799
+ case `atom`:
2800
+ case `mutable_atom`:
2801
+ addAtomToTimeline(token2, tl, store);
2802
+ break;
2803
+ }
2804
+ }
2805
+ tl.subscriptions.set(
2806
+ molecule.key,
2807
+ molecule.subject.subscribe(
2808
+ `timeline:${options.key}`,
2809
+ (stateCreationOrDisposal) => {
2810
+ handleStateLifecycleEvent(
2811
+ stateCreationOrDisposal,
2812
+ tl,
2813
+ store
2814
+ );
2815
+ }
2816
+ )
2817
+ );
2818
+ }
2819
+ }
2820
+ break;
2821
+ case `molecule_disposal`:
2822
+ (_a2 = tl.subscriptions.get(creationOrDisposal.token.key)) == null ? void 0 : _a2();
2823
+ tl.subscriptions.delete(creationOrDisposal.token.key);
2824
+ for (const familyKey of creationOrDisposal.familyKeys) {
2825
+ const stateKey = `${familyKey}(${json.stringifyJson(
2826
+ creationOrDisposal.token.key
2827
+ )})`;
2828
+ (_b2 = tl.subscriptions.get(stateKey)) == null ? void 0 : _b2();
2829
+ tl.subscriptions.delete(stateKey);
2830
+ }
2831
+ break;
2832
+ }
2833
+ }
2834
+ )
2835
+ );
2836
+ }
2220
2837
  }
2221
- }
2222
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2223
- if (existingTimelineKey) {
2224
- store.logger.error(
2225
- `\u274C`,
2226
- `timeline`,
2227
- options.key,
2228
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2229
- );
2230
- continue;
2231
- }
2232
- addAtomToTimeline(atom, tl, store);
2838
+ break;
2233
2839
  }
2234
2840
  }
2235
2841
  store.timelines.set(options.key, tl);
@@ -2240,6 +2846,27 @@ function createTimeline(options, store, data) {
2240
2846
  store.on.timelineCreation.next(token);
2241
2847
  return token;
2242
2848
  }
2849
+ function handleStateLifecycleEvent(event, tl, store) {
2850
+ var _a;
2851
+ const timestamp = Date.now();
2852
+ const timelineEvent = Object.assign(event, {
2853
+ timestamp
2854
+ });
2855
+ if (!tl.timeTraveling) {
2856
+ tl.history.push(timelineEvent);
2857
+ tl.at = tl.history.length;
2858
+ tl.subject.next(timelineEvent);
2859
+ }
2860
+ switch (event.type) {
2861
+ case `state_creation`:
2862
+ addAtomToTimeline(event.token, tl, store);
2863
+ break;
2864
+ case `state_disposal`:
2865
+ (_a = tl.subscriptions.get(event.token.key)) == null ? void 0 : _a();
2866
+ tl.subscriptions.delete(event.token.key);
2867
+ break;
2868
+ }
2869
+ }
2243
2870
 
2244
2871
  // internal/src/timeline/time-travel.ts
2245
2872
  var timeTravel = (action, token, store) => {
@@ -2287,6 +2914,22 @@ var timeTravel = (action, token, store) => {
2287
2914
  ingestTransactionUpdate(applying, update, store);
2288
2915
  break;
2289
2916
  }
2917
+ case `state_creation`: {
2918
+ ingestCreationEvent(update, applying, store);
2919
+ break;
2920
+ }
2921
+ case `state_disposal`: {
2922
+ ingestDisposalEvent(update, applying, store);
2923
+ break;
2924
+ }
2925
+ case `molecule_creation`: {
2926
+ ingestMoleculeCreationEvent(update, applying, store);
2927
+ break;
2928
+ }
2929
+ case `molecule_disposal`: {
2930
+ ingestMoleculeDisposalEvent(update, applying, store);
2931
+ break;
2932
+ }
2290
2933
  }
2291
2934
  if (action === `redo`) {
2292
2935
  ++timelineData.at;
@@ -2301,250 +2944,6 @@ var timeTravel = (action, token, store) => {
2301
2944
  );
2302
2945
  };
2303
2946
 
2304
- // internal/src/transaction/abort-transaction.ts
2305
- var abortTransaction = (store) => {
2306
- const target = newest(store);
2307
- if (!isChildStore(target)) {
2308
- store.logger.warn(
2309
- `\u{1F41E}`,
2310
- `transaction`,
2311
- `???`,
2312
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2313
- );
2314
- return;
2315
- }
2316
- store.logger.info(
2317
- `\u{1FA82}`,
2318
- `transaction`,
2319
- target.transactionMeta.update.key,
2320
- `Aborting transaction`
2321
- );
2322
- target.parent.child = null;
2323
- };
2324
-
2325
- // internal/src/transaction/act-upon-store.ts
2326
- function actUponStore(token, id, store) {
2327
- return (...parameters) => {
2328
- const tx = withdraw(token, store);
2329
- if (tx) {
2330
- return tx.run(parameters, id);
2331
- }
2332
- throw new NotFoundError(token, store);
2333
- };
2334
- }
2335
-
2336
- // internal/src/transaction/set-epoch-number.ts
2337
- function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
2338
- const isRoot = isRootStore(store);
2339
- if (isRoot && continuityKey) {
2340
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2341
- }
2342
- }
2343
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
2344
- const isRoot = isRootStore(store);
2345
- if (!isRoot) {
2346
- return;
2347
- }
2348
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
2349
- if (continuityKey !== void 0) {
2350
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2351
- }
2352
- }
2353
-
2354
- // internal/src/transaction/apply-transaction.ts
2355
- var applyTransaction = (output, store) => {
2356
- var _a;
2357
- const child = newest(store);
2358
- const { parent } = child;
2359
- if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
2360
- store.logger.warn(
2361
- `\u{1F41E}`,
2362
- `transaction`,
2363
- `???`,
2364
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2365
- );
2366
- return;
2367
- }
2368
- child.transactionMeta.phase = `applying`;
2369
- child.transactionMeta.update.output = output;
2370
- parent.child = null;
2371
- parent.on.transactionApplying.next(child.transactionMeta);
2372
- const { updates } = child.transactionMeta.update;
2373
- store.logger.info(
2374
- `\u{1F6C4}`,
2375
- `transaction`,
2376
- child.transactionMeta.update.key,
2377
- `Applying transaction with ${updates.length} updates:`,
2378
- updates
2379
- );
2380
- for (const tracker of child.trackers.values()) {
2381
- const mutableKey = tracker.mutableState.key;
2382
- if (!parent.atoms.has(mutableKey)) {
2383
- const atom = child.atoms.get(mutableKey);
2384
- atom == null ? void 0 : atom.install(parent);
2385
- }
2386
- tracker.dispose();
2387
- }
2388
- for (const atom of child.atoms.values()) {
2389
- if (!parent.atoms.has(atom.key)) {
2390
- parent.atoms.set(atom.key, atom);
2391
- parent.valueMap.set(atom.key, atom.default);
2392
- parent.logger.info(
2393
- `\u{1F528}`,
2394
- `transaction`,
2395
- child.transactionMeta.update.key,
2396
- `Adding atom "${atom.key}"`
2397
- );
2398
- }
2399
- }
2400
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
2401
- if (isRootStore(parent)) {
2402
- setEpochNumberOfAction(
2403
- child.transactionMeta.update.key,
2404
- child.transactionMeta.update.epoch,
2405
- parent
2406
- );
2407
- const myTransaction = withdraw(
2408
- { key: child.transactionMeta.update.key, type: `transaction` },
2409
- store
2410
- );
2411
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
2412
- store.logger.info(
2413
- `\u{1F6EC}`,
2414
- `transaction`,
2415
- child.transactionMeta.update.key,
2416
- `Finished applying transaction.`
2417
- );
2418
- } else if (isChildStore(parent)) {
2419
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
2420
- }
2421
- parent.on.transactionApplying.next(null);
2422
- };
2423
-
2424
- // internal/src/transaction/assign-transaction-to-continuity.ts
2425
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2426
- const isRoot = isRootStore(store);
2427
- if (!isRoot) {
2428
- return;
2429
- }
2430
- const { epoch, actionContinuities } = store.transactionMeta;
2431
- actionContinuities.set(continuityKey, transactionKey);
2432
- if (!epoch.has(continuityKey)) {
2433
- epoch.set(continuityKey, -1);
2434
- }
2435
- }
2436
-
2437
- // internal/src/transaction/build-transaction.ts
2438
- var buildTransaction = (key, params, store, id) => {
2439
- const parent = newest(store);
2440
- const childBase = {
2441
- parent,
2442
- child: null,
2443
- on: parent.on,
2444
- loggers: parent.loggers,
2445
- logger: parent.logger,
2446
- config: parent.config,
2447
- atoms: new LazyMap(parent.atoms),
2448
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2449
- families: new LazyMap(parent.families),
2450
- operation: { open: false },
2451
- readonlySelectors: new LazyMap(parent.readonlySelectors),
2452
- timelines: new LazyMap(parent.timelines),
2453
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
2454
- trackers: /* @__PURE__ */ new Map(),
2455
- transactions: new LazyMap(parent.transactions),
2456
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
2457
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
2458
- makeContentKey: (...keys) => keys.sort().join(`:`)
2459
- }),
2460
- selectors: new LazyMap(parent.selectors),
2461
- valueMap: new LazyMap(parent.valueMap)
2462
- };
2463
- const epoch = getEpochNumberOfAction(key, store);
2464
- const transactionMeta = {
2465
- phase: `building`,
2466
- update: {
2467
- key,
2468
- id,
2469
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
2470
- updates: [],
2471
- params,
2472
- output: void 0
2473
- },
2474
- transactors: {
2475
- get: (token) => getFromStore(token, child),
2476
- set: (token, value) => {
2477
- setIntoStore(token, value, child);
2478
- },
2479
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2480
- find: (token, k) => findInStore(token, k, child),
2481
- env: () => getEnvironmentData(child)
2482
- }
2483
- };
2484
- const child = Object.assign(childBase, {
2485
- transactionMeta
2486
- });
2487
- parent.child = child;
2488
- store.logger.info(
2489
- `\u{1F6EB}`,
2490
- `transaction`,
2491
- key,
2492
- `Building transaction with params:`,
2493
- params
2494
- );
2495
- return child;
2496
- };
2497
-
2498
- // internal/src/transaction/create-transaction.ts
2499
- function createTransaction(options, store) {
2500
- const newTransaction = {
2501
- key: options.key,
2502
- type: `transaction`,
2503
- run: (params, id) => {
2504
- const childStore = buildTransaction(options.key, params, store, id);
2505
- try {
2506
- const target2 = newest(store);
2507
- const { transactors } = childStore.transactionMeta;
2508
- const output = options.do(transactors, ...params);
2509
- applyTransaction(output, target2);
2510
- return output;
2511
- } catch (thrown) {
2512
- abortTransaction(target);
2513
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
2514
- throw thrown;
2515
- }
2516
- },
2517
- install: (s) => createTransaction(options, s),
2518
- subject: new Subject()
2519
- };
2520
- const target = newest(store);
2521
- target.transactions.set(newTransaction.key, newTransaction);
2522
- const token = deposit(newTransaction);
2523
- store.on.transactionCreation.next(token);
2524
- return token;
2525
- }
2526
-
2527
- // internal/src/transaction/get-epoch-number.ts
2528
- function getContinuityKey(transactionKey, store) {
2529
- const isRoot = isRootStore(store);
2530
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2531
- return continuity;
2532
- }
2533
- function getEpochNumberOfContinuity(continuityKey, store) {
2534
- const isRoot = isRootStore(store);
2535
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
2536
- return epoch;
2537
- }
2538
- function getEpochNumberOfAction(transactionKey, store) {
2539
- const isRoot = isRootStore(store);
2540
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2541
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
2542
- return epoch;
2543
- }
2544
-
2545
- // internal/src/transaction/index.ts
2546
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2547
-
2548
2947
  exports.FamilyTracker = FamilyTracker;
2549
2948
  exports.Future = Future;
2550
2949
  exports.IMPLICIT = IMPLICIT;
@@ -2580,8 +2979,9 @@ exports.createTimeline = createTimeline;
2580
2979
  exports.createTransaction = createTransaction;
2581
2980
  exports.createWritableSelector = createWritableSelector;
2582
2981
  exports.deposit = deposit;
2583
- exports.disposeAtom = disposeAtom;
2584
- exports.disposeSelector = disposeSelector;
2982
+ exports.disposeAtom = disposeAtom2;
2983
+ exports.disposeFromStore = disposeFromStore;
2984
+ exports.disposeSelector = disposeSelector2;
2585
2985
  exports.evictCachedValue = evictCachedValue;
2586
2986
  exports.findInStore = findInStore;
2587
2987
  exports.getContinuityKey = getContinuityKey;
@@ -2594,8 +2994,13 @@ exports.getJsonToken = getJsonToken;
2594
2994
  exports.getSelectorDependencyKeys = getSelectorDependencyKeys;
2595
2995
  exports.getUpdateToken = getUpdateToken;
2596
2996
  exports.ingestAtomUpdate = ingestAtomUpdate;
2997
+ exports.ingestCreationEvent = ingestCreationEvent;
2998
+ exports.ingestDisposalEvent = ingestDisposalEvent;
2999
+ exports.ingestMoleculeCreationEvent = ingestMoleculeCreationEvent;
3000
+ exports.ingestMoleculeDisposalEvent = ingestMoleculeDisposalEvent;
2597
3001
  exports.ingestSelectorUpdate = ingestSelectorUpdate;
2598
3002
  exports.ingestTransactionUpdate = ingestTransactionUpdate;
3003
+ exports.initFamilyMember = initFamilyMember;
2599
3004
  exports.isAtomDefault = isAtomDefault;
2600
3005
  exports.isAtomKey = isAtomKey;
2601
3006
  exports.isChildStore = isChildStore;
@@ -2614,6 +3019,7 @@ exports.openOperation = openOperation;
2614
3019
  exports.readCachedValue = readCachedValue;
2615
3020
  exports.readOrComputeValue = readOrComputeValue;
2616
3021
  exports.registerSelector = registerSelector;
3022
+ exports.seekInStore = seekInStore;
2617
3023
  exports.setAtomOrSelector = setAtomOrSelector;
2618
3024
  exports.setEpochNumberOfAction = setEpochNumberOfAction;
2619
3025
  exports.setEpochNumberOfContinuity = setEpochNumberOfContinuity;
@@ -2627,4 +3033,3 @@ exports.traceAllSelectorAtoms = traceAllSelectorAtoms;
2627
3033
  exports.traceSelectorAtoms = traceSelectorAtoms;
2628
3034
  exports.updateSelectorAtoms = updateSelectorAtoms;
2629
3035
  exports.withdraw = withdraw;
2630
- exports.withdrawOrCreate = withdrawOrCreate;