atom.io 0.36.3 → 0.37.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/data/index.d.ts.map +1 -1
- package/dist/data/index.js.map +1 -1
- package/dist/eslint-plugin/index.js +1 -2
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/internal/index.d.ts +66 -98
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +543 -504
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +2 -2
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +1 -1
- package/dist/introspection/index.js.map +1 -1
- package/dist/json/index.d.ts +2 -1
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts +154 -139
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js.map +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-devtools/index.d.ts.map +1 -1
- package/dist/react-devtools/index.js +54 -56
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +3 -3
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +6 -6
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +5 -5
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +10 -12
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/transceivers/set-rtx/index.d.ts +1 -1
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +1 -3
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/use-o-DXPncKmZ.js.map +1 -1
- package/dist/web/index.d.ts +2 -2
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js.map +1 -1
- package/package.json +5 -5
- package/src/internal/atom/dispose-atom.ts +5 -4
- package/src/internal/caching.ts +1 -1
- package/src/internal/families/create-readonly-held-selector-family.ts +3 -5
- package/src/internal/families/create-readonly-pure-selector-family.ts +3 -5
- package/src/internal/families/create-regular-atom-family.ts +3 -6
- package/src/internal/families/create-writable-held-selector-family.ts +3 -5
- package/src/internal/families/create-writable-pure-selector-family.ts +3 -5
- package/src/internal/families/find-in-store.ts +17 -34
- package/src/internal/families/init-family-member.ts +5 -87
- package/src/internal/families/mint-in-store.ts +74 -0
- package/src/internal/get-state/read-or-compute-value.ts +4 -2
- package/src/internal/index.ts +19 -18
- package/src/internal/ingest-updates/ingest-atom-update.ts +7 -7
- package/src/internal/ingest-updates/ingest-creation-disposal.ts +11 -11
- package/src/internal/ingest-updates/ingest-selector-update.ts +8 -4
- package/src/internal/ingest-updates/ingest-transaction-update.ts +5 -6
- package/src/internal/install-into-store.ts +2 -2
- package/src/internal/join/join-internal.ts +1 -1
- package/src/internal/molecule.ts +12 -9
- package/src/internal/mutable/create-mutable-atom-family.ts +3 -6
- package/src/internal/mutable/tracker.ts +2 -2
- package/src/internal/mutable/transceiver.ts +6 -4
- package/src/internal/operation.ts +17 -14
- package/src/internal/selector/create-readonly-held-selector.ts +9 -7
- package/src/internal/selector/create-readonly-pure-selector.ts +8 -5
- package/src/internal/selector/create-writable-held-selector.ts +12 -21
- package/src/internal/selector/create-writable-pure-selector.ts +15 -28
- package/src/internal/selector/dispose-selector.ts +6 -1
- package/src/internal/selector/get-selector-dependency-keys.ts +2 -6
- package/src/internal/selector/register-selector.ts +64 -74
- package/src/internal/selector/trace-selector-atoms.ts +2 -2
- package/src/internal/selector/update-selector-atoms.ts +2 -2
- package/src/internal/set-state/dispatch-state-update.ts +101 -0
- package/src/internal/set-state/operate-on-store.ts +126 -0
- package/src/internal/set-state/reset-atom-or-selector.ts +24 -15
- package/src/internal/set-state/set-atom-or-selector.ts +9 -4
- package/src/internal/set-state/set-atom.ts +4 -49
- package/src/internal/set-state/set-into-store.ts +11 -77
- package/src/internal/set-state/set-selector.ts +35 -0
- package/src/internal/store/store.ts +4 -4
- package/src/internal/subscribe/subscribe-in-store.ts +3 -3
- package/src/internal/subscribe/subscribe-to-timeline.ts +2 -2
- package/src/internal/timeline/create-timeline.ts +57 -101
- package/src/internal/timeline/time-travel.ts +1 -1
- package/src/internal/transaction/abort-transaction.ts +1 -1
- package/src/internal/transaction/apply-transaction.ts +7 -7
- package/src/internal/transaction/build-transaction.ts +10 -9
- package/src/internal/transaction/create-transaction.ts +4 -3
- package/src/internal/transaction/index.ts +6 -2
- package/src/introspection/attach-introspection-states.ts +2 -2
- package/src/introspection/attach-transaction-logs.ts +13 -6
- package/src/json/index.ts +3 -1
- package/src/main/atom.ts +2 -1
- package/src/main/events.ts +109 -0
- package/src/main/get-state.ts +1 -1
- package/src/main/index.ts +3 -0
- package/src/main/subscribe.ts +9 -19
- package/src/main/timeline.ts +3 -21
- package/src/main/transaction.ts +0 -65
- package/src/main/validators.ts +8 -2
- package/src/react-devtools/TimelineIndex.tsx +1 -1
- package/src/react-devtools/TransactionIndex.tsx +5 -3
- package/src/react-devtools/Updates.tsx +54 -46
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +20 -10
- package/src/realtime-client/realtime-client-stores/client-sync-store.ts +4 -4
- package/src/realtime-client/sync-continuity.ts +1 -1
- package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +14 -8
- package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +5 -2
- package/src/realtime-server/continuity/subscribe-to-continuity-actions.ts +1 -1
- package/src/realtime-server/realtime-action-receiver.ts +6 -3
- package/src/realtime-server/realtime-server-stores/server-sync-store.ts +13 -16
- package/src/transceivers/set-rtx/set-rtx.ts +1 -3
- package/src/web/persist-sync.ts +2 -2
- package/src/internal/set-state/emit-update.ts +0 -40
package/dist/internal/index.js
CHANGED
|
@@ -449,7 +449,7 @@ function isChildStore(store) {
|
|
|
449
449
|
|
|
450
450
|
//#endregion
|
|
451
451
|
//#region src/internal/operation.ts
|
|
452
|
-
|
|
452
|
+
function openOperation(store, token) {
|
|
453
453
|
if (store.operation.open) {
|
|
454
454
|
const rejectionTime = performance.now();
|
|
455
455
|
store.logger.info(`❗`, token.type, token.key, `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`);
|
|
@@ -459,16 +459,17 @@ const openOperation = (store, token) => {
|
|
|
459
459
|
open: true,
|
|
460
460
|
done: /* @__PURE__ */ new Set(),
|
|
461
461
|
prev: /* @__PURE__ */ new Map(),
|
|
462
|
-
|
|
462
|
+
timestamp: Date.now(),
|
|
463
463
|
token
|
|
464
464
|
};
|
|
465
|
-
store.logger.info(`⭕`, token.type, token.key, `operation start in store "${store.config.name}"${
|
|
466
|
-
|
|
467
|
-
|
|
465
|
+
store.logger.info(`⭕`, token.type, token.key, `operation start in store "${store.config.name}"${isChildStore(store) ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"` : ``}`);
|
|
466
|
+
return store;
|
|
467
|
+
}
|
|
468
|
+
function closeOperation(store) {
|
|
468
469
|
if (store.operation.open) store.logger.info(`🔴`, store.operation.token.type, store.operation.token.key, `operation done in store "${store.config.name}"`);
|
|
469
470
|
store.operation = { open: false };
|
|
470
471
|
store.on.operationClose.next(store.operation);
|
|
471
|
-
}
|
|
472
|
+
}
|
|
472
473
|
const isDone = (store, key) => {
|
|
473
474
|
if (!store.operation.open) {
|
|
474
475
|
store.logger.error(`🐞`, `unknown`, key, `isDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
@@ -585,7 +586,7 @@ function evictCachedValue(target, key) {
|
|
|
585
586
|
const currentValue = target.valueMap.get(key);
|
|
586
587
|
if (currentValue instanceof Future) {
|
|
587
588
|
const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
|
|
588
|
-
if (selector) selector.
|
|
589
|
+
if (selector) selector.getFrom(target);
|
|
589
590
|
return;
|
|
590
591
|
}
|
|
591
592
|
if (target.operation.open) target.operation.prev.set(key, currentValue);
|
|
@@ -604,7 +605,7 @@ function readOrComputeValue(target, state, mut) {
|
|
|
604
605
|
case `writable_held_selector`:
|
|
605
606
|
case `writable_pure_selector`:
|
|
606
607
|
target.logger.info(`🧮`, state.type, key, `computing value`);
|
|
607
|
-
return state.
|
|
608
|
+
return state.getFrom(target);
|
|
608
609
|
case `atom`: {
|
|
609
610
|
let def;
|
|
610
611
|
if (state.default instanceof Function) def = state.default();
|
|
@@ -623,33 +624,104 @@ function readOrComputeValue(target, state, mut) {
|
|
|
623
624
|
}
|
|
624
625
|
|
|
625
626
|
//#endregion
|
|
626
|
-
//#region src/internal/
|
|
627
|
-
|
|
627
|
+
//#region src/internal/families/get-family-of-token.ts
|
|
628
|
+
function getFamilyOfToken(store, token) {
|
|
629
|
+
if (token.family) {
|
|
630
|
+
const family = store.families.get(token.family.key);
|
|
631
|
+
if (family) return family;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
628
634
|
|
|
629
635
|
//#endregion
|
|
630
|
-
//#region src/internal/
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
if (
|
|
634
|
-
|
|
636
|
+
//#region src/internal/transaction/abort-transaction.ts
|
|
637
|
+
const abortTransaction = (store) => {
|
|
638
|
+
const target = newest(store);
|
|
639
|
+
if (!isChildStore(target)) {
|
|
640
|
+
store.logger.warn(`🐞`, `transaction`, `???`, `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`);
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
store.logger.info(`🪂`, `transaction`, target.transactionMeta.update.token.key, `Aborting transaction`);
|
|
644
|
+
target.parent.child = null;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
//#endregion
|
|
648
|
+
//#region src/internal/capitalize.ts
|
|
649
|
+
function capitalize(string) {
|
|
650
|
+
return string[0].toUpperCase() + string.slice(1);
|
|
635
651
|
}
|
|
636
652
|
|
|
637
653
|
//#endregion
|
|
638
|
-
//#region src/internal/
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
case `readonly_held_selector`: store.logger.info(`📢`, state.type, state.key, `went (`, update.oldValue, `->`, update.newValue, `) subscribers:`, state.subject.subscribers);
|
|
654
|
+
//#region src/internal/pretty-print.ts
|
|
655
|
+
function prettyPrintTokenType(token) {
|
|
656
|
+
return token.type.split(`_`).map(capitalize).join(` `);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region src/internal/not-found-error.ts
|
|
661
|
+
var NotFoundError = class extends Error {
|
|
662
|
+
constructor(token, store) {
|
|
663
|
+
super(`${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`);
|
|
649
664
|
}
|
|
650
|
-
state.subject.next(update);
|
|
651
665
|
};
|
|
652
666
|
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region src/internal/transaction/act-upon-store.ts
|
|
669
|
+
function actUponStore(store, token, id) {
|
|
670
|
+
return (...parameters) => {
|
|
671
|
+
const tx = withdraw(store, token);
|
|
672
|
+
if (tx) return tx.run(parameters, id);
|
|
673
|
+
throw new NotFoundError(token, store);
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
//#endregion
|
|
678
|
+
//#region src/internal/set-state/become.ts
|
|
679
|
+
const become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(originalThing) : nextVersionOfThing;
|
|
680
|
+
|
|
681
|
+
//#endregion
|
|
682
|
+
//#region src/internal/set-state/dispatch-state-update.ts
|
|
683
|
+
function dispatchOrDeferStateUpdate(target, state, [oldValue, newValue], _stateIsNewlyCreated) {
|
|
684
|
+
const { key, subject, type } = state;
|
|
685
|
+
const update = {
|
|
686
|
+
oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
|
|
687
|
+
newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue
|
|
688
|
+
};
|
|
689
|
+
if (isRootStore(target)) {
|
|
690
|
+
switch (type) {
|
|
691
|
+
case `mutable_atom`:
|
|
692
|
+
target.logger.info(`📢`, type, key, `is now (`, newValue, `) subscribers:`, subject.subscribers);
|
|
693
|
+
break;
|
|
694
|
+
case `atom`:
|
|
695
|
+
case `writable_pure_selector`:
|
|
696
|
+
case `writable_held_selector`: target.logger.info(`📢`, type, key, `went (`, oldValue, `->`, newValue, `) subscribers:`, subject.subscribers);
|
|
697
|
+
}
|
|
698
|
+
subject.next(update);
|
|
699
|
+
}
|
|
700
|
+
if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
|
|
701
|
+
if (target.on.transactionApplying.state === null) {
|
|
702
|
+
const token = deposit(state);
|
|
703
|
+
if (isTransceiver(newValue)) return;
|
|
704
|
+
const { timestamp } = target.operation;
|
|
705
|
+
const atomUpdate = {
|
|
706
|
+
type: `atom_update`,
|
|
707
|
+
token,
|
|
708
|
+
timestamp,
|
|
709
|
+
update
|
|
710
|
+
};
|
|
711
|
+
target.transactionMeta.update.subEvents.push(atomUpdate);
|
|
712
|
+
target.logger.info(`📁`, `atom`, key, `stowed (`, oldValue, `->`, newValue, `)`);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (hasRole(state, `tracker:signal`)) {
|
|
716
|
+
const keyOfMutable = key.slice(1);
|
|
717
|
+
const mutable = target.atoms.get(keyOfMutable);
|
|
718
|
+
const transceiver = readOrComputeValue(target, mutable, `mut`);
|
|
719
|
+
const accepted = transceiver.do(update.newValue) === null;
|
|
720
|
+
if (accepted === true) evictDownstreamFromAtom(target, mutable);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
653
725
|
//#endregion
|
|
654
726
|
//#region src/internal/set-state/set-atom.ts
|
|
655
727
|
const setAtom = (target, atom, next) => {
|
|
@@ -659,129 +731,49 @@ const setAtom = (target, atom, next) => {
|
|
|
659
731
|
newValue = writeToCache(target, atom, newValue);
|
|
660
732
|
markDone(target, atom.key);
|
|
661
733
|
evictDownstreamFromAtom(target, atom);
|
|
662
|
-
|
|
663
|
-
oldValue,
|
|
664
|
-
newValue
|
|
665
|
-
};
|
|
666
|
-
if (!isChildStore(target)) {
|
|
667
|
-
emitUpdate(target, atom, update);
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
if (target.on.transactionApplying.state === null) {
|
|
671
|
-
const { key } = atom;
|
|
672
|
-
if (isTransceiver(update.newValue)) return;
|
|
673
|
-
const atomUpdate = {
|
|
674
|
-
type: `atom_update`,
|
|
675
|
-
key,
|
|
676
|
-
...update
|
|
677
|
-
};
|
|
678
|
-
if (atom.family) atomUpdate.family = atom.family;
|
|
679
|
-
target.transactionMeta.update.updates.push(atomUpdate);
|
|
680
|
-
target.logger.info(`📁`, `atom`, key, `stowed (`, update.oldValue, `->`, update.newValue, `)`);
|
|
681
|
-
} else if (hasRole(atom, `tracker:signal`)) {
|
|
682
|
-
const key = atom.key.slice(1);
|
|
683
|
-
const mutable = target.atoms.get(key);
|
|
684
|
-
const transceiver = readOrComputeValue(target, mutable, `mut`);
|
|
685
|
-
const accepted = transceiver.do(update.newValue) === null;
|
|
686
|
-
if (accepted === true) evictDownstreamFromAtom(target, mutable);
|
|
687
|
-
}
|
|
734
|
+
return [oldValue, newValue];
|
|
688
735
|
};
|
|
689
736
|
|
|
690
737
|
//#endregion
|
|
691
738
|
//#region src/internal/set-state/reset-atom-or-selector.ts
|
|
692
|
-
function resetAtom(
|
|
693
|
-
switch (
|
|
694
|
-
case `mutable_atom`:
|
|
695
|
-
setAtom(store, state, new state.class());
|
|
696
|
-
return;
|
|
739
|
+
function resetAtom(target, atom) {
|
|
740
|
+
switch (atom.type) {
|
|
741
|
+
case `mutable_atom`: return setAtom(target, atom, new atom.class());
|
|
697
742
|
case `atom`: {
|
|
698
|
-
let def =
|
|
743
|
+
let def = atom.default;
|
|
699
744
|
if (def instanceof Function) def = def();
|
|
700
|
-
setAtom(
|
|
745
|
+
return setAtom(target, atom, def);
|
|
701
746
|
}
|
|
702
747
|
}
|
|
703
748
|
}
|
|
704
|
-
function resetAtomOrSelector(
|
|
749
|
+
function resetAtomOrSelector(target, state) {
|
|
750
|
+
let protoUpdate;
|
|
705
751
|
switch (state.type) {
|
|
706
752
|
case `atom`:
|
|
707
753
|
case `mutable_atom`:
|
|
708
|
-
resetAtom(
|
|
754
|
+
protoUpdate = resetAtom(target, state);
|
|
709
755
|
break;
|
|
710
756
|
case `writable_pure_selector`:
|
|
711
757
|
case `writable_held_selector`:
|
|
712
758
|
{
|
|
713
|
-
const
|
|
714
|
-
|
|
759
|
+
const oldValue = state.getFrom(target);
|
|
760
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
761
|
+
for (const atom of atoms.values()) {
|
|
762
|
+
const rootProtoUpdate = resetAtom(target, atom);
|
|
763
|
+
dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
|
|
764
|
+
}
|
|
765
|
+
const newValue = state.getFrom(target);
|
|
766
|
+
protoUpdate = [oldValue, newValue];
|
|
715
767
|
}
|
|
716
768
|
break;
|
|
717
769
|
}
|
|
770
|
+
return protoUpdate;
|
|
718
771
|
}
|
|
719
772
|
|
|
720
|
-
//#endregion
|
|
721
|
-
//#region src/internal/families/get-family-of-token.ts
|
|
722
|
-
function getFamilyOfToken(store, token) {
|
|
723
|
-
if (token.family) {
|
|
724
|
-
const family = store.families.get(token.family.key);
|
|
725
|
-
if (family) return family;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
//#endregion
|
|
730
|
-
//#region src/internal/set-state/set-atom-or-selector.ts
|
|
731
|
-
const setAtomOrSelector = (store, state, value) => {
|
|
732
|
-
switch (state.type) {
|
|
733
|
-
case `atom`:
|
|
734
|
-
case `mutable_atom`:
|
|
735
|
-
setAtom(store, state, value);
|
|
736
|
-
break;
|
|
737
|
-
case `writable_pure_selector`:
|
|
738
|
-
case `writable_held_selector`:
|
|
739
|
-
state.set(value);
|
|
740
|
-
break;
|
|
741
|
-
}
|
|
742
|
-
};
|
|
743
|
-
|
|
744
773
|
//#endregion
|
|
745
774
|
//#region src/internal/set-state/set-into-store.ts
|
|
746
775
|
function setIntoStore(store, ...params) {
|
|
747
|
-
|
|
748
|
-
let family;
|
|
749
|
-
let key;
|
|
750
|
-
let value;
|
|
751
|
-
if (params.length === 2) {
|
|
752
|
-
token = params[0];
|
|
753
|
-
value = params[1];
|
|
754
|
-
if (token.family) {
|
|
755
|
-
family = getFamilyOfToken(store, token);
|
|
756
|
-
key = parseJson(token.family.subKey);
|
|
757
|
-
token = findInStore(store, family, key);
|
|
758
|
-
}
|
|
759
|
-
} else {
|
|
760
|
-
family = params[0];
|
|
761
|
-
key = params[1];
|
|
762
|
-
value = params[2];
|
|
763
|
-
token = findInStore(store, family, key);
|
|
764
|
-
}
|
|
765
|
-
const action = value === RESET_STATE ? `reset` : `set`;
|
|
766
|
-
if (`counterfeit` in token && `family` in token) {
|
|
767
|
-
const subKey = token.family.subKey;
|
|
768
|
-
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
769
|
-
store.logger.error(`❌`, token.type, token.key, `could not be`, action, `because it was not found in the store "${store.config.name}".`, disposal ? `This state was previously disposed:\n${disposal.trace}` : `No previous disposal trace was found.`);
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
const rejectionTime = openOperation(store, token);
|
|
773
|
-
if (rejectionTime) {
|
|
774
|
-
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
775
|
-
unsubscribe();
|
|
776
|
-
store.logger.info(`🟢`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
777
|
-
setIntoStore(store, token, value);
|
|
778
|
-
});
|
|
779
|
-
return;
|
|
780
|
-
}
|
|
781
|
-
const state = withdraw(store, token);
|
|
782
|
-
if (value === RESET_STATE) resetAtomOrSelector(store, state);
|
|
783
|
-
else setAtomOrSelector(store, state, value);
|
|
784
|
-
closeOperation(store);
|
|
776
|
+
operateOnStore(store, true, ...params);
|
|
785
777
|
}
|
|
786
778
|
|
|
787
779
|
//#endregion
|
|
@@ -802,233 +794,52 @@ function resetInStore(store, ...params) {
|
|
|
802
794
|
}
|
|
803
795
|
|
|
804
796
|
//#endregion
|
|
805
|
-
//#region src/internal/
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const roots = /* @__PURE__ */ new Map();
|
|
823
|
-
while (dependencies.length > 0) {
|
|
824
|
-
const dependencyKey = dependencies.pop();
|
|
825
|
-
if (covered.has(dependencyKey)) continue;
|
|
826
|
-
covered.add(dependencyKey);
|
|
827
|
-
if (isAtomKey(store, dependencyKey)) {
|
|
828
|
-
const atom = store.atoms.get(dependencyKey);
|
|
829
|
-
roots.set(atom.key, atom);
|
|
830
|
-
} else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
831
|
-
}
|
|
832
|
-
return roots;
|
|
833
|
-
};
|
|
834
|
-
|
|
835
|
-
//#endregion
|
|
836
|
-
//#region src/internal/selector/update-selector-atoms.ts
|
|
837
|
-
const updateSelectorAtoms = (store, selectorType, selectorKey, dependency, covered) => {
|
|
838
|
-
const target = newest(store);
|
|
839
|
-
const { type: dependencyType, key: dependencyKey } = dependency;
|
|
840
|
-
if (dependencyType === `atom` || dependencyType === `mutable_atom`) {
|
|
841
|
-
target.selectorAtoms.set({
|
|
842
|
-
selectorKey,
|
|
843
|
-
atomKey: dependencyKey
|
|
844
|
-
});
|
|
845
|
-
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atom "${dependencyKey}"`);
|
|
846
|
-
} else {
|
|
847
|
-
const rootKeys = traceRootSelectorAtoms(store, dependencyKey, covered);
|
|
848
|
-
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atoms: [ ${[...rootKeys.values()].map((root) => `"${root.key}"`).join(`, `)} ]`);
|
|
849
|
-
for (const { key: atomKey } of rootKeys.values()) target.selectorAtoms = target.selectorAtoms.set({
|
|
850
|
-
selectorKey,
|
|
851
|
-
atomKey
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
covered.add(dependencyKey);
|
|
855
|
-
};
|
|
856
|
-
|
|
857
|
-
//#endregion
|
|
858
|
-
//#region src/internal/selector/register-selector.ts
|
|
859
|
-
const registerSelector = (store, selectorType, selectorKey, covered) => ({
|
|
860
|
-
get: (...params) => {
|
|
861
|
-
const target = newest(store);
|
|
862
|
-
let dependency;
|
|
863
|
-
if (params.length === 2) {
|
|
864
|
-
const [family, key] = params;
|
|
865
|
-
dependency = findInStore(store, family, key);
|
|
866
|
-
} else [dependency] = params;
|
|
867
|
-
const dependencyState = withdraw(store, dependency);
|
|
868
|
-
const dependencyValue = readOrComputeValue(store, dependencyState);
|
|
869
|
-
const dependencyKey = dependency.key;
|
|
870
|
-
store.logger.info(`🔌`, selectorType, selectorKey, `registers dependency ( "${dependencyKey}" =`, dependencyValue, `)`);
|
|
871
|
-
target.selectorGraph.set({
|
|
872
|
-
upstreamSelectorKey: dependencyKey,
|
|
873
|
-
downstreamSelectorKey: selectorKey
|
|
874
|
-
}, { source: dependency.key });
|
|
875
|
-
updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered);
|
|
876
|
-
return dependencyValue;
|
|
877
|
-
},
|
|
878
|
-
set: ((...params) => {
|
|
879
|
-
let token;
|
|
880
|
-
let value;
|
|
881
|
-
if (params.length === 2) {
|
|
882
|
-
token = params[0];
|
|
883
|
-
value = params[1];
|
|
884
|
-
} else {
|
|
885
|
-
const family = params[0];
|
|
886
|
-
const key = params[1];
|
|
887
|
-
value = params[2];
|
|
888
|
-
token = findInStore(store, family, key);
|
|
889
|
-
}
|
|
890
|
-
const target = newest(store);
|
|
891
|
-
const state = withdraw(target, token);
|
|
892
|
-
setAtomOrSelector(target, state, value);
|
|
893
|
-
}),
|
|
894
|
-
find: ((...args) => findInStore(store, ...args)),
|
|
895
|
-
json: (token) => getJsonToken(store, token)
|
|
896
|
-
});
|
|
897
|
-
|
|
898
|
-
//#endregion
|
|
899
|
-
//#region src/internal/selector/create-readonly-held-selector.ts
|
|
900
|
-
const createReadonlyHeldSelector = (store, options, family) => {
|
|
901
|
-
const target = newest(store);
|
|
902
|
-
const subject = new Subject();
|
|
903
|
-
const covered = /* @__PURE__ */ new Set();
|
|
904
|
-
const { key, const: constant } = options;
|
|
905
|
-
const type = `readonly_held_selector`;
|
|
906
|
-
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
907
|
-
const getSelf = () => {
|
|
908
|
-
const innerTarget = newest(store);
|
|
909
|
-
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
910
|
-
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
911
|
-
innerTarget.selectorAtoms.delete(key);
|
|
912
|
-
options.get({
|
|
913
|
-
get,
|
|
914
|
-
find,
|
|
915
|
-
json
|
|
916
|
-
}, constant);
|
|
917
|
-
writeToCache(newest(store), readonlySelector, constant);
|
|
918
|
-
covered.clear();
|
|
919
|
-
return constant;
|
|
920
|
-
};
|
|
921
|
-
const readonlySelector = {
|
|
922
|
-
...options,
|
|
923
|
-
type,
|
|
924
|
-
subject,
|
|
925
|
-
install: (s) => createReadonlyHeldSelector(s, options, family),
|
|
926
|
-
get: getSelf,
|
|
927
|
-
...family && { family }
|
|
928
|
-
};
|
|
929
|
-
target.readonlySelectors.set(key, readonlySelector);
|
|
930
|
-
store.logger.info(`✨`, type, key, `=`, constant);
|
|
931
|
-
const token = {
|
|
932
|
-
key,
|
|
933
|
-
type
|
|
934
|
-
};
|
|
935
|
-
if (family) token.family = family;
|
|
936
|
-
return token;
|
|
937
|
-
};
|
|
938
|
-
|
|
939
|
-
//#endregion
|
|
940
|
-
//#region src/internal/selector/create-readonly-pure-selector.ts
|
|
941
|
-
const createReadonlyPureSelector = (store, options, family) => {
|
|
942
|
-
const target = newest(store);
|
|
943
|
-
const subject = new Subject();
|
|
944
|
-
const covered = /* @__PURE__ */ new Set();
|
|
945
|
-
const key = options.key;
|
|
946
|
-
const type = `readonly_pure_selector`;
|
|
947
|
-
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
948
|
-
const getSelf = () => {
|
|
949
|
-
const innerTarget = newest(store);
|
|
950
|
-
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
951
|
-
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
952
|
-
innerTarget.selectorAtoms.delete(key);
|
|
953
|
-
const value = options.get({
|
|
954
|
-
get,
|
|
955
|
-
find,
|
|
956
|
-
json
|
|
957
|
-
});
|
|
958
|
-
const cached = writeToCache(innerTarget, readonlySelector, value);
|
|
959
|
-
store.logger.info(`✨`, type, key, `=`, cached);
|
|
960
|
-
covered.clear();
|
|
961
|
-
return cached;
|
|
962
|
-
};
|
|
963
|
-
const readonlySelector = {
|
|
964
|
-
...options,
|
|
965
|
-
type,
|
|
966
|
-
subject,
|
|
967
|
-
install: (s) => createReadonlyPureSelector(s, options, family),
|
|
968
|
-
get: getSelf,
|
|
969
|
-
...family && { family }
|
|
970
|
-
};
|
|
971
|
-
target.readonlySelectors.set(key, readonlySelector);
|
|
972
|
-
const token = {
|
|
973
|
-
key,
|
|
974
|
-
type
|
|
975
|
-
};
|
|
976
|
-
if (family) token.family = family;
|
|
977
|
-
return token;
|
|
978
|
-
};
|
|
979
|
-
|
|
980
|
-
//#endregion
|
|
981
|
-
//#region src/internal/transaction/abort-transaction.ts
|
|
982
|
-
const abortTransaction = (store) => {
|
|
983
|
-
const target = newest(store);
|
|
984
|
-
if (!isChildStore(target)) {
|
|
985
|
-
store.logger.warn(`🐞`, `transaction`, `???`, `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`);
|
|
986
|
-
return;
|
|
797
|
+
//#region src/internal/set-state/set-selector.ts
|
|
798
|
+
function setSelector(target, selector, next) {
|
|
799
|
+
let oldValue;
|
|
800
|
+
let newValue;
|
|
801
|
+
let constant;
|
|
802
|
+
const { type, key } = selector;
|
|
803
|
+
switch (selector.type) {
|
|
804
|
+
case `writable_pure_selector`:
|
|
805
|
+
oldValue = selector.getFrom(target);
|
|
806
|
+
newValue = become(next)(oldValue);
|
|
807
|
+
writeToCache(target, selector, newValue);
|
|
808
|
+
break;
|
|
809
|
+
case `writable_held_selector`:
|
|
810
|
+
constant = selector.const;
|
|
811
|
+
become(next)(constant);
|
|
812
|
+
oldValue = constant;
|
|
813
|
+
newValue = constant;
|
|
987
814
|
}
|
|
988
|
-
|
|
989
|
-
target
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
//#endregion
|
|
993
|
-
//#region src/internal/capitalize.ts
|
|
994
|
-
function capitalize(string) {
|
|
995
|
-
return string[0].toUpperCase() + string.slice(1);
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
//#endregion
|
|
999
|
-
//#region src/internal/pretty-print.ts
|
|
1000
|
-
function prettyPrintTokenType(token) {
|
|
1001
|
-
return token.type.split(`_`).map(capitalize).join(` `);
|
|
815
|
+
target.logger.info(`📝`, type, key, `setting to`, newValue);
|
|
816
|
+
markDone(target, key);
|
|
817
|
+
selector.setSelf(newValue);
|
|
818
|
+
return [oldValue, newValue];
|
|
1002
819
|
}
|
|
1003
820
|
|
|
1004
821
|
//#endregion
|
|
1005
|
-
//#region src/internal/
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
822
|
+
//#region src/internal/set-state/set-atom-or-selector.ts
|
|
823
|
+
const setAtomOrSelector = (target, state, value) => {
|
|
824
|
+
let protoUpdate;
|
|
825
|
+
switch (state.type) {
|
|
826
|
+
case `atom`:
|
|
827
|
+
case `mutable_atom`:
|
|
828
|
+
protoUpdate = setAtom(target, state, value);
|
|
829
|
+
break;
|
|
830
|
+
case `writable_pure_selector`:
|
|
831
|
+
case `writable_held_selector`:
|
|
832
|
+
protoUpdate = setSelector(target, state, value);
|
|
833
|
+
break;
|
|
1009
834
|
}
|
|
835
|
+
return protoUpdate;
|
|
1010
836
|
};
|
|
1011
837
|
|
|
1012
|
-
//#endregion
|
|
1013
|
-
//#region src/internal/transaction/act-upon-store.ts
|
|
1014
|
-
function actUponStore(store, token, id) {
|
|
1015
|
-
return (...parameters) => {
|
|
1016
|
-
const tx = withdraw(store, token);
|
|
1017
|
-
if (tx) return tx.run(parameters, id);
|
|
1018
|
-
throw new NotFoundError(token, store);
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
838
|
//#endregion
|
|
1023
839
|
//#region src/internal/ingest-updates/ingest-atom-update.ts
|
|
1024
840
|
function ingestAtomUpdate(applying, atomUpdate, store) {
|
|
1025
|
-
const {
|
|
841
|
+
const { token, update: { newValue, oldValue } } = atomUpdate;
|
|
1026
842
|
const value = applying === `newValue` ? newValue : oldValue;
|
|
1027
|
-
const token = {
|
|
1028
|
-
key,
|
|
1029
|
-
type: `atom`
|
|
1030
|
-
};
|
|
1031
|
-
if (atomUpdate.family) Object.assign(token, { family: atomUpdate.family });
|
|
1032
843
|
setIntoStore(store, token, value);
|
|
1033
844
|
}
|
|
1034
845
|
|
|
@@ -1076,10 +887,11 @@ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
|
1076
887
|
const creationEvent = {
|
|
1077
888
|
type: `molecule_creation`,
|
|
1078
889
|
key,
|
|
1079
|
-
provenance: origin
|
|
890
|
+
provenance: origin,
|
|
891
|
+
timestamp: Date.now()
|
|
1080
892
|
};
|
|
1081
893
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1082
|
-
if (isTransaction) target.transactionMeta.update.
|
|
894
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(creationEvent);
|
|
1083
895
|
else target.on.moleculeCreation.next(creationEvent);
|
|
1084
896
|
for (const claim of invalidKeys) {
|
|
1085
897
|
const disposal = store.disposalTraces.buffer.find((item) => item?.key === claim);
|
|
@@ -1116,12 +928,13 @@ function deallocateFromStore(store, claim) {
|
|
|
1116
928
|
type: `molecule_disposal`,
|
|
1117
929
|
key: molecule.key,
|
|
1118
930
|
values,
|
|
1119
|
-
provenance
|
|
931
|
+
provenance,
|
|
932
|
+
timestamp: Date.now()
|
|
1120
933
|
};
|
|
1121
934
|
const target = newest(store);
|
|
1122
935
|
target.molecules.delete(stringKey);
|
|
1123
936
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1124
|
-
if (isTransaction) target.transactionMeta.update.
|
|
937
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(disposalEvent);
|
|
1125
938
|
const relatedMolecules = store.moleculeGraph.getRelationEntries({ downstreamMoleculeKey: molecule.stringKey });
|
|
1126
939
|
if (relatedMolecules) for (const [relatedStringKey, { source }] of relatedMolecules) if (source === molecule.stringKey) {
|
|
1127
940
|
const relatedKey = parseJson(relatedStringKey);
|
|
@@ -1172,10 +985,11 @@ function claimWithinStore(store, newProvenance, claim, exclusive) {
|
|
|
1172
985
|
key: molecule.key,
|
|
1173
986
|
exclusive: Boolean(exclusive),
|
|
1174
987
|
from: priorProvenance,
|
|
1175
|
-
to: [newProvenanceMolecule.key]
|
|
988
|
+
to: [newProvenanceMolecule.key],
|
|
989
|
+
timestamp: Date.now()
|
|
1176
990
|
};
|
|
1177
991
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1178
|
-
if (isTransaction) target.transactionMeta.update.
|
|
992
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(transferEvent);
|
|
1179
993
|
return claim;
|
|
1180
994
|
}
|
|
1181
995
|
|
|
@@ -1269,10 +1083,9 @@ function ingestSelectorUpdate(applying, selectorUpdate, store) {
|
|
|
1269
1083
|
//#endregion
|
|
1270
1084
|
//#region src/internal/ingest-updates/ingest-transaction-update.ts
|
|
1271
1085
|
function ingestTransactionUpdate(applying, transactionUpdate, store) {
|
|
1272
|
-
const updates = applying === `newValue` ? transactionUpdate.
|
|
1086
|
+
const updates = applying === `newValue` ? transactionUpdate.subEvents : [...transactionUpdate.subEvents].reverse();
|
|
1273
1087
|
for (const updateFromTransaction of updates) switch (updateFromTransaction.type) {
|
|
1274
1088
|
case `atom_update`:
|
|
1275
|
-
case `selector_update`:
|
|
1276
1089
|
ingestAtomUpdate(applying, updateFromTransaction, store);
|
|
1277
1090
|
break;
|
|
1278
1091
|
case `state_creation`:
|
|
@@ -1290,7 +1103,7 @@ function ingestTransactionUpdate(applying, transactionUpdate, store) {
|
|
|
1290
1103
|
case `molecule_transfer`:
|
|
1291
1104
|
ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
|
|
1292
1105
|
break;
|
|
1293
|
-
case `
|
|
1106
|
+
case `transaction_outcome`:
|
|
1294
1107
|
ingestTransactionUpdate(applying, updateFromTransaction, store);
|
|
1295
1108
|
break;
|
|
1296
1109
|
}
|
|
@@ -1340,18 +1153,18 @@ const applyTransaction = (output, store) => {
|
|
|
1340
1153
|
child.transactionMeta.update.output = output;
|
|
1341
1154
|
parent.child = null;
|
|
1342
1155
|
parent.on.transactionApplying.next(child.transactionMeta);
|
|
1343
|
-
const { updates } = child.transactionMeta.update;
|
|
1344
|
-
store.logger.info(`🛄`, `transaction`, child.transactionMeta.update.key, `Applying transaction with ${updates.length} updates:`, updates);
|
|
1156
|
+
const { subEvents: updates } = child.transactionMeta.update;
|
|
1157
|
+
store.logger.info(`🛄`, `transaction`, child.transactionMeta.update.token.key, `Applying transaction with ${updates.length} updates:`, updates);
|
|
1345
1158
|
ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
|
|
1346
1159
|
if (isRootStore(parent)) {
|
|
1347
|
-
setEpochNumberOfAction(parent, child.transactionMeta.update.key, child.transactionMeta.update.epoch);
|
|
1160
|
+
setEpochNumberOfAction(parent, child.transactionMeta.update.token.key, child.transactionMeta.update.epoch);
|
|
1348
1161
|
const myTransaction = withdraw(store, {
|
|
1349
|
-
key: child.transactionMeta.update.key,
|
|
1162
|
+
key: child.transactionMeta.update.token.key,
|
|
1350
1163
|
type: `transaction`
|
|
1351
1164
|
});
|
|
1352
1165
|
myTransaction?.subject.next(child.transactionMeta.update);
|
|
1353
|
-
store.logger.info(`🛬`, `transaction`, child.transactionMeta.update.key, `Finished applying transaction.`);
|
|
1354
|
-
} else if (isChildStore(parent)) parent.transactionMeta.update.
|
|
1166
|
+
store.logger.info(`🛬`, `transaction`, child.transactionMeta.update.token.key, `Finished applying transaction.`);
|
|
1167
|
+
} else if (isChildStore(parent)) parent.transactionMeta.update.subEvents.push(child.transactionMeta.update);
|
|
1355
1168
|
parent.on.transactionApplying.next(null);
|
|
1356
1169
|
};
|
|
1357
1170
|
|
|
@@ -1407,7 +1220,7 @@ var LazyMap = class extends Map {
|
|
|
1407
1220
|
|
|
1408
1221
|
//#endregion
|
|
1409
1222
|
//#region src/internal/transaction/build-transaction.ts
|
|
1410
|
-
const buildTransaction = (store,
|
|
1223
|
+
const buildTransaction = (store, token, params, id) => {
|
|
1411
1224
|
const parent = newest(store);
|
|
1412
1225
|
const childBase = {
|
|
1413
1226
|
parent,
|
|
@@ -1438,15 +1251,16 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1438
1251
|
moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), { makeContentKey: parent.moleculeJoins.makeContentKey }),
|
|
1439
1252
|
miscResources: new LazyMap(parent.miscResources)
|
|
1440
1253
|
};
|
|
1441
|
-
const epoch = getEpochNumberOfAction(store, key);
|
|
1254
|
+
const epoch = getEpochNumberOfAction(store, token.key);
|
|
1442
1255
|
const transactionMeta = {
|
|
1443
1256
|
phase: `building`,
|
|
1444
1257
|
update: {
|
|
1445
|
-
type: `
|
|
1446
|
-
|
|
1258
|
+
type: `transaction_outcome`,
|
|
1259
|
+
token,
|
|
1447
1260
|
id,
|
|
1448
1261
|
epoch: epoch === void 0 ? NaN : epoch + 1,
|
|
1449
|
-
|
|
1262
|
+
timestamp: Date.now(),
|
|
1263
|
+
subEvents: [],
|
|
1450
1264
|
params,
|
|
1451
1265
|
output: void 0
|
|
1452
1266
|
},
|
|
@@ -1458,9 +1272,9 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1458
1272
|
reset: ((...ps) => {
|
|
1459
1273
|
resetInStore(child, ...ps);
|
|
1460
1274
|
}),
|
|
1461
|
-
run: (
|
|
1275
|
+
run: (t, identifier = arbitrary()) => actUponStore(child, t, identifier),
|
|
1462
1276
|
find: ((...ps) => findInStore(store, ...ps)),
|
|
1463
|
-
json: (
|
|
1277
|
+
json: (t) => getJsonToken(child, t),
|
|
1464
1278
|
dispose: ((...ps) => {
|
|
1465
1279
|
disposeFromStore(child, ...ps);
|
|
1466
1280
|
}),
|
|
@@ -1469,7 +1283,7 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1469
1283
|
};
|
|
1470
1284
|
const child = Object.assign(childBase, { transactionMeta });
|
|
1471
1285
|
parent.child = child;
|
|
1472
|
-
store.logger.info(`🛫`, `transaction`, key, `Building transaction with params:`, params);
|
|
1286
|
+
store.logger.info(`🛫`, `transaction`, token.key, `Building transaction with params:`, params);
|
|
1473
1287
|
return child;
|
|
1474
1288
|
};
|
|
1475
1289
|
|
|
@@ -1482,7 +1296,8 @@ function createTransaction(store, options) {
|
|
|
1482
1296
|
key,
|
|
1483
1297
|
type: `transaction`,
|
|
1484
1298
|
run: (params, id) => {
|
|
1485
|
-
const
|
|
1299
|
+
const token$1 = deposit(newTransaction);
|
|
1300
|
+
const childStore = buildTransaction(store, token$1, params, id);
|
|
1486
1301
|
try {
|
|
1487
1302
|
const target$1 = newest(store);
|
|
1488
1303
|
const { toolkit } = childStore.transactionMeta;
|
|
@@ -1513,9 +1328,279 @@ const TRANSACTION_PHASES = [
|
|
|
1513
1328
|
`applying`
|
|
1514
1329
|
];
|
|
1515
1330
|
|
|
1331
|
+
//#endregion
|
|
1332
|
+
//#region src/internal/families/init-family-member.ts
|
|
1333
|
+
function initFamilyMemberInStore(store, token, key) {
|
|
1334
|
+
const family = withdraw(store, token);
|
|
1335
|
+
const state = family(key);
|
|
1336
|
+
return state;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
//#endregion
|
|
1340
|
+
//#region src/internal/families/mint-in-store.ts
|
|
1341
|
+
function mintInStore(store, familyToken, key) {
|
|
1342
|
+
const stringKey = stringifyJson(key);
|
|
1343
|
+
const molecule = store.molecules.get(stringKey);
|
|
1344
|
+
if (!molecule && store.config.lifespan === `immortal`) {
|
|
1345
|
+
const fakeToken = counterfeit(familyToken, key);
|
|
1346
|
+
store.logger.error(`❌`, fakeToken.type, fakeToken.key, `was not found in store "${store.config.name}"; returned a counterfeit token.`);
|
|
1347
|
+
return fakeToken;
|
|
1348
|
+
}
|
|
1349
|
+
const newStateToken = initFamilyMemberInStore(store, familyToken, key);
|
|
1350
|
+
const target = newest(store);
|
|
1351
|
+
if (newStateToken.family) {
|
|
1352
|
+
if (isRootStore(target)) switch (newStateToken.type) {
|
|
1353
|
+
case `atom`:
|
|
1354
|
+
case `mutable_atom`:
|
|
1355
|
+
store.on.atomCreation.next(newStateToken);
|
|
1356
|
+
break;
|
|
1357
|
+
case `writable_pure_selector`:
|
|
1358
|
+
case `readonly_pure_selector`:
|
|
1359
|
+
case `writable_held_selector`:
|
|
1360
|
+
case `readonly_held_selector`:
|
|
1361
|
+
store.on.selectorCreation.next(newStateToken);
|
|
1362
|
+
break;
|
|
1363
|
+
}
|
|
1364
|
+
else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.subEvents.push({
|
|
1365
|
+
type: `state_creation`,
|
|
1366
|
+
token: newStateToken,
|
|
1367
|
+
timestamp: Date.now()
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
if (molecule) target.moleculeData.set(stringKey, familyToken.key);
|
|
1371
|
+
return newStateToken;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
//#endregion
|
|
1375
|
+
//#region src/internal/set-state/operate-on-store.ts
|
|
1376
|
+
function operateOnStore(store, ownOp, ...params) {
|
|
1377
|
+
let existingToken;
|
|
1378
|
+
let brandNewToken;
|
|
1379
|
+
let token;
|
|
1380
|
+
let family;
|
|
1381
|
+
let key;
|
|
1382
|
+
let value;
|
|
1383
|
+
if (params.length === 2) {
|
|
1384
|
+
token = params[0];
|
|
1385
|
+
value = params[1];
|
|
1386
|
+
if (token.family) {
|
|
1387
|
+
family = getFamilyOfToken(store, token);
|
|
1388
|
+
key = parseJson(token.family.subKey);
|
|
1389
|
+
existingToken = seekInStore(store, family, key);
|
|
1390
|
+
if (!existingToken) {
|
|
1391
|
+
brandNewToken = mintInStore(store, family, key);
|
|
1392
|
+
token = brandNewToken;
|
|
1393
|
+
} else token = existingToken;
|
|
1394
|
+
}
|
|
1395
|
+
} else {
|
|
1396
|
+
family = params[0];
|
|
1397
|
+
key = params[1];
|
|
1398
|
+
value = params[2];
|
|
1399
|
+
existingToken = seekInStore(store, family, key);
|
|
1400
|
+
if (!existingToken) {
|
|
1401
|
+
brandNewToken = mintInStore(store, family, key);
|
|
1402
|
+
token = brandNewToken;
|
|
1403
|
+
} else token = existingToken;
|
|
1404
|
+
}
|
|
1405
|
+
const action = value === RESET_STATE ? `reset` : `set`;
|
|
1406
|
+
let target;
|
|
1407
|
+
if (ownOp) {
|
|
1408
|
+
const result = openOperation(store, token);
|
|
1409
|
+
const rejected = typeof result === `number`;
|
|
1410
|
+
if (rejected) {
|
|
1411
|
+
const rejectionTime = result;
|
|
1412
|
+
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
1413
|
+
unsubscribe();
|
|
1414
|
+
store.logger.info(`🟢`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
1415
|
+
operateOnStore(store, ownOp, token, value);
|
|
1416
|
+
});
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
target = result;
|
|
1420
|
+
} else target = store;
|
|
1421
|
+
if (`counterfeit` in token && `family` in token) {
|
|
1422
|
+
const subKey = token.family.subKey;
|
|
1423
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
1424
|
+
store.logger.error(`❌`, token.type, token.key, `could not be`, action, `because it was not found in the store "${store.config.name}".`, disposal ? `This state was previously disposed:\n${disposal.trace}` : `No previous disposal trace was found.`);
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
const state = withdraw(target, token);
|
|
1428
|
+
let protoUpdate;
|
|
1429
|
+
if (value === RESET_STATE) protoUpdate = resetAtomOrSelector(target, state);
|
|
1430
|
+
else protoUpdate = setAtomOrSelector(target, state, value);
|
|
1431
|
+
const isNewlyCreated = Boolean(brandNewToken);
|
|
1432
|
+
dispatchOrDeferStateUpdate(target, state, protoUpdate, isNewlyCreated);
|
|
1433
|
+
if (ownOp) closeOperation(target);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
//#endregion
|
|
1437
|
+
//#region src/internal/keys.ts
|
|
1438
|
+
const isAtomKey = (store, key) => newest(store).atoms.has(key);
|
|
1439
|
+
const isSelectorKey = (store, key) => newest(store).writableSelectors.has(key);
|
|
1440
|
+
const isReadonlySelectorKey = (store, key) => newest(store).readonlySelectors.has(key);
|
|
1441
|
+
const isStateKey = (store, key) => isAtomKey(store, key) || isSelectorKey(store, key) || isReadonlySelectorKey(store, key);
|
|
1442
|
+
|
|
1443
|
+
//#endregion
|
|
1444
|
+
//#region src/internal/selector/get-selector-dependency-keys.ts
|
|
1445
|
+
function getSelectorDependencyKeys(store, key) {
|
|
1446
|
+
const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(store, source));
|
|
1447
|
+
return sources;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
//#endregion
|
|
1451
|
+
//#region src/internal/selector/trace-selector-atoms.ts
|
|
1452
|
+
function traceRootSelectorAtoms(store, selectorKey, covered = /* @__PURE__ */ new Set()) {
|
|
1453
|
+
const dependencies = getSelectorDependencyKeys(store, selectorKey);
|
|
1454
|
+
const roots = /* @__PURE__ */ new Map();
|
|
1455
|
+
while (dependencies.length > 0) {
|
|
1456
|
+
const dependencyKey = dependencies.pop();
|
|
1457
|
+
if (covered.has(dependencyKey)) continue;
|
|
1458
|
+
covered.add(dependencyKey);
|
|
1459
|
+
if (isAtomKey(store, dependencyKey)) {
|
|
1460
|
+
const atom = store.atoms.get(dependencyKey);
|
|
1461
|
+
roots.set(atom.key, atom);
|
|
1462
|
+
} else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
1463
|
+
}
|
|
1464
|
+
return roots;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
//#endregion
|
|
1468
|
+
//#region src/internal/selector/update-selector-atoms.ts
|
|
1469
|
+
function updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered) {
|
|
1470
|
+
const target = newest(store);
|
|
1471
|
+
const { type: dependencyType, key: dependencyKey } = dependency;
|
|
1472
|
+
if (dependencyType === `atom` || dependencyType === `mutable_atom`) {
|
|
1473
|
+
target.selectorAtoms.set({
|
|
1474
|
+
selectorKey,
|
|
1475
|
+
atomKey: dependencyKey
|
|
1476
|
+
});
|
|
1477
|
+
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atom "${dependencyKey}"`);
|
|
1478
|
+
} else {
|
|
1479
|
+
const rootKeys = traceRootSelectorAtoms(store, dependencyKey, covered);
|
|
1480
|
+
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atoms: [ ${[...rootKeys.values()].map((root) => `"${root.key}"`).join(`, `)} ]`);
|
|
1481
|
+
for (const { key: atomKey } of rootKeys.values()) target.selectorAtoms = target.selectorAtoms.set({
|
|
1482
|
+
selectorKey,
|
|
1483
|
+
atomKey
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
covered.add(dependencyKey);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
//#endregion
|
|
1490
|
+
//#region src/internal/selector/register-selector.ts
|
|
1491
|
+
function registerSelector(store, selectorType, selectorKey, covered) {
|
|
1492
|
+
return {
|
|
1493
|
+
get: (...params) => {
|
|
1494
|
+
const target = newest(store);
|
|
1495
|
+
let dependency;
|
|
1496
|
+
if (params.length === 2) {
|
|
1497
|
+
const [family, key] = params;
|
|
1498
|
+
dependency = findInStore(store, family, key);
|
|
1499
|
+
} else [dependency] = params;
|
|
1500
|
+
const dependencyState = withdraw(store, dependency);
|
|
1501
|
+
const dependencyValue = readOrComputeValue(store, dependencyState);
|
|
1502
|
+
const dependencyKey = dependency.key;
|
|
1503
|
+
store.logger.info(`🔌`, selectorType, selectorKey, `registers dependency ( "${dependencyKey}" =`, dependencyValue, `)`);
|
|
1504
|
+
target.selectorGraph.set({
|
|
1505
|
+
upstreamSelectorKey: dependencyKey,
|
|
1506
|
+
downstreamSelectorKey: selectorKey
|
|
1507
|
+
}, { source: dependency.key });
|
|
1508
|
+
updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered);
|
|
1509
|
+
return dependencyValue;
|
|
1510
|
+
},
|
|
1511
|
+
set: ((...params) => {
|
|
1512
|
+
const target = newest(store);
|
|
1513
|
+
operateOnStore(target, false, ...params);
|
|
1514
|
+
}),
|
|
1515
|
+
find: ((...args) => findInStore(store, ...args)),
|
|
1516
|
+
json: (token) => getJsonToken(store, token)
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
//#endregion
|
|
1521
|
+
//#region src/internal/selector/create-readonly-held-selector.ts
|
|
1522
|
+
function createReadonlyHeldSelector(store, options, family) {
|
|
1523
|
+
const target = newest(store);
|
|
1524
|
+
const subject = new Subject();
|
|
1525
|
+
const covered = /* @__PURE__ */ new Set();
|
|
1526
|
+
const { key, const: constant } = options;
|
|
1527
|
+
const type = `readonly_held_selector`;
|
|
1528
|
+
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
1529
|
+
const getFrom = (innerTarget) => {
|
|
1530
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1531
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1532
|
+
innerTarget.selectorAtoms.delete(key);
|
|
1533
|
+
options.get({
|
|
1534
|
+
get,
|
|
1535
|
+
find,
|
|
1536
|
+
json
|
|
1537
|
+
}, constant);
|
|
1538
|
+
writeToCache(innerTarget, readonlySelector, constant);
|
|
1539
|
+
covered.clear();
|
|
1540
|
+
return constant;
|
|
1541
|
+
};
|
|
1542
|
+
const readonlySelector = {
|
|
1543
|
+
...options,
|
|
1544
|
+
type,
|
|
1545
|
+
subject,
|
|
1546
|
+
getFrom,
|
|
1547
|
+
install: (s) => createReadonlyHeldSelector(s, options, family)
|
|
1548
|
+
};
|
|
1549
|
+
if (family) readonlySelector.family = family;
|
|
1550
|
+
target.readonlySelectors.set(key, readonlySelector);
|
|
1551
|
+
store.logger.info(`✨`, type, key, `=`, constant);
|
|
1552
|
+
const token = {
|
|
1553
|
+
key,
|
|
1554
|
+
type
|
|
1555
|
+
};
|
|
1556
|
+
if (family) token.family = family;
|
|
1557
|
+
return token;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
//#endregion
|
|
1561
|
+
//#region src/internal/selector/create-readonly-pure-selector.ts
|
|
1562
|
+
function createReadonlyPureSelector(store, options, family) {
|
|
1563
|
+
const target = newest(store);
|
|
1564
|
+
const subject = new Subject();
|
|
1565
|
+
const covered = /* @__PURE__ */ new Set();
|
|
1566
|
+
const key = options.key;
|
|
1567
|
+
const type = `readonly_pure_selector`;
|
|
1568
|
+
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
1569
|
+
const getFrom = () => {
|
|
1570
|
+
const innerTarget = newest(store);
|
|
1571
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1572
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1573
|
+
innerTarget.selectorAtoms.delete(key);
|
|
1574
|
+
const value = options.get({
|
|
1575
|
+
get,
|
|
1576
|
+
find,
|
|
1577
|
+
json
|
|
1578
|
+
});
|
|
1579
|
+
const cached = writeToCache(innerTarget, readonlySelector, value);
|
|
1580
|
+
store.logger.info(`✨`, type, key, `=`, cached);
|
|
1581
|
+
covered.clear();
|
|
1582
|
+
return cached;
|
|
1583
|
+
};
|
|
1584
|
+
const readonlySelector = {
|
|
1585
|
+
...options,
|
|
1586
|
+
type,
|
|
1587
|
+
subject,
|
|
1588
|
+
getFrom,
|
|
1589
|
+
install: (s) => createReadonlyPureSelector(s, options, family)
|
|
1590
|
+
};
|
|
1591
|
+
if (family) readonlySelector.family = family;
|
|
1592
|
+
target.readonlySelectors.set(key, readonlySelector);
|
|
1593
|
+
const token = {
|
|
1594
|
+
key,
|
|
1595
|
+
type
|
|
1596
|
+
};
|
|
1597
|
+
if (family) token.family = family;
|
|
1598
|
+
return token;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1516
1601
|
//#endregion
|
|
1517
1602
|
//#region src/internal/selector/create-writable-held-selector.ts
|
|
1518
|
-
|
|
1603
|
+
function createWritableHeldSelector(store, options, family) {
|
|
1519
1604
|
const target = newest(store);
|
|
1520
1605
|
const subject = new Subject();
|
|
1521
1606
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -1528,38 +1613,28 @@ const createWritableHeldSelector = (store, options, family) => {
|
|
|
1528
1613
|
get,
|
|
1529
1614
|
json
|
|
1530
1615
|
};
|
|
1531
|
-
const
|
|
1616
|
+
const getFrom = (innerTarget) => {
|
|
1532
1617
|
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1533
1618
|
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1534
1619
|
innerTarget.selectorAtoms.delete(key);
|
|
1535
|
-
|
|
1620
|
+
options.get(getterToolkit, constant);
|
|
1536
1621
|
writeToCache(innerTarget, mySelector, constant);
|
|
1537
1622
|
store.logger.info(`✨`, type, key, `=`, constant);
|
|
1538
1623
|
covered.clear();
|
|
1539
1624
|
return constant;
|
|
1540
1625
|
};
|
|
1541
|
-
const setSelf = (
|
|
1542
|
-
|
|
1543
|
-
const oldValue = getSelf(options.get, innerTarget);
|
|
1544
|
-
const newValue = become(next)(oldValue);
|
|
1545
|
-
store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
|
|
1546
|
-
writeToCache(innerTarget, mySelector, newValue);
|
|
1547
|
-
markDone(innerTarget, key);
|
|
1548
|
-
if (isRootStore(innerTarget)) subject.next({
|
|
1549
|
-
newValue,
|
|
1550
|
-
oldValue
|
|
1551
|
-
});
|
|
1552
|
-
options.set(setterToolkit, newValue);
|
|
1626
|
+
const setSelf = () => {
|
|
1627
|
+
options.set(setterToolkit, constant);
|
|
1553
1628
|
};
|
|
1554
1629
|
const mySelector = {
|
|
1555
1630
|
...options,
|
|
1556
1631
|
type,
|
|
1557
1632
|
subject,
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
...family && { family }
|
|
1633
|
+
getFrom,
|
|
1634
|
+
setSelf,
|
|
1635
|
+
install: (s) => createWritableHeldSelector(s, options, family)
|
|
1562
1636
|
};
|
|
1637
|
+
if (family) mySelector.family = family;
|
|
1563
1638
|
target.writableSelectors.set(key, mySelector);
|
|
1564
1639
|
const token = {
|
|
1565
1640
|
key,
|
|
@@ -1567,11 +1642,11 @@ const createWritableHeldSelector = (store, options, family) => {
|
|
|
1567
1642
|
};
|
|
1568
1643
|
if (family) token.family = family;
|
|
1569
1644
|
return token;
|
|
1570
|
-
}
|
|
1645
|
+
}
|
|
1571
1646
|
|
|
1572
1647
|
//#endregion
|
|
1573
1648
|
//#region src/internal/selector/create-writable-pure-selector.ts
|
|
1574
|
-
|
|
1649
|
+
function createWritablePureSelector(store, options, family) {
|
|
1575
1650
|
const target = newest(store);
|
|
1576
1651
|
const subject = new Subject();
|
|
1577
1652
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -1584,40 +1659,30 @@ const createWritablePureSelector = (store, options, family) => {
|
|
|
1584
1659
|
get,
|
|
1585
1660
|
json
|
|
1586
1661
|
};
|
|
1587
|
-
const
|
|
1662
|
+
const getFrom = (innerTarget) => {
|
|
1588
1663
|
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1589
1664
|
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1590
1665
|
innerTarget.selectorAtoms.delete(key);
|
|
1591
|
-
const value =
|
|
1666
|
+
const value = options.get(getterToolkit);
|
|
1592
1667
|
const cached = writeToCache(innerTarget, mySelector, value);
|
|
1593
1668
|
store.logger.info(`✨`, type, key, `=`, cached);
|
|
1594
1669
|
covered.clear();
|
|
1595
1670
|
return cached;
|
|
1596
1671
|
};
|
|
1597
|
-
const setSelf = (
|
|
1598
|
-
const innerTarget = newest(store);
|
|
1599
|
-
const oldValue = getSelf(options.get, innerTarget);
|
|
1600
|
-
const newValue = become(next)(oldValue);
|
|
1601
|
-
store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
|
|
1602
|
-
writeToCache(innerTarget, mySelector, newValue);
|
|
1603
|
-
markDone(innerTarget, options.key);
|
|
1604
|
-
if (isRootStore(innerTarget)) subject.next({
|
|
1605
|
-
newValue,
|
|
1606
|
-
oldValue
|
|
1607
|
-
});
|
|
1672
|
+
const setSelf = (newValue) => {
|
|
1608
1673
|
options.set(setterToolkit, newValue);
|
|
1609
1674
|
};
|
|
1610
1675
|
const mySelector = {
|
|
1611
1676
|
...options,
|
|
1612
1677
|
type,
|
|
1613
1678
|
subject,
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
...family && { family }
|
|
1679
|
+
getFrom,
|
|
1680
|
+
setSelf,
|
|
1681
|
+
install: (s) => createWritablePureSelector(s, options, family)
|
|
1618
1682
|
};
|
|
1683
|
+
if (family) mySelector.family = family;
|
|
1619
1684
|
target.writableSelectors.set(key, mySelector);
|
|
1620
|
-
const initialValue =
|
|
1685
|
+
const initialValue = getFrom(target);
|
|
1621
1686
|
store.logger.info(`✨`, mySelector.type, mySelector.key, `=`, initialValue);
|
|
1622
1687
|
const token = {
|
|
1623
1688
|
key,
|
|
@@ -1625,7 +1690,7 @@ const createWritablePureSelector = (store, options, family) => {
|
|
|
1625
1690
|
};
|
|
1626
1691
|
if (family) token.family = family;
|
|
1627
1692
|
return token;
|
|
1628
|
-
}
|
|
1693
|
+
}
|
|
1629
1694
|
|
|
1630
1695
|
//#endregion
|
|
1631
1696
|
//#region src/internal/selector/create-standalone-selector.ts
|
|
@@ -1674,7 +1739,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1674
1739
|
family.subject.next({
|
|
1675
1740
|
type: `state_disposal`,
|
|
1676
1741
|
subType: `selector`,
|
|
1677
|
-
token: selectorToken
|
|
1742
|
+
token: selectorToken,
|
|
1743
|
+
timestamp: Date.now()
|
|
1678
1744
|
});
|
|
1679
1745
|
}
|
|
1680
1746
|
break;
|
|
@@ -1689,7 +1755,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1689
1755
|
family.subject.next({
|
|
1690
1756
|
type: `state_disposal`,
|
|
1691
1757
|
subType: `selector`,
|
|
1692
|
-
token: selectorToken
|
|
1758
|
+
token: selectorToken,
|
|
1759
|
+
timestamp: Date.now()
|
|
1693
1760
|
});
|
|
1694
1761
|
}
|
|
1695
1762
|
break;
|
|
@@ -1704,7 +1771,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1704
1771
|
family.subject.next({
|
|
1705
1772
|
type: `state_disposal`,
|
|
1706
1773
|
subType: `selector`,
|
|
1707
|
-
token: selectorToken
|
|
1774
|
+
token: selectorToken,
|
|
1775
|
+
timestamp: Date.now()
|
|
1708
1776
|
});
|
|
1709
1777
|
}
|
|
1710
1778
|
break;
|
|
@@ -1719,7 +1787,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1719
1787
|
family.subject.next({
|
|
1720
1788
|
type: `state_disposal`,
|
|
1721
1789
|
subType: `selector`,
|
|
1722
|
-
token: selectorToken
|
|
1790
|
+
token: selectorToken,
|
|
1791
|
+
timestamp: Date.now()
|
|
1723
1792
|
});
|
|
1724
1793
|
}
|
|
1725
1794
|
break;
|
|
@@ -1729,10 +1798,11 @@ function disposeSelector(store, selectorToken) {
|
|
|
1729
1798
|
target.selectorGraph.delete(key);
|
|
1730
1799
|
target.moleculeData.delete(familyMeta.key, familyMeta.subKey);
|
|
1731
1800
|
store.logger.info(`🔥`, selectorToken.type, key, `deleted`);
|
|
1732
|
-
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.
|
|
1801
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.subEvents.push({
|
|
1733
1802
|
type: `state_disposal`,
|
|
1734
1803
|
subType: `selector`,
|
|
1735
|
-
token: selectorToken
|
|
1804
|
+
token: selectorToken,
|
|
1805
|
+
timestamp: Date.now()
|
|
1736
1806
|
});
|
|
1737
1807
|
else store.on.selectorDisposal.next(selectorToken);
|
|
1738
1808
|
}
|
|
@@ -1764,7 +1834,8 @@ function createReadonlyPureSelectorFamily(store, options, internalRoles) {
|
|
|
1764
1834
|
}, family);
|
|
1765
1835
|
subject.next({
|
|
1766
1836
|
type: `state_creation`,
|
|
1767
|
-
token
|
|
1837
|
+
token,
|
|
1838
|
+
timestamp: Date.now()
|
|
1768
1839
|
});
|
|
1769
1840
|
return token;
|
|
1770
1841
|
};
|
|
@@ -1812,7 +1883,8 @@ function createRegularAtomFamily(store, options, internalRoles) {
|
|
|
1812
1883
|
const token = createRegularAtom(target, individualOptions, family);
|
|
1813
1884
|
subject.next({
|
|
1814
1885
|
type: `state_creation`,
|
|
1815
|
-
token
|
|
1886
|
+
token,
|
|
1887
|
+
timestamp: Date.now()
|
|
1816
1888
|
});
|
|
1817
1889
|
return token;
|
|
1818
1890
|
};
|
|
@@ -1853,7 +1925,8 @@ function createReadonlyHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1853
1925
|
}, family);
|
|
1854
1926
|
subject.next({
|
|
1855
1927
|
type: `state_creation`,
|
|
1856
|
-
token
|
|
1928
|
+
token,
|
|
1929
|
+
timestamp: Date.now()
|
|
1857
1930
|
});
|
|
1858
1931
|
return token;
|
|
1859
1932
|
};
|
|
@@ -1895,7 +1968,8 @@ function createWritableHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1895
1968
|
}, family);
|
|
1896
1969
|
subject.next({
|
|
1897
1970
|
type: `state_creation`,
|
|
1898
|
-
token
|
|
1971
|
+
token,
|
|
1972
|
+
timestamp: Date.now()
|
|
1899
1973
|
});
|
|
1900
1974
|
return token;
|
|
1901
1975
|
};
|
|
@@ -1936,7 +2010,8 @@ function createWritablePureSelectorFamily(store, options, internalRoles) {
|
|
|
1936
2010
|
}, family);
|
|
1937
2011
|
subject.next({
|
|
1938
2012
|
type: `state_creation`,
|
|
1939
|
-
token
|
|
2013
|
+
token,
|
|
2014
|
+
timestamp: Date.now()
|
|
1940
2015
|
});
|
|
1941
2016
|
return token;
|
|
1942
2017
|
};
|
|
@@ -1968,34 +2043,6 @@ function createSelectorFamily(store, options) {
|
|
|
1968
2043
|
return createReadonlyPureSelectorFamily(store, options);
|
|
1969
2044
|
}
|
|
1970
2045
|
|
|
1971
|
-
//#endregion
|
|
1972
|
-
//#region src/internal/families/init-family-member.ts
|
|
1973
|
-
function initFamilyMemberInStore(store, token, key) {
|
|
1974
|
-
const family = store.families.get(token.key);
|
|
1975
|
-
if (family === void 0) throw new NotFoundError(token, store);
|
|
1976
|
-
const state = family(key);
|
|
1977
|
-
const target = newest(store);
|
|
1978
|
-
if (state.family) {
|
|
1979
|
-
if (isRootStore(target)) switch (state.type) {
|
|
1980
|
-
case `atom`:
|
|
1981
|
-
case `mutable_atom`:
|
|
1982
|
-
store.on.atomCreation.next(state);
|
|
1983
|
-
break;
|
|
1984
|
-
case `writable_pure_selector`:
|
|
1985
|
-
case `readonly_pure_selector`:
|
|
1986
|
-
case `writable_held_selector`:
|
|
1987
|
-
case `readonly_held_selector`:
|
|
1988
|
-
store.on.selectorCreation.next(state);
|
|
1989
|
-
break;
|
|
1990
|
-
}
|
|
1991
|
-
else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.updates.push({
|
|
1992
|
-
type: `state_creation`,
|
|
1993
|
-
token: state
|
|
1994
|
-
});
|
|
1995
|
-
}
|
|
1996
|
-
return state;
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
2046
|
//#endregion
|
|
2000
2047
|
//#region src/internal/families/seek-in-store.ts
|
|
2001
2048
|
function seekInStore(store, token, key) {
|
|
@@ -2023,22 +2070,11 @@ function seekInStore(store, token, key) {
|
|
|
2023
2070
|
|
|
2024
2071
|
//#endregion
|
|
2025
2072
|
//#region src/internal/families/find-in-store.ts
|
|
2026
|
-
function findInStore(store,
|
|
2027
|
-
|
|
2028
|
-
if (
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2031
|
-
if (!molecule && store.config.lifespan === `immortal`) {
|
|
2032
|
-
const fakeToken = counterfeit(token, key);
|
|
2033
|
-
store.logger.error(`❌`, fakeToken.type, fakeToken.key, `was not found in store "${store.config.name}"; returned a counterfeit token.`);
|
|
2034
|
-
return fakeToken;
|
|
2035
|
-
}
|
|
2036
|
-
state = initFamilyMemberInStore(store, token, key);
|
|
2037
|
-
if (molecule) {
|
|
2038
|
-
const target = newest(store);
|
|
2039
|
-
target.moleculeData.set(stringKey, token.key);
|
|
2040
|
-
}
|
|
2041
|
-
return state;
|
|
2073
|
+
function findInStore(store, familyToken, key) {
|
|
2074
|
+
const existingStateToken = seekInStore(store, familyToken, key);
|
|
2075
|
+
if (existingStateToken) return existingStateToken;
|
|
2076
|
+
const newStateToken = mintInStore(store, familyToken, key);
|
|
2077
|
+
return newStateToken;
|
|
2042
2078
|
}
|
|
2043
2079
|
|
|
2044
2080
|
//#endregion
|
|
@@ -2273,7 +2309,7 @@ var Tracker = class {
|
|
|
2273
2309
|
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
2274
2310
|
const stateKey = mutableState.key;
|
|
2275
2311
|
const storeName = target.config.name;
|
|
2276
|
-
const storeStatus = isChildStore(target) ? target.transactionMeta.update.key : `main`;
|
|
2312
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
2277
2313
|
const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`;
|
|
2278
2314
|
const trackerCapturesOutboundSignal = (update) => {
|
|
2279
2315
|
setIntoStore(target, latestSignalState, update);
|
|
@@ -2288,7 +2324,7 @@ var Tracker = class {
|
|
|
2288
2324
|
}.bind(this));
|
|
2289
2325
|
}
|
|
2290
2326
|
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
2291
|
-
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
|
|
2327
|
+
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.token.key : `main`}:${mutableState.key}`;
|
|
2292
2328
|
subscribeToState(target, latestSignalState, subscriptionKey, function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
2293
2329
|
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
2294
2330
|
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
@@ -2452,7 +2488,8 @@ function createMutableAtomFamily(store, options, internalRoles) {
|
|
|
2452
2488
|
const token = createMutableAtom(target, individualOptions, family);
|
|
2453
2489
|
subject.next({
|
|
2454
2490
|
type: `state_creation`,
|
|
2455
|
-
token
|
|
2491
|
+
token,
|
|
2492
|
+
timestamp: Date.now()
|
|
2456
2493
|
});
|
|
2457
2494
|
return token;
|
|
2458
2495
|
};
|
|
@@ -2531,7 +2568,7 @@ const getUpdateToken = (mutableAtomToken) => {
|
|
|
2531
2568
|
//#endregion
|
|
2532
2569
|
//#region src/internal/mutable/transceiver.ts
|
|
2533
2570
|
function isTransceiver(value) {
|
|
2534
|
-
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
|
|
2571
|
+
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value && `cacheUpdateNumber` in value && `getUpdateNumber` in value && `READONLY_VIEW` in value && `toJSON` in value;
|
|
2535
2572
|
}
|
|
2536
2573
|
|
|
2537
2574
|
//#endregion
|
|
@@ -2731,7 +2768,8 @@ function disposeAtom(store, atomToken) {
|
|
|
2731
2768
|
type: `state_disposal`,
|
|
2732
2769
|
subType: `atom`,
|
|
2733
2770
|
token: atomToken,
|
|
2734
|
-
value: lastValue
|
|
2771
|
+
value: lastValue,
|
|
2772
|
+
timestamp: Date.now()
|
|
2735
2773
|
};
|
|
2736
2774
|
atomFamily$1.subject.next(disposal);
|
|
2737
2775
|
const isChild = isChildStore(target);
|
|
@@ -2748,14 +2786,22 @@ function disposeAtom(store, atomToken) {
|
|
|
2748
2786
|
}
|
|
2749
2787
|
store.logger.info(`🔥`, `atom`, key, `deleted`);
|
|
2750
2788
|
if (isChild && target.transactionMeta.phase === `building`) {
|
|
2751
|
-
const mostRecentUpdate = target.transactionMeta.update.
|
|
2789
|
+
const mostRecentUpdate = target.transactionMeta.update.subEvents.at(-1);
|
|
2752
2790
|
const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
|
|
2753
2791
|
const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
2754
|
-
if (!updateAlreadyCaptured) target.transactionMeta.update.
|
|
2792
|
+
if (!updateAlreadyCaptured) target.transactionMeta.update.subEvents.push(disposal);
|
|
2755
2793
|
} else store.on.atomDisposal.next(atomToken);
|
|
2756
2794
|
}
|
|
2757
2795
|
}
|
|
2758
2796
|
|
|
2797
|
+
//#endregion
|
|
2798
|
+
//#region src/internal/atom/has-role.ts
|
|
2799
|
+
const INTERNAL_ROLES = [`tracker:signal`];
|
|
2800
|
+
function hasRole(atom, role) {
|
|
2801
|
+
if (`internalRoles` in atom === false) return false;
|
|
2802
|
+
return atom.internalRoles.includes(role);
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2759
2805
|
//#endregion
|
|
2760
2806
|
//#region src/internal/install-into-store.ts
|
|
2761
2807
|
/**
|
|
@@ -2769,12 +2815,12 @@ function disposeAtom(store, atomToken) {
|
|
|
2769
2815
|
function installIntoStore(tokens, target, source) {
|
|
2770
2816
|
const sourceNewest = newest(source);
|
|
2771
2817
|
if (isChildStore(sourceNewest)) {
|
|
2772
|
-
source.logger.error(`❌`, `transaction`, sourceNewest.transactionMeta.update.key, `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`, tokens, `${sourceNewest.config.name} is undergoing a transaction.`);
|
|
2818
|
+
source.logger.error(`❌`, `transaction`, sourceNewest.transactionMeta.update.token.key, `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`, tokens, `${sourceNewest.config.name} is undergoing a transaction.`);
|
|
2773
2819
|
return;
|
|
2774
2820
|
}
|
|
2775
2821
|
const targetNewest = newest(target);
|
|
2776
2822
|
if (isChildStore(targetNewest)) {
|
|
2777
|
-
target.logger.error(`❌`, `transaction`, targetNewest.transactionMeta.update.key, `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`, tokens, `${targetNewest.config.name} is undergoing a transaction.`);
|
|
2823
|
+
target.logger.error(`❌`, `transaction`, targetNewest.transactionMeta.update.token.key, `could not install the following tokens into store "${target.config.name} from "${source.config.name}":`, tokens, `${targetNewest.config.name} is undergoing a transaction.`);
|
|
2778
2824
|
return;
|
|
2779
2825
|
}
|
|
2780
2826
|
for (const token of tokens) {
|
|
@@ -3325,37 +3371,39 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3325
3371
|
}, { topicType: `atom` });
|
|
3326
3372
|
tl.subscriptions.set(atom.key, atom.subject.subscribe(`timeline`, function timelineCapturesAtomUpdate(update) {
|
|
3327
3373
|
const target = newest(store);
|
|
3328
|
-
const
|
|
3329
|
-
const currentSelectorTime = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.
|
|
3374
|
+
const currentSelectorToken = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.token : null;
|
|
3375
|
+
const currentSelectorTime = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.timestamp : null;
|
|
3330
3376
|
const txUpdateInProgress = target.on.transactionApplying.state?.update;
|
|
3331
|
-
store.logger.info(`⏳`, `timeline`, tl.key, `atom`, atomToken.key, `went`, update.oldValue, `->`, update.newValue, txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` :
|
|
3377
|
+
store.logger.info(`⏳`, `timeline`, tl.key, `atom`, atomToken.key, `went`, update.oldValue, `->`, update.newValue, txUpdateInProgress ? `in transaction "${txUpdateInProgress.token.key}"` : currentSelectorToken ? `in selector "${currentSelectorToken.key}"` : ``);
|
|
3332
3378
|
if (tl.timeTraveling === null) if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress);
|
|
3333
|
-
else if (
|
|
3379
|
+
else if (currentSelectorToken && currentSelectorTime) {
|
|
3334
3380
|
let latestUpdate = tl.history.at(-1);
|
|
3335
3381
|
if (currentSelectorTime !== tl.selectorTime) {
|
|
3336
3382
|
latestUpdate = {
|
|
3337
3383
|
type: `selector_update`,
|
|
3338
3384
|
timestamp: currentSelectorTime,
|
|
3339
|
-
|
|
3385
|
+
token: currentSelectorToken,
|
|
3340
3386
|
atomUpdates: []
|
|
3341
3387
|
};
|
|
3342
3388
|
latestUpdate.atomUpdates.push({
|
|
3343
|
-
key: atom.key,
|
|
3344
3389
|
type: `atom_update`,
|
|
3345
|
-
|
|
3390
|
+
token: atomToken,
|
|
3391
|
+
update,
|
|
3392
|
+
timestamp: Date.now()
|
|
3346
3393
|
});
|
|
3347
3394
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3348
3395
|
tl.history.push(latestUpdate);
|
|
3349
|
-
store.logger.info(`⌛`, `timeline`, tl.key, `got a selector_update "${
|
|
3396
|
+
store.logger.info(`⌛`, `timeline`, tl.key, `got a selector_update "${currentSelectorToken.key}" with`, latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.token.key));
|
|
3350
3397
|
tl.at = tl.history.length;
|
|
3351
3398
|
tl.selectorTime = currentSelectorTime;
|
|
3352
3399
|
} else if (latestUpdate?.type === `selector_update`) {
|
|
3353
3400
|
latestUpdate.atomUpdates.push({
|
|
3354
|
-
key: atom.key,
|
|
3355
3401
|
type: `atom_update`,
|
|
3356
|
-
|
|
3402
|
+
token: atomToken,
|
|
3403
|
+
update,
|
|
3404
|
+
timestamp: Date.now()
|
|
3357
3405
|
});
|
|
3358
|
-
store.logger.info(`⌛`, `timeline`, tl.key, `set selector_update "${
|
|
3406
|
+
store.logger.info(`⌛`, `timeline`, tl.key, `set selector_update "${currentSelectorToken.key}" to`, latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.token.key));
|
|
3359
3407
|
}
|
|
3360
3408
|
if (latestUpdate) {
|
|
3361
3409
|
const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
|
|
@@ -3371,12 +3419,10 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3371
3419
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3372
3420
|
const atomUpdate = {
|
|
3373
3421
|
type: `atom_update`,
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
newValue: update.newValue
|
|
3422
|
+
token: deposit(atom),
|
|
3423
|
+
update,
|
|
3424
|
+
timestamp
|
|
3378
3425
|
};
|
|
3379
|
-
if (atom.family) atomUpdate.family = atom.family;
|
|
3380
3426
|
const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
|
|
3381
3427
|
store.logger.info(`⌛`, `timeline`, tl.key, `got an atom_update to "${atom.key}"`);
|
|
3382
3428
|
if (willCapture) {
|
|
@@ -3399,7 +3445,7 @@ function addAtomFamilyToTimeline(store, atomFamilyToken, tl) {
|
|
|
3399
3445
|
for (const atom of store.atoms.values()) if (atom.family?.key === family.key) addAtomToTimeline(store, atom, tl);
|
|
3400
3446
|
}
|
|
3401
3447
|
function joinTransaction(store, tl, txUpdateInProgress) {
|
|
3402
|
-
const currentTxKey = txUpdateInProgress.key;
|
|
3448
|
+
const currentTxKey = txUpdateInProgress.token.key;
|
|
3403
3449
|
const currentTxInstanceId = txUpdateInProgress.id;
|
|
3404
3450
|
const currentTxToken = {
|
|
3405
3451
|
key: currentTxKey,
|
|
@@ -3414,11 +3460,10 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3414
3460
|
if (tl.timeTraveling === null && currentTxInstanceId) {
|
|
3415
3461
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3416
3462
|
const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
|
|
3417
|
-
const
|
|
3463
|
+
const subEventsFiltered = filterTransactionSubEvents(transactionUpdate.subEvents, timelineTopics);
|
|
3418
3464
|
const timelineTransactionUpdate = {
|
|
3419
|
-
timestamp: Date.now(),
|
|
3420
3465
|
...transactionUpdate,
|
|
3421
|
-
|
|
3466
|
+
subEvents: subEventsFiltered
|
|
3422
3467
|
};
|
|
3423
3468
|
const willCapture = tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true;
|
|
3424
3469
|
if (willCapture) {
|
|
@@ -3430,12 +3475,13 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3430
3475
|
});
|
|
3431
3476
|
}
|
|
3432
3477
|
}
|
|
3433
|
-
function
|
|
3478
|
+
function filterTransactionSubEvents(updates, timelineTopics) {
|
|
3434
3479
|
return updates.filter((updateFromTx) => {
|
|
3435
|
-
if (updateFromTx.type === `
|
|
3480
|
+
if (updateFromTx.type === `transaction_outcome`) return true;
|
|
3436
3481
|
let key;
|
|
3437
3482
|
let familyKey;
|
|
3438
3483
|
switch (updateFromTx.type) {
|
|
3484
|
+
case `atom_update`:
|
|
3439
3485
|
case `state_creation`:
|
|
3440
3486
|
case `state_disposal`:
|
|
3441
3487
|
key = updateFromTx.token.key;
|
|
@@ -3444,35 +3490,28 @@ function filterTransactionUpdates(updates, timelineTopics) {
|
|
|
3444
3490
|
case `molecule_creation`:
|
|
3445
3491
|
case `molecule_disposal`:
|
|
3446
3492
|
case `molecule_transfer`: return true;
|
|
3447
|
-
case `atom_update`:
|
|
3448
|
-
case `selector_update`:
|
|
3449
|
-
key = updateFromTx.key;
|
|
3450
|
-
familyKey = updateFromTx.family?.key;
|
|
3451
|
-
break;
|
|
3452
3493
|
}
|
|
3453
3494
|
timelineTopics.has(key);
|
|
3454
3495
|
if (familyKey && timelineTopics.has(familyKey)) return true;
|
|
3455
3496
|
return timelineTopics.has(key);
|
|
3456
3497
|
}).map((updateFromTx) => {
|
|
3457
|
-
if (`
|
|
3498
|
+
if (`subEvents` in updateFromTx) return {
|
|
3458
3499
|
...updateFromTx,
|
|
3459
|
-
|
|
3500
|
+
subEvents: filterTransactionSubEvents(updateFromTx.subEvents, timelineTopics)
|
|
3460
3501
|
};
|
|
3461
3502
|
return updateFromTx;
|
|
3462
3503
|
});
|
|
3463
3504
|
}
|
|
3464
3505
|
function handleStateLifecycleEvent(store, event, tl) {
|
|
3465
|
-
const timestamp = Date.now();
|
|
3466
|
-
const timelineEvent = Object.assign(event, { timestamp });
|
|
3467
3506
|
if (!tl.timeTraveling) {
|
|
3468
3507
|
const target = newest(store);
|
|
3469
3508
|
if (isChildStore(target)) {} else {
|
|
3470
3509
|
const txUpdateInProgress = target.on.transactionApplying.state;
|
|
3471
3510
|
if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress.update);
|
|
3472
3511
|
else {
|
|
3473
|
-
tl.history.push(
|
|
3512
|
+
tl.history.push(event);
|
|
3474
3513
|
tl.at = tl.history.length;
|
|
3475
|
-
tl.subject.next(
|
|
3514
|
+
tl.subject.next(event);
|
|
3476
3515
|
}
|
|
3477
3516
|
}
|
|
3478
3517
|
}
|
|
@@ -3511,7 +3550,7 @@ const timeTravel = (store, action, token) => {
|
|
|
3511
3550
|
case `selector_update`:
|
|
3512
3551
|
ingestSelectorUpdate(applying, update, store);
|
|
3513
3552
|
break;
|
|
3514
|
-
case `
|
|
3553
|
+
case `transaction_outcome`:
|
|
3515
3554
|
ingestTransactionUpdate(applying, update, store);
|
|
3516
3555
|
break;
|
|
3517
3556
|
case `state_creation`:
|