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.js CHANGED
@@ -72,6 +72,7 @@ __export(src_exports, {
72
72
  setState: () => setState,
73
73
  silo: () => silo,
74
74
  subscribe: () => subscribe,
75
+ subscribeToTimeline: () => subscribeToTimeline,
75
76
  subscribeToTransaction: () => subscribeToTransaction,
76
77
  timeline: () => timeline,
77
78
  transaction: () => transaction,
@@ -156,9 +157,9 @@ function lookup(key, store) {
156
157
  return { key, type };
157
158
  }
158
159
  function withdraw(token, store) {
159
- var _a, _b, _c, _d;
160
+ var _a, _b, _c, _d, _e;
160
161
  const core = target(store);
161
- return (_d = (_c = (_b = (_a = import_hamt_plus.default.get(token.key, core.atoms)) != null ? _a : import_hamt_plus.default.get(token.key, core.selectors)) != null ? _b : import_hamt_plus.default.get(token.key, core.readonlySelectors)) != null ? _c : import_hamt_plus.default.get(token.key, core.transactions)) != null ? _d : null;
162
+ return (_e = (_d = (_c = (_b = (_a = import_hamt_plus.default.get(token.key, core.atoms)) != null ? _a : import_hamt_plus.default.get(token.key, core.selectors)) != null ? _b : import_hamt_plus.default.get(token.key, core.readonlySelectors)) != null ? _c : import_hamt_plus.default.get(token.key, core.transactions)) != null ? _d : import_hamt_plus.default.get(token.key, core.timelines)) != null ? _e : null;
162
163
  }
163
164
  function deposit(state) {
164
165
  return __spreadValues({
@@ -658,38 +659,59 @@ var Join = class _Join {
658
659
  };
659
660
 
660
661
  // src/internal/store.ts
661
- var createStore = (name) => ({
662
- atoms: import_hamt_plus2.default.make(),
663
- atomsThatAreDefault: /* @__PURE__ */ new Set(),
664
- readonlySelectors: import_hamt_plus2.default.make(),
665
- selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
666
- selectorGraph: new Join({ relationType: `n:n` }),
667
- selectors: import_hamt_plus2.default.make(),
668
- timelines: import_hamt_plus2.default.make(),
669
- timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
670
- timelineStore: import_hamt_plus2.default.make(),
671
- transactions: import_hamt_plus2.default.make(),
672
- valueMap: import_hamt_plus2.default.make(),
673
- subject: {
674
- atomCreation: new Rx.Subject(),
675
- selectorCreation: new Rx.Subject(),
676
- transactionCreation: new Rx.Subject(),
677
- timelineCreation: new Rx.Subject()
678
- },
679
- operation: {
680
- open: false
681
- },
682
- transactionStatus: {
683
- phase: `idle`
684
- },
685
- config: {
686
- name,
687
- logger: __spreadProps(__spreadValues({}, console), {
688
- info: doNothing
689
- }),
690
- logger__INTERNAL: console
691
- }
692
- });
662
+ var createStore = (name, store = null) => {
663
+ var _a;
664
+ const copiedStore = __spreadProps(__spreadValues({}, store != null ? store : (() => ({
665
+ atomsThatAreDefault: /* @__PURE__ */ new Set(),
666
+ selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
667
+ selectorGraph: new Join({ relationType: `n:n` }),
668
+ valueMap: import_hamt_plus2.default.make()
669
+ }))()), {
670
+ atoms: import_hamt_plus2.default.make(),
671
+ readonlySelectors: import_hamt_plus2.default.make(),
672
+ selectors: import_hamt_plus2.default.make(),
673
+ transactions: import_hamt_plus2.default.make(),
674
+ timelines: import_hamt_plus2.default.make(),
675
+ timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
676
+ subject: __spreadValues({
677
+ atomCreation: new Rx.Subject(),
678
+ selectorCreation: new Rx.Subject(),
679
+ transactionCreation: new Rx.Subject(),
680
+ timelineCreation: new Rx.Subject()
681
+ }, store == null ? void 0 : store.subject),
682
+ operation: __spreadValues({
683
+ open: false
684
+ }, store == null ? void 0 : store.operation),
685
+ transactionStatus: __spreadValues({
686
+ phase: `idle`
687
+ }, store == null ? void 0 : store.transactionStatus),
688
+ config: __spreadProps(__spreadValues({
689
+ logger: __spreadValues(__spreadProps(__spreadValues({}, console), {
690
+ info: doNothing
691
+ }), (_a = store == null ? void 0 : store.config) == null ? void 0 : _a.logger),
692
+ logger__INTERNAL: console
693
+ }, store == null ? void 0 : store.config), {
694
+ name
695
+ })
696
+ });
697
+ store == null ? void 0 : store.atoms.forEach((atom2) => {
698
+ const copiedAtom = __spreadProps(__spreadValues({}, atom2), { subject: new Rx.Subject() });
699
+ copiedStore.atoms = import_hamt_plus2.default.set(atom2.key, copiedAtom, copiedStore.atoms);
700
+ });
701
+ store == null ? void 0 : store.readonlySelectors.forEach((selector2) => {
702
+ selector2.install(copiedStore);
703
+ });
704
+ store == null ? void 0 : store.selectors.forEach((selector2) => {
705
+ selector2.install(copiedStore);
706
+ });
707
+ store == null ? void 0 : store.transactions.forEach((tx) => {
708
+ tx.install(copiedStore);
709
+ });
710
+ store == null ? void 0 : store.timelines.forEach((timeline2) => {
711
+ timeline2.install(copiedStore);
712
+ });
713
+ return copiedStore;
714
+ };
693
715
  var IMPLICIT = {
694
716
  STORE_INTERNAL: void 0,
695
717
  get STORE() {
@@ -720,7 +742,9 @@ var openOperation = (token, store) => {
720
742
  time: Date.now(),
721
743
  token
722
744
  };
723
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u2B55 operation start from "${token.key}"`);
745
+ (_b = store.config.logger) == null ? void 0 : _b.info(
746
+ `\u2B55 operation start from "${token.key}" in store "${store.config.name}"`
747
+ );
724
748
  };
725
749
  var closeOperation = (store) => {
726
750
  var _a;
@@ -795,112 +819,6 @@ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
795
819
  // src/internal/transaction-internal.ts
796
820
  var import_hamt_plus4 = __toESM(require("hamt_plus"));
797
821
  var Rx2 = __toESM(require("rxjs"));
798
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
799
- var buildTransaction = (key, params, store) => {
800
- var _a;
801
- store.transactionStatus = {
802
- key,
803
- phase: `building`,
804
- core: {
805
- atoms: store.atoms,
806
- atomsThatAreDefault: store.atomsThatAreDefault,
807
- operation: { open: false },
808
- readonlySelectors: store.readonlySelectors,
809
- timelines: store.timelines,
810
- timelineAtoms: store.timelineAtoms,
811
- transactions: store.transactions,
812
- selectorAtoms: store.selectorAtoms,
813
- selectorGraph: store.selectorGraph,
814
- selectors: store.selectors,
815
- valueMap: store.valueMap
816
- },
817
- atomUpdates: [],
818
- params,
819
- output: void 0
820
- };
821
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
822
- };
823
- var applyTransaction = (output, store) => {
824
- var _a, _b, _c, _d;
825
- if (store.transactionStatus.phase !== `building`) {
826
- (_a = store.config.logger) == null ? void 0 : _a.warn(
827
- `abortTransaction called outside of a transaction. This is probably a bug.`
828
- );
829
- return;
830
- }
831
- (_b = store.config.logger) == null ? void 0 : _b.info(
832
- `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
833
- );
834
- store.transactionStatus.phase = `applying`;
835
- store.transactionStatus.output = output;
836
- const { atomUpdates } = store.transactionStatus;
837
- for (const { key, newValue } of atomUpdates) {
838
- const token = { key, type: `atom` };
839
- if (!import_hamt_plus4.default.has(token.key, store.valueMap)) {
840
- const newAtom = import_hamt_plus4.default.get(token.key, store.transactionStatus.core.atoms);
841
- store.atoms = import_hamt_plus4.default.set(newAtom.key, newAtom, store.atoms);
842
- store.valueMap = import_hamt_plus4.default.set(newAtom.key, newAtom.default, store.valueMap);
843
- (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${newAtom.key}"`);
844
- }
845
- setState(token, newValue, store);
846
- }
847
- const myTransaction = withdraw(
848
- { key: store.transactionStatus.key, type: `transaction` },
849
- store
850
- );
851
- if (myTransaction === null) {
852
- throw new Error(
853
- `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
854
- );
855
- }
856
- myTransaction.subject.next({
857
- key: store.transactionStatus.key,
858
- atomUpdates,
859
- output,
860
- params: store.transactionStatus.params
861
- });
862
- store.transactionStatus = { phase: `idle` };
863
- (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
864
- };
865
- var undoTransactionUpdate = (update, store) => {
866
- var _a;
867
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
868
- for (const { key, oldValue } of update.atomUpdates) {
869
- const token = { key, type: `atom` };
870
- const state = withdraw(token, store);
871
- if (state === null) {
872
- throw new Error(
873
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
874
- );
875
- }
876
- setState(state, oldValue, store);
877
- }
878
- };
879
- var redoTransactionUpdate = (update, store) => {
880
- var _a;
881
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
882
- for (const { key, newValue } of update.atomUpdates) {
883
- const token = { key, type: `atom` };
884
- const state = withdraw(token, store);
885
- if (state === null) {
886
- throw new Error(
887
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
888
- );
889
- }
890
- setState(state, newValue, store);
891
- }
892
- };
893
- var abortTransaction = (store) => {
894
- var _a, _b;
895
- if (store.transactionStatus.phase === `idle`) {
896
- (_a = store.config.logger) == null ? void 0 : _a.warn(
897
- `abortTransaction called outside of a transaction. This is probably a bug.`
898
- );
899
- return;
900
- }
901
- store.transactionStatus = { phase: `idle` };
902
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
903
- };
904
822
  function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
905
823
  const newTransaction = {
906
824
  key: options.key,
@@ -924,6 +842,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
924
842
  throw thrown;
925
843
  }
926
844
  },
845
+ install: (store2) => transaction__INTERNAL(options, store2),
927
846
  subject: new Rx2.Subject()
928
847
  };
929
848
  const core = target(store);
@@ -1183,9 +1102,59 @@ var attachMetaState = (store = IMPLICIT.STORE) => {
1183
1102
  };
1184
1103
 
1185
1104
  // src/internal/selector-internal.ts
1105
+ var import_hamt_plus9 = __toESM(require("hamt_plus"));
1106
+
1107
+ // src/internal/selector/create-read-write-selector.ts
1186
1108
  var import_hamt_plus6 = __toESM(require("hamt_plus"));
1187
1109
  var Rx5 = __toESM(require("rxjs"));
1110
+ var createReadWriteSelector = (options, family, store, core) => {
1111
+ var _a;
1112
+ const subject = new Rx5.Subject();
1113
+ const { get, set } = registerSelector(options.key, store);
1114
+ const getSelf = () => {
1115
+ const value = options.get({ get });
1116
+ cacheValue(options.key, value, store);
1117
+ return value;
1118
+ };
1119
+ const setSelf = (next) => {
1120
+ var _a2;
1121
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1122
+ const oldValue = getSelf();
1123
+ const newValue = become(next)(oldValue);
1124
+ cacheValue(options.key, newValue, store);
1125
+ markDone(options.key, store);
1126
+ if (store.transactionStatus.phase === `idle`) {
1127
+ subject.next({ newValue, oldValue });
1128
+ }
1129
+ options.set({ get, set }, newValue);
1130
+ };
1131
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1132
+ subject,
1133
+ install: (s) => selector__INTERNAL(options, family, s),
1134
+ get: getSelf,
1135
+ set: setSelf,
1136
+ type: `selector`
1137
+ }), family && { family });
1138
+ core.selectors = import_hamt_plus6.default.set(options.key, mySelector, core.selectors);
1139
+ const initialValue = getSelf();
1140
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1141
+ const token = {
1142
+ key: options.key,
1143
+ type: `selector`,
1144
+ family
1145
+ };
1146
+ store.subject.selectorCreation.next(token);
1147
+ return token;
1148
+ };
1149
+
1150
+ // src/internal/selector/create-readonly-selector.ts
1151
+ var import_hamt_plus8 = __toESM(require("hamt_plus"));
1152
+ var Rx6 = __toESM(require("rxjs"));
1153
+
1154
+ // src/internal/selector/lookup-selector-sources.ts
1188
1155
  var lookupSelectorSources = (key, store) => target(store).selectorGraph.getRelations(key).filter(({ source }) => source !== key).map(({ source }) => lookup(source, store));
1156
+
1157
+ // src/internal/selector/trace-selector-atoms.ts
1189
1158
  var traceSelectorAtoms = (selectorKey, dependency, store) => {
1190
1159
  const roots = [];
1191
1160
  const sources = lookupSelectorSources(dependency.key, store);
@@ -1212,6 +1181,8 @@ var traceAllSelectorAtoms = (selectorKey, store) => {
1212
1181
  (source) => source.type === `atom` ? source : traceSelectorAtoms(selectorKey, source, store)
1213
1182
  );
1214
1183
  };
1184
+
1185
+ // src/internal/selector/update-selector-atoms.ts
1215
1186
  var updateSelectorAtoms = (selectorKey, dependency, store) => {
1216
1187
  var _a, _b;
1217
1188
  const core = target(store);
@@ -1237,114 +1208,6 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1237
1208
  });
1238
1209
  }
1239
1210
  };
1240
- var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1241
- get: (dependency) => {
1242
- var _a, _b;
1243
- const core = target(store);
1244
- const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1245
- const dependencyState = withdraw(dependency, store);
1246
- if (dependencyState === null) {
1247
- throw new Error(
1248
- `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1249
- );
1250
- }
1251
- const dependencyValue = getState__INTERNAL(dependencyState, store);
1252
- if (alreadyRegistered) {
1253
- (_a = store.config.logger) == null ? void 0 : _a.info(
1254
- ` || ${selectorKey} <- ${dependency.key} =`,
1255
- dependencyValue
1256
- );
1257
- } else {
1258
- (_b = store.config.logger) == null ? void 0 : _b.info(
1259
- `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1260
- dependencyValue,
1261
- `)`
1262
- );
1263
- core.selectorGraph = core.selectorGraph.set(
1264
- { from: dependency.key, to: selectorKey },
1265
- {
1266
- source: dependency.key
1267
- }
1268
- );
1269
- }
1270
- updateSelectorAtoms(selectorKey, dependency, store);
1271
- return dependencyValue;
1272
- },
1273
- set: (stateToken, newValue) => {
1274
- const state = withdraw(stateToken, store);
1275
- if (state === null) {
1276
- throw new Error(
1277
- `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1278
- );
1279
- }
1280
- setState__INTERNAL(state, newValue, store);
1281
- }
1282
- });
1283
- function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1284
- var _a, _b, _c;
1285
- const core = target(store);
1286
- if (import_hamt_plus6.default.has(options.key, core.selectors)) {
1287
- (_a = store.config.logger) == null ? void 0 : _a.error(
1288
- `Key "${options.key}" already exists in the store.`
1289
- );
1290
- }
1291
- const subject = new Rx5.Subject();
1292
- const { get, set } = registerSelector(options.key, store);
1293
- const getSelf = () => {
1294
- const value = options.get({ get });
1295
- cacheValue(options.key, value, store);
1296
- return value;
1297
- };
1298
- if (!(`set` in options)) {
1299
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1300
- subject,
1301
- get: getSelf,
1302
- type: `readonly_selector`
1303
- }), family && { family });
1304
- core.readonlySelectors = import_hamt_plus6.default.set(
1305
- options.key,
1306
- readonlySelector,
1307
- core.readonlySelectors
1308
- );
1309
- const initialValue2 = getSelf();
1310
- (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
1311
- const token2 = {
1312
- key: options.key,
1313
- type: `readonly_selector`,
1314
- family
1315
- };
1316
- store.subject.selectorCreation.next(token2);
1317
- return token2;
1318
- }
1319
- const setSelf = (next) => {
1320
- var _a2;
1321
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1322
- const oldValue = getSelf();
1323
- const newValue = become(next)(oldValue);
1324
- cacheValue(options.key, newValue, store);
1325
- markDone(options.key, store);
1326
- if (store.transactionStatus.phase === `idle`) {
1327
- subject.next({ newValue, oldValue });
1328
- }
1329
- options.set({ get, set }, newValue);
1330
- };
1331
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1332
- subject,
1333
- get: getSelf,
1334
- set: setSelf,
1335
- type: `selector`
1336
- }), family && { family });
1337
- core.selectors = import_hamt_plus6.default.set(options.key, mySelector, core.selectors);
1338
- const initialValue = getSelf();
1339
- (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
1340
- const token = {
1341
- key: options.key,
1342
- type: `selector`,
1343
- family
1344
- };
1345
- store.subject.selectorCreation.next(token);
1346
- return token;
1347
- }
1348
1211
 
