atom.io 0.1.0 → 0.3.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.
package/dist/index.js CHANGED
@@ -22,20 +22,20 @@ var __spreadValues = (a, b) => {
22
22
  };
23
23
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
24
  var __objRest = (source, exclude) => {
25
- var target = {};
25
+ var target3 = {};
26
26
  for (var prop in source)
27
27
  if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
28
- target[prop] = source[prop];
28
+ target3[prop] = source[prop];
29
29
  if (source != null && __getOwnPropSymbols)
30
30
  for (var prop of __getOwnPropSymbols(source)) {
31
31
  if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
32
- target[prop] = source[prop];
32
+ target3[prop] = source[prop];
33
33
  }
34
- return target;
34
+ return target3;
35
35
  };
36
- var __export = (target, all) => {
36
+ var __export = (target3, all) => {
37
37
  for (var name in all)
38
- __defProp(target, name, { get: all[name], enumerable: true });
38
+ __defProp(target3, name, { get: all[name], enumerable: true });
39
39
  };
40
40
  var __copyProps = (to, from, except, desc) => {
41
41
  if (from && typeof from === "object" || typeof from === "function") {
@@ -45,12 +45,12 @@ var __copyProps = (to, from, except, desc) => {
45
45
  }
46
46
  return to;
47
47
  };
48
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
48
+ var __toESM = (mod, isNodeMode, target3) => (target3 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
49
49
  // If the importer is in node compatibility mode or this is not an ESM
50
50
  // file that has been converted to a CommonJS file using a Babel-
51
51
  // compatible transform (i.e. "__esModule" has not been set), then set
52
52
  // "default" to the CommonJS "module.exports" for node compatibility.
53
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
53
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target3, "default", { value: mod, enumerable: true }) : target3,
54
54
  mod
55
55
  ));
56
56
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
@@ -61,14 +61,20 @@ __export(src_exports, {
61
61
  __INTERNAL__: () => internal_exports,
62
62
  atom: () => atom,
63
63
  atomFamily: () => atomFamily,
64
- configure: () => configure,
65
64
  getState: () => getState,
66
- registerSelector: () => registerSelector,
65
+ isDefault: () => isDefault,
66
+ redo: () => redo,
67
+ runTransaction: () => runTransaction,
67
68
  selector: () => selector,
68
69
  selectorFamily: () => selectorFamily,
70
+ setLogLevel: () => setLogLevel,
69
71
  setState: () => setState,
70
72
  subscribe: () => subscribe,
71
- transaction: () => transaction
73
+ subscribeToTransaction: () => subscribeToTransaction,
74
+ timeline: () => timeline,
75
+ transaction: () => transaction,
76
+ undo: () => undo,
77
+ useLogger: () => useLogger
72
78
  });
73
79
  module.exports = __toCommonJS(src_exports);
74
80
 
@@ -76,33 +82,133 @@ module.exports = __toCommonJS(src_exports);
76
82
  var internal_exports = {};
77
83
  __export(internal_exports, {
78
84
  IMPLICIT: () => IMPLICIT,
85
+ LOG_LEVELS: () => LOG_LEVELS,
86
+ TRANSACTION_PHASES: () => TRANSACTION_PHASES,
79
87
  abortTransaction: () => abortTransaction,
88
+ applyTransaction: () => applyTransaction,
89
+ atomFamily__INTERNAL: () => atomFamily__INTERNAL,
90
+ atom__INTERNAL: () => atom__INTERNAL,
91
+ buildTransaction: () => buildTransaction,
92
+ cacheValue: () => cacheValue,
80
93
  clearStore: () => clearStore,
81
- configure: () => configure,
94
+ closeOperation: () => closeOperation,
95
+ computeSelectorState: () => computeSelectorState,
82
96
  createStore: () => createStore,
83
97
  deposit: () => deposit,
84
- finishAction: () => finishAction,
85
- finishTransaction: () => finishTransaction,
86
- getCachedState: () => getCachedState,
87
- getSelectorState: () => getSelectorState,
98
+ emitUpdate: () => emitUpdate,
99
+ evictCachedValue: () => evictCachedValue,
100
+ evictDownStream: () => evictDownStream,
88
101
  getState__INTERNAL: () => getState__INTERNAL,
102
+ hasKeyBeenUsed: () => hasKeyBeenUsed,
103
+ isAtomDefault: () => isAtomDefault,
89
104
  isDone: () => isDone,
105
+ isSelectorDefault: () => isSelectorDefault,
106
+ isValueCached: () => isValueCached,
107
+ lookup: () => lookup,
108
+ lookupSelectorSources: () => lookupSelectorSources,
109
+ markAtomAsDefault: () => markAtomAsDefault,
110
+ markAtomAsNotDefault: () => markAtomAsNotDefault,
90
111
  markDone: () => markDone,
91
- propagateDown: () => propagateDown,
92
- recall: () => recall,
112
+ openOperation: () => openOperation,
113
+ prepareUpdate: () => prepareUpdate,
114
+ readCachedValue: () => readCachedValue,
115
+ readonlySelectorFamily__INTERNAL: () => readonlySelectorFamily__INTERNAL,
116
+ recallState: () => recallState,
117
+ redoTransactionUpdate: () => redoTransactionUpdate,
118
+ redo__INTERNAL: () => redo__INTERNAL,
119
+ registerSelector: () => registerSelector,
120
+ selectorFamily__INTERNAL: () => selectorFamily__INTERNAL,
121
+ selector__INTERNAL: () => selector__INTERNAL,
93
122
  setAtomState: () => setAtomState,
123
+ setLogLevel: () => setLogLevel,
94
124
  setSelectorState: () => setSelectorState,
95
125
  setState__INTERNAL: () => setState__INTERNAL,
96
- startAction: () => startAction,
97
- startTransaction: () => startTransaction,
126
+ storeAtom: () => storeAtom,
127
+ storeReadonlySelector: () => storeReadonlySelector,
128
+ storeSelector: () => storeSelector,
129
+ stowUpdate: () => stowUpdate,
130
+ subscribeToRootAtoms: () => subscribeToRootAtoms,
131
+ target: () => target,
132
+ timeline__INTERNAL: () => timeline__INTERNAL,
133
+ traceAllSelectorAtoms: () => traceAllSelectorAtoms,
134
+ traceSelectorAtoms: () => traceSelectorAtoms,
135
+ transaction__INTERNAL: () => transaction__INTERNAL,
136
+ undoTransactionUpdate: () => undoTransactionUpdate,
137
+ undo__INTERNAL: () => undo__INTERNAL,
138
+ updateSelectorAtoms: () => updateSelectorAtoms,
139
+ useLogger: () => useLogger,
98
140
  withdraw: () => withdraw
99
141
  });
100
142
 
143
+ // src/internal/atom-internal.ts
144
+ var Rx2 = __toESM(require("rxjs"));
145
+
101
146
  // src/internal/get.ts
