atom.io 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/data/dist/index.cjs +17 -1
  2. package/data/dist/index.js +1 -1
  3. package/data/src/join.ts +30 -1
  4. package/dist/chunk-6MLFYN32.js +18 -0
  5. package/dist/{chunk-JA4V7TJY.js → chunk-7DT3PVS3.js} +18 -2
  6. package/dist/chunk-OAYGID5B.js +27 -0
  7. package/dist/index.cjs +2 -11
  8. package/dist/index.d.ts +51 -23
  9. package/dist/index.js +2 -11
  10. package/ephemeral/dist/index.d.ts +12 -0
  11. package/eslint-plugin/dist/index.cjs +0 -1
  12. package/eslint-plugin/dist/index.d.ts +73 -0
  13. package/eslint-plugin/dist/index.js +0 -1
  14. package/eslint-plugin/src/rules/lifespan.ts +0 -1
  15. package/immortal/dist/index.cjs +180 -20
  16. package/immortal/dist/index.d.ts +103 -0
  17. package/immortal/dist/index.js +134 -19
  18. package/immortal/src/index.ts +1 -0
  19. package/immortal/src/make-molecule.ts +222 -0
  20. package/immortal/src/molecule.ts +49 -16
  21. package/immortal/src/seek-state.ts +15 -2
  22. package/internal/dist/index.cjs +1119 -754
  23. package/internal/dist/index.d.ts +109 -12
  24. package/internal/dist/index.js +1098 -760
  25. package/internal/src/atom/create-regular-atom.ts +0 -2
  26. package/internal/src/atom/create-standalone-atom.ts +6 -2
  27. package/internal/src/atom/dispose-atom.ts +22 -2
  28. package/internal/src/families/create-readonly-selector-family.ts +7 -2
  29. package/internal/src/families/create-regular-atom-family.ts +6 -2
  30. package/internal/src/families/create-writable-selector-family.ts +7 -2
  31. package/internal/src/families/dispose-from-store.ts +22 -0
  32. package/internal/src/families/find-in-store.ts +0 -1
  33. package/internal/src/families/index.ts +1 -0
  34. package/internal/src/families/init-family-member.ts +22 -1
  35. package/internal/src/families/seek-in-store.ts +23 -6
  36. package/internal/src/ingest-updates/index.ts +1 -0
  37. package/internal/src/ingest-updates/ingest-creation-disposal.ts +104 -0
  38. package/internal/src/ingest-updates/ingest-transaction-update.ts +26 -4
  39. package/internal/src/mutable/create-mutable-atom-family.ts +6 -2
  40. package/internal/src/mutable/create-mutable-atom.ts +0 -2
  41. package/internal/src/mutable/get-json-token.ts +0 -1
  42. package/internal/src/mutable/tracker-family.ts +7 -7
  43. package/internal/src/not-found-error.ts +5 -0
  44. package/internal/src/selector/create-readonly-selector.ts +2 -3
  45. package/internal/src/selector/create-standalone-selector.ts +6 -2
  46. package/internal/src/selector/create-writable-selector.ts +2 -3
  47. package/internal/src/selector/dispose-selector.ts +32 -5
  48. package/internal/src/selector/register-selector.ts +2 -0
  49. package/internal/src/set-state/stow-update.ts +5 -1
  50. package/internal/src/store/deposit.ts +41 -7
  51. package/internal/src/store/store.ts +11 -0
  52. package/internal/src/store/withdraw.ts +28 -1
  53. package/internal/src/timeline/add-atom-to-timeline.ts +206 -182
  54. package/internal/src/timeline/create-timeline.ts +181 -60
  55. package/internal/src/timeline/time-travel.ts +20 -0
  56. package/internal/src/transaction/apply-transaction.ts +2 -12
  57. package/internal/src/transaction/build-transaction.ts +11 -2
  58. package/introspection/dist/index.cjs +2 -1
  59. package/introspection/dist/index.js +2 -1
  60. package/introspection/src/attach-timeline-family.ts +1 -0
  61. package/json/dist/index.cjs +3 -3
  62. package/json/dist/index.js +6 -5
  63. package/json/src/select-json-family.ts +3 -4
  64. package/package.json +8 -5
  65. package/react-devtools/dist/index.cjs +58 -47
  66. package/react-devtools/dist/index.js +60 -48
  67. package/react-devtools/src/TimelineIndex.tsx +15 -13
  68. package/react-devtools/src/Updates.tsx +41 -32
  69. package/realtime-server/dist/index.cjs +21 -10
  70. package/realtime-server/dist/index.d.ts +1 -1
  71. package/realtime-server/dist/index.js +21 -11
  72. package/realtime-server/src/realtime-server-stores/server-sync-store.ts +21 -11
  73. package/realtime-testing/dist/index.cjs +1 -0
  74. package/realtime-testing/dist/index.js +1 -1
  75. package/src/atom.ts +9 -3
  76. package/src/dispose-state.ts +3 -12
  77. package/src/index.ts +4 -0
  78. package/src/selector.ts +3 -3
  79. package/src/subscribe.ts +8 -4
  80. package/src/timeline.ts +18 -1
  81. package/src/transaction.ts +56 -4
  82. package/dist/chunk-BF4MVQF6.js +0 -44
@@ -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
@@ -421,6 +455,7 @@ var Store = class {
421
455
  }
422
456
  );
423
457
  this.molecules = /* @__PURE__ */ new Map();
458
+ this.moleculeFamilies = /* @__PURE__ */ new Map();
424
459
  this.miscResources = /* @__PURE__ */ new Map();
