atom.io 0.5.0 → 0.6.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 (87) hide show
  1. package/dist/index.d.mts +82 -66
  2. package/dist/index.d.ts +82 -66
  3. package/dist/index.js +482 -360
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +481 -360
  6. package/dist/index.mjs.map +1 -1
  7. package/json/dist/index.js.map +1 -1
  8. package/json/dist/index.mjs.map +1 -1
  9. package/package.json +12 -5
  10. package/react/dist/index.d.mts +18 -11
  11. package/react/dist/index.d.ts +18 -11
  12. package/react/dist/index.js +45 -21
  13. package/react/dist/index.js.map +1 -1
  14. package/react/dist/index.mjs +31 -21
  15. package/react/dist/index.mjs.map +1 -1
  16. package/react-devtools/dist/index.d.mts +4 -4
  17. package/react-devtools/dist/index.d.ts +4 -4
  18. package/react-devtools/dist/index.js.map +1 -1
  19. package/react-devtools/dist/index.mjs.map +1 -1
  20. package/realtime/dist/index.d.mts +3 -1
  21. package/realtime/dist/index.d.ts +3 -1
  22. package/realtime/dist/index.js +23 -0
  23. package/realtime/dist/index.js.map +1 -1
  24. package/realtime/dist/index.mjs +22 -0
  25. package/realtime/dist/index.mjs.map +1 -1
  26. package/realtime-react/dist/index.d.mts +45 -0
  27. package/realtime-react/dist/index.d.ts +45 -0
  28. package/realtime-react/dist/index.js +213 -0
  29. package/realtime-react/dist/index.js.map +1 -0
  30. package/realtime-react/dist/index.mjs +168 -0
  31. package/realtime-react/dist/index.mjs.map +1 -0
  32. package/realtime-react/package.json +15 -0
  33. package/src/index.ts +0 -6
  34. package/src/internal/get.ts +17 -3
  35. package/src/internal/index.ts +2 -0
  36. package/src/internal/meta/meta-state.ts +1 -1
  37. package/src/internal/operation.ts +3 -1
  38. package/src/internal/selector/create-read-write-selector.ts +62 -0
  39. package/src/internal/selector/create-readonly-selector.ts +52 -0
  40. package/src/internal/selector/index.ts +4 -0
  41. package/src/internal/selector/lookup-selector-sources.ts +16 -0
  42. package/src/internal/selector/register-selector.ts +57 -0
  43. package/src/internal/selector/trace-selector-atoms.ts +43 -0
  44. package/src/internal/selector/update-selector-atoms.ts +33 -0
  45. package/src/internal/selector-internal.ts +9 -207
  46. package/src/internal/store.ts +43 -16
  47. package/src/internal/subscribe-internal.ts +1 -1
  48. package/src/internal/time-travel-internal.ts +7 -7
  49. package/src/internal/timeline/add-atom-to-timeline.ts +164 -0
  50. package/src/internal/timeline/index.ts +1 -0
  51. package/src/internal/timeline-internal.ts +37 -156
  52. package/src/internal/transaction/abort-transaction.ts +12 -0
  53. package/src/internal/transaction/apply-transaction.ts +54 -0
  54. package/src/internal/transaction/build-transaction.ts +33 -0
  55. package/src/internal/transaction/index.ts +25 -0
  56. package/src/internal/transaction/redo-transaction.ts +23 -0
  57. package/src/internal/transaction/undo-transaction.ts +23 -0
  58. package/src/internal/transaction-internal.ts +14 -146
  59. package/src/react/index.ts +2 -46
  60. package/src/react/store-context.tsx +14 -0
  61. package/src/react/store-hooks.ts +48 -0
  62. package/src/react-devtools/AtomIODevtools.tsx +1 -1
  63. package/src/react-explorer/AtomIOExplorer.tsx +2 -2
  64. package/src/react-explorer/space-states.ts +2 -2
  65. package/src/realtime/README.md +33 -0
  66. package/src/realtime/hook-composition/index.ts +1 -0
  67. package/src/realtime/hook-composition/receive-state.ts +29 -0
  68. package/src/realtime/hook-composition/receive-transaction.ts +2 -3
  69. package/src/realtime-react/index.ts +3 -0
  70. package/src/realtime-react/realtime-context.tsx +31 -0
  71. package/src/realtime-react/realtime-hooks.ts +39 -0
  72. package/src/realtime-react/realtime-state.ts +10 -0
  73. package/src/realtime-react/use-pull-family-member.ts +27 -0
  74. package/src/realtime-react/use-pull-family.ts +25 -0
  75. package/src/realtime-react/use-pull.ts +23 -0
  76. package/src/realtime-react/use-push.ts +26 -0
  77. package/src/realtime-react/use-server-action.ts +34 -0
  78. package/src/silo.ts +12 -4
  79. package/src/subscribe.ts +30 -2
  80. package/src/timeline.ts +10 -0
  81. package/src/transaction.ts +15 -10
  82. package/src/realtime-client/hook-composition/compose-realtime-hooks.ts +0 -62
  83. package/src/realtime-client/hook-composition/realtime-client-family-member.ts +0 -28
  84. package/src/realtime-client/hook-composition/realtime-client-family.ts +0 -26
  85. package/src/realtime-client/hook-composition/realtime-client-single.ts +0 -24
  86. package/src/realtime-client/hook-composition/realtime-client-transaction.ts +0 -35
  87. package/src/realtime-client/index.ts +0 -1
package/dist/index.mjs CHANGED
@@ -110,9 +110,9 @@ function lookup(key, store) {
110
110
  return { key, type };
111
111
  }