102
- var import_hamt_plus2 = __toESM(require("hamt_plus"));
147
+ var import_hamt_plus = __toESM(require("hamt_plus"));
148
+ var computeSelectorState = (selector2) => selector2.get();
149
+ function lookup(key, store) {
150
+ const core = target(store);
151
+ const type = import_hamt_plus.default.has(key, core.atoms) ? `atom` : import_hamt_plus.default.has(key, core.selectors) ? `selector` : `readonly_selector`;
152
+ return { key, type };
153
+ }
154
+ function withdraw(token, store) {
155
+ var _a, _b, _c;
156
+ 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);
158
+ }
159
+ function deposit(state) {
160
+ return __spreadValues({
161
+ key: state.key,
162
+ type: state.type
163
+ }, `family` in state && { family: state.family });
164
+ }
165
+ var getState__INTERNAL = (state, store = IMPLICIT.STORE) => {
166
+ var _a, _b, _c;
167
+ if (isValueCached(state.key, store)) {
168
+ (_a = store.config.logger) == null ? void 0 : _a.info(`>> read "${state.key}"`);
169
+ return readCachedValue(state.key, store);
170
+ }
171
+ if (`get` in state) {
172
+ (_b = store.config.logger) == null ? void 0 : _b.info(`-> calc "${state.key}"`);
173
+ return computeSelectorState(state);
174
+ }
175
+ (_c = store.config.logger) == null ? void 0 : _c.error(
176
+ `Attempted to get atom "${state.key}", which was never initialized in store "${store.config.name}".`
177
+ );
178
+ return state.default;
179
+ };
180
+
181
+ // src/internal/is-default.ts
182
+ var isAtomDefault = (key, store = IMPLICIT.STORE) => {
183
+ const core = target(store);
184
+ return core.atomsThatAreDefault.has(key);
185
+ };
186
+ var markAtomAsDefault = (key, store = IMPLICIT.STORE) => {
187
+ const core = target(store);
188
+ core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
189
+ };
190
+ var markAtomAsNotDefault = (key, store = IMPLICIT.STORE) => {
191
+ const core = target(store);
192
+ core.atomsThatAreDefault = new Set(target(store).atomsThatAreDefault);
193
+ core.atomsThatAreDefault.delete(key);
194
+ };
195
+ var isSelectorDefault = (key, store = IMPLICIT.STORE) => {
196
+ const roots = traceAllSelectorAtoms(key, store);
197
+ return roots.every((root) => isAtomDefault(root.key, store));
198
+ };
199
+
200
+ // src/internal/operation.ts
201
+ var import_hamt_plus3 = __toESM(require("hamt_plus"));
103
202
 
104
203
  // src/internal/store.ts
105
- var import_hamt_plus = __toESM(require("hamt_plus"));
204
+ var import_hamt_plus2 = __toESM(require("hamt_plus"));
205
+
206
+ // ../anvl/src/function/index.ts
207
+ var doNothing = () => void 0;
208
+ var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
209
+ originalThing instanceof Function ? originalThing() : originalThing
210
+ ) : nextVersionOfThing;
211
+ var pass = (...params) => (fn) => fn(...params);
106
212
 
107
213
  // ../anvl/src/join/core-relation-data.ts
108
214
  var import_string = require("fp-ts/string");
@@ -148,12 +254,6 @@ var mapObject = (obj, fn) => (0, import_function.pipe)(
148
254
  );
149
255
  var mob = (fn) => (obj) => mapObject(obj, fn);
150
256
 
151
- // ../anvl/src/function/index.ts
152
- var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
153
- originalThing instanceof Function ? originalThing() : originalThing
154
- ) : nextVersionOfThing;
155
- var pass = (...params) => (fn) => fn(...params);
156
-
157
257
  // ../anvl/src/nullish/index.ts
158
258
  var isUndefined = (input) => input === void 0;
159
259
  var ifNullish = (alt) => (input) => input != null ? input : alt;