425
460
  this.on = {
426
461
  atomCreation: new Subject(),
@@ -432,7 +467,10 @@ var Store = class {
432
467
  transactionApplying: new StatefulSubject(
433
468
  null
434
469
  ),
435
- operationClose: new Subject()
470
+ operationClose: new Subject(),
471
+ moleculeCreationStart: new Subject(),
472
+ moleculeCreationDone: new Subject(),
473
+ moleculeDisposal: new Subject()
436
474
  };
437
475
  this.operation = { open: false };
438
476
  this.transactionMeta = {
@@ -527,8 +565,6 @@ var clearStore = (store) => {
527
565
  Object.assign(store, new Store(config));
528
566
  store.config = config;
529
567
  };
530
-
531
- // internal/src/store/withdraw.ts
532
568
  function withdraw(token, store) {
533
569
  let withdrawn;
534
570
  let target = store;
@@ -556,6 +592,12 @@ function withdraw(token, store) {
556
592
  case `transaction`:
557
593
  withdrawn = target.transactions.get(token.key);
558
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;
559
601
  }
560
602
  if (withdrawn) {
561
603
  return withdrawn;
@@ -602,7 +644,7 @@ function createRegularAtomFamily(options, store) {
602
644
  individualOptions.effects = options.effects(key);
603
645
  }
604
646
  const token = createRegularAtom(individualOptions, family, target);
605
- subject.next(token);
647
+ subject.next({ type: `state_creation`, token });
606
648
  return token;
607
649
  },
608
650
  {
@@ -640,7 +682,7 @@ function createReadonlySelectorFamily(options, store) {
640
682
  family,
641
683
  target
642
684
  );
643
- subject.next(token);
685
+ subject.next({ type: `state_creation`, token });
644
686
  return token;
645
687
  },
646
688
  {
@@ -670,7 +712,7 @@ function createWritableSelectorFamily(options, store) {
670
712
  family,
671
713
  target
672
714
  );
673
- subject.next(token);
715
+ subject.next({ type: `state_creation`, token });
674
716
  return token;
675
717
  },
676
718
  {
@@ -692,6 +734,21 @@ function createSelectorFamily(options, store) {
692
734
  }
693
735
  return createReadonlySelectorFamily(options, store);
694
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
+ }
695
752
 
696
753
  // internal/src/not-found-error.ts
697
754
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
@@ -699,6 +756,8 @@ function prettyPrintTokenType(token) {
699
756
  switch (token.type) {
700
757
  case `atom_family`:
701
758
  return `Atom Family`;
759
+ case `molecule_family`:
760
+ return `Molecule Family`;
702
761
  case `readonly_selector`:
703
762
  return `Readonly Selector`;
704
763
  case `readonly_selector_family`:
@@ -717,53 +776,36 @@ var NotFoundError = class extends Error {
717
776
  }
718
777
  };
719
778
 
720
- // internal/src/families/init-family-member.ts
721
- function initFamilyMember(token, key, store) {
722
- const familyKey = token.key;
723
- const family = store.families.get(familyKey);
724
- if (family === void 0) {
725
- throw new NotFoundError(token, store);
726
- }
727
- const state = family(key);
728
- return state;
729
- }
730
- function seekInStore(token, key, store) {
731
- const subKey = json.stringifyJson(key);
732
- const fullKey = `${token.key}(${subKey})`;
779
+ // internal/src/transaction/abort-transaction.ts
780
+ var abortTransaction = (store) => {
733
781
  const target = newest(store);
734
- let state;
735
- switch (token.type) {
736
- case `atom_family`:
737
- case `mutable_atom_family`:
738
- state = target.atoms.get(fullKey);
739
- break;
740
- case `selector_family`: {
741
- state = target.selectors.get(fullKey);
742
- break;
743
- }
744
- case `readonly_selector_family`:
745
- state = target.readonlySelectors.get(fullKey);
746
- break;
747
- }
748
- if (state) {
749
- return deposit(state);
750
- }
751
- return state;
752
- }
753
-
754
- // internal/src/families/find-in-store.ts
755
- function findInStore(token, key, store) {
756
- if (store.config.lifespan === `immortal`) {
757
- throw new Error(
758
- `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
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.`
759
788
  );
789
+ return;
760
790
  }
761
- let state = seekInStore(token, key, store);
762
- if (state) {
763
- return state;
764
- }
765
- state = initFamilyMember(token, key, store);
766
- 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
+ };
767
809
  }
768
810
 
769
811
  // internal/src/set-state/become.ts
@@ -919,7 +961,10 @@ var stowUpdate = (state, update, store) => {
919
961
  if (!shouldStow) {
920
962
  return;
921
963
  }
922
- const atomUpdate = __spreadValues({ key }, update);
964
+ const atomUpdate = __spreadValues({
965
+ type: `atom_update`,
966
+ key
967
+ }, update);
923
968
  if (state.family) {
924
969
  atomUpdate.family = state.family;
925
970
  }
@@ -1012,160 +1057,614 @@ function setIntoStore(token, value, store) {
1012
1057
  closeOperation(store);
1013
1058
  }
1014
1059
 
1015
- // internal/src/keys.ts
1016
- var isAtomKey = (key, store) => newest(store).atoms.has(key);
1017
- var isSelectorKey = (key, store) => newest(store).selectors.has(key);
1018
- var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
1019
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1020
-
1021
- // internal/src/selector/get-selector-dependency-keys.ts
1022
- var getSelectorDependencyKeys = (key, store) => {
1023
- const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1024
- return sources;
1025
- };
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
+ }
1026
1070
 
1027
- // internal/src/selector/trace-selector-atoms.ts
1028
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1029
- const rootKeys = [];
1030
- const indirectDependencyKeys = getSelectorDependencyKeys(
1031
- directDependencyKey,
1032
- store
1033
- );
1034
- let depth = 0;
1035
- while (indirectDependencyKeys.length > 0) {
1036
- const indirectDependencyKey = indirectDependencyKeys.shift();
1037
- ++depth;
1038
- if (depth > 99999) {
1039
- throw new Error(
1040
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1041
- );
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;
1042
1078
  }
1043
- if (!isAtomKey(indirectDependencyKey, store)) {
1044
- indirectDependencyKeys.push(
1045
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
1046
- );
1047
- } else if (!rootKeys.includes(indirectDependencyKey)) {
1048
- rootKeys.push(indirectDependencyKey);
1079
+ case `oldValue`: {
1080
+ disposeFromStore(update.token, store);
1081
+ break;
1049
1082
  }
1050
1083
  }
1051
- return rootKeys;
1052
- };
1053
- var traceAllSelectorAtoms = (selector, store) => {
1054
- const selectorKey = selector.key;
1055
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1056
- return directDependencyKeys.flatMap(
1057
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1058
- );
1059
- };
1060
-
1061
- // internal/src/selector/update-selector-atoms.ts
1062
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
1063
- const target = newest(store);
1064
- if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
1065
- target.selectorAtoms.set({
1066
- selectorKey,
1067
- atomKey: dependency.key
1068
- });
1069
- store.logger.info(
1070
- `\u{1F50D}`,
1071
- `selector`,
1072
- selectorKey,
1073
- `discovers root atom "${dependency.key}"`
1074
- );
1075
- } else {
1076
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1077
- store.logger.info(
1078
- `\u{1F50D}`,
1079
- `selector`,
1080
- selectorKey,
1081
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1082
- );
1083
- for (const atomKey of rootKeys) {
1084
- target.selectorAtoms = target.selectorAtoms.set({
1085
- selectorKey,
1086
- atomKey
1087
- });
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;
1088
1095
  }
1089
1096
  }
1090
- };
1091
-
1092
- // internal/src/selector/register-selector.ts
1093
- var registerSelector = (selectorKey, store) => ({
1094
- get: (dependency) => {
1095
- const target = newest(store);
1096
- const dependencyState = withdraw(dependency, store);
1097
- const dependencyValue = readOrComputeValue(dependencyState, store);
1098
- store.logger.info(
1099
- `\u{1F50C}`,
1100
- `selector`,
1101
- selectorKey,
1102
- `registers dependency ( "${dependency.key}" =`,
1103
- dependencyValue,
1104
- `)`
1105
- );
1106
- target.selectorGraph.set(
1107
- {
1108
- upstreamSelectorKey: dependency.key,
1109
- downstreamSelectorKey: selectorKey
1110
- },
1111
- {
1112
- 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;
1113
1106
  }
1114
- );
1115
- updateSelectorAtoms(selectorKey, dependency, store);
1116
- return dependencyValue;
1117
- },
1118
- set: (WritableToken, newValue) => {
1119
- const state = withdraw(WritableToken, store);
1120
- setAtomOrSelector(state, newValue, store);
1121
- },
1122
- find: (token, key) => findInStore(token, key, store),
1123
- seek: (token, key) => seekInStore(token, key, store)
1124
- });
1125
-
1126
- // internal/src/selector/create-readonly-selector.ts
1127
- var createReadonlySelector = (options, family, store) => {
1128
- const target = newest(store);
1129
- const subject = new Subject();
1130
- const { get, find, seek } = registerSelector(options.key, target);
1131
- const getSelf = () => {
1132
- const value = options.get({ get, find, seek });
1133
- cacheValue(options.key, value, subject, newest(store));
1134
- return value;
1135
- };
1136
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1137
- subject,
1138
- install: (s) => createReadonlySelector(options, family, s),
1139
- get: getSelf,
1140
- type: `readonly_selector`
1141
- }), family && { family });
1142
- target.readonlySelectors.set(options.key, readonlySelector);
1143
- const initialValue = getSelf();
1144
- store.logger.info(
1145
- `\u2728`,
1146
- readonlySelector.type,
1147
- readonlySelector.key,
1148
- `=`,
1149
- initialValue
1150
- );
1151
- const token = {
1152
- key: options.key,
1153
- type: `readonly_selector`
1154
- };
1155
- if (family) {
1156
- 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
+ }
1157
1112
  }
