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