@@ -492,20 +592,29 @@ var Join = class {
492
592
 
493
593
  // src/internal/store.ts
494
594
  var createStore = (name) => ({
495
- valueMap: import_hamt_plus.default.make(),
595
+ atoms: import_hamt_plus2.default.make(),
596
+ atomsThatAreDefault: /* @__PURE__ */ new Set(),
597
+ readonlySelectors: import_hamt_plus2.default.make(),
598
+ selectorAtoms: new Join({ relationType: `n:n` }),
496
599
  selectorGraph: new Join({ relationType: `n:n` }),
497
- atoms: import_hamt_plus.default.make(),
498
- selectors: import_hamt_plus.default.make(),
499
- readonlySelectors: import_hamt_plus.default.make(),
600
+ selectors: import_hamt_plus2.default.make(),
601
+ timelines: import_hamt_plus2.default.make(),
602
+ timelineAtoms: new Join({ relationType: `1:n` }),
603
+ timelineStore: import_hamt_plus2.default.make(),
604
+ transactions: import_hamt_plus2.default.make(),
605
+ valueMap: import_hamt_plus2.default.make(),
500
606
  operation: {
501
607
  open: false
502
608
  },
503
- transaction: {
504
- open: false
609
+ transactionStatus: {
610
+ phase: `idle`
505
611
  },
506
612
  config: {
507
613
  name,
508
- logger: null
614
+ logger: __spreadProps(__spreadValues({}, console), {
615
+ info: doNothing
616
+ }),
617
+ logger__INTERNAL: console
509
618
  }
510
619
  });
511
620
  var IMPLICIT = {
@@ -515,421 +624,881 @@ var IMPLICIT = {
515
624
  return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = createStore(`DEFAULT`);
516
625
  }
517
626
  };
518
- var configure = (config, store = IMPLICIT.STORE) => {
519
- Object.assign(store.config, config);
520
- };
521
627
  var clearStore = (store = IMPLICIT.STORE) => {
522
628
  const { config } = store;
523
629
  Object.assign(store, createStore(config.name));
524
630
  store.config = config;
525
631
  };
526
632
 
527
- // src/internal/get.ts
528
- var getCachedState = (state, store = IMPLICIT.STORE) => {
529
- const value = import_hamt_plus2.default.get(state.key, store.valueMap);
530
- return value;
531
- };
532
- var getSelectorState = (selector2) => selector2.get();
533
- function withdraw(token, store) {
534
- var _a, _b;
535
- return (_b = (_a = import_hamt_plus2.default.get(token.key, store.atoms)) != null ? _a : import_hamt_plus2.default.get(token.key, store.selectors)) != null ? _b : import_hamt_plus2.default.get(token.key, store.readonlySelectors);
536
- }
537
- function deposit(state) {
538
- if (`get` in state) {
539
- if (`set` in state) {
540
- return { key: state.key, type: `selector` };
541
- }
542
- return { key: state.key, type: `readonly_selector` };
543
- }
544
- return { key: state.key, type: `atom` };
545
- }
546
- var getState__INTERNAL = (state, store = IMPLICIT.STORE) => {
547
- var _a;
548
- if (import_hamt_plus2.default.has(state.key, store.valueMap)) {
549
- return getCachedState(state, store);
550
- }
551
- if (`get` in state) {
552
- return getSelectorState(state);
553
- }
554
- (_a = store.config.logger) == null ? void 0 : _a.error(
555
- `Attempted to get atom "${state.key}", which was never initialized in store "${store.config.name}".`
556
- );
557
- return state.default;
558
- };
559
-
560
- // src/internal/set.ts
561
- var import_hamt_plus4 = __toESM(require("hamt_plus"));
562
-
563
633
  // src/internal/operation.ts
564
- var import_hamt_plus3 = __toESM(require("hamt_plus"));
565
- var startAction = (store) => {
634
+ var openOperation = (store) => {
566
635
  var _a;
567
- store.operation = {
636
+ const core = target(store);
637
+ core.operation = {
568
638
  open: true,
569
639
  done: /* @__PURE__ */ new Set(),
570
640
  prev: store.valueMap
571
641
  };
572
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u2610`, `operation start`);
642
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u2B55`, `operation start`);
573
643
  };
574
- var finishAction = (store) => {
644
+ var closeOperation = (store) => {
575
645
  var _a;
576
- store.operation = { open: false };
577
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u2611\uFE0F`, `operation done`);
646
+ const core = target(store);
647
+ core.operation = { open: false };
648
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F534}`, `operation done`);
578
649
  };
579
650
  var isDone = (key, store = IMPLICIT.STORE) => {
580
651
  var _a;
581
- if (!store.operation.open) {
652
+ const core = target(store);
653
+ if (!core.operation.open) {
582
654
  (_a = store.config.logger) == null ? void 0 : _a.warn(
583
- `isDone called outside of an action. This is probably a bug.`
655
+ `isDone called outside of an operation. This is probably a bug.`
584
656
  );
585
657
  return true;
586
658
  }
587
- return store.operation.done.has(key);
659
+ return core.operation.done.has(key);
588
660
  };
589
661
  var markDone = (key, store = IMPLICIT.STORE) => {
590
662
  var _a;
591
- if (!store.operation.open) {
663
+ const core = target(store);
664
+ if (!core.operation.open) {
592
665
  (_a = store.config.logger) == null ? void 0 : _a.warn(
593
- `markDone called outside of an action. This is probably a bug.`
666
+ `markDone called outside of an operation. This is probably a bug.`
594
667
  );
595
668
  return;
596
669
  }
597
- store.operation.done.add(key);
670
+ core.operation.done.add(key);
598
671
  };
599
- var recall = (state, store = IMPLICIT.STORE) => {
672
+ var recallState = (state, store = IMPLICIT.STORE) => {
600
673
  var _a;
601
- if (!store.operation.open) {
674
+ const core = target(store);
675
+ if (!core.operation.open) {
602
676
  (_a = store.config.logger) == null ? void 0 : _a.warn(
603
- `recall called outside of an action. This is probably a bug.`
677
+ `recall called outside of an operation. This is probably a bug.`
604
678
  );
605
- return import_hamt_plus3.default.get(state.key, store.valueMap);
679
+ return import_hamt_plus3.default.get(state.key, core.valueMap);
606
680
  }
607
- return import_hamt_plus3.default.get(state.key, store.operation.prev);
681
+ return import_hamt_plus3.default.get(state.key, core.operation.prev);
608
682
  };
609
-
610
- // src/internal/set.ts
611
- var propagateDown = (state, store = IMPLICIT.STORE) => {
612
- var _a, _b;
613
- const relatedStateKeys = store.selectorGraph.getRelations(state.key);
614
- (_a = store.config.logger) == null ? void 0 : _a.info(
615
- ` ||`,
616
- `bumping`,
617
- relatedStateKeys.length,
618
- `states:`,
619
- relatedStateKeys.map(({ id }) => id)
620
- );
621
- if (store.operation.open) {
622
- (_b = store.config.logger) == null ? void 0 : _b.info(` ||`, `done:`, store.operation.done);
623
- }
624
- relatedStateKeys.forEach(({ id: stateKey }) => {
625
- var _a2, _b2, _c, _d, _e;
626
- if (isDone(stateKey, store)) {
627
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(` ||`, stateKey, `already done`);
628
- return;
629
- }
630
- (_b2 = store.config.logger) == null ? void 0 : _b2.info(`->`, `bumping`, stateKey);
631
- const state2 = (_c = import_hamt_plus4.default.get(stateKey, store.selectors)) != null ? _c : import_hamt_plus4.default.get(stateKey, store.readonlySelectors);
632
- if (!state2) {
633
- (_d = store.config.logger) == null ? void 0 : _d.info(
634
- ` ||`,
635
- stateKey,
636
- `is an atom - no need to propagate down`
637
- );
638
- return;
639
- }
640
- store.valueMap = import_hamt_plus4.default.remove(stateKey, store.valueMap);
641
- const newValue = getState__INTERNAL(state2, store);
642
- (_e = store.config.logger) == null ? void 0 : _e.info(` <-`, stateKey, `became`, newValue);
643
- const oldValue = recall(state2, store);
644
- state2.subject.next({ newValue, oldValue });
645
- markDone(stateKey, store);
646
- if (`set` in state2)
647
- propagateDown(state2, store);
648
- });
683
+ var cacheValue = (key, value, store = IMPLICIT.STORE) => {
684
+ const core = target(store);
685
+ core.valueMap = import_hamt_plus3.default.set(key, value, core.valueMap);
649
686
  };
650
- var setAtomState = (atom2, next, store = IMPLICIT.STORE) => {
651
- var _a, _b;
652
- const oldValue = getState__INTERNAL(atom2, store);
653
- const newValue = become(next)(oldValue);
654
- (_a = store.config.logger) == null ? void 0 : _a.info(
655
- `->`,
656
- `setting atom`,
657
- `"${atom2.key}"`,
658
- `to`,
659
- newValue
660
- );
661
- store.valueMap = import_hamt_plus4.default.set(atom2.key, newValue, store.valueMap);
662
- markDone(atom2.key, store);
663
- atom2.subject.next({ newValue, oldValue });
664
- (_b = store.config.logger) == null ? void 0 : _b.info(
665
- ` ||`,
666
- `propagating change made to`,
667
- `"${atom2.key}"`
668
- );
669
- propagateDown(atom2, store);
687
+ var evictCachedValue = (key, store = IMPLICIT.STORE) => {
688
+ const core = target(store);
689
+ core.valueMap = import_hamt_plus3.default.remove(key, core.valueMap);
670
690
  };
671
- var setSelectorState = (selector2, next, store = IMPLICIT.STORE) => {
672
- var _a, _b;
673
- const oldValue = getState__INTERNAL(selector2, store);
674
- const newValue = become(next)(oldValue);
675
- (_a = store.config.logger) == null ? void 0 : _a.info(
676
- `->`,
677
- `setting selector`,
678
- `"${selector2.key}"`,
679
- `to`,
680
- newValue
681
- );
682
- (_b = store.config.logger) == null ? void 0 : _b.info(
683
- ` ||`,
684
- `propagating change made to`,
685
- `"${selector2.key}"`
691
+ var readCachedValue = (key, store = IMPLICIT.STORE) => import_hamt_plus3.default.get(key, target(store).valueMap);
692
+ var isValueCached = (key, store = IMPLICIT.STORE) => import_hamt_plus3.default.has(key, target(store).valueMap);
693
+ var storeAtom = (atom2, store = IMPLICIT.STORE) => {
694
+ const core = target(store);
695
+ core.atoms = import_hamt_plus3.default.set(atom2.key, atom2, core.atoms);
696
+ };
697
+ var storeSelector = (selector2, store = IMPLICIT.STORE) => {
698
+ const core = target(store);
699
+ core.selectors = import_hamt_plus3.default.set(selector2.key, selector2, core.selectors);
700
+ };
701
+ var storeReadonlySelector = (selector2, store = IMPLICIT.STORE) => {
702
+ const core = target(store);
703
+ core.readonlySelectors = import_hamt_plus3.default.set(
704
+ selector2.key,
705
+ selector2,
706
+ core.readonlySelectors
686
707
  );
687
- selector2.set(newValue);
688
- propagateDown(selector2, store);
689
708
  };
690
- var setState__INTERNAL = (token, value, store = IMPLICIT.STORE) => {
691
- const state = withdraw(token, store);
692
- if (`set` in state) {
693
- setSelectorState(state, value, store);
694
- } else {
695
- setAtomState(state, value, store);
696
- }
709
+ var hasKeyBeenUsed = (key, store = IMPLICIT.STORE) => {
710
+ const core = target(store);
711
+ return import_hamt_plus3.default.has(key, core.atoms) || import_hamt_plus3.default.has(key, core.selectors) || import_hamt_plus3.default.has(key, core.readonlySelectors);
697
712
  };
698
713
 
699
714
  // src/internal/transaction-internal.ts
700
- var finishTransaction = (store) => {
701
- var _a;
702
- store.transaction = { open: false };
703
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EC}`, `transaction done`);
704
- };
705
- var startTransaction = (store) => {
715
+ var import_hamt_plus4 = __toESM(require("hamt_plus"));
716
+ var Rx = __toESM(require("rxjs"));
717
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
718
+ var buildTransaction = (key, params, store) => {
706
719
  var _a;
707
- store.transaction = {
708
- open: true,
709
- prev: {
720
+ store.transactionStatus = {
721
+ key,
722
+ phase: `building`,
723
+ core: {
710
724
  atoms: store.atoms,
725
+ atomsThatAreDefault: store.atomsThatAreDefault,
726
+ operation: { open: false },
711
727
  readonlySelectors: store.readonlySelectors,
728
+ timelines: store.timelines,
729
+ timelineAtoms: store.timelineAtoms,
730
+ transactions: store.transactions,
731
+ selectorAtoms: store.selectorAtoms,
712
732
  selectorGraph: store.selectorGraph,
713
733
  selectors: store.selectors,
714
734
  valueMap: store.valueMap
715
- }
735
+ },
736
+ atomUpdates: [],
737
+ params,
738
+ output: void 0
716
739
  };
717
- (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction start`);
740
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F6EB}`, `transaction "${key}" started`);
741
+ };
742
+ var applyTransaction = (output, store) => {
743
+ var _a, _b, _c;
744
+ if (store.transactionStatus.phase !== `building`) {
745
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
746
+ `abortTransaction called outside of a transaction. This is probably a bug.`
747
+ );
748
+ return;
749
+ }
750
+ (_b = store.config.logger) == null ? void 0 : _b.info(
751
+ ` \u25B6\uFE0F apply transaction "${store.transactionStatus.key}" (init)`
752
+ );
753
+ store.transactionStatus.phase = `applying`;
754
+ store.transactionStatus.output = output;
755
+ const { atomUpdates } = store.transactionStatus;
756
+ for (const { key, oldValue, newValue } of atomUpdates) {
757
+ const token = { key, type: `atom` };
758
+ const state = withdraw(token, store);
759
+ setState(state, newValue, store);
760
+ }
761
+ const myTransaction = withdraw(
762
+ { key: store.transactionStatus.key, type: `transaction` },
763
+ store
764
+ );
765
+ myTransaction.subject.next({
766
+ key: store.transactionStatus.key,
767
+ atomUpdates,
768
+ output,
769
+ params: store.transactionStatus.params
770
+ });
771
+ store.transactionStatus = { phase: `idle` };
772
+ (_c = store.config.logger) == null ? void 0 : _c.info(`\u{1F6EC}`, `transaction done`);
773
+ };
774
+ var undoTransactionUpdate = (update, store) => {
775
+ var _a;
776
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23EE undo transaction "${update.key}" (undo)`);
777
+ for (const { key, oldValue, newValue } of update.atomUpdates) {
778
+ const token = { key, type: `atom` };
779
+ const state = withdraw(token, store);
780
+ setState(state, oldValue, store);
781
+ }
782
+ };
783
+ var redoTransactionUpdate = (update, store) => {
784
+ var _a;
785
+ (_a = store.config.logger) == null ? void 0 : _a.info(` \u23ED redo transaction "${update.key}" (redo)`);
786
+ for (const { key, oldValue, newValue } of update.atomUpdates) {
787
+ const token = { key, type: `atom` };
788
+ const state = withdraw(token, store);
789
+ setState(state, newValue, store);
790
+ }
718
791
  };
719
792
  var abortTransaction = (store) => {
720
793
  var _a, _b;
721
- if (!store.transaction.open) {
794
+ if (store.transactionStatus.phase === `idle`) {
722
795
  (_a = store.config.logger) == null ? void 0 : _a.warn(
723
796
  `abortTransaction called outside of a transaction. This is probably a bug.`
724
797
  );
725
798
  return;
726
799
  }
727
- store.atoms = store.transaction.prev.atoms;
728
- store.readonlySelectors = store.transaction.prev.readonlySelectors;
729
- store.selectorGraph = store.transaction.prev.selectorGraph;
730
- store.selectors = store.transaction.prev.selectors;
731
- store.valueMap = store.transaction.prev.valueMap;
732
- store.transaction = { open: false };
800
+ store.transactionStatus = { phase: `idle` };
733
801
  (_b = store.config.logger) == null ? void 0 : _b.info(`\u{1FA82}`, `transaction fail`);
734
802
  };
803
+ function transaction__INTERNAL(options, store = IMPLICIT.STORE) {
804
+ const newTransaction = {
805
+ key: options.key,
806
+ type: `transaction`,
807
+ run: (...params) => {
808
+ var _a;
809
+ buildTransaction(options.key, params, store);
810
+ try {
811
+ const output = options.do(
812
+ {
813
+ get: (token2) => getState(token2, store),
814
+ set: (token2, value) => setState(token2, value, store)
815
+ },
816
+ ...params
817
+ );
818
+ applyTransaction(output, store);
819
+ return output;
820
+ } catch (thrown) {
821
+ abortTransaction(store);
822
+ (_a = store.config.logger) == null ? void 0 : _a.error(`Transaction ${options.key} failed`, thrown);
823
+ throw thrown;
824
+ }
825
+ },
826
+ subject: new Rx.Subject()
827
+ };
828
+ const core = target(store);
829
+ core.transactions = import_hamt_plus4.default.set(
830
+ newTransaction.key,
831
+ newTransaction,
832
+ core.transactions
833
+ );
834
+ const token = deposit(newTransaction);
835
+ return token;
836
+ }
837
+ var target = (store = IMPLICIT.STORE) => store.transactionStatus.phase === `building` ? store.transactionStatus.core : store;
735
838
 
736
- // src/atom.ts
737
- var import_hamt_plus5 = __toESM(require("hamt_plus"));
738
- var Rx = __toESM(require("rxjs"));
739
-
740
- // ../anvl/src/json/index.ts
741
- var import_function8 = require("fp-ts/function");
742
- var stringifyJson = (json) => JSON.stringify(json);
743
-
744
- // src/atom.ts
745
- var atom = (options, store = IMPLICIT.STORE) => {
839
+ // src/internal/atom-internal.ts
840
+ function atom__INTERNAL(options, family, store = IMPLICIT.STORE) {
746
841
  var _a, _b, _c;
747
- if (import_hamt_plus5.default.has(options.key, store.atoms)) {
842
+ const core = target(store);
843
+ if (hasKeyBeenUsed(options.key, store)) {
748
844
  (_b = (_a = store.config.logger) == null ? void 0 : _a.error) == null ? void 0 : _b.call(
749
845
  _a,
750
846
  `Key "${options.key}" already exists in the store.`
751
847
  );
752
- return deposit(store.atoms.get(options.key));
848
+ return deposit(core.atoms.get(options.key));
753
849
  }
754
- const subject = new Rx.Subject();
755
- const newAtom = __spreadProps(__spreadValues({}, options), { subject });
756
- store.atoms = import_hamt_plus5.default.set(options.key, newAtom, store.atoms);
757
- store.valueMap = import_hamt_plus5.default.set(options.key, options.default, store.valueMap);
850
+ const subject = new Rx2.Subject();
851
+ const newAtom = __spreadValues(__spreadProps(__spreadValues({}, options), {
852
+ subject,
853
+ type: `atom`
854
+ }), family && { family });
855
+ const initialValue = options.default instanceof Function ? options.default() : options.default;
856
+ storeAtom(newAtom, store);
857
+ markAtomAsDefault(options.key, store);
858
+ cacheValue(options.key, initialValue, store);
758
859
  const token = deposit(newAtom);
759
860
  const setSelf = (next) => setState(token, next, store);
760
- const onSet = (observe) => subscribe(token, observe, store);
761
- setSelf(options.default);
861
+ const onSet = (handle) => subscribe(token, handle, store);
762
862
  (_c = options.effects) == null ? void 0 : _c.forEach((effect) => effect({ setSelf, onSet }));
763
863
  return token;
764
- };
765
- var atomFamily = (options, store = IMPLICIT.STORE) => (key) => {
766
- var _a;
767
- const fullKey = `${options.key}__${stringifyJson(key)}`;
768
- const existing = store.atoms.get(fullKey);
769
- if (existing) {
770
- return deposit(existing);
771
- }
772
- return atom(
864
+ }
865
+
866
+ // src/internal/families-internal.ts
867
+ var Rx3 = __toESM(require("rxjs"));
868
+
869
+ // ../anvl/src/json/index.ts
870
+ var import_function8 = require("fp-ts/function");
871
+ var stringifyJson = (json) => JSON.stringify(json);
872
+
873
+ // src/internal/families-internal.ts
874
+ function atomFamily__INTERNAL(options, store = IMPLICIT.STORE) {
875
+ const subject = new Rx3.Subject();
876
+ return Object.assign(
877
+ (key) => {
878
+ var _a;
879
+ const subKey = stringifyJson(key);
880
+ const family = { key: options.key, subKey };
881
+ const fullKey = `${options.key}__${subKey}`;
882
+ const existing = withdraw({ key: fullKey, type: `atom` }, store);
883
+ const token = existing ? deposit(existing) : atom__INTERNAL(
884
+ {
885
+ key: fullKey,
886
+ default: options.default instanceof Function ? options.default(key) : options.default,
887
+ effects: (_a = options.effects) == null ? void 0 : _a.call(options, key)
888
+ },
889
+ family,
890
+ store
891
+ );
892
+ subject.next(token);
893
+ return token;
894
+ },
773
895
  {
774
- key: fullKey,
775
- default: options.default instanceof Function ? options.default(key) : options.default,
776
- effects: (_a = options.effects) == null ? void 0 : _a.call(options, key)
896
+ key: options.key,
897
+ type: `atom_family`,
898
+ subject
899
+ }
900
+ );
901
+ }
902
+ function readonlySelectorFamily__INTERNAL(options, store) {
903
+ const core = target(store);
904
+ const subject = new Rx3.Subject();
905
+ return Object.assign(
906
+ (key) => {
907
+ const subKey = stringifyJson(key);
908
+ const family = { key: options.key, subKey };
909
+ const fullKey = `${options.key}__${subKey}`;
910
+ const existing = core.readonlySelectors.get(fullKey);
911
+ if (existing) {
912
+ return deposit(existing);
913
+ }
914
+ return selector__INTERNAL(
915
+ {
916
+ key: fullKey,
917
+ get: options.get(key)
918
+ },
919
+ family,
920
+ store
921
+ );
777
922
  },
778
- store
923
+ {
924
+ key: options.key,
925
+ type: `readonly_selector_family`,
926
+ subject
927
+ }
779
928
  );
929
+ }
930
+ function selectorFamily__INTERNAL(options, store = IMPLICIT.STORE) {
931
+ const isReadonly = !(`set` in options);
932
+ if (isReadonly) {
933
+ return readonlySelectorFamily__INTERNAL(options, store);
934
+ }
935
+ const core = target(store);
936
+ const subject = new Rx3.Subject();
937
+ return Object.assign(
938
+ (key) => {
939
+ const subKey = stringifyJson(key);
940
+ const family = { key: options.key, subKey };
941
+ const fullKey = `${options.key}__${subKey}`;
942
+ const existing = core.selectors.get(fullKey);
943
+ if (existing) {
944
+ return deposit(existing);
945
+ }
946
+ const token = selector__INTERNAL(
947
+ {
948
+ key: fullKey,
949
+ get: options.get(key),
950
+ set: options.set(key)
951
+ },
952
+ family,
953
+ store
954
+ );
955
+ subject.next(token);
956
+ return token;
957
+ },
958
+ {
959
+ key: options.key,
960
+ type: `selector_family`
961
+ }
962
+ );
963
+ }
964
+
965
+ // src/internal/logger.ts
966
+ var LOG_LEVELS = [
967
+ `info`,
968
+ `warn`,
969
+ `error`
970
+ ];
971
+ var setLogLevel = (preferredLevel, store = IMPLICIT.STORE) => {
972
+ const { logger__INTERNAL } = store.config;
973
+ if (preferredLevel === null) {
974
+ store.config.logger = null;
975
+ } else {
976
+ store.config.logger = __spreadValues({}, console);
977
+ LOG_LEVELS.forEach((logLevel) => {
978
+ if (LOG_LEVELS.indexOf(logLevel) < LOG_LEVELS.indexOf(preferredLevel)) {
979
+ store.config.logger[logLevel] = doNothing;
980
+ } else {
981
+ store.config.logger[logLevel] = logger__INTERNAL[logLevel];
982
+ }
983
+ });
984
+ }
985
+ };
986
+ var useLogger = (logger, store = IMPLICIT.STORE) => {
987
+ var _a;
988
+ const currentLogLevel = store.config.logger === null ? null : (_a = LOG_LEVELS.find(
989
+ (logLevel) => {
990
+ var _a2;
991
+ return ((_a2 = store.config.logger) == null ? void 0 : _a2[logLevel]) !== doNothing;
992
+ }
993
+ )) != null ? _a : null;
994
+ store.config.logger__INTERNAL = __spreadValues({}, logger);
995
+ setLogLevel(currentLogLevel, store);
780
996
  };
781
997
 
782
- // src/selector.ts
783
- var import_hamt_plus6 = __toESM(require("hamt_plus"));
784
- var Rx2 = __toESM(require("rxjs"));
785
- function selector(options, store = IMPLICIT.STORE) {
998
+ // src/internal/selector-internal.ts
999
+ var import_hamt_plus5 = __toESM(require("hamt_plus"));
1000
+ var Rx4 = __toESM(require("rxjs"));
1001
+ var lookupSelectorSources = (key, store) => target(store).selectorGraph.getRelations(key).filter(({ source }) => source !== key).map(({ source }) => lookup(source, store));
1002
+ var traceSelectorAtoms = (selectorKey, dependency, store) => {
1003
+ const roots = [];
1004
+ const sources = lookupSelectorSources(dependency.key, store);
1005
+ let depth = 0;
1006
+ while (sources.length > 0) {
1007
+ const source = sources.shift();
1008
+ ++depth;
1009
+ if (depth > 999) {
1010
+ throw new Error(
1011
+ `Maximum selector dependency depth exceeded in selector "${selectorKey}".`
1012
+ );
1013
+ }
1014
+ if (source.type !== `atom`) {
1015
+ sources.push(...lookupSelectorSources(source.key, store));
1016
+ } else {
1017
+ roots.push(source);
1018
+ }
1019
+ }
1020
+ return roots;
1021
+ };
1022
+ var traceAllSelectorAtoms = (selectorKey, store) => {
1023
+ const sources = lookupSelectorSources(selectorKey, store);
1024
+ return sources.flatMap(
1025
+ (source) => source.type === `atom` ? source : traceSelectorAtoms(selectorKey, source, store)
1026
+ );
1027
+ };
1028
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
786
1029
  var _a, _b;
787
- if (import_hamt_plus6.default.has(options.key, store.selectors)) {
788
- throw new Error(`Key "${options.key}" already exists in the store.`);
1030
+ const core = target(store);
1031
+ if (dependency.type === `atom`) {
1032
+ core.selectorAtoms = core.selectorAtoms.set(selectorKey, dependency.key);
1033
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1034
+ ` || adding root for "${selectorKey}": ${dependency.key}`
1035
+ );
1036
+ return;
789
1037
  }
790
- const subject = new Rx2.Subject();
1038
+ const roots = traceSelectorAtoms(selectorKey, dependency, store);
1039
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1040
+ ` || adding roots for "${selectorKey}":`,
1041
+ roots.map((r) => r.key)
1042
+ );
1043
+ for (const root of roots) {
1044
+ core.selectorAtoms = core.selectorAtoms.set(selectorKey, root.key);
1045
+ }
1046
+ };
1047
+ var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
1048
+ get: (dependency) => {
1049
+ var _a, _b;
1050
+ const core = target(store);
1051
+ const alreadyRegistered = core.selectorGraph.getRelations(selectorKey).some(({ source }) => source === dependency.key);
1052
+ const dependencyState = withdraw(dependency, store);
1053
+ const dependencyValue = getState__INTERNAL(dependencyState, store);
1054
+ if (alreadyRegistered) {
1055
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1056
+ ` || ${selectorKey} <- ${dependency.key} =`,
1057
+ dependencyValue
1058
+ );
1059
+ } else {
1060
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1061
+ `\u{1F50C} registerSelector "${selectorKey}" <- "${dependency.key}" =`,
1062
+ dependencyValue
1063
+ );
1064
+ core.selectorGraph = core.selectorGraph.set(selectorKey, dependency.key, {
1065
+ source: dependency.key
1066
+ });
1067
+ }
1068
+ updateSelectorAtoms(selectorKey, dependency, store);
1069
+ return dependencyValue;
1070
+ },
1071
+ set: (stateToken, newValue) => {
1072
+ const state = withdraw(stateToken, store);
1073
+ setState__INTERNAL(state, newValue, store);
1074
+ }
1075
+ });
1076
+ function selector__INTERNAL(options, family, store = IMPLICIT.STORE) {
1077
+ var _a, _b, _c;
1078
+ const core = target(store);
1079
+ if (import_hamt_plus5.default.has(options.key, core.selectors)) {
1080
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1081
+ `Key "${options.key}" already exists in the store.`
1082
+ );
1083
+ }
1084
+ const subject = new Rx4.Subject();
791
1085
  const { get, set } = registerSelector(options.key, store);
792
1086
  const getSelf = () => {
793
1087
  const value = options.get({ get });
794
- store.valueMap = import_hamt_plus6.default.set(options.key, value, store.valueMap);
1088
+ cacheValue(options.key, value, store);
795
1089
  return value;
796
1090
  };
797
1091
  if (!(`set` in options)) {
798
- const readonlySelector = __spreadProps(__spreadValues({}, options), {
1092
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
799
1093
  subject,
800
- get: getSelf
801
- });
802
- store.readonlySelectors = import_hamt_plus6.default.set(
1094
+ get: getSelf,
1095
+ type: `readonly_selector`
1096
+ }), family && { family });
1097
+ core.readonlySelectors = import_hamt_plus5.default.set(
803
1098
  options.key,
804
1099
  readonlySelector,
805
- store.readonlySelectors
1100
+ core.readonlySelectors
806
1101
  );
807
1102
  const initialValue2 = getSelf();
808
- (_a = store.config.logger) == null ? void 0 : _a.info(` \u2728`, options.key, `=`, initialValue2);
1103
+ (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728 "${options.key}" =`, initialValue2);
809
1104
  return __spreadProps(__spreadValues({}, readonlySelector), { type: `readonly_selector` });
810
1105
  }
811
1106
  const setSelf = (next) => {
812
1107
  var _a2;
813
- (_a2 = store.config.logger) == null ? void 0 : _a2.info(`${options.key}.set`, next);
1108
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(` <- "${options.key}" became`, next);
814
1109
  const oldValue = getSelf();
815
1110
  const newValue = become(next)(oldValue);
816
- store.valueMap = import_hamt_plus6.default.set(options.key, newValue, store.valueMap);
1111
+ cacheValue(options.key, newValue, store);
817
1112
  markDone(options.key, store);
818
- subject.next({ newValue, oldValue });
1113
+ if (store.transactionStatus.phase === `idle`) {
1114
+ subject.next({ newValue, oldValue });
1115
+ }
819
1116
  options.set({ get, set }, newValue);
820
1117
  };
821
- const mySelector = __spreadProps(__spreadValues({}, options), {
1118
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
822
1119
  subject,
823
1120
  get: getSelf,
824
- set: setSelf
825
- });
826
- store.selectors = import_hamt_plus6.default.set(options.key, mySelector, store.selectors);
1121
+ set: setSelf,
1122
+ type: `selector`
1123
+ }), family && { family });
1124
+ core.selectors = import_hamt_plus5.default.set(options.key, mySelector, core.selectors);
827
1125
  const initialValue = getSelf();
828
- (_b = store.config.logger) == null ? void 0 : _b.info(` \u2728`, options.key, `=`, initialValue);
1126
+ (_c = store.config.logger) == null ? void 0 : _c.info(` \u2728 "${options.key}" =`, initialValue);
829
1127
  return __spreadProps(__spreadValues({}, mySelector), { type: `selector` });
830
1128
  }
831
- function selectorFamily(options, store = IMPLICIT.STORE) {
832
- return (key) => {
833
- var _a;
834
- const fullKey = `${options.key}__${stringifyJson(key)}`;
835
- const existing = (_a = store.selectors.get(fullKey)) != null ? _a : store.readonlySelectors.get(fullKey);
836
- if (existing) {
837
- return deposit(existing);
1129
+
1130
+ // src/internal/set.ts
1131
+ var import_hamt_plus6 = __toESM(require("hamt_plus"));
1132
+ var evictDownStream = (state, store = IMPLICIT.STORE) => {
1133
+ var _a, _b;
1134
+ const core = target(store);
1135
+ const downstream = core.selectorAtoms.getRelations(state.key);
1136
+ const downstreamKeys = downstream.map(({ id }) => id);
1137
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1138
+ ` || ${downstreamKeys.length} downstream:`,
1139
+ downstreamKeys
1140
+ );
1141
+ if (core.operation.open) {
1142
+ (_b = store.config.logger) == null ? void 0 : _b.info(` ||`, [...core.operation.done], `already done`);
1143
+ }
1144
+ downstream.forEach(({ id: stateKey }) => {
1145
+ var _a2, _b2, _c, _d;
1146
+ if (isDone(stateKey, store)) {
1147
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(` || ${stateKey} already done`);
1148
+ return;
838
1149
  }
839
- const readonlySelectorOptions = {
840
- key: fullKey,
841
- get: options.get(key)
842
- };
843
- if (!(`set` in options)) {
844
- return selector(
845
- __spreadValues({}, readonlySelectorOptions),
846
- store
1150
+ const state2 = (_b2 = import_hamt_plus6.default.get(stateKey, core.selectors)) != null ? _b2 : import_hamt_plus6.default.get(stateKey, core.readonlySelectors);
1151
+ if (!state2) {
1152
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1153
+ ` || ${stateKey} is an atom, and can't be downstream`
847
1154
  );
1155
+ return;
848
1156
  }
849
- return selector(
850
- __spreadProps(__spreadValues({}, readonlySelectorOptions), {
851
- set: options.set(key)
852
- }),
853
- store
1157
+ evictCachedValue(stateKey, store);
1158
+ (_d = store.config.logger) == null ? void 0 : _d.info(` xx evicted "${stateKey}"`);
1159
+ markDone(stateKey, store);
1160
+ });
1161
+ };
1162
+ var setAtomState = (atom2, next, store = IMPLICIT.STORE) => {
1163
+ var _a, _b;
1164
+ const oldValue = getState__INTERNAL(atom2, store);
1165
+ const newValue = become(next)(oldValue);
1166
+ (_a = store.config.logger) == null ? void 0 : _a.info(`<< setting atom "${atom2.key}" to`, newValue);
1167
+ cacheValue(atom2.key, newValue, store);
1168
+ if (isAtomDefault(atom2.key)) {
1169
+ markAtomAsNotDefault(atom2.key, store);
1170
+ }
1171
+ markDone(atom2.key, store);
1172
+ (_b = store.config.logger) == null ? void 0 : _b.info(
1173
+ ` || evicting caches downstream from "${atom2.key}"`
1174
+ );
1175
+ evictDownStream(atom2, store);
1176
+ const update = { oldValue, newValue };
1177
+ if (store.transactionStatus.phase !== `building`) {
1178
+ emitUpdate(atom2, update, store);
1179
+ } else {
1180
+ stowUpdate(atom2, update, store);
1181
+ }
1182
+ };
1183
+ var setSelectorState = (selector2, next, store = IMPLICIT.STORE) => {
1184
+ var _a, _b;
1185
+ const oldValue = getState__INTERNAL(selector2, store);
1186
+ const newValue = become(next)(oldValue);
1187
+ (_a = store.config.logger) == null ? void 0 : _a.info(`<< setting selector "${selector2.key}" to`, newValue);
1188
+ (_b = store.config.logger) == null ? void 0 : _b.info(` || propagating change made to "${selector2.key}"`);
1189
+ selector2.set(newValue);
1190
+ };
1191
+ var setState__INTERNAL = (state, value, store = IMPLICIT.STORE) => {
1192
+ if (`set` in state) {
1193
+ setSelectorState(state, value, store);
1194
+ } else {
1195
+ setAtomState(state, value, store);
1196
+ }
1197
+ };
1198
+
1199
+ // src/internal/subscribe-internal.ts
1200
+ var prepareUpdate = (state, store) => {
1201
+ const oldValue = recallState(state, store);
1202
+ const newValue = getState__INTERNAL(state, store);
1203
+ return { newValue, oldValue };
1204
+ };
1205
+ var stowUpdate = (state, update, store) => {
1206
+ var _a;
1207
+ const { key } = state;
1208
+ const { logger } = store.config;
1209
+ if (store.transactionStatus.phase !== `building`) {
1210
+ (_a = store.config.logger) == null ? void 0 : _a.warn(
1211
+ `stowUpdate called outside of a transaction. This is probably a bug.`
854
1212
  );
1213
+ return;
1214
+ }
1215
+ store.transactionStatus.atomUpdates.push(__spreadValues({ key }, update));
1216
+ logger == null ? void 0 : logger.info(`\u{1F4DD} ${key} stowed (`, update.oldValue, `->`, update.newValue, `)`);
1217
+ };
1218
+ var emitUpdate = (state, update, store) => {
1219
+ const { key } = state;
1220
+ const { logger } = store.config;
1221
+ logger == null ? void 0 : logger.info(
1222
+ `\u{1F4E2} ${state.type} "${key}" went (`,
1223
+ update.oldValue,
1224
+ `->`,
1225
+ update.newValue,
1226
+ `)`
1227
+ );
1228
+ state.subject.next(update);
1229
+ };
1230
+ var subscribeToRootAtoms = (state, store) => {
1231
+ const dependencySubscriptions = `default` in state ? null : traceAllSelectorAtoms(state.key, store).map((atomToken) => {
1232
+ const atom2 = withdraw(atomToken, store);
1233
+ return atom2.subject.subscribe((atomChange) => {
1234
+ var _a, _b;
1235
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1236
+ `\u{1F4E2} selector "${state.key}" saw root "${atomToken.key}" go (`,
1237
+ atomChange.oldValue,
1238
+ `->`,
1239
+ atomChange.newValue,
1240
+ `)`
1241
+ );
1242
+ const oldValue = recallState(state, store);
1243
+ const newValue = getState__INTERNAL(state, store);
1244
+ (_b = store.config.logger) == null ? void 0 : _b.info(` <- ${state.key} became`, newValue);
1245
+ state.subject.next({ newValue, oldValue });
1246
+ });
1247
+ });
1248
+ return dependencySubscriptions;
1249
+ };
1250
+
1251
+ // src/internal/timeline-internal.ts
1252
+ var import_hamt_plus7 = __toESM(require("hamt_plus"));
1253
+ function timeline__INTERNAL(options, store = IMPLICIT.STORE) {
1254
+ let incompleteTransactionKey = null;
1255
+ const timelineData = {
1256
+ at: 0,
1257
+ timeTraveling: false,
1258
+ history: []
855
1259
  };
856
- }
857
- var registerSelector = (selectorKey, store = IMPLICIT.STORE) => ({
858
- get: (state) => {
859
- var _a, _b, _c;
860
- const isRegistered = store.selectorGraph.getRelatedIds(selectorKey).includes(state.key);
861
- if (isRegistered) {
862
- (_a = store.config.logger) == null ? void 0 : _a.info(` ||`, selectorKey, `<-`, state.key);
863
- } else {
864
- (_b = store.config.logger) == null ? void 0 : _b.info(
865
- `\u{1F50C} registerSelector`,
866
- selectorKey,
867
- `<-`,
868
- state.key
1260
+ const subscribeToAtom = (token) => {
1261
+ const state = withdraw(token, store);
1262
+ state.subject.subscribe((update) => {
1263
+ var _a, _b, _c;
1264
+ const storeCurrentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
1265
+ (_a = store.config.logger) == null ? void 0 : _a.info(
1266
+ `\u23F3 timeline "${options.key}" saw atom "${token.key}" go (`,
1267
+ update.oldValue,
1268
+ `->`,
1269
+ update.newValue,
1270
+ storeCurrentTransactionKey ? `) in "${storeCurrentTransactionKey}"` : `) independently`
869
1271
  );
870
- store.selectorGraph = store.selectorGraph.set(selectorKey, state.key);
1272
+ if (storeCurrentTransactionKey && store.transactionStatus.phase === `applying`) {
1273
+ const currentTransaction = withdraw(
1274
+ { key: storeCurrentTransactionKey, type: `transaction` },
1275
+ store
1276
+ );
1277
+ if (incompleteTransactionKey !== storeCurrentTransactionKey) {
1278
+ if (incompleteTransactionKey) {
1279
+ (_b = store.config.logger) == null ? void 0 : _b.error(
1280
+ `Timeline "${options.key}" was unable to resolve transaction "${incompleteTransactionKey}. This is probably a bug.`
1281
+ );
1282
+ }
1283
+ incompleteTransactionKey = storeCurrentTransactionKey;
1284
+ const subscription = currentTransaction.subject.subscribe((update2) => {
1285
+ var _a2;
1286
+ if (timelineData.timeTraveling === false) {
1287
+ timelineData.history.push(__spreadProps(__spreadValues({
1288
+ type: `transaction_update`
1289
+ }, update2), {
1290
+ atomUpdates: update2.atomUpdates.filter(
1291
+ (atomUpdate) => options.atoms.some((atom2) => atom2.key === atomUpdate.key)
1292
+ )
1293
+ }));
1294
+ }
1295
+ timelineData.at = timelineData.history.length;
1296
+ subscription.unsubscribe();
1297
+ incompleteTransactionKey = null;
1298
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1299
+ `\u231B timeline "${options.key}" pushed a transaction_update from "${update2.key}"`
1300
+ );
1301
+ });
1302
+ }
1303
+ } else {
1304
+ if (timelineData.timeTraveling === false) {
1305
+ timelineData.history.push({
1306
+ type: `state_update`,
1307
+ key: token.key,
1308
+ oldValue: update.oldValue,
1309
+ newValue: update.newValue
1310
+ });
1311
+ (_c = store.config.logger) == null ? void 0 : _c.info(
1312
+ `\u231B timeline "${options.key}" pushed a state_update to "${token.key}"`
1313
+ );
1314
+ timelineData.at = timelineData.history.length;
1315
+ }
1316
+ }
1317
+ });
1318
+ };
1319
+ for (const tokenOrFamily of options.atoms) {
1320
+ if (tokenOrFamily.type === `atom_family`) {
1321
+ const family = tokenOrFamily;
1322
+ family.subject.subscribe((token) => subscribeToAtom(token));
1323
+ } else {
1324
+ const token = tokenOrFamily;
1325
+ subscribeToAtom(token);
871
1326
  }
872
- const currentValue = getState(state, store);
873
- (_c = store.config.logger) == null ? void 0 : _c.info(` ||`, state.key, `=`, currentValue);
874
- return currentValue;
875
- },
876
- set: (token, newValue) => {
877
- store.selectorGraph.set(token.key, selectorKey);
878
- setState__INTERNAL(token, newValue, store);
879
1327
  }
880
- });
1328
+ store.timelineStore = import_hamt_plus7.default.set(options.key, timelineData, store.timelineStore);
1329
+ return {
1330
+ key: options.key,
1331
+ type: `timeline`
1332
+ };
1333
+ }
1334
+ var redo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1335
+ var _a, _b;
1336
+ const timelineData = store.timelineStore.get(token.key);
1337
+ if (!timelineData) {
1338
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1339
+ `Tried to redo on timeline "${token.key}" has not been initialized.`
1340
+ );
1341
+ return;
1342
+ }
1343
+ if (timelineData.at === timelineData.history.length) {
1344
+ (_b = store.config.logger) == null ? void 0 : _b.warn(
1345
+ `Tried to redo on timeline "${token.key}" but there is nothing to redo.`
1346
+ );
1347
+ return;
1348
+ }
1349
+ timelineData.timeTraveling = true;
1350
+ const update = timelineData.history[timelineData.at];
1351
+ switch (update.type) {
1352
+ case `state_update`: {
1353
+ const { key, newValue } = update;
1354
+ setState({ key, type: `atom` }, newValue);
1355
+ break;
1356
+ }
1357
+ case `transaction_update`: {
1358
+ for (const atomUpdate of update.atomUpdates) {
1359
+ const { key, newValue } = atomUpdate;
1360
+ setState({ key, type: `atom` }, newValue);
1361
+ }
1362
+ break;
1363
+ }
1364
+ }
1365
+ ++timelineData.at;
1366
+ timelineData.timeTraveling = false;
1367
+ };
1368
+ var undo__INTERNAL = (token, store = IMPLICIT.STORE) => {
1369
+ var _a, _b;
1370
+ const timelineData = store.timelineStore.get(token.key);
1371
+ if (!timelineData) {
1372
+ (_a = store.config.logger) == null ? void 0 : _a.error(
1373
+ `Tried to undo on timeline "${token.key}" has not been initialized.`
1374
+ );
1375
+ return;
1376
+ }
1377
+ if (timelineData.at === 0) {
1378
+ (_b = store.config.logger) == null ? void 0 : _b.warn(
1379
+ `Tried to undo on timeline "${token.key}" but there is nothing to undo.`
1380
+ );
1381
+ return;
1382
+ }
1383
+ timelineData.timeTraveling = true;
1384
+ --timelineData.at;
1385
+ const update = timelineData.history[timelineData.at];
1386
+ switch (update.type) {
1387
+ case `state_update`: {
1388
+ const { key, oldValue } = update;
1389
+ setState({ key, type: `atom` }, oldValue);
1390
+ break;
1391
+ }
1392
+ case `transaction_update`: {
1393
+ for (const atomUpdate of update.atomUpdates) {
1394
+ const { key, oldValue } = atomUpdate;
1395
+ setState({ key, type: `atom` }, oldValue);
1396
+ }
1397
+ break;
1398
+ }
1399
+ }
1400
+ timelineData.timeTraveling = false;
1401
+ };
1402
+
1403
+ // src/atom.ts
1404
+ function atom(options) {
1405
+ return atom__INTERNAL(options);
1406
+ }
1407
+ function atomFamily(options) {
1408
+ return atomFamily__INTERNAL(options);
1409
+ }
1410
+
1411
+ // src/selector.ts
1412
+ function selector(options) {
1413
+ return selector__INTERNAL(options);
1414
+ }
1415
+ function selectorFamily(options) {
1416
+ return selectorFamily__INTERNAL(options);
1417
+ }
1418
+
1419
+ // src/timeline.ts
1420
+ var timeline = (options) => {
1421
+ return timeline__INTERNAL(options);
1422
+ };
1423
+ var redo = (token) => {
1424
+ return redo__INTERNAL(token, IMPLICIT.STORE);
1425
+ };
1426
+ var undo = (token) => {
1427
+ return undo__INTERNAL(token, IMPLICIT.STORE);
1428
+ };
881
1429
 
882
1430
  // src/transaction.ts
883
- var transaction = (options, store = IMPLICIT.STORE) => Object.assign(
884
- (...parameters) => {
885
- var _a;
886
- startTransaction(store);
887
- try {
888
- const result = options.do(
889
- {
890
- get: (token) => getState(token, store),
891
- set: (token, value) => setState(token, value, store)
892
- },
893
- ...parameters
894
- );
895
- finishTransaction(store);
896
- return result;
897
- } catch (thrown) {
898
- abortTransaction(store);
899
- (_a = store.config.logger) == null ? void 0 : _a.error(`Transaction ${options.key} failed`, thrown);
900
- throw thrown;
1431
+ function transaction(options) {
1432
+ return transaction__INTERNAL(options);
1433
+ }
1434
+ var runTransaction = (token, store = IMPLICIT.STORE) => (...parameters) => withdraw(token, store).run(...parameters);
1435
+
1436
+ // src/subscribe.ts
1437
+ var subscribe = (token, handleUpdate, store = IMPLICIT.STORE) => {
1438
+ var _a;
1439
+ const state = withdraw(token, store);
1440
+ const subscription = state.subject.subscribe(handleUpdate);
1441
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to "${state.key}"`);
1442
+ const dependencySubscriptions = `get` in state ? subscribeToRootAtoms(state, store) : null;
1443
+ const unsubscribe = dependencySubscriptions === null ? () => {
1444
+ var _a2;
1445
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from "${state.key}"`);
1446
+ subscription.unsubscribe();
1447
+ } : () => {
1448
+ var _a2;
1449
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(
1450
+ `\u{1F648} unsubscribe from "${state.key}" and its dependencies`
1451
+ );
1452
+ subscription.unsubscribe();
1453
+ for (const dependencySubscription of dependencySubscriptions) {
1454
+ dependencySubscription.unsubscribe();
901
1455
  }
902
- },
903
- { key: options.key }
904
- );
1456
+ };
1457
+ return unsubscribe;
1458
+ };
1459
+ var subscribeToTransaction = (token, handleUpdate, store = IMPLICIT.STORE) => {
1460
+ var _a;
1461
+ const tx = withdraw(token, store);
1462
+ (_a = store.config.logger) == null ? void 0 : _a.info(`\u{1F440} subscribe to transaction "${token.key}"`);
1463
+ const subscription = tx.subject.subscribe(handleUpdate);
1464
+ const unsubscribe = () => {
1465
+ var _a2;
1466
+ (_a2 = store.config.logger) == null ? void 0 : _a2.info(`\u{1F648} unsubscribe from transaction "${token.key}"`);
1467
+ subscription.unsubscribe();
1468
+ };
1469
+ return unsubscribe;
1470
+ };
905
1471
 