1158
- store.on.selectorCreation.next(token);
1159
- return token;
1160
- };
1161
-
1162
- // internal/src/selector/create-writable-selector.ts
1163
- var createWritableSelector = (options, family, store) => {
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
+ };
1660
+
1661
+ // internal/src/selector/create-writable-selector.ts
1662
+ var createWritableSelector = (options, family, store) => {
1164
1663
  const target = newest(store);
1165
1664
  const subject = new Subject();
1166
1665
  const transactors = registerSelector(options.key, target);
1167
- const { find, get, seek } = transactors;
1168
- const readonlyTransactors = { find, get, seek };
1666
+ const { find, get, seek, json } = transactors;
1667
+ const readonlyTransactors = { find, get, seek, json };
1169
1668
  const getSelf = () => {
1170
1669
  const value = options.get(readonlyTransactors);
1171
1670
  cacheValue(options.key, value, subject, newest(store));
@@ -1208,7 +1707,6 @@ var createWritableSelector = (options, family, store) => {
1208
1707
  if (family) {
1209
1708
  token.family = family;
1210
1709
  }
1211
- store.on.selectorCreation.next(token);
1212
1710
  return token;
1213
1711
  };
1214
1712
 
@@ -1216,19 +1714,23 @@ var createWritableSelector = (options, family, store) => {
1216
1714
  function createStandaloneSelector(options, store) {
1217
1715
  const isWritable = `set` in options;
1218
1716
  if (isWritable) {
1219
- return createWritableSelector(options, void 0, store);
1717
+ const state2 = createWritableSelector(options, void 0, store);
1718
+ store.on.selectorCreation.next(state2);
1719
+ return state2;
1220
1720
  }
1221
- return createReadonlySelector(options, void 0, store);
1721
+ const state = createReadonlySelector(options, void 0, store);
1722
+ store.on.selectorCreation.next(state);
1723
+ return state;
1222
1724
  }
1223
1725
 
1224
1726
  // internal/src/selector/dispose-selector.ts
1225
- function disposeSelector(selectorToken, store) {
1727
+ function disposeSelector2(selectorToken, store) {
1226
1728
  var _a;
1227
1729
  const target = newest(store);
1228
1730
  const { key } = selectorToken;
1229
1731
  const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
1230
1732
  if (!selector) {
1231
- store.logger.error(
1733
+ store.logger.info(
1232
1734
  `\u274C`,
1233
1735
  `selector`,
1234
1736
  key,
@@ -1244,10 +1746,30 @@ function disposeSelector(selectorToken, store) {
1244
1746
  } else {
1245
1747
  switch (selectorToken.type) {
1246
1748
  case `selector`:
1247
- target.selectors.delete(key);
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
+ }
1248
1760
  break;
1249
1761
  case `readonly_selector`:
1250
- target.readonlySelectors.delete(key);
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
+ }
1251
1773
  break;
1252
1774
  }
1253
1775
  target.valueMap.delete(key);
@@ -1260,12 +1782,19 @@ function disposeSelector(selectorToken, store) {
1260
1782
  );
1261
1783
  for (const downstreamToken of downstreamTokens) {
1262
1784
  if (downstreamToken) {
1263
- disposeSelector(downstreamToken, store);
1785
+ disposeSelector2(downstreamToken, store);
1264
1786
  }
1265
1787
  }
1266
1788
  target.selectorGraph.delete(key);
1267
1789
  store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
1268
- store.on.selectorDisposal.next(selectorToken);
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);
1797
+ }
1269
1798
  }
1270
1799
  }
1271
1800
 
@@ -1601,7 +2130,6 @@ function createMutableAtom(options, family, store) {
1601
2130
  if (!family) {
1602
2131
  json.selectJson(token, options, store);
1603
2132
  }
1604
- store.on.atomCreation.next(token);
1605
2133
  return token;
1606
2134
  }
1607
2135
  var FamilyTracker = class {
@@ -1616,19 +2144,19 @@ var FamilyTracker = class {
1616
2144
  this.mutableAtoms = mutableAtoms;
1617
2145
  this.mutableAtoms.subject.subscribe(
1618
2146
  `store=${store.config.name}::tracker-atom-family`,
1619
- (atomToken) => {
1620
- if (atomToken.family) {
1621
- const key = json.parseJson(atomToken.family.subKey);
2147
+ (event) => {
2148
+ if (event.token.family) {
2149
+ const key = json.parseJson(event.token.family.subKey);
1622
2150
  seekInStore(this.latestUpdateAtoms, key, store);
1623
- new Tracker(atomToken, store);
2151
+ new Tracker(event.token, store);
1624
2152
  }
1625
2153
  }
1626
2154
  );
1627
2155
  this.latestUpdateAtoms.subject.subscribe(
1628
2156
  `store=${store.config.name}::tracker-atom-family`,
1629
- (atomToken) => {
1630
- if (atomToken.family) {
1631
- const key = json.parseJson(atomToken.family.subKey);
2157
+ (event) => {
2158
+ if (event.token.family) {
2159
+ const key = json.parseJson(event.token.family.subKey);
1632
2160
  const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
1633
2161
  if (mutableAtomToken) {
1634
2162
  new Tracker(mutableAtomToken, store);
@@ -1659,7 +2187,7 @@ function createMutableAtomFamily(options, store) {
1659
2187
  individualOptions.effects = options.effects(key);
1660
2188
  }
1661
2189
  const token = createMutableAtom(individualOptions, family, target);
1662
- subject.next(token);
2190
+ subject.next({ type: `state_creation`, token });
1663
2191
  return token;
1664
2192
  },
1665
2193
  {
@@ -1875,7 +2403,6 @@ function createRegularAtom(options, family, store) {
1875
2403
  }
1876
2404
  };
1877
2405
  }
1878
- store.on.atomCreation.next(token);
1879
2406
  return token;
1880
2407
  }
1881
2408
 
@@ -1883,13 +2410,17 @@ function createRegularAtom(options, family, store) {
1883
2410
  function createStandaloneAtom(options, store) {
1884
2411
  const isMutable2 = `mutable` in options;
1885
2412
  if (isMutable2) {
1886
- return createMutableAtom(options, void 0, store);
2413
+ const state2 = createMutableAtom(options, void 0, store);
2414
+ store.on.atomCreation.next(state2);
2415
+ return state2;
1887
2416
  }
1888
- return createRegularAtom(options, void 0, store);
2417
+ const state = createRegularAtom(options, void 0, store);
2418
+ store.on.atomCreation.next(state);
2419
+ return state;
1889
2420
  }
1890
2421
 
1891
2422
  // internal/src/atom/dispose-atom.ts
1892
- function disposeAtom(atomToken, store) {
2423
+ function disposeAtom2(atomToken, store) {
1893
2424
  var _a, _b;
1894
2425
  const target = newest(store);
1895
2426
  const { key } = atomToken;
@@ -1905,6 +2436,13 @@ function disposeAtom(atomToken, store) {
1905
2436
  store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1906
2437
  } else {
1907
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
+ });
1908
2446
  target.atoms.delete(key);
1909
2447
  target.valueMap.delete(key);
1910
2448
  const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
@@ -1912,7 +2450,7 @@ function disposeAtom(atomToken, store) {
1912
2450
  for (const selectorKey of selectorKeys) {
1913
2451
  const token = (_b = target.selectors.get(selectorKey)) != null ? _b : target.readonlySelectors.get(selectorKey);
1914
2452
  if (token) {
1915
- disposeSelector(token, store);
2453
+ disposeSelector2(token, store);
1916
2454
  }
1917
2455
  }
1918
2456
  }
@@ -1921,94 +2459,21 @@ function disposeAtom(atomToken, store) {
1921
2459
  target.timelineAtoms.delete(key);
1922
2460
  if (atomToken.type === `mutable_atom`) {
1923
2461
  const updateToken = getUpdateToken(atomToken);
1924
- disposeAtom(updateToken, store);
2462
+ disposeAtom2(updateToken, store);
1925
2463
  store.trackers.delete(key);
1926
2464
  }
1927
2465
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1928
- store.on.atomDisposal.next(atomToken);
1929
- }
1930
- }
1931
-
1932
- // internal/src/get-environment-data.ts
1933
- function getEnvironmentData(store) {
1934
- return {
1935
- window: typeof window === `undefined` ? void 0 : window,
1936
- global: typeof global === `undefined` ? void 0 : global,
1937
- store
1938
- };
1939
- }
1940
-
1941
- // internal/src/get-state/get-from-store.ts
1942
- function getFromStore(token, store) {
1943
- const state = withdraw(token, store);
1944
- return readOrComputeValue(state, store);
1945
- }
1946
-
1947
- // internal/src/ingest-updates/ingest-atom-update.ts
1948
- function ingestAtomUpdate(applying, atomUpdate, store) {
1949
- const { key, newValue, oldValue } = atomUpdate;
1950
- const value = applying === `newValue` ? newValue : oldValue;
1951
- const token = { key, type: `atom` };
1952
- if (atomUpdate.family) {
1953
- Object.assign(token, { family: atomUpdate.family });
1954
- }
1955
- setIntoStore(token, value, store);
1956
- }
1957
-
1958
- // internal/src/ingest-updates/ingest-selector-update.ts
1959
- function ingestSelectorUpdate(applying, selectorUpdate, store) {
1960
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : [...selectorUpdate.atomUpdates].reverse();
1961
- for (const atomUpdate of updates) {
1962
- ingestAtomUpdate(applying, atomUpdate, store);
1963
- }
1964
- }
1965
-
1966
- // internal/src/ingest-updates/ingest-transaction-update.ts
1967
- function ingestTransactionUpdate(applying, transactionUpdate, store) {
1968
- const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1969
- for (const updateFromTransaction of updates) {
1970
- if (`newValue` in updateFromTransaction) {
1971
- 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
+ });
1972
2471
  } else {
1973
- ingestTransactionUpdate(applying, updateFromTransaction, store);
2472
+ store.on.atomDisposal.next(atomToken);
1974
2473
  }
1975
2474
  }
1976
2475
  }
1977
2476
 
1978
- // internal/src/lazy-map.ts
1979
- var LazyMap = class extends Map {
1980
- constructor(source) {
1981
- super();
1982
- this.source = source;
1983
- this.deleted = /* @__PURE__ */ new Set();
1984
- }
1985
- get(key) {
1986
- const has = super.has(key);
1987
- if (has) {
1988
- return super.get(key);
1989
- }
1990
- if (!this.deleted.has(key) && this.source.has(key)) {
1991
- const value = this.source.get(key);
1992
- return value;
1993
- }
1994
- return void 0;
1995
- }
1996
- set(key, value) {
1997
- this.deleted.delete(key);
1998
- return super.set(key, value);
1999
- }
2000
- hasOwn(key) {
2001
- return super.has(key);
2002
- }
2003
- has(key) {
2004
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
2005
- }
2006
- delete(key) {
2007
- this.deleted.add(key);
2008
- return super.delete(key);
2009
- }
2010
- };
2011
-
2012
2477
  // internal/src/timeline/add-atom-to-timeline.ts
2013
2478
  var addAtomToTimeline = (atomToken, tl, store) => {
2014
2479
  let maybeAtom = withdraw(atomToken, store);
@@ -2018,188 +2483,212 @@ var addAtomToTimeline = (atomToken, tl, store) => {
2018
2483
  }
2019
2484
  const atom = maybeAtom;
2020
2485
  store.timelineAtoms.set({ atomKey: atom.key, timelineKey: tl.key });
2021
- atom.subject.subscribe(`timeline`, (update) => {
2022
- var _a, _b, _c, _d, _e, _f;
2023
- const target = newest(store);
2024
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2025
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2026
- const { transactionApplying } = target.on;
2027
- const currentTransactionKey = (_a = transactionApplying.state) == null ? void 0 : _a.update.key;
2028
- const currentTransactionInstanceId = (_b = transactionApplying.state) == null ? void 0 : _b.update.id;
2029
- store.logger.info(
2030
- `\u23F3`,
2031
- `timeline`,
2032
- tl.key,
2033
- `atom`,
2034
- atomToken.key,
2035
- `went`,
2036
- update.oldValue,
2037
- `->`,
2038
- update.newValue,
2039
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2040
- );
2041
- if (tl.timeTraveling === null) {
2042
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
2043
- const mostRecentUpdate = tl.history.at(-1);
2044
- if (mostRecentUpdate === void 0) {
2045
- throw new Error(
2046
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
2047
- );
2048
- }
2049
- }
2050
- if (currentTransactionKey) {
2051
- const txToken = {
2052
- key: currentTransactionKey,
2053
- type: `transaction`
2054
- };
2055
- const currentTransaction = withdraw(txToken, store);
2056
- if (tl.transactionKey !== currentTransactionKey) {
2057
- if (tl.transactionKey) {
2058
- store.logger.error(
2059
- `\u{1F41E}`,
2060
- `timeline`,
2061
- tl.key,
2062
- `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.`
2063
2514
  );
2064
2515
  }
2065
- tl.transactionKey = currentTransactionKey;
2066
- const unsubscribe = currentTransaction.subject.subscribe(
2067
- `timeline:${tl.key}`,
2068
- (transactionUpdate) => {
2069
- var _a2, _b2;
2070
- unsubscribe();
2071
- if (tl.timeTraveling === null && currentTransactionInstanceId) {
2072
- if (tl.at !== tl.history.length) {
2073
- tl.history.splice(tl.at);
2074
- }
2075
- const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
2076
- const newestStore = newest(store);
2077
- if (`updates` in updateFromTx) {
2078
- 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);
2079
2541
  }
2080
- const atomOrFamilyKeys = newestStore.timelineAtoms.getRelatedKeys(tl.key);
2081
- return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
2082
- (key) => {
2083
- var _a3;
2084
- 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;
2085
2567
  }
2086
- ) : false;
2087
- }).map((updateFromTx) => {
2088
- if (`updates` in updateFromTx) {
2089
- return __spreadProps(__spreadValues({}, updateFromTx), {
2090
- updates: filterUpdates(updateFromTx.updates)
2091
- });
2568
+ if (key === void 0) {
2569
+ return false;
2570
+ }
2571
+ if (atomOrFamilyKeys.has(key)) {
2572
+ return true;
2573
+ }
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);
2092
2597
  }
2093
- return updateFromTx;
2094
- });
2095
- const updates = filterUpdates(transactionUpdate.updates);
2096
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
2097
- type: `transaction_update`,
2098
- timestamp: Date.now()
2099
- }, transactionUpdate), {
2100
- updates
2101
- });
2102
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
2103
- if (willCapture) {
2104
- tl.history.push(timelineTransactionUpdate);
2105
- tl.at = tl.history.length;
2106
- tl.subject.next(timelineTransactionUpdate);
2107
2598
  }
2599
+ tl.transactionKey = null;
2600
+ store.logger.info(
2601
+ `\u231B`,
2602
+ `timeline`,
2603
+ tl.key,
2604
+ `got a transaction_update "${transactionUpdate.key}"`
2605
+ );
2108
2606
  }
2109
- 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));
2110
2641
  store.logger.info(
2111
2642
  `\u231B`,
2112
2643
  `timeline`,
2113
2644
  tl.key,
2114
- `got a transaction_update "${transactionUpdate.key}"`
2645
+ `set selector_update "${currentSelectorKey}" to`,
2646
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2115
2647
  );
2116
2648
  }
2117
- );
2118
- }
2119
- } else if (currentSelectorKey && currentSelectorTime) {
2120
- let latestUpdate = tl.history.at(-1);
2121
- if (currentSelectorTime !== tl.selectorTime) {
2122
- latestUpdate = {
2123
- type: `selector_update`,
2124
- timestamp: currentSelectorTime,
2125
- key: currentSelectorKey,
2126
- atomUpdates: []
2127
- };
2128
- latestUpdate.atomUpdates.push(__spreadValues({
2129
- key: atom.key,
2130
- type: `atom_update`
2131
- }, 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;
2132
2662
  if (tl.at !== tl.history.length) {
2133
2663
  tl.history.splice(tl.at);
2134
2664
  }
2135
- 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;
2136
2676
  store.logger.info(
2137
2677
  `\u231B`,
2138
2678
  `timeline`,
2139
2679
  tl.key,
2140
- `got a selector_update "${currentSelectorKey}" with`,
2141
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2680
+ `got an atom_update to "${atom.key}"`
2142
2681
  );
2143
- tl.at = tl.history.length;
2144
- tl.selectorTime = currentSelectorTime;
2145
- } else {
2146
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
2147
- latestUpdate.atomUpdates.push(__spreadValues({
2148
- key: atom.key,
2149
- type: `atom_update`
2150
- }, update));
2151
- store.logger.info(
2152
- `\u231B`,
2153
- `timeline`,
2154
- tl.key,
2155
- `set selector_update "${currentSelectorKey}" to`,
2156
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2157
- );
2158
- }
2159
- }
2160
- if (latestUpdate) {
2161
- const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
2162
- if (willCaptureSelectorUpdate) {
2163
- tl.subject.next(latestUpdate);
2164
- } else {
2165
- tl.history.pop();
2682
+ if (willCapture) {
2683
+ tl.history.push(atomUpdate);
2166
2684
  tl.at = tl.history.length;
2685
+ tl.subject.next(atomUpdate);
2167
2686
  }
2168
2687
  }
2169
- } else {
2170
- const timestamp = Date.now();
2171
- tl.selectorTime = null;
2172
- if (tl.at !== tl.history.length) {
2173
- tl.history.splice(tl.at);
2174
- }
2175
- const atomUpdate = {
2176
- type: `atom_update`,
2177
- timestamp,
2178
- key: atom.key,
2179
- oldValue: update.oldValue,
2180
- newValue: update.newValue
2181
- };
2182
- if (atom.family) {
2183
- atomUpdate.family = atom.family;
2184
- }
2185
- const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
2186
- store.logger.info(
2187
- `\u231B`,
2188
- `timeline`,
2189
- tl.key,
2190
- `got an atom_update to "${atom.key}"`
2191
- );
2192
- if (willCapture) {
2193
- tl.history.push(atomUpdate);
2194
- tl.at = tl.history.length;
2195
- tl.subject.next(atomUpdate);
2196
- }
2197
2688
  }
2198
- }
2199
- });
2689
+ })
2690
+ );
2200
2691
  };