112
112
  function withdraw(token, store) {
113
- var _a, _b, _c, _d;
113
+ var _a, _b, _c, _d, _e;
114
114
  const core = target(store);
115
- return (_d = (_c = (_b = (_a = HAMT.get(token.key, core.atoms)) != null ? _a : HAMT.get(token.key, core.selectors)) != null ? _b : HAMT.get(token.key, core.readonlySelectors)) != null ? _c : HAMT.get(token.key, core.transactions)) != null ? _d : null;
115
+ return (_e = (_d = (_c = (_b = (_a = HAMT.get(token.key, core.atoms)) != null ? _a : HAMT.get(token.key, core.selectors)) != null ? _b : HAMT.get(token.key, core.readonlySelectors)) != null ? _c : HAMT.get(token.key, core.transactions)) != null ? _d : HAMT.get(token.key, core.timelines)) != null ? _e : null;
116
116
  }
117
117
  function deposit(state) {
118
118
  return __spreadValues({
@@ -612,38 +612,59 @@ var Join = class _Join {
612
612
  };
613
613
 
614
614
  // src/internal/store.ts
615
- var createStore = (name) => ({
616
- atoms: HAMT2.make(),
617
- atomsThatAreDefault: /* @__PURE__ */ new Set(),
618
- readonlySelectors: HAMT2.make(),
619
- selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
620
- selectorGraph: new Join({ relationType: `n:n` }),
621
- selectors: HAMT2.make(),
622
- timelines: HAMT2.make(),
623
- timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
624
- timelineStore: HAMT2.make(),
625
- transactions: HAMT2.make(),
626
- valueMap: HAMT2.make(),
627
- subject: {
628
- atomCreation: new Rx.Subject(),
629
- selectorCreation: new Rx.Subject(),
630
- transactionCreation: new Rx.Subject(),
631
- timelineCreation: new Rx.Subject()
632
- },
633
- operation: {
634
- open: false
635
- },
636
- transactionStatus: {
637
- phase: `idle`
638
- },
639
- config: {
640
- name,
641
- logger: __spreadProps(__spreadValues({}, console), {
642
- info: doNothing
643
- }),
644
- logger__INTERNAL: console
645
- }
646
- });
615
+ var createStore = (name, store = null) => {
616
+ var _a;
617
+ const copiedStore = __spreadProps(__spreadValues({}, store != null ? store : (() => ({
618
+ atomsThatAreDefault: /* @__PURE__ */ new Set(),
619
+ selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
620
+ selectorGraph: new Join({ relationType: `n:n` }),
621
+ valueMap: HAMT2.make()
622
+ }))()), {
623
+ atoms: HAMT2.make(),
624
+ readonlySelectors: HAMT2.make(),
625
+ selectors: HAMT2.make(),
626
+ transactions: HAMT2.make(),
627
+ timelines: HAMT2.make(),
628
+ timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
629
+ subject: __spreadValues({
630
+ atomCreation: new Rx.Subject(),
631
+ selectorCreation: new Rx.Subject(),
632
+ transactionCreation: new Rx.Subject(),
633
+ timelineCreation: new Rx.Subject()
634
+ }, store == null ? void 0 : store.subject),
635
+ operation: __spreadValues({
636
+ open: false
637
+ }, store == null ? void 0 : store.operation),
638
+ transactionStatus: __spreadValues({
639
+ phase: `idle`
640
+ }, store == null ? void 0 : store.transactionStatus),
641
+ config: __spreadProps(__spreadValues({
642
+ logger: __spreadValues(__spreadProps(__spreadValues({}, console), {
643
+ info: doNothing
644
+ }), (_a = store == null ? void 0 : store.config) == null ? void 0 : _a.logger),
645
+ logger__INTERNAL: console
646
+ }, store == null ? void 0 : store.config), {
647
+ name
648
+ })
649
+ });
650
+ store == null ? void 0 : store.atoms.forEach((atom2) => {
651
+ const copiedAtom = __spreadProps(__spreadValues({}, atom2), { subject: new Rx.Subject() });
652
+ copiedStore.atoms = HAMT2.set(atom2.key, copiedAtom, copiedStore.atoms);
653
+ });
654
+ store == null ? void 0 : store.readonlySelectors.forEach((selector2) => {
655
+ selector2.install(copiedStore);
656
+ });
657
+ store == null ? void 0 : store.selectors.forEach((selector2) => {
658
+ selector2.install(copiedStore);
659
+ });
660
+ store == null ? void 0 : store.transactions.forEach((tx) => {
661
+ tx.install(copiedStore);
662
+ });
663
+ store == null ? void 0 : store.timelines.forEach((timeline2) => {
664
+ timeline2.install(copiedStore);
665
+ });
666
+ return copiedStore;
667
+ };
647
668
  var IMPLICIT = {
648
669
  STORE_INTERNAL: void 0,
649
670
  get STORE() {
@@ -674,7 +695,9 @@ var openOperation = (token, store) => {
674
695
  time: Date.now(),
675
696
  token
676
697
  };
677
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u2B55 operation start from "${token.key}"`);
698
+ (_b = store.config.logger) == null ? void 0 : _b.info(
699
+ `\u2B55 operation start from "${token.key}" in store "${store.config.name}"`
700
+ );
678
701
  };
679
702
  var closeOperation = (store) => {
680
703
  var _a;
@@ -749,112 +772,6 @@ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
749
772
  // src/internal/transaction-internal.ts
750
773
  import HAMT4 from "hamt_plus";
751
774
  import * as Rx2 from "rxjs";
752
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
753
- var buildTransaction = (key, params, store) => {
754
- var _a;
755
- store.transactionStatus = {
756
- key,
757
- phase: `building`,
758
- core: {
759
- atoms: store.atoms,
760
- atomsThatAreDefault: store.atomsThatAreDefault,
761
- operation: { open: false },
762
- readonlySelectors: store.readonlySelectors,
763
- timelines: store.timelines,
764
- timelineAtoms: store.timelineAtoms,
765
- transactions: store.transactions,
766
- selectorAtoms: store.selectorAtoms,
767
- selectorGraph: store.selectorGraph,
768
- selectors: store.selectors,
769
- valueMap: store.valueMap
770
- },
771
- atomUpdates: [],
772
- params,
773
- output: void 0
774
- };
775
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
776
- };
777
- var applyTransaction = (output, store) => {
778
- var _a, _b, _c, _d;
779
- if (store.transactionStatus.phase !== `building`) {
780
- (_a = store.config.logger) == null ? void 0 : _a.warn(
781
- `abortTransaction called outside of a transaction. This is probably a bug.`
782
- );
783
- return;
784
- }
785
- (_b = store.config.logger) == null ? void 0 : _b.info(
786
- `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
787
- );
788
- store.transactionStatus.phase = `applying`;
789
- store.transactionStatus.output = output;
790
- const { atomUpdates } = store.transactionStatus;
791
- for (const { key, newValue } of atomUpdates) {
792
- const token = { key, type: `atom` };
793
- if (!HAMT4.has(token.key, store.valueMap)) {
794
- const newAtom = HAMT4.get(token.key, store.transactionStatus.core.atoms);
795
- store.atoms = HAMT4.set(newAtom.key, newAtom, store.atoms);
796
- store.valueMap = HAMT4.set(newAtom.key, newAtom.default, store.valueMap);
797
- (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${newAtom.key}"`);
798
- }
799
- setState(token, newValue, store);
800
- }
801
- const myTransaction = withdraw(
802
- { key: store.transactionStatus.key, type: `transaction` },
803
- store
804
- );
805
- if (myTransaction === null) {
806
- throw new Error(
807
- `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
808
- );
809
- }
810
- myTransaction.subject.next({
811
- key: store.transactionStatus.key,
812
- atomUpdates,
813
- output,
814
- params: store.transactionStatus.params
815
- });
816
- store.transactionStatus = { phase: `idle` };
817
- (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
818
- };
819
- var undoTransactionUpdate = (update, store) => {
820
- var _a;
821
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
822
- for (const { key, oldValue } of update.atomUpdates) {
823
- const token = { key, type: `atom` };
824
- const state = withdraw(token, store);
825
- if (state === null) {
826
- throw new Error(
827
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
828
- );
829
- }
830
- setState(state, oldValue, store);
831
- }
832
- };
833
- var redoTransactionUpdate = (update, store) => {
834
- var _a;
835
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
836
- for (const { key, newValue } of update.atomUpdates) {
837
- const token = { key, type: `atom` };
838
- const state = withdraw(token, store);
839
- if (state === null) {
840
- throw new Error(
841
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
842
- );
843
- }
844
- setState(state, newValue, store);
845
- }
846
- };
847
- var abortTransaction = (store) => {
848
- var _a, _b;
849
- if (store.transactionStatus.phase === `idle`) {
850
- (_a = store.config.logger) == null ? void 0 : _a.warn(
851
- `abortTransaction called outside of a transaction. This is probably a bug.`
852
- );
853
- return;
854
- }
855
- store.transactionStatus = { phase: `idle` };
856
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
857
- };
858
775
  function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
859
776
  const newTransaction = {
860
777
  key: options.key,
@@ -878,6 +795,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
878
795
  throw thrown;
879
796
  }
880
797
  },
798
+ install: (store2) => transaction__INTERNAL(options, store2),
881
799
  subject: new Rx2.Subject()
882
800
  };
883
801
  const core = target(store);
@@ -1137,9 +1055,59 @@ var attachMetaState = (store = IMPLICIT.STORE) => {
1137
1055
  };
1138
1056
 
1139
1057
  // src/internal/selector-internal.ts
1058
+ import HAMT9 from "hamt_plus";
1059
+
1060
+ // src/internal/selector/create-read-write-selector.ts
1140
1061
  import HAMT6 from "hamt_plus";
1141
1062
  import * as Rx5 from "rxjs";
1063
+ var createReadWriteSelector = (options, family, store, core) => {
1064
+ var _a;
1065
+ const subject = new Rx5.Subject();
1066
+ const { get, set } = registerSelector(options.key, store);
1067
+ const getSelf = () => {
1068
+ const value = options.get({ get });
1069
+ cacheValue(options.key, value, store);
1070
+ return value;
1071
+ };
1072
+ const setSelf = (next) => {
1073
+ var _a2;
1074
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1075
+ const oldValue = getSelf();
1076
+ const newValue = become(next)(oldValue);
1077
+ cacheValue(options.key, newValue, store);
1078
+ markDone(options.key, store);
1079
+ if (store.transactionStatus.phase === `idle`) {
1080
+ subject.next({ newValue, oldValue });
1081
+ }
1082
+ options.set({ get, set }, newValue);
1083
+ };
1084
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1085
+ subject,
1086
+ install: (s) => selector__INTERNAL(options, family, s),
1087
+ get: getSelf,
1088
+ set: setSelf,
1089
+ type: `selector`
1090
+ }), family && { family });
1091
+ core.selectors = HAMT6.set(options.key, mySelector, core.selectors);
1092
+ const initialValue = getSelf();
1093
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1094
+ const token = {
1095
+ key: options.key,
1096
+ type: `selector`,
1097
+ family
1098
+ };
1099
+ store.subject.selectorCreation.next(token);
1100
+ return token;
1101
+ };
1102
+
1103
+ // src/internal/selector/create-readonly-selector.ts
1104
+ import HAMT8 from "hamt_plus";
1105
+ import * as Rx6 from "rxjs";
1106
+
1107
+ // src/internal/selector/lookup-selector-sources.ts
1142
1108
  var lookupSelectorSources = (key, store) => target(store).selectorGraph.getRelations(key).filter(({ source }) => source !== key).map(({ source }) => lookup(source, store));
1109
+
1110
+ // src/internal/selector/trace-selector-atoms.ts
1143
1111
  var traceSelectorAtoms = (selectorKey, dependency, store) => {
1144
1112
  const roots = [];
1145
1113
  const sources = lookupSelectorSources(dependency.key, store);
@@ -1166,6 +1134,8 @@ var traceAllSelectorAtoms = (selectorKey, store) => {
1166
1134
  (source) => source.type === `atom` ? source : traceSelectorAtoms(selectorKey, source, store)
1167
1135
  );
1168
1136
  };
1137
+
1138
+ // src/internal/selector/update-selector-atoms.ts
1169
1139
  var updateSelectorAtoms = (selectorKey, dependency, store) => {
1170
1140
  var _a, _b;
1171
1141
  const core = target(store);
@@ -1191,114 +1161,6 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1191
1161
  });
1192
1162
  }
1193
1163
  };
1194
- var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1195
- get: (dependency) => {
1196
- var _a, _b;
1197
- const core = target(store);
1198
- const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1199
- const dependencyState = withdraw(dependency, store);
1200
- if (dependencyState === null) {
1201
- throw new Error(
1202
- `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1203
- );
1204
- }
1205
- const dependencyValue = getState__INTERNAL(dependencyState, store);
1206
- if (alreadyRegistered) {
1207
- (_a = store.config.logger) == null ? void 0 : _a.info(
1208
- ` || ${selectorKey} <- ${dependency.key} =`,
1209
- dependencyValue
1210
- );
1211
- } else {
1212
- (_b = store.config.logger) == null ? void 0 : _b.info(
1213
- `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1214
- dependencyValue,
1215
- `)`
1216
- );
1217
- core.selectorGraph = core.selectorGraph.set(
1218
- { from: dependency.key, to: selectorKey },
1219
- {
1220
- source: dependency.key
1221
- }
1222
- );
1223
- }
1224
- updateSelectorAtoms(selectorKey, dependency, store);
1225
- return dependencyValue;
1226
- },
1227
- set: (stateToken, newValue) => {
1228
- const state = withdraw(stateToken, store);
1229
- if (state === null) {
1230
- throw new Error(
1231
- `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1232
- );
1233
- }
1234
- setState__INTERNAL(state, newValue, store);
1235
- }
1236
- });
1237
- function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1238
- var _a, _b, _c;
1239
- const core = target(store);
1240
- if (HAMT6.has(options.key, core.selectors)) {
1241
- (_a = store.config.logger) == null ? void 0 : _a.error(
1242
- `Key "${options.key}" already exists in the store.`
1243
- );
1244
- }
1245
- const subject = new Rx5.Subject();
1246
- const { get, set } = registerSelector(options.key, store);
1247
- const getSelf = () => {
1248
- const value = options.get({ get });
1249
- cacheValue(options.key, value, store);
1250
- return value;
1251
- };
1252
- if (!(`set` in options)) {
1253
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1254
- subject,
1255
- get: getSelf,
1256
- type: `readonly_selector`
1257
- }), family && { family });
1258
- core.readonlySelectors = HAMT6.set(
1259
- options.key,
1260
- readonlySelector,
1261
- core.readonlySelectors
1262
- );
1263
- const initialValue2 = getSelf();
1264
- (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
1265
- const token2 = {
1266
- key: options.key,
1267
- type: `readonly_selector`,
1268
- family
1269
- };
1270
- store.subject.selectorCreation.next(token2);
1271
- return token2;
1272
- }
1273
- const setSelf = (next) => {
1274
- var _a2;
1275
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1276
- const oldValue = getSelf();
1277
- const newValue = become(next)(oldValue);
1278
- cacheValue(options.key, newValue, store);
1279
- markDone(options.key, store);
1280
- if (store.transactionStatus.phase === `idle`) {
1281
- subject.next({ newValue, oldValue });
1282
- }
1283
- options.set({ get, set }, newValue);
1284
- };
1285
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1286
- subject,
1287
- get: getSelf,
1288
- set: setSelf,
1289
- type: `selector`
1290
- }), family && { family });
1291
- core.selectors = HAMT6.set(options.key, mySelector, core.selectors);
1292
- const initialValue = getSelf();
1293
- (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
1294
- const token = {
1295
- key: options.key,
1296
- type: `selector`,
1297
- family
1298
- };
1299
- store.subject.selectorCreation.next(token);
1300
- return token;
1301
- }
1302
1164
 
