atom.io 0.36.3 → 0.37.1
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 +71 -102
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +566 -515
- 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 +6 -6
- package/src/internal/atom/dispose-atom.ts +16 -9
- 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 +7 -7
- 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/get-from-store.ts +19 -6
- package/src/internal/get-state/read-or-compute-value.ts +4 -2
- package/src/internal/index.ts +25 -36
- 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 +4 -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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
}
|
|
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;
|
|
834
|
+
}
|
|
835
|
+
return protoUpdate;
|
|
836
|
+
};
|
|
1021
837
|
|
|
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,17 +1883,19 @@ 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
|
};
|
|
1819
1891
|
const atomFamily$1 = Object.assign(familyFunction, familyToken, {
|
|
1892
|
+
default: options.default,
|
|
1820
1893
|
subject,
|
|
1821
1894
|
install: (s) => createRegularAtomFamily(s, options),
|
|
1822
1895
|
internalRoles
|
|
1823
1896
|
});
|
|
1824
1897
|
store.families.set(options.key, atomFamily$1);
|
|
1825
|
-
store.defaults.set(options.key, options.default);
|
|
1898
|
+
if (options.default instanceof Function === false) store.defaults.set(options.key, options.default);
|
|
1826
1899
|
return familyToken;
|
|
1827
1900
|
}
|
|
1828
1901
|
|
|
@@ -1853,7 +1926,8 @@ function createReadonlyHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1853
1926
|
}, family);
|
|
1854
1927
|
subject.next({
|
|
1855
1928
|
type: `state_creation`,
|
|
1856
|
-
token
|
|
1929
|
+
token,
|
|
1930
|
+
timestamp: Date.now()
|
|
1857
1931
|
});
|
|
1858
1932
|
return token;
|
|
1859
1933
|
};
|
|
@@ -1895,7 +1969,8 @@ function createWritableHeldSelectorFamily(store, options, internalRoles) {
|
|
|
1895
1969
|
}, family);
|
|
1896
1970
|
subject.next({
|
|
1897
1971
|
type: `state_creation`,
|
|
1898
|
-
token
|
|
1972
|
+
token,
|
|
1973
|
+
timestamp: Date.now()
|
|
1899
1974
|
});
|
|
1900
1975
|
return token;
|
|
1901
1976
|
};
|
|
@@ -1936,7 +2011,8 @@ function createWritablePureSelectorFamily(store, options, internalRoles) {
|
|
|
1936
2011
|
}, family);
|
|
1937
2012
|
subject.next({
|
|
1938
2013
|
type: `state_creation`,
|
|
1939
|
-
token
|
|
2014
|
+
token,
|
|
2015
|
+
timestamp: Date.now()
|
|
1940
2016
|
});
|
|
1941
2017
|
return token;
|
|
1942
2018
|
};
|
|
@@ -1968,34 +2044,6 @@ function createSelectorFamily(store, options) {
|
|
|
1968
2044
|
return createReadonlyPureSelectorFamily(store, options);
|
|
1969
2045
|
}
|
|
1970
2046
|
|
|
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
2047
|
//#endregion
|
|
2000
2048
|
//#region src/internal/families/seek-in-store.ts
|
|
2001
2049
|
function seekInStore(store, token, key) {
|
|
@@ -2023,22 +2071,11 @@ function seekInStore(store, token, key) {
|
|
|
2023
2071
|
|
|
2024
2072
|
//#endregion
|
|
2025
2073
|
//#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;
|
|
2074
|
+
function findInStore(store, familyToken, key) {
|
|
2075
|
+
const existingStateToken = seekInStore(store, familyToken, key);
|
|
2076
|
+
if (existingStateToken) return existingStateToken;
|
|
2077
|
+
const newStateToken = mintInStore(store, familyToken, key);
|
|
2078
|
+
return newStateToken;
|
|
2042
2079
|
}
|
|
2043
2080
|
|
|
2044
2081
|
//#endregion
|
|
@@ -2090,14 +2127,25 @@ function getFromStore(store, ...params) {
|
|
|
2090
2127
|
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
2091
2128
|
store.logger.error(`❌`, token.type, token.key, `could not be retrieved 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.`);
|
|
2092
2129
|
switch (family.type) {
|
|
2093
|
-
case `
|
|
2094
|
-
|
|
2130
|
+
case `mutable_atom_family`: {
|
|
2131
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
2132
|
+
const mutableFamily = withdraw(store, family);
|
|
2133
|
+
const defaultValue = new mutableFamily.class();
|
|
2134
|
+
store.defaults.set(family.key, defaultValue);
|
|
2135
|
+
return defaultValue;
|
|
2136
|
+
}
|
|
2137
|
+
case `atom_family`: {
|
|
2138
|
+
if (store.defaults.has(family.key)) return store.defaults.get(token.family.key);
|
|
2139
|
+
const defaultValue = withdraw(store, family).default(parseJson(subKey));
|
|
2140
|
+
store.defaults.set(family.key, defaultValue);
|
|
2141
|
+
return defaultValue;
|
|
2142
|
+
}
|
|
2095
2143
|
case `readonly_pure_selector_family`:
|
|
2096
2144
|
case `writable_pure_selector_family`:
|
|
2097
2145
|
case `readonly_held_selector_family`:
|
|
2098
2146
|
case `writable_held_selector_family`: {
|
|
2099
2147
|
if (store.defaults.has(family.key)) return store.defaults.get(token.family.key);
|
|
2100
|
-
const defaultValue = withdraw(store, family).default(subKey);
|
|
2148
|
+
const defaultValue = withdraw(store, family).default(parseJson(subKey));
|
|
2101
2149
|
store.defaults.set(family.key, defaultValue);
|
|
2102
2150
|
return defaultValue;
|
|
2103
2151
|
}
|
|
@@ -2273,7 +2321,7 @@ var Tracker = class {
|
|
|
2273
2321
|
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
2274
2322
|
const stateKey = mutableState.key;
|
|
2275
2323
|
const storeName = target.config.name;
|
|
2276
|
-
const storeStatus = isChildStore(target) ? target.transactionMeta.update.key : `main`;
|
|
2324
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
2277
2325
|
const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`;
|
|
2278
2326
|
const trackerCapturesOutboundSignal = (update) => {
|
|
2279
2327
|
setIntoStore(target, latestSignalState, update);
|
|
@@ -2288,7 +2336,7 @@ var Tracker = class {
|
|
|
2288
2336
|
}.bind(this));
|
|
2289
2337
|
}
|
|
2290
2338
|
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
2291
|
-
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
|
|
2339
|
+
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.token.key : `main`}:${mutableState.key}`;
|
|
2292
2340
|
subscribeToState(target, latestSignalState, subscriptionKey, function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
2293
2341
|
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
2294
2342
|
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
@@ -2452,11 +2500,13 @@ function createMutableAtomFamily(store, options, internalRoles) {
|
|
|
2452
2500
|
const token = createMutableAtom(target, individualOptions, family);
|
|
2453
2501
|
subject.next({
|
|
2454
2502
|
type: `state_creation`,
|
|
2455
|
-
token
|
|
2503
|
+
token,
|
|
2504
|
+
timestamp: Date.now()
|
|
2456
2505
|
});
|
|
2457
2506
|
return token;
|
|
2458
2507
|
};
|
|
2459
2508
|
const atomFamily$1 = Object.assign(familyFunction, familyToken, {
|
|
2509
|
+
class: options.class,
|
|
2460
2510
|
subject,
|
|
2461
2511
|
install: (s) => createMutableAtomFamily(s, options),
|
|
2462
2512
|
internalRoles
|
|
@@ -2531,7 +2581,7 @@ const getUpdateToken = (mutableAtomToken) => {
|
|
|
2531
2581
|
//#endregion
|
|
2532
2582
|
//#region src/internal/mutable/transceiver.ts
|
|
2533
2583
|
function isTransceiver(value) {
|
|
2534
|
-
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
|
|
2584
|
+
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
2585
|
}
|
|
2536
2586
|
|
|
2537
2587
|
//#endregion
|
|
@@ -2723,17 +2773,17 @@ function disposeAtom(store, atomToken) {
|
|
|
2723
2773
|
else {
|
|
2724
2774
|
atom.cleanup?.();
|
|
2725
2775
|
const lastValue = store.valueMap.get(atom.key);
|
|
2726
|
-
const
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
});
|
|
2776
|
+
const familyToken = getFamilyOfToken(store, atomToken);
|
|
2777
|
+
const atomFamily$1 = withdraw(store, familyToken);
|
|
2778
|
+
const subject = atomFamily$1.subject;
|
|
2730
2779
|
const disposal = {
|
|
2731
2780
|
type: `state_disposal`,
|
|
2732
2781
|
subType: `atom`,
|
|
2733
2782
|
token: atomToken,
|
|
2734
|
-
value: lastValue
|
|
2783
|
+
value: lastValue,
|
|
2784
|
+
timestamp: Date.now()
|
|
2735
2785
|
};
|
|
2736
|
-
|
|
2786
|
+
subject.next(disposal);
|
|
2737
2787
|
const isChild = isChildStore(target);
|
|
2738
2788
|
target.atoms.delete(key);
|
|
2739
2789
|
target.valueMap.delete(key);
|
|
@@ -2748,14 +2798,22 @@ function disposeAtom(store, atomToken) {
|
|
|
2748
2798
|
}
|
|
2749
2799
|
store.logger.info(`🔥`, `atom`, key, `deleted`);
|
|
2750
2800
|
if (isChild && target.transactionMeta.phase === `building`) {
|
|
2751
|
-
const mostRecentUpdate = target.transactionMeta.update.
|
|
2801
|
+
const mostRecentUpdate = target.transactionMeta.update.subEvents.at(-1);
|
|
2752
2802
|
const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
|
|
2753
2803
|
const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
2754
|
-
if (!updateAlreadyCaptured) target.transactionMeta.update.
|
|
2804
|
+
if (!updateAlreadyCaptured) target.transactionMeta.update.subEvents.push(disposal);
|
|
2755
2805
|
} else store.on.atomDisposal.next(atomToken);
|
|
2756
2806
|
}
|
|
2757
2807
|
}
|
|
2758
2808
|
|
|
2809
|
+
//#endregion
|
|
2810
|
+
//#region src/internal/atom/has-role.ts
|
|
2811
|
+
const INTERNAL_ROLES = [`tracker:signal`];
|
|
2812
|
+
function hasRole(atom, role) {
|
|
2813
|
+
if (`internalRoles` in atom === false) return false;
|
|
2814
|
+
return atom.internalRoles.includes(role);
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2759
2817
|
//#endregion
|
|
2760
2818
|
//#region src/internal/install-into-store.ts
|
|
2761
2819
|
/**
|
|
@@ -2769,12 +2827,12 @@ function disposeAtom(store, atomToken) {
|
|
|
2769
2827
|
function installIntoStore(tokens, target, source) {
|
|
2770
2828
|
const sourceNewest = newest(source);
|
|
2771
2829
|
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.`);
|
|
2830
|
+
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
2831
|
return;
|
|
2774
2832
|
}
|
|
2775
2833
|
const targetNewest = newest(target);
|
|
2776
2834
|
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.`);
|
|
2835
|
+
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
2836
|
return;
|
|
2779
2837
|
}
|
|
2780
2838
|
for (const token of tokens) {
|
|
@@ -3325,37 +3383,39 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3325
3383
|
}, { topicType: `atom` });
|
|
3326
3384
|
tl.subscriptions.set(atom.key, atom.subject.subscribe(`timeline`, function timelineCapturesAtomUpdate(update) {
|
|
3327
3385
|
const target = newest(store);
|
|
3328
|
-
const
|
|
3329
|
-
const currentSelectorTime = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.
|
|
3386
|
+
const currentSelectorToken = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.token : null;
|
|
3387
|
+
const currentSelectorTime = store.operation.open && store.operation.token.type === `writable_pure_selector` ? store.operation.timestamp : null;
|
|
3330
3388
|
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}"` :
|
|
3389
|
+
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
3390
|
if (tl.timeTraveling === null) if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress);
|
|
3333
|
-
else if (
|
|
3391
|
+
else if (currentSelectorToken && currentSelectorTime) {
|
|
3334
3392
|
let latestUpdate = tl.history.at(-1);
|
|
3335
3393
|
if (currentSelectorTime !== tl.selectorTime) {
|
|
3336
3394
|
latestUpdate = {
|
|
3337
3395
|
type: `selector_update`,
|
|
3338
3396
|
timestamp: currentSelectorTime,
|
|
3339
|
-
|
|
3397
|
+
token: currentSelectorToken,
|
|
3340
3398
|
atomUpdates: []
|
|
3341
3399
|
};
|
|
3342
3400
|
latestUpdate.atomUpdates.push({
|
|
3343
|
-
key: atom.key,
|
|
3344
3401
|
type: `atom_update`,
|
|
3345
|
-
|
|
3402
|
+
token: atomToken,
|
|
3403
|
+
update,
|
|
3404
|
+
timestamp: Date.now()
|
|
3346
3405
|
});
|
|
3347
3406
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3348
3407
|
tl.history.push(latestUpdate);
|
|
3349
|
-
store.logger.info(`⌛`, `timeline`, tl.key, `got a selector_update "${
|
|
3408
|
+
store.logger.info(`⌛`, `timeline`, tl.key, `got a selector_update "${currentSelectorToken.key}" with`, latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.token.key));
|
|
3350
3409
|
tl.at = tl.history.length;
|
|
3351
3410
|
tl.selectorTime = currentSelectorTime;
|
|
3352
3411
|
} else if (latestUpdate?.type === `selector_update`) {
|
|
3353
3412
|
latestUpdate.atomUpdates.push({
|
|
3354
|
-
key: atom.key,
|
|
3355
3413
|
type: `atom_update`,
|
|
3356
|
-
|
|
3414
|
+
token: atomToken,
|
|
3415
|
+
update,
|
|
3416
|
+
timestamp: Date.now()
|
|
3357
3417
|
});
|
|
3358
|
-
store.logger.info(`⌛`, `timeline`, tl.key, `set selector_update "${
|
|
3418
|
+
store.logger.info(`⌛`, `timeline`, tl.key, `set selector_update "${currentSelectorToken.key}" to`, latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.token.key));
|
|
3359
3419
|
}
|
|
3360
3420
|
if (latestUpdate) {
|
|
3361
3421
|
const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
|
|
@@ -3371,12 +3431,10 @@ function addAtomToTimeline(store, atomToken, tl) {
|
|
|
3371
3431
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3372
3432
|
const atomUpdate = {
|
|
3373
3433
|
type: `atom_update`,
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
newValue: update.newValue
|
|
3434
|
+
token: deposit(atom),
|
|
3435
|
+
update,
|
|
3436
|
+
timestamp
|
|
3378
3437
|
};
|
|
3379
|
-
if (atom.family) atomUpdate.family = atom.family;
|
|
3380
3438
|
const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
|
|
3381
3439
|
store.logger.info(`⌛`, `timeline`, tl.key, `got an atom_update to "${atom.key}"`);
|
|
3382
3440
|
if (willCapture) {
|
|
@@ -3399,7 +3457,7 @@ function addAtomFamilyToTimeline(store, atomFamilyToken, tl) {
|
|
|
3399
3457
|
for (const atom of store.atoms.values()) if (atom.family?.key === family.key) addAtomToTimeline(store, atom, tl);
|
|
3400
3458
|
}
|
|
3401
3459
|
function joinTransaction(store, tl, txUpdateInProgress) {
|
|
3402
|
-
const currentTxKey = txUpdateInProgress.key;
|
|
3460
|
+
const currentTxKey = txUpdateInProgress.token.key;
|
|
3403
3461
|
const currentTxInstanceId = txUpdateInProgress.id;
|
|
3404
3462
|
const currentTxToken = {
|
|
3405
3463
|
key: currentTxKey,
|
|
@@ -3414,11 +3472,10 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3414
3472
|
if (tl.timeTraveling === null && currentTxInstanceId) {
|
|
3415
3473
|
if (tl.at !== tl.history.length) tl.history.splice(tl.at);
|
|
3416
3474
|
const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
|
|
3417
|
-
const
|
|
3475
|
+
const subEventsFiltered = filterTransactionSubEvents(transactionUpdate.subEvents, timelineTopics);
|
|
3418
3476
|
const timelineTransactionUpdate = {
|
|
3419
|
-
timestamp: Date.now(),
|
|
3420
3477
|
...transactionUpdate,
|
|
3421
|
-
|
|
3478
|
+
subEvents: subEventsFiltered
|
|
3422
3479
|
};
|
|
3423
3480
|
const willCapture = tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true;
|
|
3424
3481
|
if (willCapture) {
|
|
@@ -3430,12 +3487,13 @@ function joinTransaction(store, tl, txUpdateInProgress) {
|
|
|
3430
3487
|
});
|
|
3431
3488
|
}
|
|
3432
3489
|
}
|
|
3433
|
-
function
|
|
3490
|
+
function filterTransactionSubEvents(updates, timelineTopics) {
|
|
3434
3491
|
return updates.filter((updateFromTx) => {
|
|
3435
|
-
if (updateFromTx.type === `
|
|
3492
|
+
if (updateFromTx.type === `transaction_outcome`) return true;
|
|
3436
3493
|
let key;
|
|
3437
3494
|
let familyKey;
|
|
3438
3495
|
switch (updateFromTx.type) {
|
|
3496
|
+
case `atom_update`:
|
|
3439
3497
|
case `state_creation`:
|
|
3440
3498
|
case `state_disposal`:
|
|
3441
3499
|
key = updateFromTx.token.key;
|
|
@@ -3444,35 +3502,28 @@ function filterTransactionUpdates(updates, timelineTopics) {
|
|
|
3444
3502
|
case `molecule_creation`:
|
|
3445
3503
|
case `molecule_disposal`:
|
|
3446
3504
|
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
3505
|
}
|
|
3453
3506
|
timelineTopics.has(key);
|
|
3454
3507
|
if (familyKey && timelineTopics.has(familyKey)) return true;
|
|
3455
3508
|
return timelineTopics.has(key);
|
|
3456
3509
|
}).map((updateFromTx) => {
|
|
3457
|
-
if (`
|
|
3510
|
+
if (`subEvents` in updateFromTx) return {
|
|
3458
3511
|
...updateFromTx,
|
|
3459
|
-
|
|
3512
|
+
subEvents: filterTransactionSubEvents(updateFromTx.subEvents, timelineTopics)
|
|
3460
3513
|
};
|
|
3461
3514
|
return updateFromTx;
|
|
3462
3515
|
});
|
|
3463
3516
|
}
|
|
3464
3517
|
function handleStateLifecycleEvent(store, event, tl) {
|
|
3465
|
-
const timestamp = Date.now();
|
|
3466
|
-
const timelineEvent = Object.assign(event, { timestamp });
|
|
3467
3518
|
if (!tl.timeTraveling) {
|
|
3468
3519
|
const target = newest(store);
|
|
3469
3520
|
if (isChildStore(target)) {} else {
|
|
3470
3521
|
const txUpdateInProgress = target.on.transactionApplying.state;
|
|
3471
3522
|
if (txUpdateInProgress) joinTransaction(store, tl, txUpdateInProgress.update);
|
|
3472
3523
|
else {
|
|
3473
|
-
tl.history.push(
|
|
3524
|
+
tl.history.push(event);
|
|
3474
3525
|
tl.at = tl.history.length;
|
|
3475
|
-
tl.subject.next(
|
|
3526
|
+
tl.subject.next(event);
|
|
3476
3527
|
}
|
|
3477
3528
|
}
|
|
3478
3529
|
}
|
|
@@ -3511,7 +3562,7 @@ const timeTravel = (store, action, token) => {
|
|
|
3511
3562
|
case `selector_update`:
|
|
3512
3563
|
ingestSelectorUpdate(applying, update, store);
|
|
3513
3564
|
break;
|
|
3514
|
-
case `
|
|
3565
|
+
case `transaction_outcome`:
|
|
3515
3566
|
ingestTransactionUpdate(applying, update, store);
|
|
3516
3567
|
break;
|
|
3517
3568
|
case `state_creation`:
|