atom.io 0.4.1 → 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 (101) hide show
  1. package/README.md +38 -10
  2. package/dist/index.d.mts +614 -0
  3. package/dist/index.d.ts +130 -77
  4. package/dist/index.js +584 -347
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +582 -347
  7. package/dist/index.mjs.map +1 -1
  8. package/json/dist/index.d.mts +18 -0
  9. package/json/dist/index.d.ts +18 -0
  10. package/json/dist/index.js +51 -0
  11. package/json/dist/index.js.map +1 -0
  12. package/json/dist/index.mjs +15 -0
  13. package/json/dist/index.mjs.map +1 -0
  14. package/json/package.json +15 -0
  15. package/package.json +43 -9
  16. package/react/dist/index.d.mts +24 -0
  17. package/react/dist/index.d.ts +18 -11
  18. package/react/dist/index.js +45 -21
  19. package/react/dist/index.js.map +1 -1
  20. package/react/dist/index.mjs +31 -21
  21. package/react/dist/index.mjs.map +1 -1
  22. package/react-devtools/dist/index.d.mts +15 -0
  23. package/react-devtools/dist/index.d.ts +4 -4
  24. package/react-devtools/dist/index.js +1 -1
  25. package/react-devtools/dist/index.js.map +1 -1
  26. package/react-devtools/dist/index.mjs +1 -1
  27. package/react-devtools/dist/index.mjs.map +1 -1
  28. package/realtime/dist/index.d.mts +27 -0
  29. package/realtime/dist/index.d.ts +27 -0
  30. package/realtime/dist/index.js +191 -0
  31. package/realtime/dist/index.js.map +1 -0
  32. package/realtime/dist/index.mjs +152 -0
  33. package/realtime/dist/index.mjs.map +1 -0
  34. package/realtime/package.json +15 -0
  35. package/realtime-react/dist/index.d.mts +45 -0
  36. package/realtime-react/dist/index.d.ts +45 -0
  37. package/realtime-react/dist/index.js +213 -0
  38. package/realtime-react/dist/index.js.map +1 -0
  39. package/realtime-react/dist/index.mjs +168 -0
  40. package/realtime-react/dist/index.mjs.map +1 -0
  41. package/realtime-react/package.json +15 -0
  42. package/src/index.ts +21 -5
  43. package/src/internal/atom-internal.ts +1 -1
  44. package/src/internal/families-internal.ts +3 -3
  45. package/src/internal/get.ts +39 -15
  46. package/src/internal/index.ts +2 -0
  47. package/src/internal/meta/meta-state.ts +1 -1
  48. package/src/internal/operation.ts +3 -1
  49. package/src/internal/selector/create-read-write-selector.ts +62 -0
  50. package/src/internal/selector/create-readonly-selector.ts +52 -0
  51. package/src/internal/selector/index.ts +4 -0
  52. package/src/internal/selector/lookup-selector-sources.ts +16 -0
  53. package/src/internal/selector/register-selector.ts +57 -0
  54. package/src/internal/selector/trace-selector-atoms.ts +43 -0
  55. package/src/internal/selector/update-selector-atoms.ts +33 -0
  56. package/src/internal/selector-internal.ts +9 -197
  57. package/src/internal/set.ts +1 -1
  58. package/src/internal/store.ts +44 -17
  59. package/src/internal/subscribe-internal.ts +6 -1
  60. package/src/internal/time-travel-internal.ts +7 -7
  61. package/src/internal/timeline/add-atom-to-timeline.ts +164 -0
  62. package/src/internal/timeline/index.ts +1 -0
  63. package/src/internal/timeline-internal.ts +39 -146
  64. package/src/internal/transaction/abort-transaction.ts +12 -0
  65. package/src/internal/transaction/apply-transaction.ts +54 -0
  66. package/src/internal/transaction/build-transaction.ts +33 -0
  67. package/src/internal/transaction/index.ts +25 -0
  68. package/src/internal/transaction/redo-transaction.ts +23 -0
  69. package/src/internal/transaction/undo-transaction.ts +23 -0
  70. package/src/internal/transaction-internal.ts +16 -133
  71. package/src/json/index.ts +1 -0
  72. package/src/json/select-json.ts +18 -0
  73. package/src/react/index.ts +2 -46
  74. package/src/react/store-context.tsx +14 -0
  75. package/src/react/store-hooks.ts +48 -0
  76. package/src/react-devtools/AtomIODevtools.tsx +1 -1
  77. package/src/react-explorer/AtomIOExplorer.tsx +2 -2
  78. package/src/react-explorer/explorer-states.ts +5 -5
  79. package/src/react-explorer/index.ts +1 -1
  80. package/src/react-explorer/space-states.ts +8 -9
  81. package/src/realtime/README.md +33 -0
  82. package/src/realtime/hook-composition/expose-family.ts +101 -0
  83. package/src/realtime/hook-composition/expose-single.ts +38 -0
  84. package/src/realtime/hook-composition/index.ts +12 -0
  85. package/src/realtime/hook-composition/receive-state.ts +29 -0
  86. package/src/realtime/hook-composition/receive-transaction.ts +18 -0
  87. package/src/realtime/index.ts +1 -0
  88. package/src/realtime-react/index.ts +3 -0
  89. package/src/realtime-react/realtime-context.tsx +31 -0
  90. package/src/realtime-react/realtime-hooks.ts +39 -0
  91. package/src/realtime-react/realtime-state.ts +10 -0
  92. package/src/realtime-react/use-pull-family-member.ts +27 -0
  93. package/src/realtime-react/use-pull-family.ts +25 -0
  94. package/src/realtime-react/use-pull.ts +23 -0
  95. package/src/realtime-react/use-push.ts +26 -0
  96. package/src/realtime-react/use-server-action.ts +34 -0
  97. package/src/selector.ts +9 -6
  98. package/src/silo.ts +53 -0
  99. package/src/subscribe.ts +42 -2
  100. package/src/timeline.ts +10 -0
  101. package/src/transaction.ts +24 -12