1303
1165
  // src/internal/set.ts
1304
1166
  import HAMT7 from "hamt_plus";
@@ -1369,6 +1231,98 @@ var setState__INTERNAL = (state, value, store = IMPLICIT.STORE) => {
1369
1231
  }
1370
1232
  };
1371
1233
 
1234
+ // src/internal/selector/register-selector.ts
1235
+ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1236
+ get: (dependency) => {
1237
+ var _a, _b;
1238
+ const core = target(store);
1239
+ const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1240
+ const dependencyState = withdraw(dependency, store);
1241
+ if (dependencyState === null) {
1242
+ throw new Error(
1243
+ `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1244
+ );
1245
+ }
1246
+ const dependencyValue = getState__INTERNAL(dependencyState, store);
1247
+ if (alreadyRegistered) {
1248
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1249
+ ` || ${selectorKey} <- ${dependency.key} =`,
1250
+ dependencyValue
1251
+ );
1252
+ } else {
1253
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1254
+ `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1255
+ dependencyValue,
1256
+ `)`
1257
+ );
1258
+ core.selectorGraph = core.selectorGraph.set(
1259
+ { from: dependency.key, to: selectorKey },
1260
+ {
1261
+ source: dependency.key
1262
+ }
1263
+ );
1264
+ }
1265
+ updateSelectorAtoms(selectorKey, dependency, store);
1266
+ return dependencyValue;
1267
+ },
1268
+ set: (stateToken, newValue) => {
1269
+ const state = withdraw(stateToken, store);
1270
+ if (state === null) {
1271
+ throw new Error(
1272
+ `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1273
+ );
1274
+ }
1275
+ setState__INTERNAL(state, newValue, store);
1276
+ }
1277
+ });
1278
+
1279
+ // src/internal/selector/create-readonly-selector.ts
1280
+ var createReadonlySelector = (options, family, store, core) => {
1281
+ var _a;
1282
+ const subject = new Rx6.Subject();
1283
+ const { get } = registerSelector(options.key, store);
1284
+ const getSelf = () => {
1285
+ const value = options.get({ get });
1286
+ cacheValue(options.key, value, store);
1287
+ return value;
1288
+ };
1289
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1290
+ subject,
1291
+ install: (s) => selector__INTERNAL(options, family, s),
1292
+ get: getSelf,
1293
+ type: `readonly_selector`
1294
+ }), family && { family });
1295
+ core.readonlySelectors = HAMT8.set(
1296
+ options.key,
1297
+ readonlySelector,
1298
+ core.readonlySelectors
1299
+ );
1300
+ const initialValue = getSelf();
1301
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1302
+ const token = {
1303
+ key: options.key,
1304
+ type: `readonly_selector`,
1305
+ family
1306
+ };
1307
+ store.subject.selectorCreation.next(token);
1308
+ return token;
1309
+ };
1310
+
1311
+ // src/internal/selector-internal.ts
1312
+ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1313
+ var _a;
1314
+ const core = target(store);
1315
+ if (HAMT9.has(options.key, core.selectors)) {
1316
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1317
+ `Key "${options.key}" already exists in the store.`
1318
+ );
1319
+ }
1320
+ if (!(`set` in options)) {
1321
+ return createReadonlySelector(options, family, store, core);
1322
+ }
1323
+ return createReadWriteSelector(options, family, store, core);
1324
+ }
1325
+
1372
1326
  // src/internal/subscribe-internal.ts
1373
1327
  var prepareUpdate = (state, store) => {
1374
1328
  const oldValue = recallState(state, store);
@@ -1430,7 +1384,7 @@ var subscribeToRootAtoms = (state, store) => {
1430
1384
  var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1431
1385
  var _a, _b, _c, _d;
1432
1386
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23E9 redo "${token.key}"`);
1433
- const timelineData = store.timelineStore.get(token.key);
1387
+ const timelineData = store.timelines.get(token.key);
1434
1388
  if (!timelineData) {
1435
1389
  (_b = store.config.logger) == null ? void 0 : _b.error(
1436
1390
  `Failed to redo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1448,14 +1402,14 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1448
1402
  switch (update.type) {
1449
1403
  case `atom_update`: {
1450
1404
  const { key, newValue } = update;
1451
- setState({ key, type: `atom` }, newValue);
1405
+ setState({ key, type: `atom` }, newValue, store);
1452
1406
  break;
1453
1407
  }
1454
1408
  case `selector_update`:
1455
1409
  case `transaction_update`: {
1456
1410
  for (const atomUpdate of update.atomUpdates) {
1457
1411
  const { key, newValue } = atomUpdate;
1458
- setState({ key, type: `atom` }, newValue);
1412
+ setState({ key, type: `atom` }, newValue, store);
1459
1413
  }
1460
1414
  break;
1461
1415
  }
@@ -1469,7 +1423,7 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1469
1423
  var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1470
1424
  var _a, _b, _c, _d;
1471
1425
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23EA undo "${token.key}"`);
1472
- const timelineData = store.timelineStore.get(token.key);
1426
+ const timelineData = store.timelines.get(token.key);
1473
1427
  if (!timelineData) {
1474
1428
  (_b = store.config.logger) == null ? void 0 : _b.error(
1475
1429
  `Failed to undo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1488,14 +1442,14 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1488
1442
  switch (update.type) {
1489
1443
  case `atom_update`: {
1490
1444
  const { key, oldValue } = update;
1491
- setState({ key, type: `atom` }, oldValue);
1445
+ setState({ key, type: `atom` }, oldValue, store);
1492
1446
  break;
1493
1447
  }
1494
1448
  case `selector_update`:
1495
1449
  case `transaction_update`: {
1496
1450
  for (const atomUpdate of update.atomUpdates) {
1497
1451
  const { key, oldValue } = atomUpdate;
1498
- setState({ key, type: `atom` }, oldValue);
1452
+ setState({ key, type: `atom` }, oldValue, store);
1499
1453
  }
1500
1454
  break;
1501
1455
  }
@@ -1507,142 +1461,166 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1507
1461
  };
1508
1462
 
1509
1463
  // src/internal/timeline-internal.ts
1510
- import HAMT8 from "hamt_plus";
1511
- function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1512
- var _a, _b;
1513
- const timelineData = {
1514
- at: 0,
1515
- timeTraveling: false,
1516
- history: [],
1517
- selectorTime: null,
1518
- transactionKey: null
1519
- };
1520
- const subscribeToAtom = (token2) => {
1521
- const state = withdraw(token2, store);
1522
- if (state === null) {
1523
- throw new Error(
1524
- `Cannot subscribe to atom "${token2.key}" because it has not been initialized in store "${store.config.name}"`
1525
- );
1526
- }
1527
- state.subject.subscribe((update) => {
1528
- var _a2, _b2, _c, _d, _e;
1529
- const storeCurrentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1530
- const storeCurrentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1531
- const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1532
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1533
- `\u23F3 timeline "${options.key}" saw atom "${token2.key}" go (`,
1534
- update.oldValue,
1535
- `->`,
1536
- update.newValue,
1537
- storeCurrentTransactionKey ? `) in transaction "${storeCurrentTransactionKey}"` : storeCurrentSelectorKey ? `) in selector "${storeCurrentSelectorKey}"` : `)`
1538
- );
1539
- if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1464
+ import HAMT10 from "hamt_plus";
1465
+ import * as Rx7 from "rxjs";
1466
+
1467
+ // src/internal/timeline/add-atom-to-timeline.ts
1468
+ var addAtomToTimeline = (atomToken, atoms, tl, store = IMPLICIT.STORE) => {
1469
+ const atom2 = withdraw(atomToken, store);
1470
+ if (atom2 === null) {
1471
+ throw new Error(
1472
+ `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
1473
+ );
1474
+ }
1475
+ atom2.subject.subscribe((update) => {
1476
+ var _a, _b, _c, _d, _e;
1477
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1478
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1479
+ const currentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1480
+ const currentTransactionTime = store.transactionStatus.phase === `applying` ? store.transactionStatus.time : null;
1481
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1482
+ `\u23F3 timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
1483
+ update.oldValue,
1484
+ `->`,
1485
+ update.newValue,
1486
+ currentTransactionKey ? `) in transaction "${currentTransactionKey}"` : currentSelectorKey ? `) in selector "${currentSelectorKey}"` : `)`
1487
+ );
1488
+ if (tl.timeTraveling === false) {
1489
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1490
+ const mostRecentUpdate = tl.history.at(-1);
1491
+ if (mostRecentUpdate.type === `selector_update`) {
1492
+ tl.subject.next(mostRecentUpdate);
1493
+ }
1494
+ }
1495
+ if (currentTransactionKey && store.transactionStatus.phase === `applying`) {
1540
1496
  const currentTransaction = withdraw(
1541
- { key: storeCurrentTransactionKey, type: `transaction` },
1497
+ { key: currentTransactionKey, type: `transaction` },
1542
1498
  store
1543
1499
  );
1544
1500
  if (currentTransaction === null) {
1545
1501
  throw new Error(
1546
- `Transaction "${storeCurrentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${storeCurrentTransactionKey}".`
1502
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
1547
1503
  );
1548
1504
  }
1549
- if (timelineData.transactionKey !== storeCurrentTransactionKey) {
1550
- if (timelineData.transactionKey) {
1551
- (_b2 = store.config.logger) == null ? void 0 : _b2.error(
1552
- `Timeline "${options.key}" was unable to resolve transaction "${timelineData.transactionKey}. This is probably a bug.`
1505
+ if (tl.transactionKey !== currentTransactionKey) {
1506
+ if (tl.transactionKey) {
1507
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1508
+ `Timeline "${tl.key}" was unable to resolve transaction "${tl.transactionKey}. This is probably a bug.`
1553
1509
  );
1554
1510
  }