1349
1212
  // src/internal/set.ts
1350
1213
  var import_hamt_plus7 = __toESM(require("hamt_plus"));
@@ -1415,6 +1278,98 @@ var setState__INTERNAL = (state, value, store = IMPLICIT.STORE) => {
1415
1278
  }
1416
1279
  };
1417
1280
 
1281
+ // src/internal/selector/register-selector.ts
1282
+ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1283
+ get: (dependency) => {
1284
+ var _a, _b;
1285
+ const core = target(store);
1286
+ const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1287
+ const dependencyState = withdraw(dependency, store);
1288
+ if (dependencyState === null) {
1289
+ throw new Error(
1290
+ `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1291
+ );
1292
+ }
1293
+ const dependencyValue = getState__INTERNAL(dependencyState, store);
1294
+ if (alreadyRegistered) {
1295
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1296
+ ` || ${selectorKey} <- ${dependency.key} =`,
1297
+ dependencyValue
1298
+ );
1299
+ } else {
1300
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1301
+ `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1302
+ dependencyValue,
1303
+ `)`
1304
+ );
1305
+ core.selectorGraph = core.selectorGraph.set(
1306
+ { from: dependency.key, to: selectorKey },
1307
+ {
1308
+ source: dependency.key
1309
+ }
1310
+ );
1311
+ }
1312
+ updateSelectorAtoms(selectorKey, dependency, store);
1313
+ return dependencyValue;
1314
+ },
1315
+ set: (stateToken, newValue) => {
1316
+ const state = withdraw(stateToken, store);
1317
+ if (state === null) {
1318
+ throw new Error(
1319
+ `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1320
+ );
1321
+ }
1322
+ setState__INTERNAL(state, newValue, store);
1323
+ }
1324
+ });
1325
+
1326
+ // src/internal/selector/create-readonly-selector.ts
1327
+ var createReadonlySelector = (options, family, store, core) => {
1328
+ var _a;
1329
+ const subject = new Rx6.Subject();
1330
+ const { get } = registerSelector(options.key, store);
1331
+ const getSelf = () => {
1332
+ const value = options.get({ get });
1333
+ cacheValue(options.key, value, store);
1334
+ return value;
1335
+ };
1336
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1337
+ subject,
1338
+ install: (s) => selector__INTERNAL(options, family, s),
1339
+ get: getSelf,
1340
+ type: `readonly_selector`
1341
+ }), family && { family });
1342
+ core.readonlySelectors = import_hamt_plus8.default.set(
1343
+ options.key,
1344
+ readonlySelector,
1345
+ core.readonlySelectors
1346
+ );
1347
+ const initialValue = getSelf();
1348
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1349
+ const token = {
1350
+ key: options.key,
1351
+ type: `readonly_selector`,
1352
+ family
1353
+ };
1354
+ store.subject.selectorCreation.next(token);
1355
+ return token;
1356
+ };
1357
+
1358
+ // src/internal/selector-internal.ts
1359
+ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1360
+ var _a;
1361
+ const core = target(store);
1362
+ if (import_hamt_plus9.default.has(options.key, core.selectors)) {
1363
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1364
+ `Key "${options.key}" already exists in the store.`
1365
+ );
1366
+ }
1367
+ if (!(`set` in options)) {
1368
+ return createReadonlySelector(options, family, store, core);
1369
+ }
1370
+ return createReadWriteSelector(options, family, store, core);
1371
+ }
1372
+
1418
1373
  // src/internal/subscribe-internal.ts
1419
1374
  var prepareUpdate = (state, store) => {
1420
1375
  const oldValue = recallState(state, store);
@@ -1476,7 +1431,7 @@ var subscribeToRootAtoms = (state, store) => {
1476
1431
  var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1477
1432
  var _a, _b, _c, _d;
1478
1433
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23E9 redo "${token.key}"`);
1479
- const timelineData = store.timelineStore.get(token.key);
1434
+ const timelineData = store.timelines.get(token.key);
1480
1435
  if (!timelineData) {
1481
1436
  (_b = store.config.logger) == null ? void 0 : _b.error(
1482
1437
  `Failed to redo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1494,14 +1449,14 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1494
1449
  switch (update.type) {
1495
1450
  case `atom_update`: {
1496
1451
  const { key, newValue } = update;
1497
- setState({ key, type: `atom` }, newValue);
1452
+ setState({ key, type: `atom` }, newValue, store);
1498
1453
  break;
1499
1454
  }
1500
1455
  case `selector_update`:
1501
1456
  case `transaction_update`: {
1502
1457
  for (const atomUpdate of update.atomUpdates) {
1503
1458
  const { key, newValue } = atomUpdate;
1504
- setState({ key, type: `atom` }, newValue);
1459
+ setState({ key, type: `atom` }, newValue, store);
1505
1460
  }
1506
1461
  break;
1507
1462
  }
@@ -1515,7 +1470,7 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1515
1470
  var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1516
1471
  var _a, _b, _c, _d;
1517
1472
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23EA undo "${token.key}"`);
1518
- const timelineData = store.timelineStore.get(token.key);
1473
+ const timelineData = store.timelines.get(token.key);
1519
1474
  if (!timelineData) {
1520
1475
  (_b = store.config.logger) == null ? void 0 : _b.error(
1521
1476
  `Failed to undo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1534,14 +1489,14 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1534
1489
  switch (update.type) {
1535
1490
  case `atom_update`: {
1536
1491
  const { key, oldValue } = update;
1537
- setState({ key, type: `atom` }, oldValue);
1492
+ setState({ key, type: `atom` }, oldValue, store);
1538
1493
  break;
1539
1494
  }
1540
1495
  case `selector_update`:
1541
1496
  case `transaction_update`: {
1542
1497
  for (const atomUpdate of update.atomUpdates) {
1543
1498
  const { key, oldValue } = atomUpdate;
1544
- setState({ key, type: `atom` }, oldValue);
1499
+ setState({ key, type: `atom` }, oldValue, store);
1545
1500
  }
1546
1501
  break;
1547
1502
  }
@@ -1553,142 +1508,166 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1553
1508
  };
1554
1509
 
1555
1510
  // src/internal/timeline-internal.ts
1556
- var import_hamt_plus8 = __toESM(require("hamt_plus"));
1557
- function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1558
- var _a, _b;
1559
- const timelineData = {
1560
- at: 0,
1561
- timeTraveling: false,
1562
- history: [],
1563
- selectorTime: null,
1564
- transactionKey: null
1565
- };
1566
- const subscribeToAtom = (token2) => {
1567
- const state = withdraw(token2, store);
1568
- if (state === null) {
1569
- throw new Error(
1570
- `Cannot subscribe to atom "${token2.key}" because it has not been initialized in store "${store.config.name}"`
1571
- );
1572
- }
1573
- state.subject.subscribe((update) => {
1574
- var _a2, _b2, _c, _d, _e;
1575
- const storeCurrentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1576
- const storeCurrentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1577
- const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1578
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1579
- `\u23F3 timeline "${options.key}" saw atom "${token2.key}" go (`,
1580
- update.oldValue,
1581
- `->`,
1582
- update.newValue,
1583
- storeCurrentTransactionKey ? `) in transaction "${storeCurrentTransactionKey}"` : storeCurrentSelectorKey ? `) in selector "${storeCurrentSelectorKey}"` : `)`
1584
- );
1585
- if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1511
+ var import_hamt_plus10 = __toESM(require("hamt_plus"));
1512
+ var Rx7 = __toESM(require("rxjs"));
1513
+
1514
+ // src/internal/timeline/add-atom-to-timeline.ts
1515
+ var addAtomToTimeline = (atomToken, atoms, tl, store = IMPLICIT.STORE) => {
1516
+ const atom2 = withdraw(atomToken, store);
1517
+ if (atom2 === null) {
1518
+ throw new Error(
1519
+ `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
1520
+ );
1521
+ }
1522
+ atom2.subject.subscribe((update) => {
1523
+ var _a, _b, _c, _d, _e;
1524
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1525
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1526
+ const currentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1527
+ const currentTransactionTime = store.transactionStatus.phase === `applying` ? store.transactionStatus.time : null;
1528
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1529
+ `\u23F3 timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
1530
+ update.oldValue,
1531
+ `->`,
1532
+ update.newValue,
1533
+ currentTransactionKey ? `) in transaction "${currentTransactionKey}"` : currentSelectorKey ? `) in selector "${currentSelectorKey}"` : `)`
1534
+ );
1535
+ if (tl.timeTraveling === false) {
1536
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1537
+ const mostRecentUpdate = tl.history.at(-1);
1538
+ if (mostRecentUpdate.type === `selector_update`) {
1539
+ tl.subject.next(mostRecentUpdate);
1540
+ }
1541
+ }
1542
+ if (currentTransactionKey && store.transactionStatus.phase === `applying`) {
1586
1543
  const currentTransaction = withdraw(
1587
- { key: storeCurrentTransactionKey, type: `transaction` },
1544
+ { key: currentTransactionKey, type: `transaction` },
1588
1545
  store
1589
1546
  );
1590
1547
  if (currentTransaction === null) {
1591
1548
  throw new Error(
1592
- `Transaction "${storeCurrentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${storeCurrentTransactionKey}".`
1549
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
1593
1550
  );
1594
1551
  }
1595
- if (timelineData.transactionKey !== storeCurrentTransactionKey) {
1596
- if (timelineData.transactionKey) {
1597
- (_b2 = store.config.logger) == null ? void 0 : _b2.error(
1598
- `Timeline "${options.key}" was unable to resolve transaction "${timelineData.transactionKey}. This is probably a bug.`
1552
+ if (tl.transactionKey !== currentTransactionKey) {
1553
+ if (tl.transactionKey) {
1554
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1555
+ `Timeline "${tl.key}" was unable to resolve transaction "${tl.transactionKey}. This is probably a bug.`
1599
1556
  );
1600
1557
  }