906
1472
  // src/index.ts
907
1473
  var getState = (token, store = IMPLICIT.STORE) => {
908
1474
  const state = withdraw(token, store);
909
1475
  return getState__INTERNAL(state, store);
910
1476
  };
911
- var setState = (state, value, store = IMPLICIT.STORE) => {
912
- startAction(store);
913
- setState__INTERNAL(state, value, store);
914
- finishAction(store);
915
- };
916
- var subscribe = (token, observe, store = IMPLICIT.STORE) => {
1477
+ var setState = (token, value, store = IMPLICIT.STORE) => {
1478
+ openOperation(store);
917
1479
  const state = withdraw(token, store);
918
- const subscription = state.subject.subscribe(observe);
919
- return () => subscription.unsubscribe();
1480
+ setState__INTERNAL(state, value, store);
1481
+ closeOperation(store);
920
1482
  };
1483
+ var isDefault = (token, store = IMPLICIT.STORE) => token.type === `atom` ? isAtomDefault(token.key, store) : isSelectorDefault(token.key, store);
921
1484
  // Annotate the CommonJS export names for ESM import in node:
922
1485
  0 && (module.exports = {
923
1486
  __INTERNAL__,
924
1487
  atom,
925
1488
  atomFamily,
926
- configure,
927
1489
  getState,
928
- registerSelector,
1490
+ isDefault,
1491
+ redo,
1492
+ runTransaction,
929
1493
  selector,
930
1494
  selectorFamily,
1495
+ setLogLevel,
931
1496
  setState,
932
1497
  subscribe,
933
- transaction
1498
+ subscribeToTransaction,
1499
+ timeline,
1500
+ transaction,
1501
+ undo,
1502
+ useLogger
934
1503
  });
935
1504
  //# sourceMappingURL=index.js.map