package/dist/index.js CHANGED
@@ -70,7 +70,9 @@ __export(src_exports, {
70
70
  selectorFamily: () => selectorFamily,
71
71
  setLogLevel: () => setLogLevel,
72
72
  setState: () => setState,
73
+ silo: () => silo,
73
74
  subscribe: () => subscribe,
75
+ subscribeToTimeline: () => subscribeToTimeline,
74
76
  subscribeToTransaction: () => subscribeToTransaction,
75
77
  timeline: () => timeline,
76
78
  transaction: () => transaction,
@@ -79,6 +81,9 @@ __export(src_exports, {
79
81
  });
80
82
  module.exports = __toCommonJS(src_exports);
81
83
 
84
+ // ../anvl/src/string/capitalize.ts
85
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
86
+
82
87
  // src/internal/index.ts
83
88
  var internal_exports = {};
84
89
  __export(internal_exports, {
@@ -152,9 +157,9 @@ function lookup(key, store) {
152
157
  return { key, type };
153
158
  }
154
159
  function withdraw(token, store) {
155
- var _a, _b, _c;
160
+ var _a, _b, _c, _d, _e;
156
161
  const core = target(store);
157
- return (_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);
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;
158
163
  }
159
164
  function deposit(state) {
160
165
  return __spreadValues({
@@ -246,7 +251,7 @@ var recordToEntries = (obj) => Object.entries(obj);
246
251
  var entriesToRecord = (entries) => Object.fromEntries(entries);
247
252
 
248
253
  // ../anvl/src/object/mapObject.ts
249
- var import_function = require("fp-ts/lib/function");
254
+ var import_function = require("fp-ts/function");
250
255
  var mapObject = (obj, fn) => (0, import_function.pipe)(
251
256
  obj,
252
257
  recordToEntries,
@@ -350,13 +355,19 @@ var EMPTY_RELATION_DATA = {
350
355
  a: `from`,
351
356
  b: `to`
352
357
  };
353
- var isRelationData = (isContent, a = `from`, b = `to`) => (input) => hasExactProperties({
354
- contents: isContent ? isRecord(import_string.isString, isContent) : hasExactProperties({}),
355
- relations: isRecord(import_string.isString, isArray(import_string.isString)),
356
- relationType: isRelationType,
357
- a: isLiteral(a),
358
- b: isLiteral(b)
359
- })(input);
358
+ var isRelationData = ({
359
+ from: a = `from`,
360
+ to: b = `to`,
361
+ isContent
362
+ } = {}) => (input) => {
363
+ return hasExactProperties({
364
+ contents: isContent ? isRecord(import_string.isString, isContent) : hasExactProperties({}),
365
+ relations: isRecord(import_string.isString, isArray(import_string.isString)),
366
+ relationType: isRelationType,
367
+ a: isLiteral(a),
368
+ b: isLiteral(b)
369
+ })(input);
370
+ };
360
371
 
361
372
  // ../anvl/src/join/get-related-ids.ts
362
373
  var getRelatedIds = (relationMap, id) => {
@@ -373,6 +384,21 @@ var getRelatedId = (relationMap, id) => {
373
384
  return relations[0];
374
385
  };
375
386
 
387
+ // ../anvl/src/join/make-json-interface.ts
388
+ var makeJsonInterface = (join, ...params) => {
389
+ const isContent = params[0];
390
+ const { a, b } = join;
391
+ const options = {
392
+ from: a,
393
+ to: b,
394
+ isContent
395
+ };
396
+ return {
397
+ toJson: (join2) => join2.toJSON(),
398
+ fromJson: (json) => Join.fromJSON(json, options)
399
+ };
400
+ };
401
+
376
402
  // ../anvl/src/join/relation-contents.ts
377
403
  var import_function6 = require("fp-ts/function");
378
404
 
@@ -563,11 +589,16 @@ var setRelations = (current, subject, relations) => {
563
589
  };
564
590
 
565
591
  // ../anvl/src/join/index.ts
566
- var Join = class {
592
+ var Join = class _Join {
567
593
  constructor(json) {
568
594
  this.a = `from`;
569
595
  this.b = `to`;
570
- Object.assign(this, __spreadValues(__spreadValues({}, EMPTY_RELATION_DATA), json));
596
+ this.makeJsonInterface = (...params) => {
597
+ return makeJsonInterface(this, ...params);
598
+ };
599
+ Object.assign(this, __spreadProps(__spreadValues(__spreadValues({}, EMPTY_RELATION_DATA), json), {
600
+ makeJsonInterface: this.makeJsonInterface
601
+ }));
571
602
  }
572
603
  toJSON() {
573
604
  return {
@@ -578,20 +609,20 @@ var Join = class {
578
609
  b: this.b
579
610
  };
580
611
  }
581
- static fromJSON(json, isContent = cannotExist, a = `from`, b = `to`) {
582
- const isValid = isRelationData(isContent, a, b)(json);
612
+ static fromJSON(json, options) {
613
+ const isValid = isRelationData(options)(json);
583
614
  if (isValid) {
584
- return new Join(json);
615
+ return new _Join(json);
585
616
  }
586
617
  throw new Error(
587
618
  `Saved JSON for this Join is invalid: ${JSON.stringify(json)}`
588
619
  );
589
620
  }
590
621
  from(newA) {
591
- return new Join(__spreadProps(__spreadValues({}, this), { a: newA }));
622
+ return new _Join(__spreadProps(__spreadValues({}, this), { a: newA }));
592
623
  }
593
624
  to(newB) {
594
- return new Join(__spreadProps(__spreadValues({}, this), { b: newB }));
625
+ return new _Join(__spreadProps(__spreadValues({}, this), { b: newB }));
595
626
  }
596
627
  getRelatedId(id) {
597
628
  return getRelatedId(this, id);
@@ -615,51 +646,72 @@ var Join = class {
615
646
  return getRelations(this, id);
616
647
  }
617
648
  setRelations(subject, relations) {
618
- return new Join(setRelations(this, subject, relations));
649
+ return new _Join(setRelations(this, subject, relations));
619
650
  }
620
651
  set(relation, ...rest) {
621
- return new Join(setRelationWithContent(this, relation, ...rest));
652
+ return new _Join(setRelationWithContent(this, relation, ...rest));
622
653
  }
623
654
  remove(relation) {
624
- return new Join(
655
+ return new _Join(
625
656
  removeRelation(this, relation)
626
657
  );
627
658
  }
628
659
  };
629
660
 
630
661
  // src/internal/store.ts
631
- var createStore = (name) => ({
632
- atoms: import_hamt_plus2.default.make(),
633
- atomsThatAreDefault: /* @__PURE__ */ new Set(),
634
- readonlySelectors: import_hamt_plus2.default.make(),
635
- selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
636
- selectorGraph: new Join({ relationType: `n:n` }),
637
- selectors: import_hamt_plus2.default.make(),
638
- timelines: import_hamt_plus2.default.make(),
639
- timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
640
- timelineStore: import_hamt_plus2.default.make(),
641
- transactions: import_hamt_plus2.default.make(),
642
- valueMap: import_hamt_plus2.default.make(),
643
- subject: {
644
- atomCreation: new Rx.Subject(),
645
- selectorCreation: new Rx.Subject(),
646
- transactionCreation: new Rx.Subject(),
647
- timelineCreation: new Rx.Subject()
648
- },
649
- operation: {
650
- open: false
651
- },
652
- transactionStatus: {
653
- phase: `idle`
654
- },
655
- config: {
656
- name,
657
- logger: __spreadProps(__spreadValues({}, console), {
658
- info: doNothing
659
- }),
660
- logger__INTERNAL: console
661
- }
662
- });
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
+ };
663
715
  var IMPLICIT = {
664
716
  STORE_INTERNAL: void 0,
665
717
  get STORE() {
@@ -690,7 +742,9 @@ var openOperation = (token, store) => {
690
742
  time: Date.now(),
691
743
  token
692
744
  };
693
- (_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
+ );
694
748
  };
695
749
  var closeOperation = (store) => {
696
750
  var _a;
@@ -765,98 +819,6 @@ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
765
819
  // src/internal/transaction-internal.ts
766
820
  var import_hamt_plus4 = __toESM(require("hamt_plus"));
767
821
  var Rx2 = __toESM(require("rxjs"));
768
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
769
- var buildTransaction = (key, params, store) => {
770
- var _a;
771
- store.transactionStatus = {
772
- key,
773
- phase: `building`,
774
- core: {
775
- atoms: store.atoms,
776
- atomsThatAreDefault: store.atomsThatAreDefault,
777
- operation: { open: false },
778
- readonlySelectors: store.readonlySelectors,
779
- timelines: store.timelines,
780
- timelineAtoms: store.timelineAtoms,
781
- transactions: store.transactions,
782
- selectorAtoms: store.selectorAtoms,
783
- selectorGraph: store.selectorGraph,
784
- selectors: store.selectors,
785
- valueMap: store.valueMap
786
- },
787
- atomUpdates: [],
788
- params,
789
- output: void 0
790
- };
791
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
792
- };
793
- var applyTransaction = (output, store) => {
794
- var _a, _b, _c, _d;
795
- if (store.transactionStatus.phase !== `building`) {
796
- (_a = store.config.logger) == null ? void 0 : _a.warn(
797
- `abortTransaction called outside of a transaction. This is probably a bug.`
798
- );
799
- return;
800
- }
801
- (_b = store.config.logger) == null ? void 0 : _b.info(
802
- `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
803
- );
804
- store.transactionStatus.phase = `applying`;
805
- store.transactionStatus.output = output;
806
- const { atomUpdates } = store.transactionStatus;
807
- for (const { key, newValue } of atomUpdates) {
808
- const token = { key, type: `atom` };
809
- if (!import_hamt_plus4.default.has(token.key, store.valueMap)) {
810
- const atom2 = import_hamt_plus4.default.get(token.key, store.transactionStatus.core.atoms);
811
- store.atoms = import_hamt_plus4.default.set(atom2.key, atom2, store.atoms);
812
- store.valueMap = import_hamt_plus4.default.set(atom2.key, atom2.default, store.valueMap);
813
- (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${atom2.key}"`);
814
- }
815
- const state = withdraw(token, store);
816
- setState(state, newValue, store);
817
- }
818
- const myTransaction = withdraw(
819
- { key: store.transactionStatus.key, type: `transaction` },
820
- store
821
- );
822
- myTransaction.subject.next({
823
- key: store.transactionStatus.key,
824
- atomUpdates,
825
- output,
826
- params: store.transactionStatus.params
827
- });
828
- store.transactionStatus = { phase: `idle` };
829
- (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
830
- };
831
- var undoTransactionUpdate = (update, store) => {
832
- var _a;
833
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
834
- for (const { key, oldValue } of update.atomUpdates) {
835
- const token = { key, type: `atom` };
836
- const state = withdraw(token, store);
837
- setState(state, oldValue, store);
838
- }
839
- };
840
- var redoTransactionUpdate = (update, store) => {
841
- var _a;
842
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
843
- for (const { key, newValue } of update.atomUpdates) {
844
- const token = { key, type: `atom` };
845
- const state = withdraw(token, store);
846
- setState(state, newValue, store);
847
- }
848
- };
849
- var abortTransaction = (store) => {
850
- var _a, _b;
851
- if (store.transactionStatus.phase === `idle`) {
852
- (_a = store.config.logger) == null ? void 0 : _a.warn(
853
- `abortTransaction called outside of a transaction. This is probably a bug.`
854
- );
855
- return;
856
- }
857
- store.transactionStatus = { phase: `idle` };
858
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
859
- };
860
822
  function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
861
823
  const newTransaction = {
862
824
  key: options.key,
@@ -880,6 +842,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
880
842
  throw thrown;
881
843
  }
882
844
  },
845
+ install: (store2) => transaction__INTERNAL(options, store2),
883
846
  subject: new Rx2.Subject()
884
847
  };
885
848
  const core = target(store);
@@ -1139,9 +1102,59 @@ var attachMetaState = (store = IMPLICIT.STORE) => {
1139
1102
  };
1140
1103
 
1141
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
1142
1108
  var import_hamt_plus6 = __toESM(require("hamt_plus"));
1143
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
1144
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
1145
1158
  var traceSelectorAtoms = (selectorKey, dependency, store) => {
1146
1159
  const roots = [];
1147
1160
  const sources = lookupSelectorSources(dependency.key, store);
@@ -1168,6 +1181,8 @@ var traceAllSelectorAtoms = (selectorKey, store) => {
1168
1181
  (source) => source.type === `atom` ? source : traceSelectorAtoms(selectorKey, source, store)
1169
1182
  );
1170
1183
  };
1184
+
1185
+ // src/internal/selector/update-selector-atoms.ts
1171
1186
  var updateSelectorAtoms = (selectorKey, dependency, store) => {
1172
1187
  var _a, _b;
1173
1188
  const core = target(store);
@@ -1193,104 +1208,6 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1193
1208
  });
1194
1209
  }
1195
1210
  };
1196
- var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1197
- get: (dependency) => {
1198
- var _a, _b;
1199
- const core = target(store);
1200
- const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1201
- const dependencyState = withdraw(dependency, store);
1202
- const dependencyValue = getState__INTERNAL(dependencyState, store);
1203
- if (alreadyRegistered) {
1204
- (_a = store.config.logger) == null ? void 0 : _a.info(
1205
- ` || ${selectorKey} <- ${dependency.key} =`,
1206
- dependencyValue
1207
- );
1208
- } else {
1209
- (_b = store.config.logger) == null ? void 0 : _b.info(
1210
- `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1211
- dependencyValue,
1212
- `)`
1213
- );
1214
- core.selectorGraph = core.selectorGraph.set(
1215
- { from: dependency.key, to: selectorKey },
1216
- {
1217
- source: dependency.key
1218
- }
1219
- );
1220
- }
1221
- updateSelectorAtoms(selectorKey, dependency, store);
1222
- return dependencyValue;
1223
- },
1224
- set: (stateToken, newValue) => {
1225
- const state = withdraw(stateToken, store);
1226
- setState__INTERNAL(state, newValue, store);
1227
- }
1228
- });
1229
- function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1230
- var _a, _b, _c;
1231
- const core = target(store);
1232
- if (import_hamt_plus6.default.has(options.key, core.selectors)) {
1233
- (_a = store.config.logger) == null ? void 0 : _a.error(
1234
- `Key "${options.key}" already exists in the store.`
1235
- );
1236
- }
1237
- const subject = new Rx5.Subject();
1238
- const { get, set } = registerSelector(options.key, store);
1239
- const getSelf = () => {
1240
- const value = options.get({ get });
1241
- cacheValue(options.key, value, store);
1242
- return value;
1243
- };
1244
- if (!(`set` in options)) {
1245
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1246
- subject,
1247
- get: getSelf,
1248
- type: `readonly_selector`
1249
- }), family && { family });
1250
- core.readonlySelectors = import_hamt_plus6.default.set(
1251
- options.key,
1252
- readonlySelector,
1253
- core.readonlySelectors
1254
- );
1255
- const initialValue2 = getSelf();
1256
- (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
1257
- const token2 = {
1258
- key: options.key,
1259
- type: `readonly_selector`,
1260
- family
1261
- };
1262
- store.subject.selectorCreation.next(token2);
1263
- return token2;
1264
- }
1265
- const setSelf = (next) => {
1266
- var _a2;
1267
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1268
- const oldValue = getSelf();
1269
- const newValue = become(next)(oldValue);
1270
- cacheValue(options.key, newValue, store);
1271
- markDone(options.key, store);
1272
- if (store.transactionStatus.phase === `idle`) {
1273
- subject.next({ newValue, oldValue });
1274
- }
1275
- options.set({ get, set }, newValue);
1276
- };
1277
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1278
- subject,
1279
- get: getSelf,
1280
- set: setSelf,
1281
- type: `selector`
1282
- }), family && { family });
1283
- core.selectors = import_hamt_plus6.default.set(options.key, mySelector, core.selectors);
1284
- const initialValue = getSelf();
1285
- (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
1286
- const token = {
1287
- key: options.key,
1288
- type: `selector`,
1289
- family
1290
- };
1291
- store.subject.selectorCreation.next(token);
1292
- return token;
1293
- }
1294
1211
 
1295
1212
  // src/internal/set.ts
1296
1213
  var import_hamt_plus7 = __toESM(require("hamt_plus"));
@@ -1330,7 +1247,7 @@ var setAtomState = (atom2, next, store = IMPLICIT.STORE) => {
1330
1247
  const newValue = become(next)(oldValue);
1331
1248
  (_a = store.config.logger) == null ? void 0 : _a.info(`<< setting atom "${atom2.key}" to`, newValue);
1332
1249
  cacheValue(atom2.key, newValue, store);
1333
- if (isAtomDefault(atom2.key)) {
1250
+ if (isAtomDefault(atom2.key, store)) {
1334
1251
  markAtomAsNotDefault(atom2.key, store);
1335
1252
  }
1336
1253
  markDone(atom2.key, store);
@@ -1361,6 +1278,98 @@ var setState__INTERNAL = (state, value, store = IMPLICIT.STORE) => {
1361
1278
  }
1362
1279
  };
1363
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
+
1364
1373
  // src/internal/subscribe-internal.ts
1365
1374
  var prepareUpdate = (state, store) => {
1366
1375
  const oldValue = recallState(state, store);
@@ -1395,6 +1404,11 @@ var emitUpdate = (state, update, store) => {
1395
1404
  var subscribeToRootAtoms = (state, store) => {
1396
1405
  const dependencySubscriptions = `default` in state ? null : traceAllSelectorAtoms(state.key, store).map((atomToken) => {
1397
1406
  const atom2 = withdraw(atomToken, store);
1407
+ if (atom2 === null) {
1408
+ throw new Error(
1409
+ `Atom "${atomToken.key}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`
1410
+ );
1411
+ }
1398
1412
  return atom2.subject.subscribe((atomChange) => {
1399
1413
  var _a, _b;
1400
1414
  (_a = store.config.logger) == null ? void 0 : _a.info(
@@ -1417,7 +1431,7 @@ var subscribeToRootAtoms = (state, store) => {
1417
1431
  var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1418
1432
  var _a, _b, _c, _d;
1419
1433
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23E9 redo "${token.key}"`);
1420
- const timelineData = store.timelineStore.get(token.key);
1434
+ const timelineData = store.timelines.get(token.key);
1421
1435
  if (!timelineData) {
1422
1436
  (_b = store.config.logger) == null ? void 0 : _b.error(
1423
1437
  `Failed to redo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1435,14 +1449,14 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1435
1449
  switch (update.type) {
1436
1450
  case `atom_update`: {
1437
1451
  const { key, newValue } = update;
1438
- setState({ key, type: `atom` }, newValue);
1452
+ setState({ key, type: `atom` }, newValue, store);
1439
1453
  break;
1440
1454
  }
1441
1455
  case `selector_update`:
1442
1456
  case `transaction_update`: {
1443
1457
  for (const atomUpdate of update.atomUpdates) {
1444
1458
  const { key, newValue } = atomUpdate;
1445
- setState({ key, type: `atom` }, newValue);
1459
+ setState({ key, type: `atom` }, newValue, store);
1446
1460
  }
1447
1461
  break;
1448
1462
  }
@@ -1456,7 +1470,7 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1456
1470
  var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1457
1471
  var _a, _b, _c, _d;
1458
1472
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23EA undo "${token.key}"`);
1459
- const timelineData = store.timelineStore.get(token.key);
1473
+ const timelineData = store.timelines.get(token.key);
1460
1474
  if (!timelineData) {
1461
1475
  (_b = store.config.logger) == null ? void 0 : _b.error(
1462
1476
  `Failed to undo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1475,14 +1489,14 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1475
1489
  switch (update.type) {
1476
1490
  case `atom_update`: {
1477
1491
  const { key, oldValue } = update;
1478
- setState({ key, type: `atom` }, oldValue);
1492
+ setState({ key, type: `atom` }, oldValue, store);
1479
1493
  break;
1480
1494
  }
1481
1495
  case `selector_update`:
1482
1496
  case `transaction_update`: {
1483
1497
  for (const atomUpdate of update.atomUpdates) {
1484
1498
  const { key, oldValue } = atomUpdate;
1485
- setState({ key, type: `atom` }, oldValue);
1499
+ setState({ key, type: `atom` }, oldValue, store);
1486
1500
  }
1487
1501
  break;
1488
1502
  }
@@ -1494,132 +1508,166 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1494
1508
  };
1495
1509
 
1496
1510
  // src/internal/timeline-internal.ts
1497
- var import_hamt_plus8 = __toESM(require("hamt_plus"));
1498
- function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1499
- var _a, _b;
1500
- const timelineData = {
1501
- at: 0,
1502
- timeTraveling: false,
1503
- history: [],
1504
- selectorTime: null,
1505
- transactionKey: null
1506
- };
1507
- const subscribeToAtom = (token2) => {
1508
- const state = withdraw(token2, store);
1509
- state.subject.subscribe((update) => {
1510
- var _a2, _b2, _c, _d, _e;
1511
- const storeCurrentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1512
- const storeCurrentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1513
- const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1514
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1515
- `\u23F3 timeline "${options.key}" saw atom "${token2.key}" go (`,
1516
- update.oldValue,
1517
- `->`,
1518
- update.newValue,
1519
- storeCurrentTransactionKey ? `) in transaction "${storeCurrentTransactionKey}"` : storeCurrentSelectorKey ? `) in selector "${storeCurrentSelectorKey}"` : `)`
1520
- );
1521
- 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`) {
1522
1543
  const currentTransaction = withdraw(
1523
- { key: storeCurrentTransactionKey, type: `transaction` },
1544
+ { key: currentTransactionKey, type: `transaction` },
1524
1545
  store
1525
1546
  );
1526
- if (timelineData.transactionKey !== storeCurrentTransactionKey) {
1527
- if (timelineData.transactionKey) {
1528
- (_b2 = store.config.logger) == null ? void 0 : _b2.error(
1529
- `Timeline "${options.key}" was unable to resolve transaction "${timelineData.transactionKey}. This is probably a bug.`
1547
+ if (currentTransaction === null) {
1548
+ throw new Error(
1549
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
1550
+ );
1551
+ }
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.`
1530
1556
  );
1531
1557
  }
1532
- timelineData.transactionKey = storeCurrentTransactionKey;
1558
+ tl.transactionKey = currentTransactionKey;
1533
1559
  const subscription = currentTransaction.subject.subscribe((update2) => {
1534
- var _a3;
1535
- if (timelineData.timeTraveling === false) {
1536
- if (timelineData.at !== timelineData.history.length) {
1537
- 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);
1538
1564
  }
1539
- timelineData.history.push(__spreadProps(__spreadValues({
1540
- type: `transaction_update`
1565
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
1566
+ type: `transaction_update`,
1567
+ timestamp: currentTransactionTime
1541
1568
  }, update2), {
1542
1569
  atomUpdates: update2.atomUpdates.filter(
1543
- (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1570
+ (atomUpdate) => atoms.some((atom3) => atom3.key === atomUpdate.key)
1544
1571
  )
1545
- }));
1572
+ });
1573
+ tl.history.push(timelineTransactionUpdate);
1574
+ tl.subject.next(timelineTransactionUpdate);
1546
1575
  }
1547
- timelineData.at = timelineData.history.length;
1576
+ tl.at = tl.history.length;
1548
1577
  subscription.unsubscribe();
1549
- timelineData.transactionKey = null;
1550
- (_a3 = store.config.logger) == null ? void 0 : _a3.info(
1551
- `\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}"`
1552
1581
  );
1553
1582
  });
1554
1583
  }
1555
- } else if (storeCurrentSelectorKey) {
1556
- if (timelineData.timeTraveling === false) {
1557
- if (storeCurrentSelectorTime !== timelineData.selectorTime) {
1558
- const newSelectorUpdate = {
1559
- type: `selector_update`,
1560
- key: storeCurrentSelectorKey,
1561
- atomUpdates: []
1562
- };
1563
- newSelectorUpdate.atomUpdates.push(__spreadValues({
1564
- 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,
1565
1611
  type: `atom_update`
1566
1612
  }, update));
1567
- if (timelineData.at !== timelineData.history.length) {
1568
- timelineData.history.splice(timelineData.at);
1569
- }
1570
- timelineData.history.push(newSelectorUpdate);
1571
- (_c = store.config.logger) == null ? void 0 : _c.info(
1572
- `\u231B timeline "${options.key}" got a selector_update "${storeCurrentSelectorKey}" with`,
1573
- 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)
1574
1616
  );
1575
- timelineData.at = timelineData.history.length;
1576
- timelineData.selectorTime = storeCurrentSelectorTime;
1577
- } else {
1578
- const latestUpdate = timelineData.history.at(-1);
1579
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1580
- latestUpdate.atomUpdates.push(__spreadValues({
1581
- key: token2.key,
1582
- type: `atom_update`
1583
- }, update));
1584
- (_d = store.config.logger) == null ? void 0 : _d.info(
1585
- ` \u231B timeline "${options.key}" set selector_update "${storeCurrentSelectorKey}" to`,
1586
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1587
- );
1588
- }
1589
1617
  }
1590
1618
  }
1591
1619
  } else {
1592
- if (timelineData.timeTraveling === false) {
1593
- timelineData.selectorTime = null;
1594
- if (timelineData.at !== timelineData.history.length) {
1595
- timelineData.history.splice(timelineData.at);
1596
- }
1597
- timelineData.history.push({
1598
- type: `atom_update`,
1599
- key: token2.key,
1600
- oldValue: update.oldValue,
1601
- newValue: update.newValue
1602
- });
1603
- (_e = store.config.logger) == null ? void 0 : _e.info(
1604
- `\u231B timeline "${options.key}" got a state_update to "${token2.key}"`
1605
- );
1606
- 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);
1607
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;
1608
1638
  }
1609
- });
1610
- };
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
+ });
1611
1657
  const core = target(store);
1612
1658
  for (const tokenOrFamily of options.atoms) {
1613
1659
  const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key);
1614
1660
  if (timelineKey) {
1615
- (_a = store.config.logger) == null ? void 0 : _a.error(
1661
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1616
1662
  `\u274C Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
1617
1663
  );
1618
1664
  continue;
1619
1665
  }
1620
1666
  if (tokenOrFamily.type === `atom_family`) {
1621
1667
  const family = tokenOrFamily;
1622
- family.subject.subscribe((token2) => subscribeToAtom(token2));
1668
+ family.subject.subscribe(
1669
+ (token2) => addAtomToTimeline(token2, options.atoms, tl, store)
1670
+ );
1623
1671
  } else {
1624
1672
  const token2 = tokenOrFamily;
1625
1673
  if (`family` in token2 && token2.family) {
@@ -1627,20 +1675,20 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1627
1675
  token2.family.key
1628
1676
  );
1629
1677
  if (familyTimelineKey) {
1630
- (_b = store.config.logger) == null ? void 0 : _b.error(
1678
+ (_c = store.config.logger) == null ? void 0 : _c.error(
1631
1679
  `\u274C Failed to add atom "${token2.key}" to timeline "${options.key}" because its family "${token2.family.key}" belongs to timeline "${familyTimelineKey}"`
1632
1680
  );
1633
1681
  continue;
1634
1682
  }
1635
1683
  }
1636
- subscribeToAtom(token2);
1684
+ addAtomToTimeline(token2, options.atoms, tl, store);
1637
1685
  }
1638
1686
  core.timelineAtoms = core.timelineAtoms.set({
1639
1687
  atomKey: tokenOrFamily.key,
1640
1688
  timelineKey: options.key
1641
1689
  });
1642
1690
  }
1643
- 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);
1644
1692
  const token = {
1645
1693
  key: options.key,
1646
1694
  type: `timeline`
@@ -1649,6 +1697,129 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1649
1697
  return token;
1650
1698
  }
1651
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
+
1652
1823
  // src/atom.ts
1653
1824
  function atom(options) {
1654
1825
  return atom__INTERNAL(options);
@@ -1698,10 +1869,34 @@ function selectorFamily(options) {
1698
1869
  return selectorFamily__INTERNAL(options);
1699
1870
  }
1700
1871
 
1872
+ // src/silo.ts
1873
+ var silo = (name, fromStore = null) => {
1874
+ const store = createStore(name, fromStore);
1875
+ return {
1876
+ store,
1877
+ atom: (options) => atom__INTERNAL(options, void 0, store),
1878
+ atomFamily: (options) => atomFamily__INTERNAL(options, store),
1879
+ selector: (options) => selector__INTERNAL(options, void 0, store),
1880
+ selectorFamily: (options) => selectorFamily__INTERNAL(options, store),
1881
+ transaction: (options) => transaction__INTERNAL(options, store),
1882
+ timeline: (options) => timeline__INTERNAL(options, store),
1883
+ getState: (token) => getState(token, store),
1884
+ setState: (token, newValue) => setState(token, newValue, store),
1885
+ subscribe: (token, handler) => subscribe(token, handler, store),
1886
+ undo: (token) => undo__INTERNAL(token, store),
1887
+ redo: (token) => redo__INTERNAL(token, store)
1888
+ };
1889
+ };
1890
+
1701
1891
  // src/subscribe.ts
1702
1892
  var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1703
1893
  var _a;
1704
1894
  const state = withdraw(token, store);
1895
+ if (state === null) {
1896
+ throw new Error(
1897
+ `State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1898
+ );
1899
+ }
1705
1900
  const subscription = state.subject.subscribe(handleUpdate);
1706
1901
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to "${state.key}"`);
1707
1902
  const dependencySubscriptions = state.type !== `atom` ? subscribeToRootAtoms(state, store) : null;
@@ -1724,6 +1919,11 @@ var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1724
1919
  var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1725
1920
  var _a;
1726
1921
  const tx = withdraw(token, store);
1922
+ if (tx === null) {
1923
+ throw new Error(
1924
+ `Cannot subscribe to transaction "${token.key}": transaction not found in store "${store.config.name}".`
1925
+ );
1926
+ }
1727
1927
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to transaction "${token.key}"`);
1728
1928
  const subscription = tx.subject.subscribe(handleUpdate);
1729
1929
  const unsubscribe = () => {
@@ -1733,6 +1933,23 @@ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1733
1933
  };
1734
1934
  return unsubscribe;
1735
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
+ };
1736
1953
 
1737
1954
  // src/timeline.ts
1738
1955
  var timeline = (options) => {
@@ -1749,11 +1966,24 @@ var undo = (token) => {
1749
1966
  function transaction(options) {
1750
1967
  return transaction__INTERNAL(options);
1751
1968
  }
1752
- var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => withdraw(token, store).run(...parameters);
1969
+ var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => {
1970
+ const tx = withdraw(token, store);
1971
+ if (tx) {
1972
+ return tx.run(...parameters);
1973
+ }
1974
+ throw new Error(
1975
+ `Cannot run transaction "${token.key}": transaction not found in store "${store.config.name}".`
1976
+ );
1977
+ };
1753
1978
 
1754
1979
  // src/index.ts
1755
1980
  var getState = (token, store = IMPLICIT.STORE) => {
1756
1981
  const state = withdraw(token, store);
1982
+ if (state === null) {
1983
+ throw new Error(
1984
+ `${capitalize(token.type)} "${token.key}" not found in store "${store.config.name}".`
1985
+ );
1986
+ }
1757
1987
  return getState__INTERNAL(state, store);
1758
1988
  };
1759
1989
  var setState = (token, value, store = IMPLICIT.STORE) => {
@@ -1766,6 +1996,11 @@ var setState = (token, value, store = IMPLICIT.STORE) => {
1766
1996
  return;
1767
1997
  }
1768
1998
  const state = withdraw(token, store);
1999
+ if (state === null) {
2000
+ throw new Error(
2001
+ `${capitalize(token.type)} "${token.key}" not found in store "${store.config.name}".`
2002
+ );
2003
+ }
1769
2004
  setState__INTERNAL(state, value, store);
1770
2005
  closeOperation(store);
1771
2006
  };
@@ -1784,7 +2019,9 @@ var isDefault = (token, store = IMPLICIT.STORE) => token.type === `atom` ? isAto
1784
2019
  selectorFamily,
1785
2020
  setLogLevel,
1786
2021
  setState,
2022
+ silo,
1787
2023
  subscribe,
2024
+ subscribeToTimeline,
1788
2025
  subscribeToTransaction,
1789
2026
  timeline,
1790
2027
  transaction,