1555
- timelineData.transactionKey = storeCurrentTransactionKey;
1511
+ tl.transactionKey = currentTransactionKey;
1556
1512
  const subscription = currentTransaction.subject.subscribe((update2) => {
1557
- var _a3;
1558
- if (timelineData.timeTraveling === false) {
1559
- if (timelineData.at !== timelineData.history.length) {
1560
- timelineData.history.splice(timelineData.at);
1513
+ var _a2;
1514
+ if (tl.timeTraveling === false && currentTransactionTime) {
1515
+ if (tl.at !== tl.history.length) {
1516
+ tl.history.splice(tl.at);
1561
1517
  }
1562
- timelineData.history.push(__spreadProps(__spreadValues({
1563
- type: `transaction_update`
1518
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
1519
+ type: `transaction_update`,
1520
+ timestamp: currentTransactionTime
1564
1521
  }, update2), {
1565
1522
  atomUpdates: update2.atomUpdates.filter(
1566
- (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1523
+ (atomUpdate) => atoms.some((atom3) => atom3.key === atomUpdate.key)
1567
1524
  )
1568
- }));
1525
+ });
1526
+ tl.history.push(timelineTransactionUpdate);
1527
+ tl.subject.next(timelineTransactionUpdate);
1569
1528
  }
1570
- timelineData.at = timelineData.history.length;
1529
+ tl.at = tl.history.length;
1571
1530
  subscription.unsubscribe();
1572
- timelineData.transactionKey = null;
1573
- (_a3 = store.config.logger) == null ? void 0 : _a3.info(
1574
- `\u231B timeline "${options.key}" got a transaction_update "${update2.key}"`
1531
+ tl.transactionKey = null;
1532
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1533
+ `\u231B timeline "${tl.key}" got a transaction_update "${update2.key}"`
1575
1534
  );
1576
1535
  });
1577
1536
  }
