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.mjs CHANGED
@@ -34,6 +34,9 @@ var __export = (target2, all) => {
34
34
  __defProp(target2, name, { get: all[name], enumerable: true });
35
35
  };
36
36
 
37
+ // ../anvl/src/string/capitalize.ts
38
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
39
+
37
40
  // src/internal/index.ts
38
41
  var internal_exports = {};
39
42
  __export(internal_exports, {
@@ -107,9 +110,9 @@ function lookup(key, store) {
107
110
  return { key, type };
108
111
  }
109
112
  function withdraw(token, store) {
110
- var _a, _b, _c;
113
+ var _a, _b, _c, _d, _e;
111
114
  const core = target(store);
112
- return (_c = (_b = (_a = HAMT.get(token.key, core.atoms)) != null ? _a : HAMT.get(token.key, core.selectors)) != null ? _b : HAMT.get(token.key, core.readonlySelectors)) != null ? _c : HAMT.get(token.key, core.transactions);
115
+ return (_e = (_d = (_c = (_b = (_a = HAMT.get(token.key, core.atoms)) != null ? _a : HAMT.get(token.key, core.selectors)) != null ? _b : HAMT.get(token.key, core.readonlySelectors)) != null ? _c : HAMT.get(token.key, core.transactions)) != null ? _d : HAMT.get(token.key, core.timelines)) != null ? _e : null;
113
116
  }
114
117
  function deposit(state) {
115
118
  return __spreadValues({
@@ -201,7 +204,7 @@ var recordToEntries = (obj) => Object.entries(obj);
201
204
  var entriesToRecord = (entries) => Object.fromEntries(entries);
202
205
 
203
206
  // ../anvl/src/object/mapObject.ts
204
- import { pipe } from "fp-ts/lib/function";
207
+ import { pipe } from "fp-ts/function";
205
208
  var mapObject = (obj, fn) => pipe(
206
209
  obj,
207
210
  recordToEntries,
@@ -305,13 +308,19 @@ var EMPTY_RELATION_DATA = {
305
308
  a: `from`,
306
309
  b: `to`
307
310
  };
308
- var isRelationData = (isContent, a = `from`, b = `to`) => (input) => hasExactProperties({
309
- contents: isContent ? isRecord(isString, isContent) : hasExactProperties({}),
310
- relations: isRecord(isString, isArray(isString)),
311
- relationType: isRelationType,
312
- a: isLiteral(a),
313
- b: isLiteral(b)
314
- })(input);
311
+ var isRelationData = ({
312
+ from: a = `from`,
313
+ to: b = `to`,
314
+ isContent
315
+ } = {}) => (input) => {
316
+ return hasExactProperties({
317
+ contents: isContent ? isRecord(isString, isContent) : hasExactProperties({}),
318
+ relations: isRecord(isString, isArray(isString)),
319
+ relationType: isRelationType,
320
+ a: isLiteral(a),
321
+ b: isLiteral(b)
322
+ })(input);
323
+ };
315
324
 
316
325
  // ../anvl/src/join/get-related-ids.ts
317
326
  var getRelatedIds = (relationMap, id) => {
@@ -328,6 +337,21 @@ var getRelatedId = (relationMap, id) => {
328
337
  return relations[0];
329
338
  };
330
339
 
340
+ // ../anvl/src/join/make-json-interface.ts
341
+ var makeJsonInterface = (join, ...params) => {
342
+ const isContent = params[0];
343
+ const { a, b } = join;
344
+ const options = {
345
+ from: a,
346
+ to: b,
347
+ isContent
348
+ };
349
+ return {
350
+ toJson: (join2) => join2.toJSON(),
351
+ fromJson: (json) => Join.fromJSON(json, options)
352
+ };
353
+ };
354
+
331
355
  // ../anvl/src/join/relation-contents.ts
332
356
  import { pipe as pipe5 } from "fp-ts/function";
333
357
 
@@ -518,11 +542,16 @@ var setRelations = (current, subject, relations) => {
518
542
  };
519
543
 
520
544
  // ../anvl/src/join/index.ts
521
- var Join = class {
545
+ var Join = class _Join {
522
546
  constructor(json) {
523
547
  this.a = `from`;
524
548
  this.b = `to`;
525
- Object.assign(this, __spreadValues(__spreadValues({}, EMPTY_RELATION_DATA), json));
549
+ this.makeJsonInterface = (...params) => {
550
+ return makeJsonInterface(this, ...params);
551
+ };
552
+ Object.assign(this, __spreadProps(__spreadValues(__spreadValues({}, EMPTY_RELATION_DATA), json), {
553
+ makeJsonInterface: this.makeJsonInterface
554
+ }));
526
555
  }
527
556
  toJSON() {
528
557
  return {
@@ -533,20 +562,20 @@ var Join = class {
533
562
  b: this.b
534
563
  };
535
564
  }
536
- static fromJSON(json, isContent = cannotExist, a = `from`, b = `to`) {
537
- const isValid = isRelationData(isContent, a, b)(json);
565
+ static fromJSON(json, options) {
566
+ const isValid = isRelationData(options)(json);
538
567
  if (isValid) {
539
- return new Join(json);
568
+ return new _Join(json);
540
569
  }
541
570
  throw new Error(
542
571
  `Saved JSON for this Join is invalid: ${JSON.stringify(json)}`
543
572
  );
544
573
  }
545
574
  from(newA) {
546
- return new Join(__spreadProps(__spreadValues({}, this), { a: newA }));
575
+ return new _Join(__spreadProps(__spreadValues({}, this), { a: newA }));
547
576
  }
548
577
  to(newB) {
549
- return new Join(__spreadProps(__spreadValues({}, this), { b: newB }));
578
+ return new _Join(__spreadProps(__spreadValues({}, this), { b: newB }));
550
579
  }
551
580
  getRelatedId(id) {
552
581
  return getRelatedId(this, id);
@@ -570,51 +599,72 @@ var Join = class {
570
599
  return getRelations(this, id);
571
600
  }
572
601
  setRelations(subject, relations) {
573
- return new Join(setRelations(this, subject, relations));
602
+ return new _Join(setRelations(this, subject, relations));
574
603
  }
575
604
  set(relation, ...rest) {
576
- return new Join(setRelationWithContent(this, relation, ...rest));
605
+ return new _Join(setRelationWithContent(this, relation, ...rest));
577
606
  }
578
607
  remove(relation) {
579
- return new Join(
608
+ return new _Join(
580
609
  removeRelation(this, relation)
581
610
  );
582
611
  }
583
612
  };
584
613
 
585
614
  // src/internal/store.ts
586
- var createStore = (name) => ({
587
- atoms: HAMT2.make(),
588
- atomsThatAreDefault: /* @__PURE__ */ new Set(),
589
- readonlySelectors: HAMT2.make(),
590
- selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
591
- selectorGraph: new Join({ relationType: `n:n` }),
592
- selectors: HAMT2.make(),
593
- timelines: HAMT2.make(),
594
- timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
595
- timelineStore: HAMT2.make(),
596
- transactions: HAMT2.make(),
597
- valueMap: HAMT2.make(),
598
- subject: {
599
- atomCreation: new Rx.Subject(),
600
- selectorCreation: new Rx.Subject(),
601
- transactionCreation: new Rx.Subject(),
602
- timelineCreation: new Rx.Subject()
603
- },
604
- operation: {
605
- open: false
606
- },
607
- transactionStatus: {
608
- phase: `idle`
609
- },
610
- config: {
611
- name,
612
- logger: __spreadProps(__spreadValues({}, console), {
613
- info: doNothing
614
- }),
615
- logger__INTERNAL: console
616
- }
617
- });
615
+ var createStore = (name, store = null) => {
616
+ var _a;
617
+ const copiedStore = __spreadProps(__spreadValues({}, store != null ? store : (() => ({
618
+ atomsThatAreDefault: /* @__PURE__ */ new Set(),
619
+ selectorAtoms: new Join({ relationType: `n:n` }).from(`selectorKey`).to(`atomKey`),
620
+ selectorGraph: new Join({ relationType: `n:n` }),
621
+ valueMap: HAMT2.make()
622
+ }))()), {
623
+ atoms: HAMT2.make(),
624
+ readonlySelectors: HAMT2.make(),
625
+ selectors: HAMT2.make(),
626
+ transactions: HAMT2.make(),
627
+ timelines: HAMT2.make(),
628
+ timelineAtoms: new Join({ relationType: `1:n` }).from(`timelineKey`).to(`atomKey`),
629
+ subject: __spreadValues({
630
+ atomCreation: new Rx.Subject(),
631
+ selectorCreation: new Rx.Subject(),
632
+ transactionCreation: new Rx.Subject(),
633
+ timelineCreation: new Rx.Subject()
634
+ }, store == null ? void 0 : store.subject),
635
+ operation: __spreadValues({
636
+ open: false
637
+ }, store == null ? void 0 : store.operation),
638
+ transactionStatus: __spreadValues({
639
+ phase: `idle`
640
+ }, store == null ? void 0 : store.transactionStatus),
641
+ config: __spreadProps(__spreadValues({
642
+ logger: __spreadValues(__spreadProps(__spreadValues({}, console), {
643
+ info: doNothing
644
+ }), (_a = store == null ? void 0 : store.config) == null ? void 0 : _a.logger),
645
+ logger__INTERNAL: console
646
+ }, store == null ? void 0 : store.config), {
647
+ name
648
+ })
649
+ });
650
+ store == null ? void 0 : store.atoms.forEach((atom2) => {
651
+ const copiedAtom = __spreadProps(__spreadValues({}, atom2), { subject: new Rx.Subject() });
652
+ copiedStore.atoms = HAMT2.set(atom2.key, copiedAtom, copiedStore.atoms);
653
+ });
654
+ store == null ? void 0 : store.readonlySelectors.forEach((selector2) => {
655
+ selector2.install(copiedStore);
656
+ });
657
+ store == null ? void 0 : store.selectors.forEach((selector2) => {
658
+ selector2.install(copiedStore);
659
+ });
660
+ store == null ? void 0 : store.transactions.forEach((tx) => {
661
+ tx.install(copiedStore);
662
+ });
663
+ store == null ? void 0 : store.timelines.forEach((timeline2) => {
664
+ timeline2.install(copiedStore);
665
+ });
666
+ return copiedStore;
667
+ };
618
668
  var IMPLICIT = {
619
669
  STORE_INTERNAL: void 0,
620
670
  get STORE() {
@@ -645,7 +695,9 @@ var openOperation = (token, store) => {
645
695
  time: Date.now(),
646
696
  token
647
697
  };
648
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u2B55 operation start from "${token.key}"`);
698
+ (_b = store.config.logger) == null ? void 0 : _b.info(
699
+ `\u2B55 operation start from "${token.key}" in store "${store.config.name}"`
700
+ );
649
701
  };
650
702
  var closeOperation = (store) => {
651
703
  var _a;
@@ -720,98 +772,6 @@ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
720
772
  // src/internal/transaction-internal.ts
721
773
  import HAMT4 from "hamt_plus";
722
774
  import * as Rx2 from "rxjs";
723
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
724
- var buildTransaction = (key, params, store) => {
725
- var _a;
726
- store.transactionStatus = {
727
- key,
728
- phase: `building`,
729
- core: {
730
- atoms: store.atoms,
731
- atomsThatAreDefault: store.atomsThatAreDefault,
732
- operation: { open: false },
733
- readonlySelectors: store.readonlySelectors,
734
- timelines: store.timelines,
735
- timelineAtoms: store.timelineAtoms,
736
- transactions: store.transactions,
737
- selectorAtoms: store.selectorAtoms,
738
- selectorGraph: store.selectorGraph,
739
- selectors: store.selectors,
740
- valueMap: store.valueMap
741
- },
742
- atomUpdates: [],
743
- params,
744
- output: void 0
745
- };
746
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
747
- };
748
- var applyTransaction = (output, store) => {
749
- var _a, _b, _c, _d;
750
- if (store.transactionStatus.phase !== `building`) {
751
- (_a = store.config.logger) == null ? void 0 : _a.warn(
752
- `abortTransaction called outside of a transaction. This is probably a bug.`
753
- );
754
- return;
755
- }
756
- (_b = store.config.logger) == null ? void 0 : _b.info(
757
- `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
758
- );
759
- store.transactionStatus.phase = `applying`;
760
- store.transactionStatus.output = output;
761
- const { atomUpdates } = store.transactionStatus;
762
- for (const { key, newValue } of atomUpdates) {
763
- const token = { key, type: `atom` };
764
- if (!HAMT4.has(token.key, store.valueMap)) {
765
- const atom2 = HAMT4.get(token.key, store.transactionStatus.core.atoms);
766
- store.atoms = HAMT4.set(atom2.key, atom2, store.atoms);
767
- store.valueMap = HAMT4.set(atom2.key, atom2.default, store.valueMap);
768
- (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${atom2.key}"`);
769
- }
770
- const state = withdraw(token, store);
771
- setState(state, newValue, store);
772
- }
773
- const myTransaction = withdraw(
774
- { key: store.transactionStatus.key, type: `transaction` },
775
- store
776
- );
777
- myTransaction.subject.next({
778
- key: store.transactionStatus.key,
779
- atomUpdates,
780
- output,
781
- params: store.transactionStatus.params
782
- });
783
- store.transactionStatus = { phase: `idle` };
784
- (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
785
- };
786
- var undoTransactionUpdate = (update, store) => {
787
- var _a;
788
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
789
- for (const { key, oldValue } of update.atomUpdates) {
790
- const token = { key, type: `atom` };
791
- const state = withdraw(token, store);
792
- setState(state, oldValue, store);
793
- }
794
- };
795
- var redoTransactionUpdate = (update, store) => {
796
- var _a;
797
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
798
- for (const { key, newValue } of update.atomUpdates) {
799
- const token = { key, type: `atom` };
800
- const state = withdraw(token, store);
801
- setState(state, newValue, store);
802
- }
803
- };
804
- var abortTransaction = (store) => {
805
- var _a, _b;
806
- if (store.transactionStatus.phase === `idle`) {
807
- (_a = store.config.logger) == null ? void 0 : _a.warn(
808
- `abortTransaction called outside of a transaction. This is probably a bug.`
809
- );
810
- return;
811
- }
812
- store.transactionStatus = { phase: `idle` };
813
- (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
814
- };
815
775
  function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
816
776
  const newTransaction = {
817
777
  key: options.key,
@@ -835,6 +795,7 @@ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
835
795
  throw thrown;
836
796
  }
837
797
  },
798
+ install: (store2) => transaction__INTERNAL(options, store2),
838
799
  subject: new Rx2.Subject()
839
800
  };
840
801
  const core = target(store);
@@ -1094,9 +1055,59 @@ var attachMetaState = (store = IMPLICIT.STORE) => {
1094
1055
  };
1095
1056
 
1096
1057
  // src/internal/selector-internal.ts
1058
+ import HAMT9 from "hamt_plus";
1059
+
1060
+ // src/internal/selector/create-read-write-selector.ts
1097
1061
  import HAMT6 from "hamt_plus";
1098
1062
  import * as Rx5 from "rxjs";
1063
+ var createReadWriteSelector = (options, family, store, core) => {
1064
+ var _a;
1065
+ const subject = new Rx5.Subject();
1066
+ const { get, set } = registerSelector(options.key, store);
1067
+ const getSelf = () => {
1068
+ const value = options.get({ get });
1069
+ cacheValue(options.key, value, store);
1070
+ return value;
1071
+ };
1072
+ const setSelf = (next) => {
1073
+ var _a2;
1074
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1075
+ const oldValue = getSelf();
1076
+ const newValue = become(next)(oldValue);
1077
+ cacheValue(options.key, newValue, store);
1078
+ markDone(options.key, store);
1079
+ if (store.transactionStatus.phase === `idle`) {
1080
+ subject.next({ newValue, oldValue });
1081
+ }
1082
+ options.set({ get, set }, newValue);
1083
+ };
1084
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1085
+ subject,
1086
+ install: (s) => selector__INTERNAL(options, family, s),
1087
+ get: getSelf,
1088
+ set: setSelf,
1089
+ type: `selector`
1090
+ }), family && { family });
1091
+ core.selectors = HAMT6.set(options.key, mySelector, core.selectors);
1092
+ const initialValue = getSelf();
1093
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1094
+ const token = {
1095
+ key: options.key,
1096
+ type: `selector`,
1097
+ family
1098
+ };
1099
+ store.subject.selectorCreation.next(token);
1100
+ return token;
1101
+ };
1102
+
1103
+ // src/internal/selector/create-readonly-selector.ts
1104
+ import HAMT8 from "hamt_plus";
1105
+ import * as Rx6 from "rxjs";
1106
+
1107
+ // src/internal/selector/lookup-selector-sources.ts
1099
1108
  var lookupSelectorSources = (key, store) => target(store).selectorGraph.getRelations(key).filter(({ source }) => source !== key).map(({ source }) => lookup(source, store));
1109
+
1110
+ // src/internal/selector/trace-selector-atoms.ts
1100
1111
  var traceSelectorAtoms = (selectorKey, dependency, store) => {
1101
1112
  const roots = [];
1102
1113
  const sources = lookupSelectorSources(dependency.key, store);
@@ -1123,6 +1134,8 @@ var traceAllSelectorAtoms = (selectorKey, store) => {
1123
1134
  (source) => source.type === `atom` ? source : traceSelectorAtoms(selectorKey, source, store)
1124
1135
  );
1125
1136
  };
1137
+
1138
+ // src/internal/selector/update-selector-atoms.ts
1126
1139
  var updateSelectorAtoms = (selectorKey, dependency, store) => {
1127
1140
  var _a, _b;
1128
1141
  const core = target(store);
@@ -1148,104 +1161,6 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
1148
1161
  });
1149
1162
  }
1150
1163
  };
1151
- var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1152
- get: (dependency) => {
1153
- var _a, _b;
1154
- const core = target(store);
1155
- const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1156
- const dependencyState = withdraw(dependency, store);
1157
- const dependencyValue = getState__INTERNAL(dependencyState, store);
1158
- if (alreadyRegistered) {
1159
- (_a = store.config.logger) == null ? void 0 : _a.info(
1160
- ` || ${selectorKey} <- ${dependency.key} =`,
1161
- dependencyValue
1162
- );
1163
- } else {
1164
- (_b = store.config.logger) == null ? void 0 : _b.info(
1165
- `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1166
- dependencyValue,
1167
- `)`
1168
- );
1169
- core.selectorGraph = core.selectorGraph.set(
1170
- { from: dependency.key, to: selectorKey },
1171
- {
1172
- source: dependency.key
1173
- }
1174
- );
1175
- }
1176
- updateSelectorAtoms(selectorKey, dependency, store);
1177
- return dependencyValue;
1178
- },
1179
- set: (stateToken, newValue) => {
1180
- const state = withdraw(stateToken, store);
1181
- setState__INTERNAL(state, newValue, store);
1182
- }
1183
- });
1184
- function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1185
- var _a, _b, _c;
1186
- const core = target(store);
1187
- if (HAMT6.has(options.key, core.selectors)) {
1188
- (_a = store.config.logger) == null ? void 0 : _a.error(
1189
- `Key "${options.key}" already exists in the store.`
1190
- );
1191
- }
1192
- const subject = new Rx5.Subject();
1193
- const { get, set } = registerSelector(options.key, store);
1194
- const getSelf = () => {
1195
- const value = options.get({ get });
1196
- cacheValue(options.key, value, store);
1197
- return value;
1198
- };
1199
- if (!(`set` in options)) {
1200
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1201
- subject,
1202
- get: getSelf,
1203
- type: `readonly_selector`
1204
- }), family && { family });
1205
- core.readonlySelectors = HAMT6.set(
1206
- options.key,
1207
- readonlySelector,
1208
- core.readonlySelectors
1209
- );
1210
- const initialValue2 = getSelf();
1211
- (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
1212
- const token2 = {
1213
- key: options.key,
1214
- type: `readonly_selector`,
1215
- family
1216
- };
1217
- store.subject.selectorCreation.next(token2);
1218
- return token2;
1219
- }
1220
- const setSelf = (next) => {
1221
- var _a2;
1222
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
1223
- const oldValue = getSelf();
1224
- const newValue = become(next)(oldValue);
1225
- cacheValue(options.key, newValue, store);
1226
- markDone(options.key, store);
1227
- if (store.transactionStatus.phase === `idle`) {
1228
- subject.next({ newValue, oldValue });
1229
- }
1230
- options.set({ get, set }, newValue);
1231
- };
1232
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1233
- subject,
1234
- get: getSelf,
1235
- set: setSelf,
1236
- type: `selector`
1237
- }), family && { family });
1238
- core.selectors = HAMT6.set(options.key, mySelector, core.selectors);
1239
- const initialValue = getSelf();
1240
- (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
1241
- const token = {
1242
- key: options.key,
1243
- type: `selector`,
1244
- family
1245
- };
1246
- store.subject.selectorCreation.next(token);
1247
- return token;
1248
- }
1249
1164
 
1250
1165
  // src/internal/set.ts
1251
1166
  import HAMT7 from "hamt_plus";
@@ -1285,7 +1200,7 @@ var setAtomState = (atom2, next, store = IMPLICIT.STORE) => {
1285
1200
  const newValue = become(next)(oldValue);
1286
1201
  (_a = store.config.logger) == null ? void 0 : _a.info(`<< setting atom "${atom2.key}" to`, newValue);
1287
1202
  cacheValue(atom2.key, newValue, store);
1288
- if (isAtomDefault(atom2.key)) {
1203
+ if (isAtomDefault(atom2.key, store)) {
1289
1204
  markAtomAsNotDefault(atom2.key, store);
1290
1205
  }
1291
1206
  markDone(atom2.key, store);
@@ -1316,6 +1231,98 @@ var setState__INTERNAL = (state, value, store = IMPLICIT.STORE) => {
1316
1231
  }
1317
1232
  };
1318
1233
 
1234
+ // src/internal/selector/register-selector.ts
1235
+ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1236
+ get: (dependency) => {
1237
+ var _a, _b;
1238
+ const core = target(store);
1239
+ const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1240
+ const dependencyState = withdraw(dependency, store);
1241
+ if (dependencyState === null) {
1242
+ throw new Error(
1243
+ `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1244
+ );
1245
+ }
1246
+ const dependencyValue = getState__INTERNAL(dependencyState, store);
1247
+ if (alreadyRegistered) {
1248
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1249
+ ` || ${selectorKey} <- ${dependency.key} =`,
1250
+ dependencyValue
1251
+ );
1252
+ } else {
1253
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1254
+ `\u{1F50C} registerSelector "${selectorKey}" <- ( "${dependency.key}" =`,
1255
+ dependencyValue,
1256
+ `)`
1257
+ );
1258
+ core.selectorGraph = core.selectorGraph.set(
1259
+ { from: dependency.key, to: selectorKey },
1260
+ {
1261
+ source: dependency.key
1262
+ }
1263
+ );
1264
+ }
1265
+ updateSelectorAtoms(selectorKey, dependency, store);
1266
+ return dependencyValue;
1267
+ },
1268
+ set: (stateToken, newValue) => {
1269
+ const state = withdraw(stateToken, store);
1270
+ if (state === null) {
1271
+ throw new Error(
1272
+ `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1273
+ );
1274
+ }
1275
+ setState__INTERNAL(state, newValue, store);
1276
+ }
1277
+ });
1278
+
1279
+ // src/internal/selector/create-readonly-selector.ts
1280
+ var createReadonlySelector = (options, family, store, core) => {
1281
+ var _a;
1282
+ const subject = new Rx6.Subject();
1283
+ const { get } = registerSelector(options.key, store);
1284
+ const getSelf = () => {
1285
+ const value = options.get({ get });
1286
+ cacheValue(options.key, value, store);
1287
+ return value;
1288
+ };
1289
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1290
+ subject,
1291
+ install: (s) => selector__INTERNAL(options, family, s),
1292
+ get: getSelf,
1293
+ type: `readonly_selector`
1294
+ }), family && { family });
1295
+ core.readonlySelectors = HAMT8.set(
1296
+ options.key,
1297
+ readonlySelector,
1298
+ core.readonlySelectors
1299
+ );
1300
+ const initialValue = getSelf();
1301
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728 "${options.key}" =`, initialValue);
1302
+ const token = {
1303
+ key: options.key,
1304
+ type: `readonly_selector`,
1305
+ family
1306
+ };
1307
+ store.subject.selectorCreation.next(token);
1308
+ return token;
1309
+ };
1310
+
1311
+ // src/internal/selector-internal.ts
1312
+ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1313
+ var _a;
1314
+ const core = target(store);
1315
+ if (HAMT9.has(options.key, core.selectors)) {
1316
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1317
+ `Key "${options.key}" already exists in the store.`
1318
+ );
1319
+ }
1320
+ if (!(`set` in options)) {
1321
+ return createReadonlySelector(options, family, store, core);
1322
+ }
1323
+ return createReadWriteSelector(options, family, store, core);
1324
+ }
1325
+
1319
1326
  // src/internal/subscribe-internal.ts
1320
1327
  var prepareUpdate = (state, store) => {
1321
1328
  const oldValue = recallState(state, store);
@@ -1350,6 +1357,11 @@ var emitUpdate = (state, update, store) => {
1350
1357
  var subscribeToRootAtoms = (state, store) => {
1351
1358
  const dependencySubscriptions = `default` in state ? null : traceAllSelectorAtoms(state.key, store).map((atomToken) => {
1352
1359
  const atom2 = withdraw(atomToken, store);
1360
+ if (atom2 === null) {
1361
+ throw new Error(
1362
+ `Atom "${atomToken.key}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`
1363
+ );
1364
+ }
1353
1365
  return atom2.subject.subscribe((atomChange) => {
1354
1366
  var _a, _b;
1355
1367
  (_a = store.config.logger) == null ? void 0 : _a.info(
@@ -1372,7 +1384,7 @@ var subscribeToRootAtoms = (state, store) => {
1372
1384
  var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1373
1385
  var _a, _b, _c, _d;
1374
1386
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23E9 redo "${token.key}"`);
1375
- const timelineData = store.timelineStore.get(token.key);
1387
+ const timelineData = store.timelines.get(token.key);
1376
1388
  if (!timelineData) {
1377
1389
  (_b = store.config.logger) == null ? void 0 : _b.error(
1378
1390
  `Failed to redo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1390,14 +1402,14 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1390
1402
  switch (update.type) {
1391
1403
  case `atom_update`: {
1392
1404
  const { key, newValue } = update;
1393
- setState({ key, type: `atom` }, newValue);
1405
+ setState({ key, type: `atom` }, newValue, store);
1394
1406
  break;
1395
1407
  }
1396
1408
  case `selector_update`:
1397
1409
  case `transaction_update`: {
1398
1410
  for (const atomUpdate of update.atomUpdates) {
1399
1411
  const { key, newValue } = atomUpdate;
1400
- setState({ key, type: `atom` }, newValue);
1412
+ setState({ key, type: `atom` }, newValue, store);
1401
1413
  }
1402
1414
  break;
1403
1415
  }
@@ -1411,7 +1423,7 @@ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1411
1423
  var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1412
1424
  var _a, _b, _c, _d;
1413
1425
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u23EA undo "${token.key}"`);
1414
- const timelineData = store.timelineStore.get(token.key);
1426
+ const timelineData = store.timelines.get(token.key);
1415
1427
  if (!timelineData) {
1416
1428
  (_b = store.config.logger) == null ? void 0 : _b.error(
1417
1429
  `Failed to undo on timeline "${token.key}". This timeline has not been initialized.`
@@ -1430,14 +1442,14 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1430
1442
  switch (update.type) {
1431
1443
  case `atom_update`: {
1432
1444
  const { key, oldValue } = update;
1433
- setState({ key, type: `atom` }, oldValue);
1445
+ setState({ key, type: `atom` }, oldValue, store);
1434
1446
  break;
1435
1447
  }
1436
1448
  case `selector_update`:
1437
1449
  case `transaction_update`: {
1438
1450
  for (const atomUpdate of update.atomUpdates) {
1439
1451
  const { key, oldValue } = atomUpdate;
1440
- setState({ key, type: `atom` }, oldValue);
1452
+ setState({ key, type: `atom` }, oldValue, store);
1441
1453
  }
1442
1454
  break;
1443
1455
  }
@@ -1449,132 +1461,166 @@ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1449
1461
  };
1450
1462
 
1451
1463
  // src/internal/timeline-internal.ts
1452
- import HAMT8 from "hamt_plus";
1453
- function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1454
- var _a, _b;
1455
- const timelineData = {
1456
- at: 0,
1457
- timeTraveling: false,
1458
- history: [],
1459
- selectorTime: null,
1460
- transactionKey: null
1461
- };
1462
- const subscribeToAtom = (token2) => {
1463
- const state = withdraw(token2, store);
1464
- state.subject.subscribe((update) => {
1465
- var _a2, _b2, _c, _d, _e;
1466
- const storeCurrentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1467
- const storeCurrentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1468
- const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1469
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1470
- `\u23F3 timeline "${options.key}" saw atom "${token2.key}" go (`,
1471
- update.oldValue,
1472
- `->`,
1473
- update.newValue,
1474
- storeCurrentTransactionKey ? `) in transaction "${storeCurrentTransactionKey}"` : storeCurrentSelectorKey ? `) in selector "${storeCurrentSelectorKey}"` : `)`
1475
- );
1476
- if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1464
+ import HAMT10 from "hamt_plus";
1465
+ import * as Rx7 from "rxjs";
1466
+
1467
+ // src/internal/timeline/add-atom-to-timeline.ts
1468
+ var addAtomToTimeline = (atomToken, atoms, tl, store = IMPLICIT.STORE) => {
1469
+ const atom2 = withdraw(atomToken, store);
1470
+ if (atom2 === null) {
1471
+ throw new Error(
1472
+ `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
1473
+ );
1474
+ }
1475
+ atom2.subject.subscribe((update) => {
1476
+ var _a, _b, _c, _d, _e;
1477
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1478
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1479
+ const currentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1480
+ const currentTransactionTime = store.transactionStatus.phase === `applying` ? store.transactionStatus.time : null;
1481
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1482
+ `\u23F3 timeline "${tl.key}" saw atom "${atomToken.key}" go (`,
1483
+ update.oldValue,
1484
+ `->`,
1485
+ update.newValue,
1486
+ currentTransactionKey ? `) in transaction "${currentTransactionKey}"` : currentSelectorKey ? `) in selector "${currentSelectorKey}"` : `)`
1487
+ );
1488
+ if (tl.timeTraveling === false) {
1489
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1490
+ const mostRecentUpdate = tl.history.at(-1);
1491
+ if (mostRecentUpdate.type === `selector_update`) {
1492
+ tl.subject.next(mostRecentUpdate);
1493
+ }
1494
+ }
1495
+ if (currentTransactionKey && store.transactionStatus.phase === `applying`) {
1477
1496
  const currentTransaction = withdraw(
1478
- { key: storeCurrentTransactionKey, type: `transaction` },
1497
+ { key: currentTransactionKey, type: `transaction` },
1479
1498
  store
1480
1499
  );
1481
- if (timelineData.transactionKey !== storeCurrentTransactionKey) {
1482
- if (timelineData.transactionKey) {
1483
- (_b2 = store.config.logger) == null ? void 0 : _b2.error(
1484
- `Timeline "${options.key}" was unable to resolve transaction "${timelineData.transactionKey}. This is probably a bug.`
1500
+ if (currentTransaction === null) {
1501
+ throw new Error(
1502
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
1503
+ );
1504
+ }
1505
+ if (tl.transactionKey !== currentTransactionKey) {
1506
+ if (tl.transactionKey) {
1507
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1508
+ `Timeline "${tl.key}" was unable to resolve transaction "${tl.transactionKey}. This is probably a bug.`
1485
1509
  );
1486
1510
  }
1487
- timelineData.transactionKey = storeCurrentTransactionKey;
1511
+ tl.transactionKey = currentTransactionKey;
1488
1512
  const subscription = currentTransaction.subject.subscribe((update2) => {
1489
- var _a3;
1490
- if (timelineData.timeTraveling === false) {
1491
- if (timelineData.at !== timelineData.history.length) {
1492
- timelineData.history.splice(timelineData.at);
1513
+ var _a2;
1514
+ if (tl.timeTraveling === false && currentTransactionTime) {
1515
+ if (tl.at !== tl.history.length) {
1516
+ tl.history.splice(tl.at);
1493
1517
  }
1494
- timelineData.history.push(__spreadProps(__spreadValues({
1495
- type: `transaction_update`
1518
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
1519
+ type: `transaction_update`,
1520
+ timestamp: currentTransactionTime
1496
1521
  }, update2), {
1497
1522
  atomUpdates: update2.atomUpdates.filter(
1498
- (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1523
+ (atomUpdate) => atoms.some((atom3) => atom3.key === atomUpdate.key)
1499
1524
  )
1500
- }));
1525
+ });
1526
+ tl.history.push(timelineTransactionUpdate);
1527
+ tl.subject.next(timelineTransactionUpdate);
1501
1528
  }
1502
- timelineData.at = timelineData.history.length;
1529
+ tl.at = tl.history.length;
1503
1530
  subscription.unsubscribe();
1504
- timelineData.transactionKey = null;
1505
- (_a3 = store.config.logger) == null ? void 0 : _a3.info(
1506
- `\u231B timeline "${options.key}" got a transaction_update "${update2.key}"`
1531
+ tl.transactionKey = null;
1532
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1533
+ `\u231B timeline "${tl.key}" got a transaction_update "${update2.key}"`
1507
1534
  );
1508
1535
  });
1509
1536
  }
1510
- } else if (storeCurrentSelectorKey) {
1511
- if (timelineData.timeTraveling === false) {
1512
- if (storeCurrentSelectorTime !== timelineData.selectorTime) {
1513
- const newSelectorUpdate = {
1514
- type: `selector_update`,
1515
- key: storeCurrentSelectorKey,
1516
- atomUpdates: []
1517
- };
1518
- newSelectorUpdate.atomUpdates.push(__spreadValues({
1519
- key: token2.key,
1537
+ } else if (currentSelectorKey && currentSelectorTime) {
1538
+ if (currentSelectorTime !== tl.selectorTime) {
1539
+ const newSelectorUpdate = {
1540
+ type: `selector_update`,
1541
+ timestamp: currentSelectorTime,
1542
+ key: currentSelectorKey,
1543
+ atomUpdates: []
1544
+ };
1545
+ newSelectorUpdate.atomUpdates.push(__spreadValues({
1546
+ key: atom2.key,
1547
+ type: `atom_update`
1548
+ }, update));
1549
+ if (tl.at !== tl.history.length) {
1550
+ tl.history.splice(tl.at);
1551
+ }
1552
+ tl.history.push(newSelectorUpdate);
1553
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1554
+ `\u231B timeline "${tl.key}" got a selector_update "${currentSelectorKey}" with`,
1555
+ newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1556
+ );
1557
+ tl.at = tl.history.length;
1558
+ tl.selectorTime = currentSelectorTime;
1559
+ } else {
1560
+ const latestUpdate = tl.history.at(-1);
1561
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1562
+ latestUpdate.atomUpdates.push(__spreadValues({
1563
+ key: atom2.key,
1520
1564
  type: `atom_update`
1521
1565
  }, update));
1522
- if (timelineData.at !== timelineData.history.length) {
1523
- timelineData.history.splice(timelineData.at);
1524
- }
1525
- timelineData.history.push(newSelectorUpdate);
1526
- (_c = store.config.logger) == null ? void 0 : _c.info(
1527
- `\u231B timeline "${options.key}" got a selector_update "${storeCurrentSelectorKey}" with`,
1528
- newSelectorUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1566
+ (_d = store.config.logger) == null ? void 0 : _d.info(
1567
+ ` \u231B timeline "${tl.key}" set selector_update "${currentSelectorKey}" to`,
1568
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1529
1569
  );
1530
- timelineData.at = timelineData.history.length;
1531
- timelineData.selectorTime = storeCurrentSelectorTime;
1532
- } else {
1533
- const latestUpdate = timelineData.history.at(-1);
1534
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1535
- latestUpdate.atomUpdates.push(__spreadValues({
1536
- key: token2.key,
1537
- type: `atom_update`
1538
- }, update));
1539
- (_d = store.config.logger) == null ? void 0 : _d.info(
1540
- ` \u231B timeline "${options.key}" set selector_update "${storeCurrentSelectorKey}" to`,
1541
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1542
- );
1543
- }
1544
1570
  }
1545
1571
  }
1546
1572
  } else {
1547
- if (timelineData.timeTraveling === false) {
1548
- timelineData.selectorTime = null;
1549
- if (timelineData.at !== timelineData.history.length) {
1550
- timelineData.history.splice(timelineData.at);
1551
- }
1552
- timelineData.history.push({
1553
- type: `atom_update`,
1554
- key: token2.key,
1555
- oldValue: update.oldValue,
1556
- newValue: update.newValue
1557
- });
1558
- (_e = store.config.logger) == null ? void 0 : _e.info(
1559
- `\u231B timeline "${options.key}" got a state_update to "${token2.key}"`
1560
- );
1561
- timelineData.at = timelineData.history.length;
1573
+ const timestamp = Date.now();
1574
+ tl.selectorTime = null;
1575
+ if (tl.at !== tl.history.length) {
1576
+ tl.history.splice(tl.at);
1562
1577
  }
1578
+ const atomUpdate = {
1579
+ type: `atom_update`,
1580
+ timestamp,
1581
+ key: atom2.key,
1582
+ oldValue: update.oldValue,
1583
+ newValue: update.newValue
1584
+ };
1585
+ tl.history.push(atomUpdate);
1586
+ tl.subject.next(atomUpdate);
1587
+ (_e = store.config.logger) == null ? void 0 : _e.info(
1588
+ `\u231B timeline "${tl.key}" got a state_update to "${atom2.key}"`
1589
+ );
1590
+ tl.at = tl.history.length;
1563
1591
  }
1564
- });
1565
- };
1592
+ }
1593
+ });
1594
+ };
1595
+
1596
+ // src/internal/timeline-internal.ts
1597
+ function timeline__INTERNAL(options, store = IMPLICIT.STORE, data = null) {
1598
+ var _a, _b, _c;
1599
+ const tl = __spreadProps(__spreadValues({
1600
+ key: options.key,
1601
+ at: 0,
1602
+ timeTraveling: false,
1603
+ selectorTime: null,
1604
+ transactionKey: null
1605
+ }, data), {
1606
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1607
+ install: (store2) => timeline__INTERNAL(options, store2, tl),
1608
+ subject: new Rx7.Subject()
1609
+ });
1566
1610
  const core = target(store);
1567
1611
  for (const tokenOrFamily of options.atoms) {
1568
1612
  const timelineKey = core.timelineAtoms.getRelatedId(tokenOrFamily.key);
1569
1613
  if (timelineKey) {
1570
- (_a = store.config.logger) == null ? void 0 : _a.error(
1614
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1571
1615
  `\u274C Failed to add atom "${tokenOrFamily.key}" to timeline "${options.key}" because it belongs to timeline "${timelineKey}"`
1572
1616
  );
1573
1617
  continue;
1574
1618
  }
1575
1619
  if (tokenOrFamily.type === `atom_family`) {
1576
1620
  const family = tokenOrFamily;
1577
- family.subject.subscribe((token2) => subscribeToAtom(token2));
1621
+ family.subject.subscribe(
1622
+ (token2) => addAtomToTimeline(token2, options.atoms, tl, store)
1623
+ );
1578
1624
  } else {
1579
1625
  const token2 = tokenOrFamily;
1580
1626
  if (`family` in token2 && token2.family) {
@@ -1582,20 +1628,20 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1582
1628
  token2.family.key
1583
1629
  );
1584
1630
  if (familyTimelineKey) {
1585
- (_b = store.config.logger) == null ? void 0 : _b.error(
1631
+ (_c = store.config.logger) == null ? void 0 : _c.error(
1586
1632
  `\u274C Failed to add atom "${token2.key}" to timeline "${options.key}" because its family "${token2.family.key}" belongs to timeline "${familyTimelineKey}"`
1587
1633
  );
1588
1634
  continue;
1589
1635
  }
1590
1636
  }
1591
- subscribeToAtom(token2);
1637
+ addAtomToTimeline(token2, options.atoms, tl, store);
1592
1638
  }
1593
1639
  core.timelineAtoms = core.timelineAtoms.set({
1594
1640
  atomKey: tokenOrFamily.key,
1595
1641
  timelineKey: options.key
1596
1642
  });
1597
1643
  }
1598
- store.timelineStore = HAMT8.set(options.key, timelineData, store.timelineStore);
1644
+ store.timelines = HAMT10.set(options.key, tl, store.timelines);
1599
1645
  const token = {
1600
1646
  key: options.key,
1601
1647
  type: `timeline`
@@ -1604,6 +1650,129 @@ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1604
1650
  return token;
1605
1651
  }
1606
1652
 
1653
+ // src/internal/transaction/abort-transaction.ts
1654
+ var abortTransaction = (store) => {
1655
+ var _a, _b;
1656
+ if (store.transactionStatus.phase === `idle`) {
1657
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1658
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1659
+ );
1660
+ return;
1661
+ }
1662
+ store.transactionStatus = { phase: `idle` };
1663
+ (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
1664
+ };
1665
+
1666
+ // src/internal/transaction/apply-transaction.ts
1667
+ import HAMT11 from "hamt_plus";
1668
+ var applyTransaction = (output, store) => {
1669
+ var _a, _b, _c, _d;
1670
+ if (store.transactionStatus.phase !== `building`) {
1671
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1672
+ `abortTransaction called outside of a transaction. This is probably a bug.`
1673
+ );
1674
+ return;
1675
+ }
1676
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1677
+ `\u{1F6C3} apply transaction "${store.transactionStatus.key}"`
1678
+ );
1679
+ store.transactionStatus.phase = `applying`;
1680
+ store.transactionStatus.output = output;
1681
+ const { atomUpdates } = store.transactionStatus;
1682
+ for (const { key, newValue } of atomUpdates) {
1683
+ const token = { key, type: `atom` };
1684
+ if (!HAMT11.has(token.key, store.valueMap)) {
1685
+ const newAtom = HAMT11.get(token.key, store.transactionStatus.core.atoms);
1686
+ store.atoms = HAMT11.set(newAtom.key, newAtom, store.atoms);
1687
+ store.valueMap = HAMT11.set(newAtom.key, newAtom.default, store.valueMap);
1688
+ (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F527}`, `add atom "${newAtom.key}"`);
1689
+ }
1690
+ setState(token, newValue, store);
1691
+ }
1692
+ const myTransaction = withdraw(
1693
+ { key: store.transactionStatus.key, type: `transaction` },
1694
+ store
1695
+ );
1696
+ if (myTransaction === null) {
1697
+ throw new Error(
1698
+ `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
1699
+ );
1700
+ }
1701
+ myTransaction.subject.next({
1702
+ key: store.transactionStatus.key,
1703
+ atomUpdates,
1704
+ output,
1705
+ params: store.transactionStatus.params
1706
+ });
1707
+ store.transactionStatus = { phase: `idle` };
1708
+ (_d = store.config.logger) == null ? void 0 : _d.info(`\u{1F6EC}`, `transaction done`);
1709
+ };
1710
+
1711
+ // src/internal/transaction/build-transaction.ts
1712
+ var buildTransaction = (key, params, store) => {
1713
+ var _a;
1714
+ store.transactionStatus = {
1715
+ key,
1716
+ phase: `building`,
1717
+ time: Date.now(),
1718
+ core: {
1719
+ atoms: store.atoms,
1720
+ atomsThatAreDefault: store.atomsThatAreDefault,
1721
+ operation: { open: false },
1722
+ readonlySelectors: store.readonlySelectors,
1723
+ timelines: store.timelines,
1724
+ timelineAtoms: store.timelineAtoms,
1725
+ transactions: store.transactions,
1726
+ selectorAtoms: store.selectorAtoms,
1727
+ selectorGraph: store.selectorGraph,
1728
+ selectors: store.selectors,
1729
+ valueMap: store.valueMap
1730
+ },
1731
+ atomUpdates: [],
1732
+ params,
1733
+ output: void 0
1734
+ };
1735
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1736
+ `\u{1F6EB}`,
1737
+ `transaction "${key}" started in store "${store.config.name}"`
1738
+ );
1739
+ };
1740
+
1741
+ // src/internal/transaction/redo-transaction.ts
1742
+ var redoTransactionUpdate = (update, store) => {
1743
+ var _a;
1744
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
1745
+ for (const { key, newValue } of update.atomUpdates) {
1746
+ const token = { key, type: `atom` };
1747
+ const state = withdraw(token, store);
1748
+ if (state === null) {
1749
+ throw new Error(
1750
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1751
+ );
1752
+ }
1753
+ setState(state, newValue, store);
1754
+ }
1755
+ };
1756
+
1757
+ // src/internal/transaction/undo-transaction.ts
1758
+ var undoTransactionUpdate = (update, store) => {
1759
+ var _a;
1760
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
1761
+ for (const { key, oldValue } of update.atomUpdates) {
1762
+ const token = { key, type: `atom` };
1763
+ const state = withdraw(token, store);
1764
+ if (state === null) {
1765
+ throw new Error(
1766
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1767
+ );
1768
+ }
1769
+ setState(state, oldValue, store);
1770
+ }
1771
+ };
1772
+
1773
+ // src/internal/transaction/index.ts
1774
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1775
+
1607
1776
  // src/atom.ts
1608
1777
  function atom(options) {
1609
1778
  return atom__INTERNAL(options);
@@ -1653,10 +1822,34 @@ function selectorFamily(options) {
1653
1822
  return selectorFamily__INTERNAL(options);
1654
1823
  }
1655
1824
 
1825
+ // src/silo.ts
1826
+ var silo = (name, fromStore = null) => {
1827
+ const store = createStore(name, fromStore);
1828
+ return {
1829
+ store,
1830
+ atom: (options) => atom__INTERNAL(options, void 0, store),
1831
+ atomFamily: (options) => atomFamily__INTERNAL(options, store),
1832
+ selector: (options) => selector__INTERNAL(options, void 0, store),
1833
+ selectorFamily: (options) => selectorFamily__INTERNAL(options, store),
1834
+ transaction: (options) => transaction__INTERNAL(options, store),
1835
+ timeline: (options) => timeline__INTERNAL(options, store),
1836
+ getState: (token) => getState(token, store),
1837
+ setState: (token, newValue) => setState(token, newValue, store),
1838
+ subscribe: (token, handler) => subscribe(token, handler, store),
1839
+ undo: (token) => undo__INTERNAL(token, store),
1840
+ redo: (token) => redo__INTERNAL(token, store)
1841
+ };
1842
+ };
1843
+
1656
1844
  // src/subscribe.ts
1657
1845
  var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1658
1846
  var _a;
1659
1847
  const state = withdraw(token, store);
1848
+ if (state === null) {
1849
+ throw new Error(
1850
+ `State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1851
+ );
1852
+ }
1660
1853
  const subscription = state.subject.subscribe(handleUpdate);
1661
1854
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to "${state.key}"`);
1662
1855
  const dependencySubscriptions = state.type !== `atom` ? subscribeToRootAtoms(state, store) : null;
@@ -1679,6 +1872,11 @@ var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1679
1872
  var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1680
1873
  var _a;
1681
1874
  const tx = withdraw(token, store);
1875
+ if (tx === null) {
1876
+ throw new Error(
1877
+ `Cannot subscribe to transaction "${token.key}": transaction not found in store "${store.config.name}".`
1878
+ );
1879
+ }
1682
1880
  (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to transaction "${token.key}"`);
1683
1881
  const subscription = tx.subject.subscribe(handleUpdate);
1684
1882
  const unsubscribe = () => {
@@ -1688,6 +1886,23 @@ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1688
1886
  };
1689
1887
  return unsubscribe;
1690
1888
  };
1889
+ var subscribeToTimeline = (token, handleUpdate, store = IMPLICIT.STORE) => {
1890
+ var _a;
1891
+ const tl = withdraw(token, store);
1892
+ if (tl === null) {
1893
+ throw new Error(
1894
+ `Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`
1895
+ );
1896
+ }
1897
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to timeline "${token.key}"`);
1898
+ const subscription = tl.subject.subscribe(handleUpdate);
1899
+ const unsubscribe = () => {
1900
+ var _a2;
1901
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from timeline "${token.key}"`);
1902
+ subscription.unsubscribe();
1903
+ };
1904
+ return unsubscribe;
1905
+ };
1691
1906
 
1692
1907
  // src/timeline.ts
1693
1908
  var timeline = (options) => {
@@ -1704,11 +1919,24 @@ var undo = (token) => {
1704
1919
  function transaction(options) {
1705
1920
  return transaction__INTERNAL(options);
1706
1921
  }
1707
- var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => withdraw(token, store).run(...parameters);
1922
+ var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => {
1923
+ const tx = withdraw(token, store);
1924
+ if (tx) {
1925
+ return tx.run(...parameters);
1926
+ }
1927
+ throw new Error(
1928
+ `Cannot run transaction "${token.key}": transaction not found in store "${store.config.name}".`
1929
+ );
1930
+ };
1708
1931
 
1709
1932
  // src/index.ts
1710
1933
  var getState = (token, store = IMPLICIT.STORE) => {
1711
1934
  const state = withdraw(token, store);
1935
+ if (state === null) {
1936
+ throw new Error(
1937
+ `${capitalize(token.type)} "${token.key}" not found in store "${store.config.name}".`
1938
+ );
1939
+ }
1712
1940
  return getState__INTERNAL(state, store);
1713
1941
  };
1714
1942
  var setState = (token, value, store = IMPLICIT.STORE) => {
@@ -1721,6 +1949,11 @@ var setState = (token, value, store = IMPLICIT.STORE) => {
1721
1949
  return;
1722
1950
  }
1723
1951
  const state = withdraw(token, store);
1952
+ if (state === null) {
1953
+ throw new Error(
1954
+ `${capitalize(token.type)} "${token.key}" not found in store "${store.config.name}".`
1955
+ );
1956
+ }
1724
1957
  setState__INTERNAL(state, value, store);
1725
1958
  closeOperation(store);
1726
1959
  };
@@ -1738,7 +1971,9 @@ export {
1738
1971
  selectorFamily,
1739
1972
  setLogLevel,
1740
1973
  setState,
1974
+ silo,
1741
1975
  subscribe,
1976
+ subscribeToTimeline,
1742
1977
  subscribeToTransaction,
1743
1978
  timeline,
1744
1979
  transaction,