1601
- timelineData.transactionKey = storeCurrentTransactionKey;
1558
+ tl.transactionKey = currentTransactionKey;
1602
1559
  const subscription = currentTransaction.subject.subscribe((update2) => {
1603
- var _a3;
1604
- if (timelineData.timeTraveling === false) {
1605
- if (timelineData.at !== timelineData.history.length) {
1606
- timelineData.history.splice(timelineData.at);
1560
+ var _a2;
1561
+ if (tl.timeTraveling === false && currentTransactionTime) {
1562
+ if (tl.at !== tl.history.length) {
1563
+ tl.history.splice(tl.at);
1607
1564
  }
1608
- timelineData.history.push(__spreadProps(__spreadValues({
1609
- type: `transaction_update`
1565
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
1566
+ type: `transaction_update`,
1567
+ timestamp: currentTransactionTime
1610
1568
  }, update2), {
1611
1569
  atomUpdates: update2.atomUpdates.filter(
1612
- (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1570
+ (atomUpdate) => atoms.some((atom3) => atom3.key === atomUpdate.key)
1613
1571
  )
1614
- }));
1572
+ });
1573
+ tl.history.push(timelineTransactionUpdate);
1574
+ tl.subject.next(timelineTransactionUpdate);
1615
1575
  }
1616
- timelineData.at = timelineData.history.length;
1576
+ tl.at = tl.history.length;
1617
1577
  subscription.unsubscribe();
1618
- timelineData.transactionKey = null;
1619
- (_a3 = store.config.logger) == null ? void 0 : _a3.info(
1620
- `\u231B timeline "${options.key}" got a transaction_update "${update2.key}"`
1578
+ tl.transactionKey = null;
1579
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1580
+ `\u231B timeline "${tl.key}" got a transaction_update "${update2.key}"`
1621
1581
  );
1622
1582
  });
1623
1583
  }