1578
- } else if (storeCurrentSelectorKey) {
1579
- if (timelineData.timeTraveling === false) {
1580
- if (storeCurrentSelectorTime !== timelineData.selectorTime) {
1581
- const newSelectorUpdate = {
1582
- type: `selector_update`,
1583
- key: storeCurrentSelectorKey,
1584
- atomUpdates: []
1585
- };
1586
- newSelectorUpdate.atomUpdates.push(__spreadValues({
1587
- key: token2.key,
1537
+ } else if (currentSelectorKey && currentSelectorTime) {
1538
+ if (currentSelectorTime !== tl.selectorTime) {
1539
+ const newSelectorUpdate = {
1540
+ type: `selector_update`,
1541
+ timestamp: currentSelectorTime,
1542
+ key: currentSelectorKey,
1543
+ atomUpdates: []
1544
+ };
1545
+ newSelectorUpdate.atomUpdates.push(__spreadValues({
1546
+ key: atom2.key,
1547
+ type: `atom_update`
1548
+ }, update));
1549
+ if (tl.at !== tl.history.length) {
1550
+ tl.history.splice(tl.at);
1551
+ }
1552
+ tl.history.push(newSelectorUpdate);
1553
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1554
+ `\u231B timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
1555
+ newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1556
+ );
1557
+ tl.at = tl.history.length;
1558
+ tl.selectorTime = currentSelectorTime;
1559
+ } else {
1560
+ const latestUpdate = tl.history.at(-1);
1561
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1562
+ latestUpdate.atomUpdates.push(__spreadValues({
1563
+ key: atom2.key,
1588
1564
  type: `atom_update`
1589
1565
  }, update));
1590
- if (timelineData.at !== timelineData.history.length) {
1591
- timelineData.history.splice(timelineData.at);
1592
- }
1593
- timelineData.history.push(newSelectorUpdate);
1594
- (_c = store.config.logger) == null ? void 0 : _c.info(
1595
- `\u231B timeline "${options.key}" got a selector_update "${storeCurrentSelectorKey}" with`,
1596
- newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1566
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1567
+ ` \u231B timeline "${tl.key}" set selector_update "${currentSelectorKey}" to`,
1568
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1597
1569
  );
1598
- timelineData.at = timelineData.history.length;
1599
- timelineData.selectorTime = storeCurrentSelectorTime;
1600
- } else {
1601
- const latestUpdate = timelineData.history.at(-1);
1602
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1603
- latestUpdate.atomUpdates.push(__spreadValues({
1604
- key: token2.key,
1605
- type: `atom_update`
1606
- }, update));
1607
- (_d = store.config.logger) == null ? void 0 : _d.info(
1608
- ` \u231B timeline "${options.key}" set selector_update "${storeCurrentSelectorKey}" to`,
1609
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1610
- );
1611
- }
1612
1570
  }
1613
1571
  }
1614
1572
  } else {
1615
- if (timelineData.timeTraveling === false) {
1616
- timelineData.selectorTime = null;
1617
- if (timelineData.at !== timelineData.history.length) {
1618
- timelineData.history.splice(timelineData.at);
1619
- }
1620
- timelineData.history.push({
1621
- type: `atom_update`,
1622
- key: token2.key,
1623
- oldValue: update.oldValue,
1624
- newValue: update.newValue
1625
- });
1626
- (_e = store.config.logger) == null ? void 0 : _e.info(
1627
- `\u231B timeline "${options.key}" got a state_update to "${token2.key}"`
1628
- );
1629
- timelineData.at = timelineData.history.length;
1573
+ const timestamp = Date.now();
1574
+ tl.selectorTime = null;
1575
+ if (tl.at !== tl.history.length) {
1576
+ tl.history.splice(tl.at);
1630
1577
  }
1578
+ const atomUpdate = {
1579
+ type: `atom_update`,
1580
+ timestamp,
1581
+ key: atom2.key,
1582
+ oldValue: update.oldValue,
1583
+ newValue: update.newValue
1584
+ };
1585
+ tl.history.push(atomUpdate);
1586
+ tl.subject.next(atomUpdate);
1587
+ (_e = store.config.logger) == null ? void 0 : _e.info(
1588
+ `\u231B timeline "${tl.key}" got a state_update to "${atom2.key}"`
1589
+ );
1590
+ tl.at = tl.history.length;
1631
1591
  }
1632
- });
1633
- };
1592
+ }
1593
+ });
1594
+ };
1595
+
1596
+ // src/internal/timeline-internal.ts
1597
+ function timeline__INTERNAL(options, store = IMPLICIT.STORE, data = null) {
1598
+ var _a, _b, _c;
1599
+ const tl = __spreadProps(__spreadValues({
1600
+ key: options.key,
1601
+ at: 0,
1602
+ timeTraveling: false,
1603
+ selectorTime: null,
1604
+ transactionKey: null
1605
+ }, data), {
1606
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1607
+ install: (store2) => timeline__INTERNAL(options, store2, tl),
1608
+ subject: new Rx7.Subject()
1609
+ });
1634
1610
  const core = target(store);
1635
1611
  for (const tokenOrFamily of options.atoms) {
1636
1612
  const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key);
1637
1613
  if (timelineKey) {
1638
- (_a = store.config.logger) == null ? void 0 : _a.error(
1614
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1639
1615
  `\u274C Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
1640
1616
  );
1641
1617
  continue;
1642
1618
  }
1643
1619
  if (tokenOrFamily.type === `atom_family`) {
1644
1620
  const family = tokenOrFamily;
1645
- family.subject.subscribe((token2) => subscribeToAtom(token2));
1621
+ family.subject.subscribe(
1622
+ (token2) => addAtomToTimeline(token2, options.atoms, tl, store)
1623
+ );
1646
1624
  } else {
1647
1625
  const token2 = tokenOrFamily;
1648
1626
  if (`family` in token2 && token2.family) {
@@ -1650,20 +1628,20 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1650
1628
  token2.family.key
1651
1629
  );
1652
1630
  if (familyTimelineKey) {
1653
- (_b = store.config.logger) == null ? void 0 : _b.error(
1631
+ (_c = store.config.logger) == null ? void 0 : _c.error(
1654
1632
  `\u274C Failed to add atom "${token2.key}" to timeline "${options.key}" because its family "${token2.family.key}" belongs to timeline "${familyTimelineKey}"`
1655
1633
  );
1656
1634
  continue;
1657
1635
  }
1658
1636
  }
1659
- subscribeToAtom(token2);
1637
+ addAtomToTimeline(token2, options.atoms, tl, store);
1660
1638
  }
1661
1639
  core.timelineAtoms = core.timelineAtoms.set({
1662
1640
  atomKey: tokenOrFamily.key,
1663
1641
  timelineKey: options.key
1664
1642
  });
1665
1643
  }
1666
- store.timelineStore = HAMT8.set(options.key, timelineData, store.timelineStore);
1644
+ store.timelines = HAMT10.set(options.key, tl, store.timelines);
1667
1645
  const token = {
1668
1646
  key: options.key,
1669
1647
  type: `timeline`
@@ -1672,6 +1650,129 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1672
1650
  return token;
1673
1651
  }
1674
1652
 
1653
+ // src/internal/transaction/abort-transaction.ts
1654
+ var abortTransaction = (store) => {
1655
+ var _a, _b;
1656
+ if (store.transactionStatus.phase === `idle`) {
1657
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1658
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1659
+ );
1660
+ return;
1661
+ }
1662
+ store.transactionStatus = { phase: `idle` };
1663
+ (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
1664
+ };
1665
+
1666
+ // src/internal/transaction/apply-transaction.ts
1667
+ import HAMT11 from "hamt_plus";
1668
+ var applyTransaction = (output, store) => {
1669
+ var _a, _b, _c, _d;
1670
+ if (store.transactionStatus.phase !== `building`) {
1671
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1672
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1673
+ );
1674
+ return;
1675
+ }
1676
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1677
+ `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
1678
+ );
1679
+ store.transactionStatus.phase = `applying`;
1680
+ store.transactionStatus.output = output;
1681
+ const { atomUpdates } = store.transactionStatus;
1682
+ for (const { key, newValue } of atomUpdates) {
1683
+ const token = { key, type: `atom` };
1684
+ if (!HAMT11.has(token.key, store.valueMap)) {
1685
+ const newAtom = HAMT11.get(token.key, store.transactionStatus.core.atoms);
1686
+ store.atoms = HAMT11.set(newAtom.key, newAtom, store.atoms);
1687
+ store.valueMap = HAMT11.set(newAtom.key, newAtom.default, store.valueMap);
1688
+ (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${newAtom.key}"`);
1689
+ }
1690
+ setState(token, newValue, store);
1691
+ }
1692
+ const myTransaction = withdraw(
1693
+ { key: store.transactionStatus.key, type: `transaction` },
1694
+ store
1695
+ );
1696
+ if (myTransaction === null) {
1697
+ throw new Error(
1698
+ `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
1699
+ );
1700
+ }
1701
+ myTransaction.subject.next({
1702
+ key: store.transactionStatus.key,
1703
+ atomUpdates,
1704
+ output,
1705
+ params: store.transactionStatus.params
1706
+ });
1707
+ store.transactionStatus = { phase: `idle` };
1708
+ (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
1709
+ };
1710
+
1711
+ // src/internal/transaction/build-transaction.ts
1712
+ var buildTransaction = (key, params, store) => {
1713
+ var _a;
1714
+ store.transactionStatus = {
1715
+ key,
1716
+ phase: `building`,
1717
+ time: Date.now(),
1718
+ core: {
1719
+ atoms: store.atoms,
1720
+ atomsThatAreDefault: store.atomsThatAreDefault,
1721
+ operation: { open: false },
1722
+ readonlySelectors: store.readonlySelectors,
1723
+ timelines: store.timelines,
1724
+ timelineAtoms: store.timelineAtoms,
1725
+ transactions: store.transactions,
1726
+ selectorAtoms: store.selectorAtoms,
1727
+ selectorGraph: store.selectorGraph,
1728
+ selectors: store.selectors,
1729
+ valueMap: store.valueMap
1730
+ },
1731
+ atomUpdates: [],
1732
+ params,
1733
+ output: void 0
1734
+ };
1735
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1736
+ `\u{1F6EB}`,
1737
+ `transaction "${key}" started in store "${store.config.name}"`
1738
+ );
1739
+ };
1740
+
1741
+ // src/internal/transaction/redo-transaction.ts
1742
+ var redoTransactionUpdate = (update, store) => {
1743
+ var _a;
1744
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
1745
+ for (const { key, newValue } of update.atomUpdates) {
1746
+ const token = { key, type: `atom` };
1747
+ const state = withdraw(token, store);
1748
+ if (state === null) {
1749
+ throw new Error(
1750
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1751
+ );
1752
+ }
1753
+ setState(state, newValue, store);
1754
+ }
1755
+ };
1756
+
1757
+ // src/internal/transaction/undo-transaction.ts
1758
+ var undoTransactionUpdate = (update, store) => {
1759
+ var _a;
1760
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
1761
+ for (const { key, oldValue } of update.atomUpdates) {
1762
+ const token = { key, type: `atom` };
1763
+ const state = withdraw(token, store);
1764
+ if (state === null) {
1765
+ throw new Error(
1766
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1767
+ );
1768
+ }
1769
+ setState(state, oldValue, store);
1770
+ }
1771
+ };
1772
+
1773
+ // src/internal/transaction/index.ts
1774
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1775
+
1675
1776
  // src/atom.ts
1676
1777
  function atom(options) {
1677
1778
  return atom__INTERNAL(options);
@@ -1722,8 +1823,8 @@ function selectorFamily(options) {
1722
1823
  }
1723
1824
 
1724
1825
  // src/silo.ts
1725
- var silo = (name) => {
1726
- const store = createStore(name);
1826
+ var silo = (name, fromStore = null) => {
1827
+ const store = createStore(name, fromStore);
1727
1828
  return {
1728
1829
  store,
1729
1830
  atom: (options) => atom__INTERNAL(options, void 0, store),
@@ -1734,7 +1835,9 @@ var silo = (name) => {
1734
1835
  timeline: (options) => timeline__INTERNAL(options, store),
1735
1836
  getState: (token) => getState(token, store),
1736
1837
  setState: (token, newValue) => setState(token, newValue, store),
1737
- subscribe: (token, handler) => subscribe(token, handler, store)
1838
+ subscribe: (token, handler) => subscribe(token, handler, store),
1839
+ undo: (token) => undo__INTERNAL(token, store),
1840
+ redo: (token) => redo__INTERNAL(token, store)
1738
1841
  };
1739
1842
  };
1740
1843
 
@@ -1783,6 +1886,23 @@ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1783
1886
  };
1784
1887
  return unsubscribe;
1785
1888
  };
1889
+ var subscribeToTimeline = (token, handleUpdate, store = IMPLICIT.STORE) => {
1890
+ var _a;
1891
+ const tl = withdraw(token, store);
1892
+ if (tl === null) {
1893
+ throw new Error(
1894
+ `Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`
1895
+ );
1896
+ }
1897
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to timeline "${token.key}"`);
1898
+ const subscription = tl.subject.subscribe(handleUpdate);
1899
+ const unsubscribe = () => {
1900
+ var _a2;
1901
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from timeline "${token.key}"`);
1902
+ subscription.unsubscribe();
1903
+ };
1904
+ return unsubscribe;
1905
+ };
1786
1906
 
1787
1907
  // src/timeline.ts
1788
1908
  var timeline = (options) => {
@@ -1853,6 +1973,7 @@ export {
1853
1973
  setState,
1854
1974
  silo,
1855
1975
  subscribe,
1976
+ subscribeToTimeline,
1856
1977
  subscribeToTransaction,
1857
1978
  timeline,
1858
1979
  transaction,