2201
-
2202
- // internal/src/timeline/create-timeline.ts
2203
2692
  function createTimeline(options, store, data) {
2204
2693
  var _a, _b;
2205
2694
  const tl = __spreadProps(__spreadValues({
@@ -2212,60 +2701,141 @@ function createTimeline(options, store, data) {
2212
2701
  }, data), {
2213
2702
  history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
2214
2703
  install: (s) => createTimeline(options, s, tl),
2215
- subject: new Subject()
2704
+ subject: new Subject(),
2705
+ subscriptions: /* @__PURE__ */ new Map()
2216
2706
  });
2217
2707
  if (options.shouldCapture) {
2218
2708
  tl.shouldCapture = options.shouldCapture;
2219
2709
  }
2220
2710
  const timelineKey = options.key;
2221
2711
  const target = newest(store);
2222
- for (const tokenOrFamily of options.atoms) {
2712
+ for (const tokenOrFamily of options.scope) {
2223
2713
  let atomKey = tokenOrFamily.key;
2224
- if (tokenOrFamily.type === `atom_family` || tokenOrFamily.type === `mutable_atom_family`) {
2225
- const familyToken = tokenOrFamily;
2226
- const family = withdraw(familyToken, store);
2227
- const familyKey = family.key;
2228
- target.timelineAtoms.set({ atomKey: familyKey, timelineKey });
2229
- family.subject.subscribe(`timeline:${options.key}`, (token2) => {
2230
- addAtomToTimeline(token2, tl, store);
2231
- });
2232
- for (const atom of target.atoms.values()) {
2233
- if (((_b = atom.family) == null ? void 0 : _b.key) === familyKey) {
2234
- addAtomToTimeline(atom, tl, store);
2235
- }
2236
- }
2237
- } else {
2238
- let atom = withdraw(tokenOrFamily, store);
2239
- if (isMutable(atom)) {
2240
- const updateAtom = withdraw(getUpdateToken(atom), store);
2241
- atom = updateAtom;
2242
- atomKey = atom.key;
2243
- }
2244
- if (`family` in atom) {
2245
- const familyTimelineKey = target.timelineAtoms.getRelatedKey(
2246
- atom.family.key
2247
- );
2248
- if (familyTimelineKey) {
2249
- store.logger.error(
2250
- `\u274C`,
2251
- `timeline`,
2252
- options.key,
2253
- `Failed to add atom "${atom.key}" because its family "${atom.family.key}" already belongs to timeline "${familyTimelineKey}"`
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
+ )
2254
2730
  );
2255
- continue;
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
+ }
2256
2736
  }
2257
- }
2258
- const existingTimelineKey = target.timelineAtoms.getRelatedKey(atomKey);
2259
- if (existingTimelineKey) {
2260
- store.logger.error(
2261
- `\u274C`,
2262
- `timeline`,
2263
- options.key,
2264
- `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2265
- );
2266
- continue;
2267
- }
2268
- addAtomToTimeline(atom, tl, store);
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
+ }
2771
+ addAtomToTimeline(atom, tl, store);
2772
+ }
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
+ }
2837
+ }
2838
+ break;
2269
2839
  }
2270
2840
  }
2271
2841
  store.timelines.set(options.key, tl);
@@ -2276,6 +2846,27 @@ function createTimeline(options, store, data) {
2276
2846
  store.on.timelineCreation.next(token);
2277
2847
  return token;
2278
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
+ }
2279
2870
 
2280
2871
  // internal/src/timeline/time-travel.ts
2281
2872
  var timeTravel = (action, token, store) => {
@@ -2323,6 +2914,22 @@ var timeTravel = (action, token, store) => {
2323
2914
  ingestTransactionUpdate(applying, update, store);
2324
2915
  break;
2325
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
+ }
2326
2933
  }
2327
2934
  if (action === `redo`) {
2328
2935
  ++timelineData.at;
@@ -2337,253 +2944,6 @@ var timeTravel = (action, token, store) => {
2337
2944
  );
2338
2945
  };
2339
2946
 
2340
- // internal/src/transaction/abort-transaction.ts
2341
- var abortTransaction = (store) => {
2342
- const target = newest(store);
2343
- if (!isChildStore(target)) {
2344
- store.logger.warn(
2345
- `\u{1F41E}`,
2346
- `transaction`,
2347
- `???`,
2348
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2349
- );
2350
- return;
2351
- }
2352
- store.logger.info(
2353
- `\u{1FA82}`,
2354
- `transaction`,
2355
- target.transactionMeta.update.key,
2356
- `Aborting transaction`
2357
- );
2358
- target.parent.child = null;
2359
- };
2360
-
2361
- // internal/src/transaction/act-upon-store.ts
2362
- function actUponStore(token, id, store) {
2363
- return (...parameters) => {
2364
- const tx = withdraw(token, store);
2365
- if (tx) {
2366
- return tx.run(parameters, id);
2367
- }
2368
- throw new NotFoundError(token, store);
2369
- };
2370
- }
2371
-
2372
- // internal/src/transaction/set-epoch-number.ts
2373
- function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
2374
- const isRoot = isRootStore(store);
2375
- if (isRoot && continuityKey) {
2376
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2377
- }
2378
- }
2379
- function setEpochNumberOfAction(transactionKey, newEpoch, store) {
2380
- const isRoot = isRootStore(store);
2381
- if (!isRoot) {
2382
- return;
2383
- }
2384
- const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
2385
- if (continuityKey !== void 0) {
2386
- store.transactionMeta.epoch.set(continuityKey, newEpoch);
2387
- }
2388
- }
2389
-
2390
- // internal/src/transaction/apply-transaction.ts
2391
- var applyTransaction = (output, store) => {
2392
- var _a;
2393
- const child = newest(store);
2394
- const { parent } = child;
2395
- if (parent === null || !isChildStore(child) || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
2396
- store.logger.warn(
2397
- `\u{1F41E}`,
2398
- `transaction`,
2399
- `???`,
2400
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2401
- );
2402
- return;
2403
- }
2404
- child.transactionMeta.phase = `applying`;
2405
- child.transactionMeta.update.output = output;
2406
- parent.child = null;
2407
- parent.on.transactionApplying.next(child.transactionMeta);
2408
- const { updates } = child.transactionMeta.update;
2409
- store.logger.info(
2410
- `\u{1F6C4}`,
2411
- `transaction`,
2412
- child.transactionMeta.update.key,
2413
- `Applying transaction with ${updates.length} updates:`,
2414
- updates
2415
- );
2416
- for (const tracker of child.trackers.values()) {
2417
- const mutableKey = tracker.mutableState.key;
2418
- if (!parent.atoms.has(mutableKey)) {
2419
- const atom = child.atoms.get(mutableKey);
2420
- atom == null ? void 0 : atom.install(parent);
2421
- }
2422
- tracker.dispose();
2423
- }
2424
- for (const atom of child.atoms.values()) {
2425
- if (!parent.atoms.has(atom.key)) {
2426
- parent.atoms.set(atom.key, atom);
2427
- parent.valueMap.set(atom.key, atom.default);
2428
- parent.logger.info(
2429
- `\u{1F528}`,
2430
- `transaction`,
2431
- child.transactionMeta.update.key,
2432
- `Adding atom "${atom.key}"`
2433
- );
2434
- }
2435
- }
2436
- ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
2437
- if (isRootStore(parent)) {
2438
- setEpochNumberOfAction(
2439
- child.transactionMeta.update.key,
2440
- child.transactionMeta.update.epoch,
2441
- parent
2442
- );
2443
- const myTransaction = withdraw(
2444
- { key: child.transactionMeta.update.key, type: `transaction` },
2445
- store
2446
- );
2447
- myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
2448
- store.logger.info(
2449
- `\u{1F6EC}`,
2450
- `transaction`,
2451
- child.transactionMeta.update.key,
2452
- `Finished applying transaction.`
2453
- );
2454
- } else if (isChildStore(parent)) {
2455
- parent.transactionMeta.update.updates.push(child.transactionMeta.update);
2456
- }
2457
- parent.on.transactionApplying.next(null);
2458
- };
2459
-
2460
- // internal/src/transaction/assign-transaction-to-continuity.ts
2461
- function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2462
- const isRoot = isRootStore(store);
2463
- if (!isRoot) {
2464
- return;
2465
- }
2466
- const { epoch, actionContinuities } = store.transactionMeta;
2467
- actionContinuities.set(continuityKey, transactionKey);
2468
- if (!epoch.has(continuityKey)) {
2469
- epoch.set(continuityKey, -1);
2470
- }
2471
- }
2472
-
2473
- // internal/src/transaction/build-transaction.ts
2474
- var buildTransaction = (key, params, store, id) => {
2475
- const parent = newest(store);
2476
- const childBase = {
2477
- parent,
2478
- child: null,
2479
- on: parent.on,
2480
- loggers: parent.loggers,
2481
- logger: parent.logger,
2482
- config: parent.config,
2483
- atoms: new LazyMap(parent.atoms),
2484
- atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2485
- families: new LazyMap(parent.families),
2486
- operation: { open: false },
2487
- readonlySelectors: new LazyMap(parent.readonlySelectors),
2488
- timelines: new LazyMap(parent.timelines),
2489
- timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
2490
- trackers: /* @__PURE__ */ new Map(),
2491
- transactions: new LazyMap(parent.transactions),
2492
- selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
2493
- selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
2494
- makeContentKey: (...keys) => keys.sort().join(`:`)
2495
- }),
2496
- selectors: new LazyMap(parent.selectors),
2497
- valueMap: new LazyMap(parent.valueMap),
2498
- molecules: new LazyMap(parent.molecules),
2499
- miscResources: new LazyMap(parent.miscResources)
2500
- };
2501
- const epoch = getEpochNumberOfAction(key, store);
2502
- const transactionMeta = {
2503
- phase: `building`,
2504
- update: {
2505
- key,
2506
- id,
2507
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
2508
- updates: [],
2509
- params,
2510
- output: void 0
2511
- },
2512
- transactors: {
2513
- get: (token) => getFromStore(token, child),
2514
- set: (token, value) => {
2515
- setIntoStore(token, value, child);
2516
- },
2517
- run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2518
- find: (token, k) => findInStore(token, k, child),
2519
- seek: (token, k) => seekInStore(token, k, child),
2520
- env: () => getEnvironmentData(child)
2521
- }
2522
- };
2523
- const child = Object.assign(childBase, {
2524
- transactionMeta
2525
- });
2526
- parent.child = child;
2527
- store.logger.info(
2528
- `\u{1F6EB}`,
2529
- `transaction`,
2530
- key,
2531
- `Building transaction with params:`,
2532
- params
2533
- );
2534
- return child;
2535
- };
2536
-
2537
- // internal/src/transaction/create-transaction.ts
2538
- function createTransaction(options, store) {
2539
- const newTransaction = {
2540
- key: options.key,
2541
- type: `transaction`,
2542
- run: (params, id) => {
2543
- const childStore = buildTransaction(options.key, params, store, id);
2544
- try {
2545
- const target2 = newest(store);
2546
- const { transactors } = childStore.transactionMeta;
2547
- const output = options.do(transactors, ...params);
2548
- applyTransaction(output, target2);
2549
- return output;
2550
- } catch (thrown) {
2551
- abortTransaction(target);
2552
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
2553
- throw thrown;
2554
- }
2555
- },
2556
- install: (s) => createTransaction(options, s),
2557
- subject: new Subject()
2558
- };
2559
- const target = newest(store);
2560
- target.transactions.set(newTransaction.key, newTransaction);
2561
- const token = deposit(newTransaction);
2562
- store.on.transactionCreation.next(token);
2563
- return token;
2564
- }
2565
-
2566
- // internal/src/transaction/get-epoch-number.ts
2567
- function getContinuityKey(transactionKey, store) {
2568
- const isRoot = isRootStore(store);
2569
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2570
- return continuity;
2571
- }
2572
- function getEpochNumberOfContinuity(continuityKey, store) {
2573
- const isRoot = isRootStore(store);
2574
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
2575
- return epoch;
2576
- }
2577
- function getEpochNumberOfAction(transactionKey, store) {
2578
- const isRoot = isRootStore(store);
2579
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2580
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
2581
- return epoch;
2582
- }
2583
-
2584
- // internal/src/transaction/index.ts
2585
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2586
-
2587
2947
  exports.FamilyTracker = FamilyTracker;
2588
2948
  exports.Future = Future;
2589
2949
  exports.IMPLICIT = IMPLICIT;
@@ -2619,8 +2979,9 @@ exports.createTimeline = createTimeline;
2619
2979
  exports.createTransaction = createTransaction;
2620
2980
  exports.createWritableSelector = createWritableSelector;
2621
2981
  exports.deposit = deposit;
2622
- exports.disposeAtom = disposeAtom;
2623
- exports.disposeSelector = disposeSelector;
2982
+ exports.disposeAtom = disposeAtom2;
2983
+ exports.disposeFromStore = disposeFromStore;
2984
+ exports.disposeSelector = disposeSelector2;
2624
2985
  exports.evictCachedValue = evictCachedValue;
2625
2986
  exports.findInStore = findInStore;
2626
2987
  exports.getContinuityKey = getContinuityKey;
@@ -2633,6 +2994,10 @@ exports.getJsonToken = getJsonToken;
2633
2994
  exports.getSelectorDependencyKeys = getSelectorDependencyKeys;
2634
2995
  exports.getUpdateToken = getUpdateToken;
2635
2996
  exports.ingestAtomUpdate = ingestAtomUpdate;
2997
+ exports.ingestCreationEvent = ingestCreationEvent;
2998
+ exports.ingestDisposalEvent = ingestDisposalEvent;
2999
+ exports.ingestMoleculeCreationEvent = ingestMoleculeCreationEvent;
3000
+ exports.ingestMoleculeDisposalEvent = ingestMoleculeDisposalEvent;
2636
3001
  exports.ingestSelectorUpdate = ingestSelectorUpdate;
2637
3002
  exports.ingestTransactionUpdate = ingestTransactionUpdate;
2638
3003
  exports.initFamilyMember = initFamilyMember;