1624
- } else if (storeCurrentSelectorKey) {
1625
- if (timelineData.timeTraveling === false) {
1626
- if (storeCurrentSelectorTime !== timelineData.selectorTime) {
1627
- const newSelectorUpdate = {
1628
- type: `selector_update`,
1629
- key: storeCurrentSelectorKey,
1630
- atomUpdates: []
1631
- };
1632
- newSelectorUpdate.atomUpdates.push(__spreadValues({
1633
- key: token2.key,
1584
+ } else if (currentSelectorKey && currentSelectorTime) {
1585
+ if (currentSelectorTime !== tl.selectorTime) {
1586
+ const newSelectorUpdate = {
1587
+ type: `selector_update`,
1588
+ timestamp: currentSelectorTime,
1589
+ key: currentSelectorKey,
1590
+ atomUpdates: []
1591
+ };
1592
+ newSelectorUpdate.atomUpdates.push(__spreadValues({
1593
+ key: atom2.key,
1594
+ type: `atom_update`
1595
+ }, update));
1596
+ if (tl.at !== tl.history.length) {
1597
+ tl.history.splice(tl.at);
1598
+ }
1599
+ tl.history.push(newSelectorUpdate);
1600
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1601
+ `\u231B timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
1602
+ newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1603
+ );
1604
+ tl.at = tl.history.length;
1605
+ tl.selectorTime = currentSelectorTime;
1606
+ } else {
1607
+ const latestUpdate = tl.history.at(-1);
1608
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1609
+ latestUpdate.atomUpdates.push(__spreadValues({
1610
+ key: atom2.key,
1634
1611
  type: `atom_update`
1635
1612
  }, update));
1636
- if (timelineData.at !== timelineData.history.length) {
1637
- timelineData.history.splice(timelineData.at);
1638
- }
1639
- timelineData.history.push(newSelectorUpdate);
1640
- (_c = store.config.logger) == null ? void 0 : _c.info(
1641
- `\u231B timeline "${options.key}" got a selector_update "${storeCurrentSelectorKey}" with`,
1642
- newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1613
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1614
+ ` \u231B timeline "${tl.key}" set selector_update "${currentSelectorKey}" to`,
1615
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1643
1616
  );
1644
- timelineData.at = timelineData.history.length;
1645
- timelineData.selectorTime = storeCurrentSelectorTime;
1646
- } else {
1647
- const latestUpdate = timelineData.history.at(-1);
1648
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1649
- latestUpdate.atomUpdates.push(__spreadValues({
1650
- key: token2.key,
1651
- type: `atom_update`
1652
- }, update));
1653
- (_d = store.config.logger) == null ? void 0 : _d.info(
1654
- ` \u231B timeline "${options.key}" set selector_update "${storeCurrentSelectorKey}" to`,
1655
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1656
- );
1657
- }
1658
1617
  }
1659
1618
  }
1660
1619
  } else {
1661
- if (timelineData.timeTraveling === false) {
1662
- timelineData.selectorTime = null;
1663
- if (timelineData.at !== timelineData.history.length) {
1664
- timelineData.history.splice(timelineData.at);
1665
- }
1666
- timelineData.history.push({
1667
- type: `atom_update`,
1668
- key: token2.key,
1669
- oldValue: update.oldValue,
1670
- newValue: update.newValue
1671
- });
1672
- (_e = store.config.logger) == null ? void 0 : _e.info(
1673
- `\u231B timeline "${options.key}" got a state_update to "${token2.key}"`
1674
- );
1675
- timelineData.at = timelineData.history.length;
1620
+ const timestamp = Date.now();
1621
+ tl.selectorTime = null;
1622
+ if (tl.at !== tl.history.length) {
1623
+ tl.history.splice(tl.at);
1676
1624
  }
1625
+ const atomUpdate = {
1626
+ type: `atom_update`,
1627
+ timestamp,
1628
+ key: atom2.key,
1629
+ oldValue: update.oldValue,
1630
+ newValue: update.newValue
1631
+ };
1632
+ tl.history.push(atomUpdate);
1633
+ tl.subject.next(atomUpdate);
1634
+ (_e = store.config.logger) == null ? void 0 : _e.info(
1635
+ `\u231B timeline "${tl.key}" got a state_update to "${atom2.key}"`
1636
+ );
1637
+ tl.at = tl.history.length;
1677
1638
  }
1678
- });
1679
- };
1639
+ }
1640
+ });
1641
+ };
1642
+
1643
+ // src/internal/timeline-internal.ts
1644
+ function timeline__INTERNAL(options, store = IMPLICIT.STORE, data = null) {
1645
+ var _a, _b, _c;
1646
+ const tl = __spreadProps(__spreadValues({
1647
+ key: options.key,
1648
+ at: 0,
1649
+ timeTraveling: false,
1650
+ selectorTime: null,
1651
+ transactionKey: null
1652
+ }, data), {
1653
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1654
+ install: (store2) => timeline__INTERNAL(options, store2, tl),
1655
+ subject: new Rx7.Subject()
1656
+ });
1680
1657
  const core = target(store);
1681
1658
  for (const tokenOrFamily of options.atoms) {
1682
1659
  const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key);
1683
1660
  if (timelineKey) {
1684
- (_a = store.config.logger) == null ? void 0 : _a.error(
1661
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1685
1662
  `\u274C Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
1686
1663
  );
1687
1664
  continue;
1688
1665
  }
1689
1666
  if (tokenOrFamily.type === `atom_family`) {
1690
1667
  const family = tokenOrFamily;
1691
- family.subject.subscribe((token2) => subscribeToAtom(token2));
1668
+ family.subject.subscribe(
1669
+ (token2) => addAtomToTimeline(token2, options.atoms, tl, store)
1670
+ );
1692
1671
  } else {
1693
1672
  const token2 = tokenOrFamily;
1694
1673
  if (`family` in token2 && token2.family) {
@@ -1696,20 +1675,20 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1696
1675
  token2.family.key
1697
1676
  );
1698
1677
  if (familyTimelineKey) {
1699
- (_b = store.config.logger) == null ? void 0 : _b.error(
1678
+ (_c = store.config.logger) == null ? void 0 : _c.error(
1700
1679
  `\u274C Failed to add atom "${token2.key}" to timeline "${options.key}" because its family "${token2.family.key}" belongs to timeline "${familyTimelineKey}"`
1701
1680
  );
1702
1681
  continue;
1703
1682
  }
1704
1683
  }
1705
- subscribeToAtom(token2);
1684
+ addAtomToTimeline(token2, options.atoms, tl, store);
1706
1685
  }
1707
1686
  core.timelineAtoms = core.timelineAtoms.set({
1708
1687
  atomKey: tokenOrFamily.key,
1709
1688
  timelineKey: options.key
1710
1689
  });
1711
1690
  }
1712
- store.timelineStore = import_hamt_plus8.default.set(options.key, timelineData, store.timelineStore);
1691
+ store.timelines = import_hamt_plus10.default.set(options.key, tl, store.timelines);
1713
1692
  const token = {
1714
1693
  key: options.key,
1715
1694
  type: `timeline`
@@ -1718,6 +1697,129 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1718
1697
  return token;
1719
1698
  }
1720
1699
 
1700
+ // src/internal/transaction/abort-transaction.ts
1701
+ var abortTransaction = (store) => {
1702
+ var _a, _b;
1703
+ if (store.transactionStatus.phase === `idle`) {
1704
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1705
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1706
+ );
1707
+ return;
1708
+ }
1709
+ store.transactionStatus = { phase: `idle` };
1710
+ (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
1711
+ };
1712
+
1713
+ // src/internal/transaction/apply-transaction.ts
1714
+ var import_hamt_plus11 = __toESM(require("hamt_plus"));
1715
+ var applyTransaction = (output, store) => {
1716
+ var _a, _b, _c, _d;
1717
+ if (store.transactionStatus.phase !== `building`) {
1718
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1719
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1720
+ );
1721
+ return;
1722
+ }
1723
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1724
+ `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
1725
+ );
1726
+ store.transactionStatus.phase = `applying`;
1727
+ store.transactionStatus.output = output;
1728
+ const { atomUpdates } = store.transactionStatus;
1729
+ for (const { key, newValue } of atomUpdates) {
1730
+ const token = { key, type: `atom` };
1731
+ if (!import_hamt_plus11.default.has(token.key, store.valueMap)) {
1732
+ const newAtom = import_hamt_plus11.default.get(token.key, store.transactionStatus.core.atoms);
1733
+ store.atoms = import_hamt_plus11.default.set(newAtom.key, newAtom, store.atoms);
1734
+ store.valueMap = import_hamt_plus11.default.set(newAtom.key, newAtom.default, store.valueMap);
1735
+ (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${newAtom.key}"`);
1736
+ }
1737
+ setState(token, newValue, store);
1738
+ }
1739
+ const myTransaction = withdraw(
1740
+ { key: store.transactionStatus.key, type: `transaction` },
1741
+ store
1742
+ );
1743
+ if (myTransaction === null) {
1744
+ throw new Error(
1745
+ `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
1746
+ );
1747
+ }
1748
+ myTransaction.subject.next({
1749
+ key: store.transactionStatus.key,
1750
+ atomUpdates,
1751
+ output,
1752
+ params: store.transactionStatus.params
1753
+ });
1754
+ store.transactionStatus = { phase: `idle` };
1755
+ (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
1756
+ };
1757
+
1758
+ // src/internal/transaction/build-transaction.ts
1759
+ var buildTransaction = (key, params, store) => {
1760
+ var _a;
1761
+ store.transactionStatus = {
1762
+ key,
1763
+ phase: `building`,
1764
+ time: Date.now(),
1765
+ core: {
1766
+ atoms: store.atoms,
1767
+ atomsThatAreDefault: store.atomsThatAreDefault,
1768
+ operation: { open: false },
1769
+ readonlySelectors: store.readonlySelectors,
1770
+ timelines: store.timelines,
1771
+ timelineAtoms: store.timelineAtoms,
1772
+ transactions: store.transactions,
1773
+ selectorAtoms: store.selectorAtoms,
1774
+ selectorGraph: store.selectorGraph,
1775
+ selectors: store.selectors,
1776
+ valueMap: store.valueMap
1777
+ },
1778
+ atomUpdates: [],
1779
+ params,
1780
+ output: void 0
1781
+ };
1782
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1783
+ `\u{1F6EB}`,
1784
+ `transaction "${key}" started in store "${store.config.name}"`
1785
+ );
1786
+ };
1787
+
1788
+ // src/internal/transaction/redo-transaction.ts
1789
+ var redoTransactionUpdate = (update, store) => {
1790
+ var _a;
1791
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
1792
+ for (const { key, newValue } of update.atomUpdates) {
1793
+ const token = { key, type: `atom` };
1794
+ const state = withdraw(token, store);
1795
+ if (state === null) {
1796
+ throw new Error(
1797
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1798
+ );
1799
+ }
1800
+ setState(state, newValue, store);
1801
+ }
1802
+ };
1803
+
1804
+ // src/internal/transaction/undo-transaction.ts
1805
+ var undoTransactionUpdate = (update, store) => {
1806
+ var _a;
1807
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
1808
+ for (const { key, oldValue } of update.atomUpdates) {
1809
+ const token = { key, type: `atom` };
1810
+ const state = withdraw(token, store);
1811
+ if (state === null) {
1812
+ throw new Error(
1813
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1814
+ );
1815
+ }
1816
+ setState(state, oldValue, store);
1817
+ }
1818
+ };
1819
+
1820
+ // src/internal/transaction/index.ts
1821
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1822
+
1721
1823
  // src/atom.ts
1722
1824
  function atom(options) {
1723
1825
  return atom__INTERNAL(options);
@@ -1768,8 +1870,8 @@ function selectorFamily(options) {
1768
1870
  }
1769
1871
 
1770
1872
  // src/silo.ts
1771
- var silo = (name) => {
1772
- const store = createStore(name);
1873
+ var silo = (name, fromStore = null) => {
1874
+ const store = createStore(name, fromStore);
1773
1875
  return {
1774
1876
  store,
1775
1877
  atom: (options) => atom__INTERNAL(options, void 0, store),
@@ -1780,7 +1882,9 @@ var silo = (name) => {
1780
1882
  timeline: (options) => timeline__INTERNAL(options, store),
1781
1883
  getState: (token) => getState(token, store),
1782
1884
  setState: (token, newValue) => setState(token, newValue, store),
1783
- subscribe: (token, handler) => subscribe(token, handler, store)
1885
+ subscribe: (token, handler) => subscribe(token, handler, store),
1886
+ undo: (token) => undo__INTERNAL(token, store),
1887
+ redo: (token) => redo__INTERNAL(token, store)
1784
1888
  };
1785
1889
  };
1786
1890
 
@@ -1829,6 +1933,23 @@ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1829
1933
  };
1830
1934
  return unsubscribe;
1831
1935
  };
1936
+ var subscribeToTimeline = (token, handleUpdate, store = IMPLICIT.STORE) => {
1937
+ var _a;
1938
+ const tl = withdraw(token, store);
1939
+ if (tl === null) {
1940
+ throw new Error(
1941
+ `Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`
1942
+ );
1943
+ }
1944
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to timeline "${token.key}"`);
1945
+ const subscription = tl.subject.subscribe(handleUpdate);
1946
+ const unsubscribe = () => {
1947
+ var _a2;
1948
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from timeline "${token.key}"`);
1949
+ subscription.unsubscribe();
1950
+ };
1951
+ return unsubscribe;
1952
+ };
1832
1953
 
1833
1954
  // src/timeline.ts
1834
1955
  var timeline = (options) => {
@@ -1900,6 +2021,7 @@ var isDefault = (token, store = IMPLICIT.STORE) => token.type === `atom` ? isAto
1900
2021
  setState,
1901
2022
  silo,
1902
2023
  subscribe,
2024
+ subscribeToTimeline,
1903
2025
  subscribeToTransaction,
1904
2026
  timeline,
1905
2027
  transaction,