atom.io 0.36.2 → 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 +544 -507
- 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 +14 -14
- package/src/internal/atom/dispose-atom.ts +5 -4
- package/src/internal/caching.ts +3 -3
- 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 +16 -29
- 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.`);
|
|
@@ -538,9 +539,7 @@ function writeToCache(target, state, value) {
|
|
|
538
539
|
case `mutable_atom`:
|
|
539
540
|
evictDownstreamFromAtom(target, state);
|
|
540
541
|
break;
|
|
541
|
-
case `readonly_held_selector`:
|
|
542
542
|
case `readonly_pure_selector`:
|
|
543
|
-
case `writable_held_selector`:
|
|
544
543
|
case `writable_pure_selector`:
|
|
545
544
|
evictDownstreamFromSelector(target, key);
|
|
546
545
|
break;
|
|
@@ -587,7 +586,7 @@ function evictCachedValue(target, key) {
|
|
|
587
586
|
const currentValue = target.valueMap.get(key);
|
|
588
587
|
if (currentValue instanceof Future) {
|
|
589
588
|
const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
|
|
590
|
-
if (selector) selector.
|
|
589
|
+
if (selector) selector.getFrom(target);
|
|
591
590
|
return;
|
|
592
591
|
}
|
|
593
592
|
if (target.operation.open) target.operation.prev.set(key, currentValue);
|
|
@@ -606,7 +605,7 @@ function readOrComputeValue(target, state, mut) {
|
|
|
606
605
|
case `writable_held_selector`:
|
|
607
606
|
case `writable_pure_selector`:
|
|
608
607
|
target.logger.info(`🧮`, state.type, key, `computing value`);
|
|
609
|
-
return state.
|
|
608
|
+
return state.getFrom(target);
|
|
610
609
|
case `atom`: {
|
|
611
610
|
let def;
|
|
612
611
|
if (state.default instanceof Function) def = state.default();
|
|
@@ -625,33 +624,104 @@ function readOrComputeValue(target, state, mut) {
|
|
|
625
624
|
}
|
|
626
625
|
|
|
627
626
|
//#endregion
|
|
628
|
-
//#region src/internal/
|
|
629
|
-
|
|
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
|
+
}
|
|
630
634
|
|
|
631
635
|
//#endregion
|
|
632
|
-
//#region src/internal/
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
if (
|
|
636
|
-
|
|
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);
|
|
637
651
|
}
|
|
638
652
|
|
|
639
653
|
//#endregion
|
|
640
|
-
//#region src/internal/
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
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}".`);
|
|
651
664
|
}
|
|
652
|
-
state.subject.next(update);
|
|
653
665
|
};
|
|
654
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
|
+
|
|
655
725
|
//#endregion
|
|
656
726
|
//#region src/internal/set-state/set-atom.ts
|
|
657
727
|
const setAtom = (target, atom, next) => {
|
|
@@ -661,129 +731,49 @@ const setAtom = (target, atom, next) => {
|
|
|
661
731
|
newValue = writeToCache(target, atom, newValue);
|
|
662
732
|
markDone(target, atom.key);
|
|
663
733
|
evictDownstreamFromAtom(target, atom);
|
|
664
|
-
|
|
665
|
-
oldValue,
|
|
666
|
-
newValue
|
|
667
|
-
};
|
|
668
|
-
if (!isChildStore(target)) {
|
|
669
|
-
emitUpdate(target, atom, update);
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
if (target.on.transactionApplying.state === null) {
|
|
673
|
-
const { key } = atom;
|
|
674
|
-
if (isTransceiver(update.newValue)) return;
|
|
675
|
-
const atomUpdate = {
|
|
676
|
-
type: `atom_update`,
|
|
677
|
-
key,
|
|
678
|
-
...update
|
|
679
|
-
};
|
|
680
|
-
if (atom.family) atomUpdate.family = atom.family;
|
|
681
|
-
target.transactionMeta.update.updates.push(atomUpdate);
|
|
682
|
-
target.logger.info(`📁`, `atom`, key, `stowed (`, update.oldValue, `->`, update.newValue, `)`);
|
|
683
|
-
} else if (hasRole(atom, `tracker:signal`)) {
|
|
684
|
-
const key = atom.key.slice(1);
|
|
685
|
-
const mutable = target.atoms.get(key);
|
|
686
|
-
const transceiver = readOrComputeValue(target, mutable, `mut`);
|
|
687
|
-
const accepted = transceiver.do(update.newValue) === null;
|
|
688
|
-
if (accepted === true) evictDownstreamFromAtom(target, mutable);
|
|
689
|
-
}
|
|
734
|
+
return [oldValue, newValue];
|
|
690
735
|
};
|
|
691
736
|
|
|
692
737
|
//#endregion
|
|
693
738
|
//#region src/internal/set-state/reset-atom-or-selector.ts
|
|
694
|
-
function resetAtom(
|
|
695
|
-
switch (
|
|
696
|
-
case `mutable_atom`:
|
|
697
|
-
setAtom(store, state, new state.class());
|
|
698
|
-
return;
|
|
739
|
+
function resetAtom(target, atom) {
|
|
740
|
+
switch (atom.type) {
|
|
741
|
+
case `mutable_atom`: return setAtom(target, atom, new atom.class());
|
|
699
742
|
case `atom`: {
|
|
700
|
-
let def =
|
|
743
|
+
let def = atom.default;
|
|
701
744
|
if (def instanceof Function) def = def();
|
|
702
|
-
setAtom(
|
|
745
|
+
return setAtom(target, atom, def);
|
|
703
746
|
}
|
|
704
747
|
}
|
|
705
748
|
}
|
|
706
|
-
function resetAtomOrSelector(
|
|
749
|
+
function resetAtomOrSelector(target, state) {
|
|
750
|
+
let protoUpdate;
|
|
707
751
|
switch (state.type) {
|
|
708
752
|
case `atom`:
|
|
709
753
|
case `mutable_atom`:
|
|
710
|
-
resetAtom(
|
|
754
|
+
protoUpdate = resetAtom(target, state);
|
|
711
755
|
break;
|
|
712
756
|
case `writable_pure_selector`:
|
|
713
757
|
case `writable_held_selector`:
|
|
714
758
|
{
|
|
715
|
-
const
|
|
716
|
-
|
|
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];
|
|
717
767
|
}
|
|
718
768
|
break;
|
|
719
769
|
}
|
|
770
|
+
return protoUpdate;
|
|
720
771
|
}
|
|
721
772
|
|
|
722
|
-
//#endregion
|
|
723
|
-
//#region src/internal/families/get-family-of-token.ts
|
|
724
|
-
function getFamilyOfToken(store, token) {
|
|
725
|
-
if (token.family) {
|
|
726
|
-
const family = store.families.get(token.family.key);
|
|
727
|
-
if (family) return family;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
//#endregion
|
|
732
|
-
//#region src/internal/set-state/set-atom-or-selector.ts
|
|
733
|
-
const setAtomOrSelector = (store, state, value) => {
|
|
734
|
-
switch (state.type) {
|
|
735
|
-
case `atom`:
|
|
736
|
-
case `mutable_atom`:
|
|
737
|
-
setAtom(store, state, value);
|
|
738
|
-
break;
|
|
739
|
-
case `writable_pure_selector`:
|
|
740
|
-
case `writable_held_selector`:
|
|
741
|
-
state.set(value);
|
|
742
|
-
break;
|
|
743
|
-
}
|
|
744
|
-
};
|
|
745
|
-
|
|
746
773
|
//#endregion
|
|
747
774
|
//#region src/internal/set-state/set-into-store.ts
|
|
748
775
|
function setIntoStore(store, ...params) {
|
|
749
|
-
|
|
750
|
-
let family;
|
|
751
|
-
let key;
|
|
752
|
-
let value;
|
|
753
|
-
if (params.length === 2) {
|
|
754
|
-
token = params[0];
|
|
755
|
-
value = params[1];
|
|
756
|
-
if (token.family) {
|
|
757
|
-
family = getFamilyOfToken(store, token);
|
|
758
|
-
key = parseJson(token.family.subKey);
|
|
759
|
-
token = findInStore(store, family, key);
|
|
760
|
-
}
|
|
761
|
-
} else {
|
|
762
|
-
family = params[0];
|
|
763
|
-
key = params[1];
|
|
764
|
-
value = params[2];
|
|
765
|
-
token = findInStore(store, family, key);
|
|
766
|
-
}
|
|
767
|
-
const action = value === RESET_STATE ? `reset` : `set`;
|
|
768
|
-
if (`counterfeit` in token && `family` in token) {
|
|
769
|
-
const subKey = token.family.subKey;
|
|
770
|
-
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
771
|
-
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.`);
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
const rejectionTime = openOperation(store, token);
|
|
775
|
-
if (rejectionTime) {
|
|
776
|
-
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
777
|
-
unsubscribe();
|
|
778
|
-
store.logger.info(`🟢`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
779
|
-
setIntoStore(store, token, value);
|
|
780
|
-
});
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
const state = withdraw(store, token);
|
|
784
|
-
if (value === RESET_STATE) resetAtomOrSelector(store, state);
|
|
785
|
-
else setAtomOrSelector(store, state, value);
|
|
786
|
-
closeOperation(store);
|
|
776
|
+
operateOnStore(store, true, ...params);
|
|
787
777
|
}
|
|
788
778
|
|
|
789
779
|
//#endregion
|
|
@@ -804,233 +794,52 @@ function resetInStore(store, ...params) {
|
|
|
804
794
|
}
|
|
805
795
|
|
|
806
796
|
//#endregion
|
|
807
|
-
//#region src/internal/
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const roots = /* @__PURE__ */ new Map();
|
|
825
|
-
while (dependencies.length > 0) {
|
|
826
|
-
const dependencyKey = dependencies.pop();
|
|
827
|
-
if (covered.has(dependencyKey)) continue;
|
|
828
|
-
covered.add(dependencyKey);
|
|
829
|
-
if (isAtomKey(store, dependencyKey)) {
|
|
830
|
-
const atom = store.atoms.get(dependencyKey);
|
|
831
|
-
roots.set(atom.key, atom);
|
|
832
|
-
} else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
833
|
-
}
|
|
834
|
-
return roots;
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
//#endregion
|
|
838
|
-
//#region src/internal/selector/update-selector-atoms.ts
|
|
839
|
-
const updateSelectorAtoms = (store, selectorType, selectorKey, dependency, covered) => {
|
|
840
|
-
const target = newest(store);
|
|
841
|
-
const { type: dependencyType, key: dependencyKey } = dependency;
|
|
842
|
-
if (dependencyType === `atom` || dependencyType === `mutable_atom`) {
|
|
843
|
-
target.selectorAtoms.set({
|
|
844
|
-
selectorKey,
|
|
845
|
-
atomKey: dependencyKey
|
|
846
|
-
});
|
|
847
|
-
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atom "${dependencyKey}"`);
|
|
848
|
-
} else {
|
|
849
|
-
const rootKeys = traceRootSelectorAtoms(store, dependencyKey, covered);
|
|
850
|
-
store.logger.info(`🔍`, selectorType, selectorKey, `discovers root atoms: [ ${[...rootKeys.values()].map((root) => `"${root.key}"`).join(`, `)} ]`);
|
|
851
|
-
for (const { key: atomKey } of rootKeys.values()) target.selectorAtoms = target.selectorAtoms.set({
|
|
852
|
-
selectorKey,
|
|
853
|
-
atomKey
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
covered.add(dependencyKey);
|
|
857
|
-
};
|
|
858
|
-
|
|
859
|
-
//#endregion
|
|
860
|
-
//#region src/internal/selector/register-selector.ts
|
|
861
|
-
const registerSelector = (store, selectorType, selectorKey, covered) => ({
|
|
862
|
-
get: (...params) => {
|
|
863
|
-
const target = newest(store);
|
|
864
|
-
let dependency;
|
|
865
|
-
if (params.length === 2) {
|
|
866
|
-
const [family, key] = params;
|
|
867
|
-
dependency = findInStore(store, family, key);
|
|
868
|
-
} else [dependency] = params;
|
|
869
|
-
const dependencyState = withdraw(store, dependency);
|
|
870
|
-
const dependencyValue = readOrComputeValue(store, dependencyState);
|
|
871
|
-
const dependencyKey = dependency.key;
|
|
872
|
-
store.logger.info(`🔌`, selectorType, selectorKey, `registers dependency ( "${dependencyKey}" =`, dependencyValue, `)`);
|
|
873
|
-
target.selectorGraph.set({
|
|
874
|
-
upstreamSelectorKey: dependencyKey,
|
|
875
|
-
downstreamSelectorKey: selectorKey
|
|
876
|
-
}, { source: dependency.key });
|
|
877
|
-
updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered);
|
|
878
|
-
return dependencyValue;
|
|
879
|
-
},
|
|
880
|
-
set: ((...params) => {
|
|
881
|
-
let token;
|
|
882
|
-
let value;
|
|
883
|
-
if (params.length === 2) {
|
|
884
|
-
token = params[0];
|
|
885
|
-
value = params[1];
|
|
886
|
-
} else {
|
|
887
|
-
const family = params[0];
|
|
888
|
-
const key = params[1];
|
|
889
|
-
value = params[2];
|
|
890
|
-
token = findInStore(store, family, key);
|
|
891
|
-
}
|
|
892
|
-
const target = newest(store);
|
|
893
|
-
const state = withdraw(target, token);
|
|
894
|
-
setAtomOrSelector(target, state, value);
|
|
895
|
-
}),
|
|
896
|
-
find: ((...args) => findInStore(store, ...args)),
|
|
897
|
-
json: (token) => getJsonToken(store, token)
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
//#endregion
|
|
901
|
-
//#region src/internal/selector/create-readonly-held-selector.ts
|
|
902
|
-
const createReadonlyHeldSelector = (store, options, family) => {
|
|
903
|
-
const target = newest(store);
|
|
904
|
-
const subject = new Subject();
|
|
905
|
-
const covered = /* @__PURE__ */ new Set();
|
|
906
|
-
const { key, const: constant } = options;
|
|
907
|
-
const type = `readonly_held_selector`;
|
|
908
|
-
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
909
|
-
const getSelf = () => {
|
|
910
|
-
const innerTarget = newest(store);
|
|
911
|
-
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
912
|
-
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
913
|
-
innerTarget.selectorAtoms.delete(key);
|
|
914
|
-
options.get({
|
|
915
|
-
get,
|
|
916
|
-
find,
|
|
917
|
-
json
|
|
918
|
-
}, constant);
|
|
919
|
-
writeToCache(newest(store), readonlySelector, constant);
|
|
920
|
-
covered.clear();
|
|
921
|
-
return constant;
|
|
922
|
-
};
|
|
923
|
-
const readonlySelector = {
|
|
924
|
-
...options,
|
|
925
|
-
type,
|
|
926
|
-
subject,
|
|
927
|
-
install: (s) => createReadonlyHeldSelector(s, options, family),
|
|
928
|
-
get: getSelf,
|
|
929
|
-
...family && { family }
|
|
930
|
-
};
|
|
931
|
-
target.readonlySelectors.set(key, readonlySelector);
|
|
932
|
-
store.logger.info(`✨`, type, key, `=`, constant);
|
|
933
|
-
const token = {
|
|
934
|
-
key,
|
|
935
|
-
type
|
|
936
|
-
};
|
|
937
|
-
if (family) token.family = family;
|
|
938
|
-
return token;
|
|
939
|
-
};
|
|
940
|
-
|
|
941
|
-
//#endregion
|
|
942
|
-
//#region src/internal/selector/create-readonly-pure-selector.ts
|
|
943
|
-
const createReadonlyPureSelector = (store, options, family) => {
|
|
944
|
-
const target = newest(store);
|
|
945
|
-
const subject = new Subject();
|
|
946
|
-
const covered = /* @__PURE__ */ new Set();
|
|
947
|
-
const key = options.key;
|
|
948
|
-
const type = `readonly_pure_selector`;
|
|
949
|
-
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
950
|
-
const getSelf = () => {
|
|
951
|
-
const innerTarget = newest(store);
|
|
952
|
-
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
953
|
-
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
954
|
-
innerTarget.selectorAtoms.delete(key);
|
|
955
|
-
const value = options.get({
|
|
956
|
-
get,
|
|
957
|
-
find,
|
|
958
|
-
json
|
|
959
|
-
});
|
|
960
|
-
const cached = writeToCache(innerTarget, readonlySelector, value);
|
|
961
|
-
store.logger.info(`✨`, type, key, `=`, cached);
|
|
962
|
-
covered.clear();
|
|
963
|
-
return cached;
|
|
964
|
-
};
|
|
965
|
-
const readonlySelector = {
|
|
966
|
-
...options,
|
|
967
|
-
type,
|
|
968
|
-
subject,
|
|
969
|
-
install: (s) => createReadonlyPureSelector(s, options, family),
|
|
970
|
-
get: getSelf,
|
|
971
|
-
...family && { family }
|
|
972
|
-
};
|
|
973
|
-
target.readonlySelectors.set(key, readonlySelector);
|
|
974
|
-
const token = {
|
|
975
|
-
key,
|
|
976
|
-
type
|
|
977
|
-
};
|
|
978
|
-
if (family) token.family = family;
|
|
979
|
-
return token;
|
|
980
|
-
};
|
|
981
|
-
|
|
982
|
-
//#endregion
|
|
983
|
-
//#region src/internal/transaction/abort-transaction.ts
|
|
984
|
-
const abortTransaction = (store) => {
|
|
985
|
-
const target = newest(store);
|
|
986
|
-
if (!isChildStore(target)) {
|
|
987
|
-
store.logger.warn(`🐞`, `transaction`, `???`, `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`);
|
|
988
|
-
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;
|
|
989
814
|
}
|
|
990
|
-
|
|
991
|
-
target
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
//#endregion
|
|
995
|
-
//#region src/internal/capitalize.ts
|
|
996
|
-
function capitalize(string) {
|
|
997
|
-
return string[0].toUpperCase() + string.slice(1);
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
//#endregion
|
|
1001
|
-
//#region src/internal/pretty-print.ts
|
|
1002
|
-
function prettyPrintTokenType(token) {
|
|
1003
|
-
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];
|
|
1004
819
|
}
|
|
1005
820
|
|
|
1006
821
|
//#endregion
|
|
1007
|
-
//#region src/internal/
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
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;
|
|
1011
834
|
}
|
|
835
|
+
return protoUpdate;
|
|
1012
836
|
};
|
|
1013
837
|
|
|
1014
|
-
//#endregion
|
|
1015
|
-
//#region src/internal/transaction/act-upon-store.ts
|
|
1016
|
-
function actUponStore(store, token, id) {
|
|
1017
|
-
return (...parameters) => {
|
|
1018
|
-
const tx = withdraw(store, token);
|
|
1019
|
-
if (tx) return tx.run(parameters, id);
|
|
1020
|
-
throw new NotFoundError(token, store);
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
838
|
//#endregion
|
|
1025
839
|
//#region src/internal/ingest-updates/ingest-atom-update.ts
|
|
1026
840
|
function ingestAtomUpdate(applying, atomUpdate, store) {
|
|
1027
|
-
const {
|
|
841
|
+
const { token, update: { newValue, oldValue } } = atomUpdate;
|
|
1028
842
|
const value = applying === `newValue` ? newValue : oldValue;
|
|
1029
|
-
const token = {
|
|
1030
|
-
key,
|
|
1031
|
-
type: `atom`
|
|
1032
|
-
};
|
|
1033
|
-
if (atomUpdate.family) Object.assign(token, { family: atomUpdate.family });
|
|
1034
843
|
setIntoStore(store, token, value);
|
|
1035
844
|
}
|
|
1036
845
|
|
|
@@ -1078,10 +887,11 @@ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
|
1078
887
|
const creationEvent = {
|
|
1079
888
|
type: `molecule_creation`,
|
|
1080
889
|
key,
|
|
1081
|
-
provenance: origin
|
|
890
|
+
provenance: origin,
|
|
891
|
+
timestamp: Date.now()
|
|
1082
892
|
};
|
|
1083
893
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1084
|
-
if (isTransaction) target.transactionMeta.update.
|
|
894
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(creationEvent);
|
|
1085
895
|
else target.on.moleculeCreation.next(creationEvent);
|
|
1086
896
|
for (const claim of invalidKeys) {
|
|
1087
897
|
const disposal = store.disposalTraces.buffer.find((item) => item?.key === claim);
|
|
@@ -1118,12 +928,13 @@ function deallocateFromStore(store, claim) {
|
|
|
1118
928
|
type: `molecule_disposal`,
|
|
1119
929
|
key: molecule.key,
|
|
1120
930
|
values,
|
|
1121
|
-
provenance
|
|
931
|
+
provenance,
|
|
932
|
+
timestamp: Date.now()
|
|
1122
933
|
};
|
|
1123
934
|
const target = newest(store);
|
|
1124
935
|
target.molecules.delete(stringKey);
|
|
1125
936
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1126
|
-
if (isTransaction) target.transactionMeta.update.
|
|
937
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(disposalEvent);
|
|
1127
938
|
const relatedMolecules = store.moleculeGraph.getRelationEntries({ downstreamMoleculeKey: molecule.stringKey });
|
|
1128
939
|
if (relatedMolecules) for (const [relatedStringKey, { source }] of relatedMolecules) if (source === molecule.stringKey) {
|
|
1129
940
|
const relatedKey = parseJson(relatedStringKey);
|
|
@@ -1174,10 +985,11 @@ function claimWithinStore(store, newProvenance, claim, exclusive) {
|
|
|
1174
985
|
key: molecule.key,
|
|
1175
986
|
exclusive: Boolean(exclusive),
|
|
1176
987
|
from: priorProvenance,
|
|
1177
|
-
to: [newProvenanceMolecule.key]
|
|
988
|
+
to: [newProvenanceMolecule.key],
|
|
989
|
+
timestamp: Date.now()
|
|
1178
990
|
};
|
|
1179
991
|
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1180
|
-
if (isTransaction) target.transactionMeta.update.
|
|
992
|
+
if (isTransaction) target.transactionMeta.update.subEvents.push(transferEvent);
|
|
1181
993
|
return claim;
|
|
1182
994
|
}
|
|
1183
995
|
|
|
@@ -1271,10 +1083,9 @@ function ingestSelectorUpdate(applying, selectorUpdate, store) {
|
|
|
1271
1083
|
//#endregion
|
|
1272
1084
|
//#region src/internal/ingest-updates/ingest-transaction-update.ts
|
|
1273
1085
|
function ingestTransactionUpdate(applying, transactionUpdate, store) {
|
|
1274
|
-
const updates = applying === `newValue` ? transactionUpdate.
|
|
1086
|
+
const updates = applying === `newValue` ? transactionUpdate.subEvents : [...transactionUpdate.subEvents].reverse();
|
|
1275
1087
|
for (const updateFromTransaction of updates) switch (updateFromTransaction.type) {
|
|
1276
1088
|
case `atom_update`:
|
|
1277
|
-
case `selector_update`:
|
|
1278
1089
|
ingestAtomUpdate(applying, updateFromTransaction, store);
|
|
1279
1090
|
break;
|
|
1280
1091
|
case `state_creation`:
|
|
@@ -1292,7 +1103,7 @@ function ingestTransactionUpdate(applying, transactionUpdate, store) {
|
|
|
1292
1103
|
case `molecule_transfer`:
|
|
1293
1104
|
ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
|
|
1294
1105
|
break;
|
|
1295
|
-
case `
|
|
1106
|
+
case `transaction_outcome`:
|
|
1296
1107
|
ingestTransactionUpdate(applying, updateFromTransaction, store);
|
|
1297
1108
|
break;
|
|
1298
1109
|
}
|
|
@@ -1342,18 +1153,18 @@ const applyTransaction = (output, store) => {
|
|
|
1342
1153
|
child.transactionMeta.update.output = output;
|
|
1343
1154
|
parent.child = null;
|
|
1344
1155
|
parent.on.transactionApplying.next(child.transactionMeta);
|
|
1345
|
-
const { updates } = child.transactionMeta.update;
|
|
1346
|
-
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);
|
|
1347
1158
|
ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
|
|
1348
1159
|
if (isRootStore(parent)) {
|
|
1349
|
-
setEpochNumberOfAction(parent, child.transactionMeta.update.key, child.transactionMeta.update.epoch);
|
|
1160
|
+
setEpochNumberOfAction(parent, child.transactionMeta.update.token.key, child.transactionMeta.update.epoch);
|
|
1350
1161
|
const myTransaction = withdraw(store, {
|
|
1351
|
-
key: child.transactionMeta.update.key,
|
|
1162
|
+
key: child.transactionMeta.update.token.key,
|
|
1352
1163
|
type: `transaction`
|
|
1353
1164
|
});
|
|
1354
1165
|
myTransaction?.subject.next(child.transactionMeta.update);
|
|
1355
|
-
store.logger.info(`🛬`, `transaction`, child.transactionMeta.update.key, `Finished applying transaction.`);
|
|
1356
|
-
} 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);
|
|
1357
1168
|
parent.on.transactionApplying.next(null);
|
|
1358
1169
|
};
|
|
1359
1170
|
|
|
@@ -1409,7 +1220,7 @@ var LazyMap = class extends Map {
|
|
|
1409
1220
|
|
|
1410
1221
|
//#endregion
|
|
1411
1222
|
//#region src/internal/transaction/build-transaction.ts
|
|
1412
|
-
const buildTransaction = (store,
|
|
1223
|
+
const buildTransaction = (store, token, params, id) => {
|
|
1413
1224
|
const parent = newest(store);
|
|
1414
1225
|
const childBase = {
|
|
1415
1226
|
parent,
|
|
@@ -1440,15 +1251,16 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1440
1251
|
moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), { makeContentKey: parent.moleculeJoins.makeContentKey }),
|
|
1441
1252
|
miscResources: new LazyMap(parent.miscResources)
|
|
1442
1253
|
};
|
|
1443
|
-
const epoch = getEpochNumberOfAction(store, key);
|
|
1254
|
+
const epoch = getEpochNumberOfAction(store, token.key);
|
|
1444
1255
|
const transactionMeta = {
|
|
1445
1256
|
phase: `building`,
|
|
1446
1257
|
update: {
|
|
1447
|
-
type: `
|
|
1448
|
-
|
|
1258
|
+
type: `transaction_outcome`,
|
|
1259
|
+
token,
|
|
1449
1260
|
id,
|
|
1450
1261
|
epoch: epoch === void 0 ? NaN : epoch + 1,
|
|
1451
|
-
|
|
1262
|
+
timestamp: Date.now(),
|
|
1263
|
+
subEvents: [],
|
|
1452
1264
|
params,
|
|
1453
1265
|
output: void 0
|
|
1454
1266
|
},
|
|
@@ -1460,9 +1272,9 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1460
1272
|
reset: ((...ps) => {
|
|
1461
1273
|
resetInStore(child, ...ps);
|
|
1462
1274
|
}),
|
|
1463
|
-
run: (
|
|
1275
|
+
run: (t, identifier = arbitrary()) => actUponStore(child, t, identifier),
|
|
1464
1276
|
find: ((...ps) => findInStore(store, ...ps)),
|
|
1465
|
-
json: (
|
|
1277
|
+
json: (t) => getJsonToken(child, t),
|
|
1466
1278
|
dispose: ((...ps) => {
|
|
1467
1279
|
disposeFromStore(child, ...ps);
|
|
1468
1280
|
}),
|
|
@@ -1471,7 +1283,7 @@ const buildTransaction = (store, key, params, id) => {
|
|
|
1471
1283
|
};
|
|
1472
1284
|
const child = Object.assign(childBase, { transactionMeta });
|
|
1473
1285
|
parent.child = child;
|
|
1474
|
-
store.logger.info(`🛫`, `transaction`, key, `Building transaction with params:`, params);
|
|
1286
|
+
store.logger.info(`🛫`, `transaction`, token.key, `Building transaction with params:`, params);
|
|
1475
1287
|
return child;
|
|
1476
1288
|
};
|
|
1477
1289
|
|
|
@@ -1484,7 +1296,8 @@ function createTransaction(store, options) {
|
|
|
1484
1296
|
key,
|
|
1485
1297
|
type: `transaction`,
|
|
1486
1298
|
run: (params, id) => {
|
|
1487
|
-
const
|
|
1299
|
+
const token$1 = deposit(newTransaction);
|
|
1300
|
+
const childStore = buildTransaction(store, token$1, params, id);
|
|
1488
1301
|
try {
|
|
1489
1302
|
const target$1 = newest(store);
|
|
1490
1303
|
const { toolkit } = childStore.transactionMeta;
|
|
@@ -1515,9 +1328,279 @@ const TRANSACTION_PHASES = [
|
|
|
1515
1328
|
`applying`
|
|
1516
1329
|
];
|
|
1517
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
|
+
|
|
1518
1601
|
//#endregion
|
|
1519
1602
|
//#region src/internal/selector/create-writable-held-selector.ts
|
|
1520
|
-
|
|
1603
|
+
function createWritableHeldSelector(store, options, family) {
|
|
1521
1604
|
const target = newest(store);
|
|
1522
1605
|
const subject = new Subject();
|
|
1523
1606
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -1530,38 +1613,28 @@ const createWritableHeldSelector = (store, options, family) => {
|
|
|
1530
1613
|
get,
|
|
1531
1614
|
json
|
|
1532
1615
|
};
|
|
1533
|
-
const
|
|
1616
|
+
const getFrom = (innerTarget) => {
|
|
1534
1617
|
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1535
1618
|
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1536
1619
|
innerTarget.selectorAtoms.delete(key);
|
|
1537
|
-
|
|
1620
|
+
options.get(getterToolkit, constant);
|
|
1538
1621
|
writeToCache(innerTarget, mySelector, constant);
|
|
1539
1622
|
store.logger.info(`✨`, type, key, `=`, constant);
|
|
1540
1623
|
covered.clear();
|
|
1541
1624
|
return constant;
|
|
1542
1625
|
};
|
|
1543
|
-
const setSelf = (
|
|
1544
|
-
|
|
1545
|
-
const oldValue = getSelf(options.get, innerTarget);
|
|
1546
|
-
const newValue = become(next)(oldValue);
|
|
1547
|
-
store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
|
|
1548
|
-
writeToCache(innerTarget, mySelector, newValue);
|
|
1549
|
-
markDone(innerTarget, key);
|
|
1550
|
-
if (isRootStore(innerTarget)) subject.next({
|
|
1551
|
-
newValue,
|
|
1552
|
-
oldValue
|
|
1553
|
-
});
|
|
1554
|
-
options.set(setterToolkit, newValue);
|
|
1626
|
+
const setSelf = () => {
|
|
1627
|
+
options.set(setterToolkit, constant);
|
|
1555
1628
|
};
|
|
1556
1629
|
const mySelector = {
|
|
1557
1630
|
...options,
|
|
1558
1631
|
type,
|
|
1559
1632
|
subject,
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
...family && { family }
|
|
1633
|
+
getFrom,
|
|
1634
|
+
setSelf,
|
|
1635
|
+
install: (s) => createWritableHeldSelector(s, options, family)
|
|
1564
1636
|
};
|
|
1637
|
+
if (family) mySelector.family = family;
|
|
1565
1638
|
target.writableSelectors.set(key, mySelector);
|
|
1566
1639
|
const token = {
|
|
1567
1640
|
key,
|
|
@@ -1569,11 +1642,11 @@ const createWritableHeldSelector = (store, options, family) => {
|
|
|
1569
1642
|
};
|
|
1570
1643
|
if (family) token.family = family;
|
|
1571
1644
|
return token;
|
|
1572
|
-
}
|
|
1645
|
+
}
|
|
1573
1646
|
|
|
1574
1647
|
//#endregion
|
|
1575
1648
|
//#region src/internal/selector/create-writable-pure-selector.ts
|
|
1576
|
-
|
|
1649
|
+
function createWritablePureSelector(store, options, family) {
|
|
1577
1650
|
const target = newest(store);
|
|
1578
1651
|
const subject = new Subject();
|
|
1579
1652
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -1586,40 +1659,30 @@ const createWritablePureSelector = (store, options, family) => {
|
|
|
1586
1659
|
get,
|
|
1587
1660
|
json
|
|
1588
1661
|
};
|
|
1589
|
-
const
|
|
1662
|
+
const getFrom = (innerTarget) => {
|
|
1590
1663
|
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
1591
1664
|
for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
1592
1665
|
innerTarget.selectorAtoms.delete(key);
|
|
1593
|
-
const value =
|
|
1666
|
+
const value = options.get(getterToolkit);
|
|
1594
1667
|
const cached = writeToCache(innerTarget, mySelector, value);
|
|
1595
1668
|
store.logger.info(`✨`, type, key, `=`, cached);
|
|
1596
1669
|
covered.clear();
|
|
1597
|
-
return
|
|
1670
|
+
return cached;
|
|
1598
1671
|
};
|
|
1599
|
-
const setSelf = (
|
|
1600
|
-
const innerTarget = newest(store);
|
|
1601
|
-
const oldValue = getSelf(options.get, innerTarget);
|
|
1602
|
-
const newValue = become(next)(oldValue);
|
|
1603
|
-
store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
|
|
1604
|
-
writeToCache(innerTarget, mySelector, newValue);
|
|
1605
|
-
markDone(innerTarget, options.key);
|
|
1606
|
-
if (isRootStore(innerTarget)) subject.next({
|
|
1607
|
-
newValue,
|
|
1608
|
-
oldValue
|
|
1609
|
-
});
|
|
1672
|
+
const setSelf = (newValue) => {
|
|
1610
1673
|
options.set(setterToolkit, newValue);
|
|
1611
1674
|
};
|
|
1612
1675
|
const mySelector = {
|
|
1613
1676
|
...options,
|
|
1614
1677
|
type,
|
|
1615
1678
|
subject,
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
...family && { family }
|
|
1679
|
+
getFrom,
|
|
1680
|
+
setSelf,
|
|
1681
|
+
install: (s) => createWritablePureSelector(s, options, family)
|
|
1620
1682
|
};
|
|
1683
|
+
if (family) mySelector.family = family;
|
|
1621
1684
|
target.writableSelectors.set(key, mySelector);
|
|
1622
|
-
const initialValue =
|
|
1685
|
+
const initialValue = getFrom(target);
|
|
1623
1686
|
store.logger.info(`✨`, mySelector.type, mySelector.key, `=`, initialValue);
|
|
1624
1687
|
const token = {
|
|
1625
1688
|
key,
|
|
@@ -1627,7 +1690,7 @@ const createWritablePureSelector = (store, options, family) => {
|
|
|
1627
1690
|
};
|
|
1628
1691
|
if (family) token.family = family;
|
|
1629
1692
|
return token;
|
|
1630
|
-
}
|
|
1693
|
+
}
|
|
1631
1694
|
|
|
1632
1695
|
//#endregion
|
|
1633
1696
|
//#region src/internal/selector/create-standalone-selector.ts
|
|
@@ -1676,7 +1739,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1676
1739
|
family.subject.next({
|
|
1677
1740
|
type: `state_disposal`,
|
|
1678
1741
|
subType: `selector`,
|
|
1679
|
-
token: selectorToken
|
|
1742
|
+
token: selectorToken,
|
|
1743
|
+
timestamp: Date.now()
|
|
1680
1744
|
});
|
|
1681
1745
|
}
|
|
1682
1746
|
break;
|
|
@@ -1691,7 +1755,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1691
1755
|
family.subject.next({
|
|
1692
1756
|
type: `state_disposal`,
|
|
1693
1757
|
subType: `selector`,
|
|
1694
|
-
token: selectorToken
|
|
1758
|
+
token: selectorToken,
|
|
1759
|
+
timestamp: Date.now()
|
|
1695
1760
|
});
|
|
1696
1761
|
}
|
|
1697
1762
|
break;
|
|
@@ -1706,7 +1771,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1706
1771
|
family.subject.next({
|
|
1707
1772
|
type: `state_disposal`,
|
|
1708
1773
|
subType: `selector`,
|
|
1709
|
-
token: selectorToken
|
|
1774
|
+
token: selectorToken,
|
|
1775
|
+
timestamp: Date.now()
|
|
1710
1776
|
});
|
|
1711
1777
|
}
|
|
1712
1778
|
break;
|
|
@@ -1721,7 +1787,8 @@ function disposeSelector(store, selectorToken) {
|
|
|
1721
1787
|
family.subject.next({
|
|
1722
1788
|
type: `state_disposal`,
|
|
1723
1789
|
subType: `selector`,
|
|
1724
|
-
token: selectorToken
|
|
1790
|
+
token: selectorToken,
|
|
1791
|
+
timestamp: Date.now()
|
|
1725
1792
|
});
|
|
1726
1793
|
}
|
|
1727
1794
|
break;
|
|
@@ -1731,10 +1798,11 @@ function disposeSelector(store, selectorToken) {
|
|
|
1731
1798
|
target.selectorGraph.delete(key);
|
|
1732
1799
|
target.moleculeData.delete(familyMeta.key, familyMeta.subKey);
|
|
1733
1800
|
store.logger.info(`🔥`, selectorToken.type, key, `deleted`);
|
|
1734
|
-
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.
|
|
1801
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.subEvents.push({
|
|
1735
1802
|
type: `state_disposal`,
|
|
1736
1803
|
subType: `selector`,
|
|
1737
|
-
token: selectorToken
|
|
1804
|
+
token: selectorToken,
|
|
1805
|
+
timestamp: Date.now()
|
|
1738
1806
|
});
|
|
1739
1807
|
else store.on.selectorDisposal.next(selectorToken);
|
|
1740
1808
|
}
|
|
@@ -1766,7 +1834,8 @@ function createReadonlyPureSelectorFamily(store, options, internalRoles) {
|
|
|
1766
1834
|
}, family);
|
|
1767
1835
|
subject.next({
|
|
1768
1836
|
type: `state_creation`,
|
|
1769
|
-
token
|
|
1837
|
+
token,
|
|
1838
|
+
timestamp: Date.now()
|
|
1770
1839
|
});
|
|
1771
1840
|
return token;
|
|
1772
1841
|
};
|
|
@@ -1814,7 +1883,8 @@ function createRegularAtomFamily(store, options, internalRoles) {
|
|
|
1814
1883
|
const token = createRegularAtom(target, individualOptions, family);
|
|
1815
1884
|
subject.next({
|
|
1816
1885
|
type: `state_creation`,
|
|
1817
|
-
token
|
|
1886
|
+
token,
|
|
1887
|
+
timestamp: Date.now()
|
|
1818
1888
|
});
|
|
1819
1889
|
return token;
|
|
1820
1890
|
};
|
|
@@ -1855,7 +1925,8 @@ function createReadonlyHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1855
1925
|
}, family);
|
|
1856
1926
|
subject.next({
|
|
1857
1927
|
type: `state_creation`,
|
|
1858
|
-
token
|
|
1928
|
+
token,
|
|
1929
|
+
timestamp: Date.now()
|
|
1859
1930
|
});
|
|
1860
1931
|
return token;
|
|
1861
1932
|
};
|
|
@@ -1897,7 +1968,8 @@ function createWritableHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1897
1968
|
}, family);
|
|
1898
1969
|
subject.next({
|
|
1899
1970
|
type: `state_creation`,
|
|
1900
|
-
token
|
|
1971
|
+
token,
|
|
1972
|
+
timestamp: Date.now()
|
|
1901
1973
|
});
|
|
1902
1974
|
return token;
|
|
1903
1975
|
};
|
|
@@ -1938,7 +2010,8 @@ function createWritablePureSelectorFamily(store, options, internalRoles) {
|
|
|
1938
2010
|
}, family);
|
|
1939
2011
|
subject.next({
|
|
1940
2012
|
type: `state_creation`,
|
|
1941
|
-
token
|
|
2013
|
+
token,
|
|
2014
|
+
timestamp: Date.now()
|
|
1942
2015
|
});
|
|
1943
2016
|
return token;
|
|
1944
2017
|
};
|
|
@@ -1970,34 +2043,6 @@ function createSelectorFamily(store, options) {
|
|
|
1970
2043
|
return createReadonlyPureSelectorFamily(store, options);
|
|
1971
2044
|
}
|
|
1972
2045
|
|
|
1973
|
-
//#endregion
|
|
1974
|
-
//#region src/internal/families/init-family-member.ts
|
|
1975
|
-
function initFamilyMemberInStore(store, token, key) {
|
|
1976
|
-
const family = store.families.get(token.key);
|
|
1977
|
-
if (family === void 0) throw new NotFoundError(token, store);
|
|
1978
|
-
const state = family(key);
|
|
1979
|
-
const target = newest(store);
|
|
1980
|
-
if (state.family) {
|
|
1981
|
-
if (isRootStore(target)) switch (state.type) {
|
|
1982
|
-
case `atom`:
|
|
1983
|
-
case `mutable_atom`:
|
|
1984
|
-
store.on.atomCreation.next(state);
|
|
1985
|
-
break;
|
|
1986
|
-
case `writable_pure_selector`:
|
|
1987
|
-
case `readonly_pure_selector`:
|
|
1988
|
-
case `writable_held_selector`:
|
|
1989
|
-
case `readonly_held_selector`:
|
|
1990
|
-
store.on.selectorCreation.next(state);
|
|
1991
|
-
break;
|
|
1992
|
-
}
|
|
1993
|
-
else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.updates.push({
|
|
1994
|
-
type: `state_creation`,
|
|
1995
|
-
token: state
|
|
1996
|
-
});
|
|
1997
|
-
}
|
|
1998
|
-
return state;
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
2046
|
//#endregion
|
|
2002
2047
|
//#region src/internal/families/seek-in-store.ts
|
|
2003
2048
|
function seekInStore(store, token, key) {
|
|
@@ -2025,22 +2070,11 @@ function seekInStore(store, token, key) {
|
|
|
2025
2070
|
|
|
2026
2071
|
//#endregion
|
|
2027
2072
|
//#region src/internal/families/find-in-store.ts
|
|
2028
|
-
function findInStore(store,
|
|
2029
|
-
|
|
2030
|
-
if (
|
|
2031
|
-
const
|
|
2032
|
-
|
|
2033
|
-
if (!molecule && store.config.lifespan === `immortal`) {
|
|
2034
|
-
const fakeToken = counterfeit(token, key);
|
|
2035
|
-
store.logger.error(`❌`, fakeToken.type, fakeToken.key, `was not found in store "${store.config.name}"; returned a counterfeit token.`);
|
|
2036
|
-
return fakeToken;
|
|
2037
|
-
}
|
|
2038
|
-
state = initFamilyMemberInStore(store, token, key);
|
|
2039
|
-
if (molecule) {
|
|
2040
|
-
const target = newest(store);
|
|
2041
|
-
target.moleculeData.set(stringKey, token.key);
|
|
2042
|
-
}
|
|
2043
|
-
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;
|
|
2044
2078
|
}
|
|
2045
2079
|
|
|
2046
2080
|
//#endregion
|
|
@@ -2275,7 +2309,7 @@ var Tracker = class {
|
|
|
2275
2309
|
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
2276
2310
|
const stateKey = mutableState.key;
|
|
2277
2311
|
const storeName = target.config.name;
|
|
2278
|
-
const storeStatus = isChildStore(target) ? target.transactionMeta.update.key : `main`;
|
|
2312
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
2279
2313
|
const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`;
|
|
2280
2314
|
const trackerCapturesOutboundSignal = (update) => {
|
|
2281
2315
|
setIntoStore(target, latestSignalState, update);
|
|
@@ -2290,7 +2324,7 @@ var Tracker = class {
|
|
|
2290
2324
|
}.bind(this));
|
|
2291
2325
|
}
|
|
2292
2326
|
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
2293
|
-
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}`;
|
|
2294
2328
|
subscribeToState(target, latestSignalState, subscriptionKey, function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
2295
2329
|
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
2296
2330
|
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
@@ -2454,7 +2488,8 @@ function createMutableAtomFamily(store, options, internalRoles) {
|
|
|
2454
2488
|
const token = createMutableAtom(target, individualOptions, family);
|
|
2455
2489
|
subject.next({
|
|
2456
2490
|
type: `state_creation`,
|
|
2457
|
-
token
|
|
2491
|
+
token,
|
|
2492
|
+
timestamp: Date.now()
|
|
2458
2493
|
});
|
|
2459
2494
|
return token;
|
|
2460
2495
|
};
|
|
@@ -2533,7 +2568,7 @@ const getUpdateToken = (mutableAtomToken) => {
|
|
|
2533
2568
|
//#endregion
|
|
2534
2569
|
//#region src/internal/mutable/transceiver.ts
|
|
2535
2570
|
function isTransceiver(value) {
|
|
2536
|
-
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;
|
|
2537
2572
|
}
|
|
2538
2573
|
|
|
2539
2574
|
//#endregion
|
|
@@ -2733,7 +2768,8 @@ function disposeAtom(store, atomToken) {
|
|
|
2733
2768
|
type: `state_disposal`,
|
|
2734
2769
|
subType: `atom`,
|
|
2735
2770
|
token: atomToken,
|
|
2736
|
-
value: lastValue
|
|
2771
|
+
value: lastValue,
|
|
2772
|
+
timestamp: Date.now()
|
|
2737
2773
|
};
|
|
2738
2774
|
atomFamily$1.subject.next(disposal);
|
|
2739
2775
|
const isChild = isChildStore(target);
|
|
@@ -2750,14 +2786,22 @@ function disposeAtom(store, atomToken) {
|
|
|
2750
2786
|
}
|
|
2751
2787
|
store.logger.info(`🔥`, `atom`, key, `deleted`);
|
|
2752
2788
|
if (isChild && target.transactionMeta.phase === `building`) {
|
|
2753
|
-
const mostRecentUpdate = target.transactionMeta.update.
|
|
2789
|
+
const mostRecentUpdate = target.transactionMeta.update.subEvents.at(-1);
|
|
2754
2790
|
const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
|
|
2755
2791
|
const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
2756
|
-
if (!updateAlreadyCaptured) target.transactionMeta.update.
|
|
2792
|
+
if (!updateAlreadyCaptured) target.transactionMeta.update.subEvents.push(disposal);
|
|
2757
2793
|
} else store.on.atomDisposal.next(atomToken);
|
|
2758
2794
|
}
|
|
2759
2795
|
}
|
|
2760
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
|
+
|
|
2761
2805
|
//#endregion
|
|
2762
2806
|
//#region src/internal/install-into-store.ts
|
|
2763
2807
|
/**
|
|
@@ -2771,12 +2815,12 @@ function disposeAtom(store, atomToken) {
|
|
|
2771
2815
|
function installIntoStore(tokens, target, source) {
|
|
2772
2816
|
const sourceNewest = newest(source);
|
|
2773
2817
|
if (isChildStore(sourceNewest)) {
|
|
2774
|
-
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.`);
|
|
2775
2819
|
return;
|
|
2776
2820
|
}
|
|
2777
2821
|
const targetNewest = newest(target);
|
|
2778
2822
|
if (isChildStore(targetNewest)) {
|
|
2779
|
-
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.`);
|
|
2780
2824
|
return;
|
|
2781
2825
|
}
|
|
2782
2826
|
for (const token of tokens) {
|
|
@@ -3327,37 +3371,39 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3327
3371
|
}, { topicType: `atom` });
|
|
3328
3372
|
tl.subscriptions.set(atom.key, atom.subject.subscribe(`timeline`, function timelineCapturesAtomUpdate(update) {
|
|
3329
3373
|
const target = newest(store);
|
|
3330
|
-
const
|
|
3331
|
-
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;
|
|
3332
3376
|
const txUpdateInProgress = target.on.transactionApplying.state?.update;
|
|
3333
|
-
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}"` : ``);
|
|
3334
3378
|
if (tl.timeTraveling === null) if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress);
|
|
3335
|
-
else if (
|
|
3379
|
+
else if (currentSelectorToken && currentSelectorTime) {
|
|
3336
3380
|
let latestUpdate = tl.history.at(-1);
|
|
3337
3381
|
if (currentSelectorTime !== tl.selectorTime) {
|
|
3338
3382
|
latestUpdate = {
|
|
3339
3383
|
type: `selector_update`,
|
|
3340
3384
|
timestamp: currentSelectorTime,
|
|
3341
|
-
|
|
3385
|
+
token: currentSelectorToken,
|
|
3342
3386
|
atomUpdates: []
|
|
3343
3387
|
};
|
|
3344
3388
|
latestUpdate.atomUpdates.push({
|
|
3345
|
-
key: atom.key,
|
|
3346
3389
|
type: `atom_update`,
|
|
3347
|
-
|
|
3390
|
+
token: atomToken,
|
|
3391
|
+
update,
|
|
3392
|
+
timestamp: Date.now()
|
|
3348
3393
|
});
|
|
3349
3394
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3350
3395
|
tl.history.push(latestUpdate);
|
|
3351
|
-
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));
|
|
3352
3397
|
tl.at = tl.history.length;
|
|
3353
3398
|
tl.selectorTime = currentSelectorTime;
|
|
3354
3399
|
} else if (latestUpdate?.type === `selector_update`) {
|
|
3355
3400
|
latestUpdate.atomUpdates.push({
|
|
3356
|
-
key: atom.key,
|
|
3357
3401
|
type: `atom_update`,
|
|
3358
|
-
|
|
3402
|
+
token: atomToken,
|
|
3403
|
+
update,
|
|
3404
|
+
timestamp: Date.now()
|
|
3359
3405
|
});
|
|
3360
|
-
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));
|
|
3361
3407
|
}
|
|
3362
3408
|
if (latestUpdate) {
|
|
3363
3409
|
const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
|
|
@@ -3373,12 +3419,10 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3373
3419
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3374
3420
|
const atomUpdate = {
|
|
3375
3421
|
type: `atom_update`,
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
newValue: update.newValue
|
|
3422
|
+
token: deposit(atom),
|
|
3423
|
+
update,
|
|
3424
|
+
timestamp
|
|
3380
3425
|
};
|
|
3381
|
-
if (atom.family) atomUpdate.family = atom.family;
|
|
3382
3426
|
const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
|
|
3383
3427
|
store.logger.info(`⌛`, `timeline`, tl.key, `got an atom_update to "${atom.key}"`);
|
|
3384
3428
|
if (willCapture) {
|
|
@@ -3401,7 +3445,7 @@ function addAtomFamilyToTimeline(store, atomFamilyToken, tl) {
|
|
|
3401
3445
|
for (const atom of store.atoms.values()) if (atom.family?.key === family.key) addAtomToTimeline(store, atom, tl);
|
|
3402
3446
|
}
|
|
3403
3447
|
function joinTransaction(store, tl, txUpdateInProgress) {
|
|
3404
|
-
const currentTxKey = txUpdateInProgress.key;
|
|
3448
|
+
const currentTxKey = txUpdateInProgress.token.key;
|
|
3405
3449
|
const currentTxInstanceId = txUpdateInProgress.id;
|
|
3406
3450
|
const currentTxToken = {
|
|
3407
3451
|
key: currentTxKey,
|
|
@@ -3416,11 +3460,10 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3416
3460
|
if (tl.timeTraveling === null && currentTxInstanceId) {
|
|
3417
3461
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3418
3462
|
const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
|
|
3419
|
-
const
|
|
3463
|
+
const subEventsFiltered = filterTransactionSubEvents(transactionUpdate.subEvents, timelineTopics);
|
|
3420
3464
|
const timelineTransactionUpdate = {
|
|
3421
|
-
timestamp: Date.now(),
|
|
3422
3465
|
...transactionUpdate,
|
|
3423
|
-
|
|
3466
|
+
subEvents: subEventsFiltered
|
|
3424
3467
|
};
|
|
3425
3468
|
const willCapture = tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true;
|
|
3426
3469
|
if (willCapture) {
|
|
@@ -3432,12 +3475,13 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3432
3475
|
});
|
|
3433
3476
|
}
|
|
3434
3477
|
}
|
|
3435
|
-
function
|
|
3478
|
+
function filterTransactionSubEvents(updates, timelineTopics) {
|
|
3436
3479
|
return updates.filter((updateFromTx) => {
|
|
3437
|
-
if (updateFromTx.type === `
|
|
3480
|
+
if (updateFromTx.type === `transaction_outcome`) return true;
|
|
3438
3481
|
let key;
|
|
3439
3482
|
let familyKey;
|
|
3440
3483
|
switch (updateFromTx.type) {
|
|
3484
|
+
case `atom_update`:
|
|
3441
3485
|
case `state_creation`:
|
|
3442
3486
|
case `state_disposal`:
|
|
3443
3487
|
key = updateFromTx.token.key;
|
|
@@ -3446,35 +3490,28 @@ function filterTransactionUpdates(updates, timelineTopics) {
|
|
|
3446
3490
|
case `molecule_creation`:
|
|
3447
3491
|
case `molecule_disposal`:
|
|
3448
3492
|
case `molecule_transfer`: return true;
|
|
3449
|
-
case `atom_update`:
|
|
3450
|
-
case `selector_update`:
|
|
3451
|
-
key = updateFromTx.key;
|
|
3452
|
-
familyKey = updateFromTx.family?.key;
|
|
3453
|
-
break;
|
|
3454
3493
|
}
|
|
3455
3494
|
timelineTopics.has(key);
|
|
3456
3495
|
if (familyKey && timelineTopics.has(familyKey)) return true;
|
|
3457
3496
|
return timelineTopics.has(key);
|
|
3458
3497
|
}).map((updateFromTx) => {
|
|
3459
|
-
if (`
|
|
3498
|
+
if (`subEvents` in updateFromTx) return {
|
|
3460
3499
|
...updateFromTx,
|
|
3461
|
-
|
|
3500
|
+
subEvents: filterTransactionSubEvents(updateFromTx.subEvents, timelineTopics)
|
|
3462
3501
|
};
|
|
3463
3502
|
return updateFromTx;
|
|
3464
3503
|
});
|
|
3465
3504
|
}
|
|
3466
3505
|
function handleStateLifecycleEvent(store, event, tl) {
|
|
3467
|
-
const timestamp = Date.now();
|
|
3468
|
-
const timelineEvent = Object.assign(event, { timestamp });
|
|
3469
3506
|
if (!tl.timeTraveling) {
|
|
3470
3507
|
const target = newest(store);
|
|
3471
3508
|
if (isChildStore(target)) {} else {
|
|
3472
3509
|
const txUpdateInProgress = target.on.transactionApplying.state;
|
|
3473
3510
|
if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress.update);
|
|
3474
3511
|
else {
|
|
3475
|
-
tl.history.push(
|
|
3512
|
+
tl.history.push(event);
|
|
3476
3513
|
tl.at = tl.history.length;
|
|
3477
|
-
tl.subject.next(
|
|
3514
|
+
tl.subject.next(event);
|
|
3478
3515
|
}
|
|
3479
3516
|
}
|
|
3480
3517
|
}
|
|
@@ -3513,7 +3550,7 @@ const timeTravel = (store, action, token) => {
|
|
|
3513
3550
|
case `selector_update`:
|
|
3514
3551
|
ingestSelectorUpdate(applying, update, store);
|
|
3515
3552
|
break;
|
|
3516
|
-
case `
|
|
3553
|
+
case `transaction_outcome`:
|
|
3517
3554
|
ingestTransactionUpdate(applying, update, store);
|
|
3518
3555
|
break;
|
|
3519
3556
|
case `state_creation`:
|