atom.io 0.40.7 → 0.40.9
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/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
- package/dist/data/index.js +1 -2
- package/dist/data/index.js.map +1 -1
- package/dist/eslint-plugin/index.js +2 -3
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/internal/index.d.ts +4 -3
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1231 -176
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +13 -32
- package/dist/introspection/index.js.map +1 -1
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +1 -2
- 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 +2 -4
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +29 -5
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +47 -5
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +2 -6
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +6 -22
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +6 -9
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +4 -16
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +38 -57
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +128 -178
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +2 -0
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +15 -9
- 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 +5 -9
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/transceivers/u-list/index.d.ts +29 -0
- package/dist/transceivers/u-list/index.d.ts.map +1 -0
- package/dist/transceivers/u-list/index.js +87 -0
- package/dist/transceivers/u-list/index.js.map +1 -0
- package/dist/web/index.js.map +1 -1
- package/package.json +17 -13
- package/src/internal/mutable/tracker.ts +61 -46
- package/src/internal/mutable/transceiver.ts +4 -4
- package/src/internal/set-state/index.ts +1 -0
- package/src/internal/subscribe/subscribe-to-state.ts +9 -0
- package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
- package/src/realtime/index.ts +2 -0
- package/src/realtime/shared-room-store.ts +12 -11
- package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
- package/src/realtime-client/index.ts +0 -1
- package/src/realtime-client/push-state.ts +1 -2
- package/src/realtime-react/index.ts +0 -1
- package/src/realtime-react/use-single-effect.ts +1 -1
- package/src/realtime-server/continuity/continuity-store.ts +2 -27
- package/src/realtime-server/continuity/provide-continuity.ts +50 -0
- package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +16 -14
- package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +11 -10
- package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +8 -6
- package/src/realtime-server/continuity/receive-action-requests.ts +66 -0
- package/src/realtime-server/continuity/{prepare-to-track-client-acknowledgement.ts → track-acknowledgements.ts} +15 -9
- package/src/realtime-server/index.ts +1 -3
- package/src/realtime-server/ipc-sockets/custom-socket.ts +4 -5
- package/src/realtime-server/ipc-sockets/parent-socket.ts +21 -17
- package/src/realtime-server/realtime-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
- package/src/realtime-server/realtime-mutable-provider.ts +1 -1
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
- package/src/realtime-server/realtime-state-provider.ts +1 -1
- package/src/realtime-server/realtime-state-receiver.ts +3 -6
- package/src/realtime-server/server-config.ts +1 -3
- package/src/realtime-testing/setup-realtime-test.tsx +23 -18
- package/src/transceivers/set-rtx/set-rtx.ts +3 -3
- package/src/transceivers/u-list/index.ts +1 -0
- package/src/transceivers/u-list/u-list.ts +123 -0
- package/dist/employ-socket-D6wgByWh.js +0 -12
- package/dist/employ-socket-D6wgByWh.js.map +0 -1
- package/dist/has-role-hv4-hJMw.js +0 -1149
- package/dist/has-role-hv4-hJMw.js.map +0 -1
- package/dist/is-fn-DY1wZ-md.js +0 -10
- package/dist/is-fn-DY1wZ-md.js.map +0 -1
- package/dist/mutex-store-CSvxY9i3.js +0 -11
- package/dist/mutex-store-CSvxY9i3.js.map +0 -1
- package/dist/shared-room-store-COGGKqes.js +0 -32
- package/dist/shared-room-store-COGGKqes.js.map +0 -1
- package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
- package/src/realtime-client/server-action.ts +0 -23
- package/src/realtime-react/use-server-action.ts +0 -19
- package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
- package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
- package/src/realtime-server/realtime-action-receiver.ts +0 -40
- /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
package/dist/internal/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { DO_NOT_CREATE, Future, INTERNAL_ROLES, JOIN_OP, NotFoundError, RESET_STATE, StatefulSubject, Subject, Tracker, become, closeOperation, createRegularAtom, deposit, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, getFallback, getFamilyOfToken, getFromStore, getSelectorDependencyKeys, hasRole, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markDone, mintInStore, newest, openOperation, operateOnStore, readFromCache, readOrComputeValue, recallState, reduceReference, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setIntoStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, traceRootSelectorAtoms, withdraw, writeToCache } from "../has-role-hv4-hJMw.js";
|
|
2
|
-
import { isFn } from "../is-fn-DY1wZ-md.js";
|
|
3
1
|
import { Anarchy, AtomIOLogger, PRETTY_TOKEN_TYPES } from "atom.io";
|
|
4
2
|
import { parseJson, stringifyJson } from "atom.io/json";
|
|
5
3
|
import { SetRTX } from "atom.io/transceivers/set-rtx";
|
|
@@ -9,6 +7,120 @@ function arbitrary(random = Math.random) {
|
|
|
9
7
|
return random().toString(36).slice(2);
|
|
10
8
|
}
|
|
11
9
|
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/internal/lineage.ts
|
|
12
|
+
function newest(scion) {
|
|
13
|
+
while (scion.child !== null) scion = scion.child;
|
|
14
|
+
return scion;
|
|
15
|
+
}
|
|
16
|
+
function eldest(scion) {
|
|
17
|
+
while (scion.parent !== null) scion = scion.parent;
|
|
18
|
+
return scion;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/internal/is-fn.ts
|
|
23
|
+
const NON_CTOR_FN_REGEX = /^\[object (?:Async|Generator|AsyncGenerator)?Function\]$/;
|
|
24
|
+
function isFn(input) {
|
|
25
|
+
const protoString = Object.prototype.toString.call(input);
|
|
26
|
+
return NON_CTOR_FN_REGEX.test(protoString);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/internal/set-state/become.ts
|
|
31
|
+
function become(nextVersionOfThing, originalThing) {
|
|
32
|
+
if (isFn(nextVersionOfThing)) return nextVersionOfThing(originalThing);
|
|
33
|
+
return nextVersionOfThing;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/internal/future.ts
|
|
38
|
+
/**
|
|
39
|
+
* A Promise whose incoming value can be hot swapped.
|
|
40
|
+
* @internal
|
|
41
|
+
* @private
|
|
42
|
+
* @typeParam T The type of the value that the promise will resolve to.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* Can be constructed like a Promise, or from an existing Promise.
|
|
46
|
+
*/
|
|
47
|
+
var Future = class extends Promise {
|
|
48
|
+
fate;
|
|
49
|
+
resolve;
|
|
50
|
+
reject;
|
|
51
|
+
done = false;
|
|
52
|
+
constructor(executor) {
|
|
53
|
+
let superResolve;
|
|
54
|
+
let superReject;
|
|
55
|
+
super((resolve, reject) => {
|
|
56
|
+
superResolve = resolve;
|
|
57
|
+
superReject = reject;
|
|
58
|
+
});
|
|
59
|
+
this.resolve = superResolve;
|
|
60
|
+
this.reject = superReject;
|
|
61
|
+
this.use(executor instanceof Promise ? executor : new Promise(executor));
|
|
62
|
+
}
|
|
63
|
+
pass(promise, value) {
|
|
64
|
+
if (promise === this.fate) {
|
|
65
|
+
this.resolve(value);
|
|
66
|
+
this.done = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
fail(promise, reason) {
|
|
70
|
+
if (promise === this.fate) {
|
|
71
|
+
this.reject(reason);
|
|
72
|
+
this.done = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
use(value) {
|
|
76
|
+
if (this === value) return;
|
|
77
|
+
if (value instanceof Promise) {
|
|
78
|
+
const promise = value;
|
|
79
|
+
this.fate = promise;
|
|
80
|
+
promise.then((resolved) => {
|
|
81
|
+
this.pass(promise, resolved);
|
|
82
|
+
}, (reason) => {
|
|
83
|
+
this.fail(promise, reason);
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
this.resolve(value);
|
|
87
|
+
this.fate = void 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/internal/subject.ts
|
|
94
|
+
var Subject = class {
|
|
95
|
+
Subscriber;
|
|
96
|
+
subscribers = /* @__PURE__ */ new Map();
|
|
97
|
+
subscribe(key, subscriber) {
|
|
98
|
+
this.subscribers.set(key, subscriber);
|
|
99
|
+
const unsubscribe = () => {
|
|
100
|
+
this.unsubscribe(key);
|
|
101
|
+
};
|
|
102
|
+
return unsubscribe;
|
|
103
|
+
}
|
|
104
|
+
unsubscribe(key) {
|
|
105
|
+
this.subscribers.delete(key);
|
|
106
|
+
}
|
|
107
|
+
next(value) {
|
|
108
|
+
const subscribers = this.subscribers.values();
|
|
109
|
+
for (const subscriber of subscribers) subscriber(value);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var StatefulSubject = class extends Subject {
|
|
113
|
+
state;
|
|
114
|
+
constructor(initialState) {
|
|
115
|
+
super();
|
|
116
|
+
this.state = initialState;
|
|
117
|
+
}
|
|
118
|
+
next(value) {
|
|
119
|
+
this.state = value;
|
|
120
|
+
super.next(value);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
12
124
|
//#endregion
|
|
13
125
|
//#region src/internal/store/circular-buffer.ts
|
|
14
126
|
var CircularBuffer = class CircularBuffer {
|
|
@@ -37,6 +149,17 @@ var CircularBuffer = class CircularBuffer {
|
|
|
37
149
|
}
|
|
38
150
|
};
|
|
39
151
|
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/internal/store/deposit.ts
|
|
154
|
+
function deposit(state) {
|
|
155
|
+
const token = {
|
|
156
|
+
key: state.key,
|
|
157
|
+
type: state.type
|
|
158
|
+
};
|
|
159
|
+
if (`family` in state) token.family = state.family;
|
|
160
|
+
return token;
|
|
161
|
+
}
|
|
162
|
+
|
|
40
163
|
//#endregion
|
|
41
164
|
//#region src/internal/overlays/map-overlay.ts
|
|
42
165
|
var MapOverlay = class extends Map {
|
|
@@ -48,13 +171,8 @@ var MapOverlay = class extends Map {
|
|
|
48
171
|
this.source = source;
|
|
49
172
|
}
|
|
50
173
|
get(key) {
|
|
51
|
-
|
|
52
|
-
if (has) return
|
|
53
|
-
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
54
|
-
const value = this.source.get(key);
|
|
55
|
-
return value;
|
|
56
|
-
}
|
|
57
|
-
return void 0;
|
|
174
|
+
if (super.has(key)) return super.get(key);
|
|
175
|
+
if (!this.deleted.has(key) && this.source.has(key)) return this.source.get(key);
|
|
58
176
|
}
|
|
59
177
|
set(key, value) {
|
|
60
178
|
this.deleted.delete(key);
|
|
@@ -156,15 +274,13 @@ var RelationsOverlay = class extends Map {
|
|
|
156
274
|
this.source = source;
|
|
157
275
|
}
|
|
158
276
|
get(key) {
|
|
159
|
-
|
|
160
|
-
if (has) return super.get(key);
|
|
277
|
+
if (super.has(key)) return super.get(key);
|
|
161
278
|
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
162
279
|
const value = this.source.get(key);
|
|
163
280
|
const valueOverlay = new SetOverlay(value);
|
|
164
281
|
super.set(key, valueOverlay);
|
|
165
282
|
return valueOverlay;
|
|
166
283
|
}
|
|
167
|
-
return void 0;
|
|
168
284
|
}
|
|
169
285
|
set(key, value) {
|
|
170
286
|
this.deleted.delete(key);
|
|
@@ -438,10 +554,7 @@ var Junction = class Junction {
|
|
|
438
554
|
return [];
|
|
439
555
|
}
|
|
440
556
|
has(a, b) {
|
|
441
|
-
if (b)
|
|
442
|
-
const setA = this.getRelatedKeys(a);
|
|
443
|
-
return setA?.has(b) ?? false;
|
|
444
|
-
}
|
|
557
|
+
if (b) return this.getRelatedKeys(a)?.has(b) ?? false;
|
|
445
558
|
return this.relations.has(a);
|
|
446
559
|
}
|
|
447
560
|
overlay() {
|
|
@@ -487,8 +600,7 @@ const abortTransaction = (target) => {
|
|
|
487
600
|
//#region src/internal/transaction/act-upon-store.ts
|
|
488
601
|
function actUponStore(store, token, id) {
|
|
489
602
|
return (...parameters) => {
|
|
490
|
-
|
|
491
|
-
return tx.run(parameters, id);
|
|
603
|
+
return withdraw(store, token).run(parameters, id);
|
|
492
604
|
};
|
|
493
605
|
}
|
|
494
606
|
|
|
@@ -496,8 +608,7 @@ function actUponStore(store, token, id) {
|
|
|
496
608
|
//#region src/internal/events/ingest-atom-update.ts
|
|
497
609
|
function ingestAtomUpdateEvent(store, event, applying) {
|
|
498
610
|
const { token, update: { newValue, oldValue } } = event;
|
|
499
|
-
|
|
500
|
-
setIntoStore(store, token, value);
|
|
611
|
+
setIntoStore(store, token, applying === `newValue` ? newValue : oldValue);
|
|
501
612
|
}
|
|
502
613
|
|
|
503
614
|
//#endregion
|
|
@@ -526,14 +637,12 @@ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
|
526
637
|
const target = newest(store);
|
|
527
638
|
if (Array.isArray(origin)) for (const formerClaim of origin) {
|
|
528
639
|
const claimString = stringifyJson(formerClaim);
|
|
529
|
-
|
|
530
|
-
if (claim) store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
640
|
+
if (target.molecules.get(claimString)) store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
531
641
|
else invalidKeys.push(claimString);
|
|
532
642
|
}
|
|
533
643
|
else {
|
|
534
644
|
const claimString = stringifyJson(origin);
|
|
535
|
-
|
|
536
|
-
if (claim) store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
645
|
+
if (target.molecules.get(claimString)) store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
537
646
|
else invalidKeys.push(claimString);
|
|
538
647
|
}
|
|
539
648
|
if (invalidKeys.length === 0) target.molecules.set(stringKey, {
|
|
@@ -547,8 +656,7 @@ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
|
547
656
|
provenance: origin,
|
|
548
657
|
timestamp: Date.now()
|
|
549
658
|
};
|
|
550
|
-
|
|
551
|
-
if (isTransaction) target.transactionMeta.update.subEvents.push(creationEvent);
|
|
659
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.subEvents.push(creationEvent);
|
|
552
660
|
else target.on.moleculeCreation.next(creationEvent);
|
|
553
661
|
for (const claim of invalidKeys) {
|
|
554
662
|
const disposal = store.disposalTraces.buffer.find((item) => item?.key === claim);
|
|
@@ -558,8 +666,7 @@ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
|
558
666
|
}
|
|
559
667
|
function fuseWithinStore(store, type, sideA, sideB) {
|
|
560
668
|
const compoundKey = `T$--${type}==${sideA}++${sideB}`;
|
|
561
|
-
|
|
562
|
-
allocateIntoStore(store, above, compoundKey, `all`);
|
|
669
|
+
allocateIntoStore(store, [sideA, sideB], compoundKey, `all`);
|
|
563
670
|
return compoundKey;
|
|
564
671
|
}
|
|
565
672
|
function createDeallocateTX(store) {
|
|
@@ -657,8 +764,7 @@ function claimWithinStore(store, newProvenance, claim, exclusive) {
|
|
|
657
764
|
to: [newProvenanceMolecule.key],
|
|
658
765
|
timestamp: Date.now()
|
|
659
766
|
};
|
|
660
|
-
|
|
661
|
-
if (isTransaction) target.transactionMeta.update.subEvents.push(transferEvent);
|
|
767
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.subEvents.push(transferEvent);
|
|
662
768
|
return claim;
|
|
663
769
|
}
|
|
664
770
|
|
|
@@ -777,19 +883,26 @@ function ingestTransactionOutcomeEvent(store, event, applying) {
|
|
|
777
883
|
}
|
|
778
884
|
}
|
|
779
885
|
|
|
886
|
+
//#endregion
|
|
887
|
+
//#region src/internal/transaction/is-root-store.ts
|
|
888
|
+
function isRootStore(store) {
|
|
889
|
+
return `epoch` in store.transactionMeta;
|
|
890
|
+
}
|
|
891
|
+
function isChildStore(store) {
|
|
892
|
+
return `phase` in store.transactionMeta;
|
|
893
|
+
}
|
|
894
|
+
|
|
780
895
|
//#endregion
|
|
781
896
|
//#region src/internal/transaction/get-epoch-number.ts
|
|
782
897
|
function getContinuityKey(store, transactionKey) {
|
|
783
|
-
|
|
784
|
-
return continuity;
|
|
898
|
+
return store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
|
|
785
899
|
}
|
|
786
900
|
function getEpochNumberOfContinuity(store, continuityKey) {
|
|
787
|
-
|
|
788
|
-
return epoch;
|
|
901
|
+
return store.transactionMeta.epoch.get(continuityKey);
|
|
789
902
|
}
|
|
790
903
|
function getEpochNumberOfAction(store, transactionKey) {
|
|
791
904
|
const continuityKey = getContinuityKey(store, transactionKey);
|
|
792
|
-
if (continuityKey === void 0) return
|
|
905
|
+
if (continuityKey === void 0) return;
|
|
793
906
|
return getEpochNumberOfContinuity(store, continuityKey);
|
|
794
907
|
}
|
|
795
908
|
|
|
@@ -817,11 +930,10 @@ function applyTransaction(store, output) {
|
|
|
817
930
|
ingestTransactionOutcomeEvent(parent, child.transactionMeta.update, `newValue`);
|
|
818
931
|
if (isRootStore(parent)) {
|
|
819
932
|
setEpochNumberOfAction(parent, child.transactionMeta.update.token.key, child.transactionMeta.update.epoch);
|
|
820
|
-
|
|
933
|
+
withdraw(store, {
|
|
821
934
|
key: child.transactionMeta.update.token.key,
|
|
822
935
|
type: `transaction`
|
|
823
|
-
});
|
|
824
|
-
myTransaction?.subject.next(child.transactionMeta.update);
|
|
936
|
+
})?.subject.next(child.transactionMeta.update);
|
|
825
937
|
store.logger.info(`🛬`, `transaction`, child.transactionMeta.update.token.key, `applied`);
|
|
826
938
|
} else if (isChildStore(parent)) parent.transactionMeta.update.subEvents.push(child.transactionMeta.update);
|
|
827
939
|
parent.on.transactionApplying.next(null);
|
|
@@ -920,14 +1032,14 @@ function createTransaction(store, options) {
|
|
|
920
1032
|
type: `transaction`,
|
|
921
1033
|
run: (params, id) => {
|
|
922
1034
|
const token$1 = deposit(newTransaction);
|
|
923
|
-
const target
|
|
1035
|
+
const target = buildTransaction(store, token$1, params, id);
|
|
924
1036
|
try {
|
|
925
|
-
const { toolkit } = target
|
|
1037
|
+
const { toolkit } = target.transactionMeta;
|
|
926
1038
|
const output = options.do(toolkit, ...params);
|
|
927
|
-
applyTransaction(target
|
|
1039
|
+
applyTransaction(target, output);
|
|
928
1040
|
return output;
|
|
929
1041
|
} catch (thrown) {
|
|
930
|
-
abortTransaction(target
|
|
1042
|
+
abortTransaction(target);
|
|
931
1043
|
store.logger.warn(`💥`, `transaction`, key, `caught:`, thrown);
|
|
932
1044
|
throw thrown;
|
|
933
1045
|
}
|
|
@@ -935,8 +1047,7 @@ function createTransaction(store, options) {
|
|
|
935
1047
|
install: (s) => createTransaction(s, options),
|
|
936
1048
|
subject: new Subject()
|
|
937
1049
|
};
|
|
938
|
-
|
|
939
|
-
target.transactions.set(key, newTransaction);
|
|
1050
|
+
newest(store).transactions.set(key, newTransaction);
|
|
940
1051
|
const token = deposit(newTransaction);
|
|
941
1052
|
if (!transactionAlreadyExists) store.on.transactionCreation.next(token);
|
|
942
1053
|
return token;
|
|
@@ -1079,14 +1190,349 @@ const clearStore = (store) => {
|
|
|
1079
1190
|
store.config = config;
|
|
1080
1191
|
};
|
|
1081
1192
|
|
|
1193
|
+
//#endregion
|
|
1194
|
+
//#region src/internal/not-found-error.ts
|
|
1195
|
+
var NotFoundError = class extends Error {
|
|
1196
|
+
constructor(token, store) {
|
|
1197
|
+
super(`${PRETTY_TOKEN_TYPES[token.type]} ${stringifyJson(token.key)} not found in store "${store.config.name}".`);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/internal/store/withdraw.ts
|
|
1203
|
+
function withdraw(store, token) {
|
|
1204
|
+
let withdrawn;
|
|
1205
|
+
let target = store;
|
|
1206
|
+
while (target !== null) {
|
|
1207
|
+
switch (token.type) {
|
|
1208
|
+
case `atom`:
|
|
1209
|
+
case `mutable_atom`:
|
|
1210
|
+
withdrawn = target.atoms.get(token.key);
|
|
1211
|
+
break;
|
|
1212
|
+
case `writable_pure_selector`:
|
|
1213
|
+
case `writable_held_selector`:
|
|
1214
|
+
withdrawn = target.writableSelectors.get(token.key);
|
|
1215
|
+
break;
|
|
1216
|
+
case `readonly_pure_selector`:
|
|
1217
|
+
case `readonly_held_selector`:
|
|
1218
|
+
withdrawn = target.readonlySelectors.get(token.key);
|
|
1219
|
+
break;
|
|
1220
|
+
case `atom_family`:
|
|
1221
|
+
case `mutable_atom_family`:
|
|
1222
|
+
case `writable_pure_selector_family`:
|
|
1223
|
+
case `readonly_pure_selector_family`:
|
|
1224
|
+
case `writable_held_selector_family`:
|
|
1225
|
+
case `readonly_held_selector_family`:
|
|
1226
|
+
withdrawn = target.families.get(token.key);
|
|
1227
|
+
break;
|
|
1228
|
+
case `timeline`:
|
|
1229
|
+
withdrawn = target.timelines.get(token.key);
|
|
1230
|
+
break;
|
|
1231
|
+
case `transaction`:
|
|
1232
|
+
withdrawn = target.transactions.get(token.key);
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
if (withdrawn) return withdrawn;
|
|
1236
|
+
target = target.child;
|
|
1237
|
+
}
|
|
1238
|
+
throw new NotFoundError(token, store);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
//#endregion
|
|
1242
|
+
//#region src/internal/get-state/get-fallback.ts
|
|
1243
|
+
function getFallback(store, token, family, subKey) {
|
|
1244
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === stringifyJson(subKey));
|
|
1245
|
+
store.logger.error(`❌`, token.type, token.key, `gets a fallback value because key`, subKey, `is not allocated`, disposal ? `This key was previously disposed:\n${disposal.trace}` : `(no previous disposal trace found)`);
|
|
1246
|
+
switch (family.type) {
|
|
1247
|
+
case `mutable_atom_family`: {
|
|
1248
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
1249
|
+
const defaultValue = new family.class();
|
|
1250
|
+
store.defaults.set(family.key, defaultValue);
|
|
1251
|
+
return defaultValue.READONLY_VIEW;
|
|
1252
|
+
}
|
|
1253
|
+
case `atom_family`: {
|
|
1254
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
1255
|
+
const def = family.default;
|
|
1256
|
+
const defaultValue = def(subKey);
|
|
1257
|
+
store.defaults.set(family.key, defaultValue);
|
|
1258
|
+
return defaultValue;
|
|
1259
|
+
}
|
|
1260
|
+
case `readonly_pure_selector_family`:
|
|
1261
|
+
case `writable_pure_selector_family`:
|
|
1262
|
+
case `readonly_held_selector_family`:
|
|
1263
|
+
case `writable_held_selector_family`: {
|
|
1264
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
1265
|
+
const defaultValue = family.default(subKey);
|
|
1266
|
+
store.defaults.set(family.key, defaultValue);
|
|
1267
|
+
return defaultValue;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
//#endregion
|
|
1273
|
+
//#region src/internal/safe-compute.ts
|
|
1274
|
+
function safeCompute(target, state) {
|
|
1275
|
+
const { type, key, catch: canCatch } = state;
|
|
1276
|
+
switch (type) {
|
|
1277
|
+
case `readonly_pure_selector`:
|
|
1278
|
+
case `writable_pure_selector`: {
|
|
1279
|
+
let val;
|
|
1280
|
+
target.logger.info(`🧮`, type, key, `computing value`);
|
|
1281
|
+
try {
|
|
1282
|
+
val = state.getFrom(target);
|
|
1283
|
+
if (val instanceof Promise) return val.catch((thrown) => {
|
|
1284
|
+
target.logger.error(`💥`, type, key, `rejected:`, thrown);
|
|
1285
|
+
if (canCatch) {
|
|
1286
|
+
for (const Class of canCatch) if (thrown instanceof Class) return thrown;
|
|
1287
|
+
}
|
|
1288
|
+
throw thrown;
|
|
1289
|
+
});
|
|
1290
|
+
} catch (e) {
|
|
1291
|
+
target.logger.error(`💥`, type, key, `rejected:`, e);
|
|
1292
|
+
if (canCatch) {
|
|
1293
|
+
for (const Class of canCatch) if (e instanceof Class) return writeToCache(target, state, e);
|
|
1294
|
+
}
|
|
1295
|
+
throw e;
|
|
1296
|
+
}
|
|
1297
|
+
return writeToCache(target, state, val);
|
|
1298
|
+
}
|
|
1299
|
+
case `atom`: {
|
|
1300
|
+
let def;
|
|
1301
|
+
if (isFn(state.default)) try {
|
|
1302
|
+
def = state.default();
|
|
1303
|
+
if (def instanceof Promise) def = def.catch((thrown) => {
|
|
1304
|
+
target.logger.error(`💥`, type, key, `rejected:`, thrown);
|
|
1305
|
+
if (canCatch) {
|
|
1306
|
+
for (const Class of canCatch) if (thrown instanceof Class) return thrown;
|
|
1307
|
+
}
|
|
1308
|
+
throw thrown;
|
|
1309
|
+
});
|
|
1310
|
+
} catch (e) {
|
|
1311
|
+
target.logger.error(`💥`, type, key, `rejected:`, e);
|
|
1312
|
+
if (canCatch) {
|
|
1313
|
+
for (const Class of canCatch) if (e instanceof Class) {
|
|
1314
|
+
def = writeToCache(target, state, e);
|
|
1315
|
+
target.logger.info(`✨`, state.type, key, `computed default`, def);
|
|
1316
|
+
return def;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
throw e;
|
|
1320
|
+
}
|
|
1321
|
+
else {
|
|
1322
|
+
def = state.default;
|
|
1323
|
+
target.logger.info(`✨`, state.type, key, `using static default`, def);
|
|
1324
|
+
}
|
|
1325
|
+
return writeToCache(target, state, def);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
//#endregion
|
|
1331
|
+
//#region src/internal/get-state/read-or-compute-value.ts
|
|
1332
|
+
function readOrComputeValue(target, state, mut) {
|
|
1333
|
+
if (target.valueMap.has(state.key)) return readFromCache(target, state, mut);
|
|
1334
|
+
target.logger.info(`❔`, state.type, state.key, `value not found in cache`);
|
|
1335
|
+
const { key } = state;
|
|
1336
|
+
switch (state.type) {
|
|
1337
|
+
case `readonly_held_selector`:
|
|
1338
|
+
case `writable_held_selector`:
|
|
1339
|
+
target.logger.info(`🧮`, state.type, key, `computing value`);
|
|
1340
|
+
return state.getFrom(target);
|
|
1341
|
+
case `writable_pure_selector`:
|
|
1342
|
+
case `readonly_pure_selector`:
|
|
1343
|
+
case `atom`: return safeCompute(target, state);
|
|
1344
|
+
case `mutable_atom`: {
|
|
1345
|
+
const instance = new state.class();
|
|
1346
|
+
target.logger.info(`✨`, state.type, key, `created new instance`, instance);
|
|
1347
|
+
return writeToCache(target, state, instance);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
//#endregion
|
|
1353
|
+
//#region src/internal/families/get-family-of-token.ts
|
|
1354
|
+
function getFamilyOfToken(store, token) {
|
|
1355
|
+
return withdraw(store, {
|
|
1356
|
+
key: token.family.key,
|
|
1357
|
+
type: `${token.type}_family`
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
//#endregion
|
|
1362
|
+
//#region src/internal/families/mint-in-store.ts
|
|
1363
|
+
const FAMILY_MEMBER_TOKEN_TYPES = {
|
|
1364
|
+
atom_family: `atom`,
|
|
1365
|
+
molecule_family: `molecule`,
|
|
1366
|
+
mutable_atom_family: `mutable_atom`,
|
|
1367
|
+
readonly_held_selector_family: `readonly_held_selector`,
|
|
1368
|
+
readonly_pure_selector_family: `readonly_pure_selector`,
|
|
1369
|
+
writable_held_selector_family: `writable_held_selector`,
|
|
1370
|
+
writable_pure_selector_family: `writable_pure_selector`
|
|
1371
|
+
};
|
|
1372
|
+
const MUST_CREATE = Symbol(`MUST_CREATE`);
|
|
1373
|
+
const DO_NOT_CREATE = Symbol(`DO_NOT_CREATE`);
|
|
1374
|
+
function mintInStore(mustCreate, store, family, key) {
|
|
1375
|
+
const stringKey = stringifyJson(key);
|
|
1376
|
+
const molecule = store.molecules.get(stringKey);
|
|
1377
|
+
if (!molecule && store.config.lifespan === `immortal`) {
|
|
1378
|
+
const { type: familyType, key: familyKey } = family;
|
|
1379
|
+
store.logger.warn(`💣`, `key`, stringKey, `was used to mint a counterfeit token for`, familyType, `"${familyKey}"`);
|
|
1380
|
+
const fullKey = `${familyKey}(${stringKey})`;
|
|
1381
|
+
const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
|
|
1382
|
+
return {
|
|
1383
|
+
counterfeit: true,
|
|
1384
|
+
key: fullKey,
|
|
1385
|
+
type,
|
|
1386
|
+
family: {
|
|
1387
|
+
key: familyKey,
|
|
1388
|
+
subKey: stringKey
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
let token;
|
|
1393
|
+
if (mustCreate === MUST_CREATE) {
|
|
1394
|
+
store.logger.info(`👪`, family.type, family.key, `adds member`, typeof key === `string` ? `\`${key}\`` : key);
|
|
1395
|
+
token = family.create(key);
|
|
1396
|
+
if (molecule) store.moleculeData.set(stringKey, family.key);
|
|
1397
|
+
} else {
|
|
1398
|
+
const { type: familyType, key: familyKey } = family;
|
|
1399
|
+
const fullKey = `${familyKey}(${stringKey})`;
|
|
1400
|
+
const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
|
|
1401
|
+
return {
|
|
1402
|
+
key: fullKey,
|
|
1403
|
+
type,
|
|
1404
|
+
family: {
|
|
1405
|
+
key: familyKey,
|
|
1406
|
+
subKey: stringKey
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
return token;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
//#endregion
|
|
1414
|
+
//#region src/internal/get-state/reduce-reference.ts
|
|
1415
|
+
function reduceReference(store, ...params) {
|
|
1416
|
+
let existingToken;
|
|
1417
|
+
let brandNewToken;
|
|
1418
|
+
let family;
|
|
1419
|
+
let subKey;
|
|
1420
|
+
let token;
|
|
1421
|
+
if (params.length === 1) {
|
|
1422
|
+
token = params[0];
|
|
1423
|
+
if (`family` in token) {
|
|
1424
|
+
const familyToken = getFamilyOfToken(store, token);
|
|
1425
|
+
family = withdraw(store, familyToken);
|
|
1426
|
+
subKey = parseJson(token.family.subKey);
|
|
1427
|
+
existingToken = seekInStore(store, familyToken, subKey);
|
|
1428
|
+
if (`counterfeit` in token) return {
|
|
1429
|
+
token,
|
|
1430
|
+
family,
|
|
1431
|
+
subKey,
|
|
1432
|
+
isNew: false
|
|
1433
|
+
};
|
|
1434
|
+
if (!existingToken) {
|
|
1435
|
+
brandNewToken = mintInStore(MUST_CREATE, store, familyToken, subKey);
|
|
1436
|
+
token = brandNewToken;
|
|
1437
|
+
} else token = existingToken;
|
|
1438
|
+
}
|
|
1439
|
+
} else {
|
|
1440
|
+
family = withdraw(store, params[0]);
|
|
1441
|
+
subKey = params[1];
|
|
1442
|
+
existingToken = seekInStore(store, family, subKey);
|
|
1443
|
+
if (!existingToken) {
|
|
1444
|
+
brandNewToken = mintInStore(MUST_CREATE, store, family, subKey);
|
|
1445
|
+
token = brandNewToken;
|
|
1446
|
+
} else token = existingToken;
|
|
1447
|
+
}
|
|
1448
|
+
const isCounterfeit = `counterfeit` in token;
|
|
1449
|
+
if (Boolean(brandNewToken) && isCounterfeit === false && family) {
|
|
1450
|
+
let subType;
|
|
1451
|
+
switch (token.type) {
|
|
1452
|
+
case `readonly_pure_selector`:
|
|
1453
|
+
case `readonly_held_selector`:
|
|
1454
|
+
subType = `readable`;
|
|
1455
|
+
break;
|
|
1456
|
+
case `atom`:
|
|
1457
|
+
case `mutable_atom`:
|
|
1458
|
+
case `writable_pure_selector`:
|
|
1459
|
+
case `writable_held_selector`:
|
|
1460
|
+
subType = `writable`;
|
|
1461
|
+
break;
|
|
1462
|
+
}
|
|
1463
|
+
const stateCreationEvent = {
|
|
1464
|
+
type: `state_creation`,
|
|
1465
|
+
subType,
|
|
1466
|
+
token,
|
|
1467
|
+
timestamp: Date.now()
|
|
1468
|
+
};
|
|
1469
|
+
family.subject.next(stateCreationEvent);
|
|
1470
|
+
const target = newest(store);
|
|
1471
|
+
if (token.family) {
|
|
1472
|
+
if (isRootStore(target)) switch (token.type) {
|
|
1473
|
+
case `atom`:
|
|
1474
|
+
case `mutable_atom`:
|
|
1475
|
+
store.on.atomCreation.next(token);
|
|
1476
|
+
break;
|
|
1477
|
+
case `writable_pure_selector`:
|
|
1478
|
+
case `readonly_pure_selector`:
|
|
1479
|
+
case `writable_held_selector`:
|
|
1480
|
+
case `readonly_held_selector`:
|
|
1481
|
+
store.on.selectorCreation.next(token);
|
|
1482
|
+
break;
|
|
1483
|
+
}
|
|
1484
|
+
else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return {
|
|
1488
|
+
token,
|
|
1489
|
+
family,
|
|
1490
|
+
subKey,
|
|
1491
|
+
isNew: Boolean(brandNewToken)
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
//#endregion
|
|
1496
|
+
//#region src/internal/get-state/get-from-store.ts
|
|
1497
|
+
function getFromStore(store, ...params) {
|
|
1498
|
+
const { token, family, subKey } = reduceReference(store, ...params);
|
|
1499
|
+
if (`counterfeit` in token && family && subKey) return getFallback(store, token, family, subKey);
|
|
1500
|
+
const state = withdraw(store, token);
|
|
1501
|
+
return readOrComputeValue(store, state);
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
//#endregion
|
|
1505
|
+
//#region src/internal/families/seek-in-store.ts
|
|
1506
|
+
function seekInStore(store, token, key) {
|
|
1507
|
+
const subKey = stringifyJson(key);
|
|
1508
|
+
const fullKey = `${token.key}(${subKey})`;
|
|
1509
|
+
const target = newest(store);
|
|
1510
|
+
let state;
|
|
1511
|
+
switch (token.type) {
|
|
1512
|
+
case `atom_family`:
|
|
1513
|
+
case `mutable_atom_family`:
|
|
1514
|
+
state = target.atoms.get(fullKey);
|
|
1515
|
+
break;
|
|
1516
|
+
case `writable_held_selector_family`:
|
|
1517
|
+
case `writable_pure_selector_family`:
|
|
1518
|
+
state = target.writableSelectors.get(fullKey);
|
|
1519
|
+
break;
|
|
1520
|
+
case `readonly_held_selector_family`:
|
|
1521
|
+
case `readonly_pure_selector_family`:
|
|
1522
|
+
state = target.readonlySelectors.get(fullKey);
|
|
1523
|
+
break;
|
|
1524
|
+
}
|
|
1525
|
+
if (state) return deposit(state);
|
|
1526
|
+
return state;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1082
1529
|
//#endregion
|
|
1083
1530
|
//#region src/internal/families/find-in-store.ts
|
|
1084
1531
|
function findInStore(store, familyToken, key) {
|
|
1085
1532
|
const family = withdraw(store, familyToken);
|
|
1086
1533
|
const existingStateToken = seekInStore(store, familyToken, key);
|
|
1087
1534
|
if (existingStateToken) return existingStateToken;
|
|
1088
|
-
|
|
1089
|
-
return newStateToken;
|
|
1535
|
+
return mintInStore(DO_NOT_CREATE, store, family, key);
|
|
1090
1536
|
}
|
|
1091
1537
|
|
|
1092
1538
|
//#endregion
|
|
@@ -1123,8 +1569,7 @@ function createReadonlyPureSelectorFamily(store, options, internalRoles) {
|
|
|
1123
1569
|
subject,
|
|
1124
1570
|
install: (s) => createReadonlyPureSelectorFamily(s, options),
|
|
1125
1571
|
default: (key) => {
|
|
1126
|
-
|
|
1127
|
-
return getFn({
|
|
1572
|
+
return options.get(key)({
|
|
1128
1573
|
get: ((...args) => getFromStore(store, ...args)),
|
|
1129
1574
|
find: ((...args) => findInStore(store, ...args)),
|
|
1130
1575
|
json: (token) => getJsonToken(store, token)
|
|
@@ -1287,8 +1732,7 @@ function createWritablePureSelectorFamily(store, options, internalRoles) {
|
|
|
1287
1732
|
subject,
|
|
1288
1733
|
install: (s) => createWritablePureSelectorFamily(s, options),
|
|
1289
1734
|
default: (key) => {
|
|
1290
|
-
|
|
1291
|
-
return getFn({
|
|
1735
|
+
return options.get(key)({
|
|
1292
1736
|
get: ((...args) => getFromStore(store, ...args)),
|
|
1293
1737
|
find: ((...args) => findInStore(store, ...args)),
|
|
1294
1738
|
json: (token) => getJsonToken(store, token)
|
|
@@ -1318,8 +1762,7 @@ function disposeFromStore(store, ...params) {
|
|
|
1318
1762
|
else {
|
|
1319
1763
|
const family = params[0];
|
|
1320
1764
|
const key = params[1];
|
|
1321
|
-
|
|
1322
|
-
token = maybeToken;
|
|
1765
|
+
token = findInStore(store, family, key);
|
|
1323
1766
|
}
|
|
1324
1767
|
try {
|
|
1325
1768
|
withdraw(store, token);
|
|
@@ -1341,6 +1784,330 @@ function disposeFromStore(store, ...params) {
|
|
|
1341
1784
|
}
|
|
1342
1785
|
}
|
|
1343
1786
|
|
|
1787
|
+
//#endregion
|
|
1788
|
+
//#region src/internal/operation.ts
|
|
1789
|
+
function openOperation(store, token) {
|
|
1790
|
+
if (store.operation.open) {
|
|
1791
|
+
const rejectionTime = performance.now();
|
|
1792
|
+
store.logger.info(`🚫`, token.type, token.key, `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`);
|
|
1793
|
+
return rejectionTime;
|
|
1794
|
+
}
|
|
1795
|
+
store.operation = {
|
|
1796
|
+
open: true,
|
|
1797
|
+
done: /* @__PURE__ */ new Set(),
|
|
1798
|
+
prev: /* @__PURE__ */ new Map(),
|
|
1799
|
+
timestamp: Date.now(),
|
|
1800
|
+
token,
|
|
1801
|
+
subEvents: []
|
|
1802
|
+
};
|
|
1803
|
+
store.logger.info(`⭕`, token.type, token.key, `operation start in store "${store.config.name}"${isChildStore(store) ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"` : ``}`);
|
|
1804
|
+
return store;
|
|
1805
|
+
}
|
|
1806
|
+
function closeOperation(store) {
|
|
1807
|
+
if (store.operation.open) store.logger.info(`🔴`, store.operation.token.type, store.operation.token.key, `operation done in store "${store.config.name}"`);
|
|
1808
|
+
store.operation = { open: false };
|
|
1809
|
+
store.on.operationClose.next(store.operation);
|
|
1810
|
+
}
|
|
1811
|
+
const isDone = (store, key) => {
|
|
1812
|
+
if (!store.operation.open) {
|
|
1813
|
+
store.logger.error(`🐞`, `unknown`, key, `isDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
1814
|
+
return true;
|
|
1815
|
+
}
|
|
1816
|
+
return store.operation.done.has(key);
|
|
1817
|
+
};
|
|
1818
|
+
const markDone = (store, key) => {
|
|
1819
|
+
if (!store.operation.open) {
|
|
1820
|
+
store.logger.error(`🐞`, `unknown`, key, `markDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
store.operation.done.add(key);
|
|
1824
|
+
};
|
|
1825
|
+
|
|
1826
|
+
//#endregion
|
|
1827
|
+
//#region src/internal/set-state/dispatch-state-update.ts
|
|
1828
|
+
function dispatchOrDeferStateUpdate(target, state, { oldValue, newValue }, stateIsNewlyCreated, family) {
|
|
1829
|
+
const token = deposit(state);
|
|
1830
|
+
if (stateIsNewlyCreated && family) {
|
|
1831
|
+
state.subject.next({ newValue });
|
|
1832
|
+
const stateCreationEvent = {
|
|
1833
|
+
checkpoint: true,
|
|
1834
|
+
type: `state_creation`,
|
|
1835
|
+
subType: `writable`,
|
|
1836
|
+
token,
|
|
1837
|
+
timestamp: Date.now(),
|
|
1838
|
+
value: newValue
|
|
1839
|
+
};
|
|
1840
|
+
target.operation.subEvents.push(stateCreationEvent);
|
|
1841
|
+
family.subject.next(stateCreationEvent);
|
|
1842
|
+
const innerTarget = newest(target);
|
|
1843
|
+
if (token.family) {
|
|
1844
|
+
if (isRootStore(innerTarget)) switch (token.type) {
|
|
1845
|
+
case `atom`:
|
|
1846
|
+
case `mutable_atom`:
|
|
1847
|
+
target.on.atomCreation.next(token);
|
|
1848
|
+
break;
|
|
1849
|
+
case `writable_pure_selector`:
|
|
1850
|
+
case `writable_held_selector`:
|
|
1851
|
+
target.on.selectorCreation.next(token);
|
|
1852
|
+
break;
|
|
1853
|
+
}
|
|
1854
|
+
else if (isChildStore(innerTarget) && innerTarget.on.transactionApplying.state === null) innerTarget.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
1855
|
+
}
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
const { key, subject, type } = state;
|
|
1859
|
+
const update = {
|
|
1860
|
+
oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
|
|
1861
|
+
newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue
|
|
1862
|
+
};
|
|
1863
|
+
if (isRootStore(target)) {
|
|
1864
|
+
switch (type) {
|
|
1865
|
+
case `mutable_atom`:
|
|
1866
|
+
target.logger.info(`📢`, type, key, `is now (`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
1867
|
+
break;
|
|
1868
|
+
case `atom`:
|
|
1869
|
+
case `writable_pure_selector`:
|
|
1870
|
+
case `writable_held_selector`: target.logger.info(`📢`, type, key, `went (`, oldValue, `->`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
1871
|
+
}
|
|
1872
|
+
subject.next(update);
|
|
1873
|
+
}
|
|
1874
|
+
if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
|
|
1875
|
+
if (target.on.transactionApplying.state === null) {
|
|
1876
|
+
if (isTransceiver(newValue)) return;
|
|
1877
|
+
const { timestamp } = target.operation;
|
|
1878
|
+
const atomUpdate = {
|
|
1879
|
+
type: `atom_update`,
|
|
1880
|
+
token,
|
|
1881
|
+
timestamp,
|
|
1882
|
+
update
|
|
1883
|
+
};
|
|
1884
|
+
target.transactionMeta.update.subEvents.push(atomUpdate);
|
|
1885
|
+
target.logger.info(`📁`, `atom`, key, `stowed (`, oldValue, `->`, newValue, `)`);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
if (hasRole(state, `tracker:signal`)) {
|
|
1889
|
+
const keyOfMutable = key.slice(1);
|
|
1890
|
+
const mutable = target.atoms.get(keyOfMutable);
|
|
1891
|
+
if (readOrComputeValue(target, mutable, `mut`).do(update.newValue) === null === true) evictDownstreamFromAtom(target, mutable);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
//#endregion
|
|
1897
|
+
//#region src/internal/set-state/set-atom.ts
|
|
1898
|
+
const setAtom = (target, atom, next) => {
|
|
1899
|
+
const oldValue = readOrComputeValue(target, atom, `mut`);
|
|
1900
|
+
let newValue = become(next, oldValue);
|
|
1901
|
+
target.logger.info(`⭐`, `atom`, atom.key, `setting value`, newValue);
|
|
1902
|
+
newValue = writeToCache(target, atom, newValue);
|
|
1903
|
+
markDone(target, atom.key);
|
|
1904
|
+
evictDownstreamFromAtom(target, atom);
|
|
1905
|
+
return {
|
|
1906
|
+
oldValue,
|
|
1907
|
+
newValue
|
|
1908
|
+
};
|
|
1909
|
+
};
|
|
1910
|
+
|
|
1911
|
+
//#endregion
|
|
1912
|
+
//#region src/internal/set-state/reset-atom-or-selector.ts
|
|
1913
|
+
function resetAtom(target, atom) {
|
|
1914
|
+
switch (atom.type) {
|
|
1915
|
+
case `mutable_atom`: return setAtom(target, atom, new atom.class());
|
|
1916
|
+
case `atom`: {
|
|
1917
|
+
let def;
|
|
1918
|
+
if (isFn(atom.default)) def = safeCompute(target, atom);
|
|
1919
|
+
else def = atom.default;
|
|
1920
|
+
return setAtom(target, atom, def);
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
function resetAtomOrSelector(target, state) {
|
|
1925
|
+
let protoUpdate;
|
|
1926
|
+
switch (state.type) {
|
|
1927
|
+
case `atom`:
|
|
1928
|
+
case `mutable_atom`:
|
|
1929
|
+
protoUpdate = resetAtom(target, state);
|
|
1930
|
+
break;
|
|
1931
|
+
case `writable_held_selector`:
|
|
1932
|
+
{
|
|
1933
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
1934
|
+
for (const atom of atoms.values()) {
|
|
1935
|
+
const rootProtoUpdate = resetAtom(target, atom);
|
|
1936
|
+
dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
|
|
1937
|
+
}
|
|
1938
|
+
const value = state.getFrom(target);
|
|
1939
|
+
protoUpdate = {
|
|
1940
|
+
oldValue: value,
|
|
1941
|
+
newValue: value
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
break;
|
|
1945
|
+
case `writable_pure_selector`:
|
|
1946
|
+
{
|
|
1947
|
+
const oldValue = safeCompute(target, state);
|
|
1948
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
1949
|
+
for (const atom of atoms.values()) {
|
|
1950
|
+
const rootProtoUpdate = resetAtom(target, atom);
|
|
1951
|
+
dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
|
|
1952
|
+
}
|
|
1953
|
+
const newValue = safeCompute(target, state);
|
|
1954
|
+
protoUpdate = {
|
|
1955
|
+
oldValue,
|
|
1956
|
+
newValue
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
break;
|
|
1960
|
+
}
|
|
1961
|
+
return protoUpdate;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
//#endregion
|
|
1965
|
+
//#region src/internal/set-state/set-into-store.ts
|
|
1966
|
+
function setIntoStore(store, ...params) {
|
|
1967
|
+
operateOnStore(OWN_OP, store, ...params);
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
//#endregion
|
|
1971
|
+
//#region src/internal/set-state/reset-in-store.ts
|
|
1972
|
+
const RESET_STATE = Symbol(`RESET`);
|
|
1973
|
+
function resetInStore(store, ...params) {
|
|
1974
|
+
const subParams = [...params, RESET_STATE];
|
|
1975
|
+
setIntoStore(store, ...subParams);
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
//#endregion
|
|
1979
|
+
//#region src/internal/set-state/set-selector.ts
|
|
1980
|
+
function setSelector(target, selector, next) {
|
|
1981
|
+
let oldValue;
|
|
1982
|
+
let newValue;
|
|
1983
|
+
let constant;
|
|
1984
|
+
const { type, key } = selector;
|
|
1985
|
+
switch (selector.type) {
|
|
1986
|
+
case `writable_pure_selector`:
|
|
1987
|
+
oldValue = readOrComputeValue(target, selector, `mut`);
|
|
1988
|
+
newValue = become(next, oldValue);
|
|
1989
|
+
newValue = writeToCache(target, selector, newValue);
|
|
1990
|
+
break;
|
|
1991
|
+
case `writable_held_selector`:
|
|
1992
|
+
constant = selector.const;
|
|
1993
|
+
become(next, constant);
|
|
1994
|
+
oldValue = constant;
|
|
1995
|
+
newValue = constant;
|
|
1996
|
+
}
|
|
1997
|
+
target.logger.info(`⭐`, type, key, `setting to`, newValue);
|
|
1998
|
+
markDone(target, key);
|
|
1999
|
+
selector.setSelf(newValue);
|
|
2000
|
+
return {
|
|
2001
|
+
oldValue,
|
|
2002
|
+
newValue
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
//#endregion
|
|
2007
|
+
//#region src/internal/set-state/set-atom-or-selector.ts
|
|
2008
|
+
const setAtomOrSelector = (target, state, value) => {
|
|
2009
|
+
let protoUpdate;
|
|
2010
|
+
switch (state.type) {
|
|
2011
|
+
case `atom`:
|
|
2012
|
+
case `mutable_atom`:
|
|
2013
|
+
protoUpdate = setAtom(target, state, value);
|
|
2014
|
+
break;
|
|
2015
|
+
case `writable_pure_selector`:
|
|
2016
|
+
case `writable_held_selector`:
|
|
2017
|
+
protoUpdate = setSelector(target, state, value);
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
return protoUpdate;
|
|
2021
|
+
};
|
|
2022
|
+
|
|
2023
|
+
//#endregion
|
|
2024
|
+
//#region src/internal/set-state/operate-on-store.ts
|
|
2025
|
+
const OWN_OP = Symbol(`OWN_OP`);
|
|
2026
|
+
const JOIN_OP = Symbol(`JOIN_OP`);
|
|
2027
|
+
function operateOnStore(opMode, store, ...params) {
|
|
2028
|
+
let existingToken;
|
|
2029
|
+
let brandNewToken;
|
|
2030
|
+
let token;
|
|
2031
|
+
let family;
|
|
2032
|
+
let key;
|
|
2033
|
+
let value;
|
|
2034
|
+
if (params.length === 2) {
|
|
2035
|
+
token = params[0];
|
|
2036
|
+
value = params[1];
|
|
2037
|
+
if (`family` in token) {
|
|
2038
|
+
family = getFamilyOfToken(store, token);
|
|
2039
|
+
key = parseJson(token.family.subKey);
|
|
2040
|
+
existingToken = seekInStore(store, family, key);
|
|
2041
|
+
if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
2042
|
+
else token = existingToken;
|
|
2043
|
+
}
|
|
2044
|
+
} else {
|
|
2045
|
+
family = withdraw(store, params[0]);
|
|
2046
|
+
key = params[1];
|
|
2047
|
+
value = params[2];
|
|
2048
|
+
existingToken = seekInStore(store, family, key);
|
|
2049
|
+
if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
2050
|
+
else token = existingToken;
|
|
2051
|
+
}
|
|
2052
|
+
const action = value === RESET_STATE ? `reset` : `set`;
|
|
2053
|
+
let target;
|
|
2054
|
+
if (opMode === OWN_OP) {
|
|
2055
|
+
const result = openOperation(store, token);
|
|
2056
|
+
if (typeof result === `number`) {
|
|
2057
|
+
const rejectionTime = result;
|
|
2058
|
+
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
2059
|
+
unsubscribe();
|
|
2060
|
+
store.logger.info(`🟢`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
2061
|
+
operateOnStore(opMode, store, token, value);
|
|
2062
|
+
});
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
target = result;
|
|
2066
|
+
} else target = store;
|
|
2067
|
+
if (`counterfeit` in token && `family` in token) {
|
|
2068
|
+
const subKey = token.family.subKey;
|
|
2069
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
2070
|
+
store.logger.error(`❌`, token.type, token.key, `could not be`, action, `because key`, subKey, `is not allocated.`, disposal ? `this key was previously disposed:${disposal.trace}` : `(no previous disposal trace found)`);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
const state = withdraw(target, token);
|
|
2074
|
+
let protoUpdate;
|
|
2075
|
+
if (value === RESET_STATE) protoUpdate = resetAtomOrSelector(target, state);
|
|
2076
|
+
else protoUpdate = setAtomOrSelector(target, state, value);
|
|
2077
|
+
dispatchOrDeferStateUpdate(target, state, protoUpdate, Boolean(brandNewToken), family);
|
|
2078
|
+
if (opMode === OWN_OP) closeOperation(target);
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
//#endregion
|
|
2082
|
+
//#region src/internal/keys.ts
|
|
2083
|
+
const isAtomKey = (store, key) => newest(store).atoms.has(key);
|
|
2084
|
+
const isSelectorKey = (store, key) => newest(store).writableSelectors.has(key);
|
|
2085
|
+
const isReadonlySelectorKey = (store, key) => newest(store).readonlySelectors.has(key);
|
|
2086
|
+
const isStateKey = (store, key) => isAtomKey(store, key) || isSelectorKey(store, key) || isReadonlySelectorKey(store, key);
|
|
2087
|
+
|
|
2088
|
+
//#endregion
|
|
2089
|
+
//#region src/internal/selector/get-selector-dependency-keys.ts
|
|
2090
|
+
function getSelectorDependencyKeys(store, key) {
|
|
2091
|
+
return newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(store, source));
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
//#endregion
|
|
2095
|
+
//#region src/internal/selector/trace-selector-atoms.ts
|
|
2096
|
+
function traceRootSelectorAtoms(store, selectorKey, covered = /* @__PURE__ */ new Set()) {
|
|
2097
|
+
const dependencies = getSelectorDependencyKeys(store, selectorKey);
|
|
2098
|
+
const roots = /* @__PURE__ */ new Map();
|
|
2099
|
+
while (dependencies.length > 0) {
|
|
2100
|
+
const dependencyKey = dependencies.pop();
|
|
2101
|
+
if (covered.has(dependencyKey)) continue;
|
|
2102
|
+
covered.add(dependencyKey);
|
|
2103
|
+
if (isAtomKey(store, dependencyKey)) {
|
|
2104
|
+
const atom = store.atoms.get(dependencyKey);
|
|
2105
|
+
roots.set(atom.key, atom);
|
|
2106
|
+
} else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
2107
|
+
}
|
|
2108
|
+
return roots;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
1344
2111
|
//#endregion
|
|
1345
2112
|
//#region src/internal/selector/update-selector-atoms.ts
|
|
1346
2113
|
function updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered) {
|
|
@@ -1602,73 +2369,60 @@ function disposeSelector(store, selectorToken) {
|
|
|
1602
2369
|
const { key, type, family: familyMeta } = selectorToken;
|
|
1603
2370
|
if (!familyMeta) store.logger.error(`❌`, type, key, `Standalone selectors cannot be disposed.`);
|
|
1604
2371
|
else {
|
|
1605
|
-
|
|
1606
|
-
if (molecule) target.moleculeData.delete(familyMeta.subKey, familyMeta.key);
|
|
2372
|
+
if (target.molecules.get(familyMeta.subKey)) target.moleculeData.delete(familyMeta.subKey, familyMeta.key);
|
|
1607
2373
|
let familyToken;
|
|
1608
2374
|
switch (selectorToken.type) {
|
|
1609
2375
|
case `writable_held_selector`:
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
timestamp: Date.now()
|
|
1622
|
-
});
|
|
1623
|
-
}
|
|
2376
|
+
target.writableSelectors.delete(key);
|
|
2377
|
+
familyToken = {
|
|
2378
|
+
key: familyMeta.key,
|
|
2379
|
+
type: `writable_held_selector_family`
|
|
2380
|
+
};
|
|
2381
|
+
withdraw(store, familyToken).subject.next({
|
|
2382
|
+
type: `state_disposal`,
|
|
2383
|
+
subType: `selector`,
|
|
2384
|
+
token: selectorToken,
|
|
2385
|
+
timestamp: Date.now()
|
|
2386
|
+
});
|
|
1624
2387
|
break;
|
|
1625
2388
|
case `writable_pure_selector`:
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
timestamp: Date.now()
|
|
1638
|
-
});
|
|
1639
|
-
}
|
|
2389
|
+
target.writableSelectors.delete(key);
|
|
2390
|
+
familyToken = {
|
|
2391
|
+
key: familyMeta.key,
|
|
2392
|
+
type: `writable_pure_selector_family`
|
|
2393
|
+
};
|
|
2394
|
+
withdraw(store, familyToken).subject.next({
|
|
2395
|
+
type: `state_disposal`,
|
|
2396
|
+
subType: `selector`,
|
|
2397
|
+
token: selectorToken,
|
|
2398
|
+
timestamp: Date.now()
|
|
2399
|
+
});
|
|
1640
2400
|
break;
|
|
1641
2401
|
case `readonly_held_selector`:
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
timestamp: Date.now()
|
|
1654
|
-
});
|
|
1655
|
-
}
|
|
2402
|
+
target.readonlySelectors.delete(key);
|
|
2403
|
+
familyToken = {
|
|
2404
|
+
key: familyMeta.key,
|
|
2405
|
+
type: `readonly_held_selector_family`
|
|
2406
|
+
};
|
|
2407
|
+
withdraw(store, familyToken).subject.next({
|
|
2408
|
+
type: `state_disposal`,
|
|
2409
|
+
subType: `selector`,
|
|
2410
|
+
token: selectorToken,
|
|
2411
|
+
timestamp: Date.now()
|
|
2412
|
+
});
|
|
1656
2413
|
break;
|
|
1657
2414
|
case `readonly_pure_selector`:
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
timestamp: Date.now()
|
|
1670
|
-
});
|
|
1671
|
-
}
|
|
2415
|
+
target.readonlySelectors.delete(key);
|
|
2416
|
+
familyToken = {
|
|
2417
|
+
key: familyMeta.key,
|
|
2418
|
+
type: `readonly_pure_selector_family`
|
|
2419
|
+
};
|
|
2420
|
+
withdraw(store, familyToken).subject.next({
|
|
2421
|
+
type: `state_disposal`,
|
|
2422
|
+
subType: `selector`,
|
|
2423
|
+
token: selectorToken,
|
|
2424
|
+
timestamp: Date.now()
|
|
2425
|
+
});
|
|
1672
2426
|
break;
|
|
1673
2427
|
}
|
|
1674
2428
|
target.valueMap.delete(key);
|
|
@@ -1686,6 +2440,82 @@ function disposeSelector(store, selectorToken) {
|
|
|
1686
2440
|
}
|
|
1687
2441
|
}
|
|
1688
2442
|
|
|
2443
|
+
//#endregion
|
|
2444
|
+
//#region src/internal/subscribe/recall-state.ts
|
|
2445
|
+
const recallState = (store, state) => {
|
|
2446
|
+
const target = newest(store);
|
|
2447
|
+
if (target.operation.open) return target.operation.prev.get(state.key);
|
|
2448
|
+
return target.valueMap.get(state.key);
|
|
2449
|
+
};
|
|
2450
|
+
|
|
2451
|
+
//#endregion
|
|
2452
|
+
//#region src/internal/subscribe/subscribe-to-root-atoms.ts
|
|
2453
|
+
const subscribeToRootDependency = (target, selector, atom) => {
|
|
2454
|
+
return atom.subject.subscribe(`${selector.type}:${selector.key}`, (atomChange) => {
|
|
2455
|
+
target.logger.info(`📢`, selector.type, selector.key, `root`, atom.key, `went`, atomChange.oldValue, `->`, atomChange.newValue);
|
|
2456
|
+
const oldValue = recallState(target, selector);
|
|
2457
|
+
const newValue = readOrComputeValue(target, selector);
|
|
2458
|
+
target.logger.info(`✨`, selector.type, selector.key, `went`, oldValue, `->`, newValue);
|
|
2459
|
+
selector.subject.next({
|
|
2460
|
+
newValue,
|
|
2461
|
+
oldValue
|
|
2462
|
+
});
|
|
2463
|
+
});
|
|
2464
|
+
};
|
|
2465
|
+
|
|
2466
|
+
//#endregion
|
|
2467
|
+
//#region src/internal/subscribe/subscribe-to-state.ts
|
|
2468
|
+
function subscribeToState(store, token, key, handleUpdate) {
|
|
2469
|
+
function safelyHandleUpdate(update) {
|
|
2470
|
+
if (store.operation.open) {
|
|
2471
|
+
if (state?.type === `atom` && hasRole(state, `tracker:signal`) && `*` + store.operation.token.key === token.key && `inboundTracker` in handleUpdate) return;
|
|
2472
|
+
const unsubscribe$1 = store.on.operationClose.subscribe(`state subscription ${key}`, () => {
|
|
2473
|
+
unsubscribe$1();
|
|
2474
|
+
handleUpdate(update);
|
|
2475
|
+
});
|
|
2476
|
+
} else handleUpdate(update);
|
|
2477
|
+
}
|
|
2478
|
+
reduceReference(store, token);
|
|
2479
|
+
const state = withdraw(store, token);
|
|
2480
|
+
store.logger.info(`👀`, state.type, state.key, `Adding subscription "${key}"`);
|
|
2481
|
+
const isSelector = state.type === `writable_pure_selector` || state.type === `readonly_pure_selector`;
|
|
2482
|
+
const rootSubs = /* @__PURE__ */ new Map();
|
|
2483
|
+
let updateHandler = safelyHandleUpdate;
|
|
2484
|
+
if (isSelector) {
|
|
2485
|
+
readOrComputeValue(store, state);
|
|
2486
|
+
for (const [atomKey, atom] of traceRootSelectorAtoms(store, state.key)) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
2487
|
+
updateHandler = function updateRootsBeforeHandlingUpdate(update) {
|
|
2488
|
+
const dependencies = traceRootSelectorAtoms(store, state.key);
|
|
2489
|
+
for (const [previousRootKey, unsub] of rootSubs) if (dependencies.get(previousRootKey)) dependencies.delete(previousRootKey);
|
|
2490
|
+
else {
|
|
2491
|
+
unsub();
|
|
2492
|
+
rootSubs.delete(previousRootKey);
|
|
2493
|
+
}
|
|
2494
|
+
for (const [atomKey, atom] of dependencies) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
2495
|
+
safelyHandleUpdate(update);
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
|
|
2499
|
+
const unsubscribe = () => {
|
|
2500
|
+
store.logger.info(`🙈`, state.type, state.key, `Removing subscription "${key}"`);
|
|
2501
|
+
mainUnsubFunction();
|
|
2502
|
+
for (const unsubFromDependency of rootSubs.values()) unsubFromDependency();
|
|
2503
|
+
};
|
|
2504
|
+
return unsubscribe;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
//#endregion
|
|
2508
|
+
//#region src/internal/subscribe/subscribe-to-timeline.ts
|
|
2509
|
+
const subscribeToTimeline = (store, token, key, handleUpdate) => {
|
|
2510
|
+
const tl = withdraw(store, token);
|
|
2511
|
+
store.logger.info(`👀`, `timeline`, token.key, `Adding subscription "${key}"`);
|
|
2512
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate);
|
|
2513
|
+
return () => {
|
|
2514
|
+
store.logger.info(`🙈`, `timeline`, token.key, `Removing subscription "${key}" from timeline`);
|
|
2515
|
+
unsubscribe();
|
|
2516
|
+
};
|
|
2517
|
+
};
|
|
2518
|
+
|
|
1689
2519
|
//#endregion
|
|
1690
2520
|
//#region src/internal/subscribe/subscribe-to-transaction.ts
|
|
1691
2521
|
const subscribeToTransaction = (store, token, key, handleUpdate) => {
|
|
@@ -1713,6 +2543,93 @@ function subscribeInStore(store, token, handleUpdate, key = arbitrary()) {
|
|
|
1713
2543
|
}
|
|
1714
2544
|
}
|
|
1715
2545
|
|
|
2546
|
+
//#endregion
|
|
2547
|
+
//#region src/internal/mutable/tracker.ts
|
|
2548
|
+
/**
|
|
2549
|
+
* @internal Give the tracker a transceiver state and a store, and it will
|
|
2550
|
+
* subscribe to the transceiver's inner value. When the inner value changes,
|
|
2551
|
+
* the tracker will update its own state to reflect the change.
|
|
2552
|
+
*/
|
|
2553
|
+
var Tracker = class {
|
|
2554
|
+
initializeSignalAtom(mutableState, store) {
|
|
2555
|
+
const latestSignalStateKey = `*${mutableState.key}`;
|
|
2556
|
+
store.atoms.delete(latestSignalStateKey);
|
|
2557
|
+
store.valueMap.delete(latestSignalStateKey);
|
|
2558
|
+
const familyMetaData = mutableState.family ? {
|
|
2559
|
+
key: `*${mutableState.family.key}`,
|
|
2560
|
+
subKey: mutableState.family.subKey
|
|
2561
|
+
} : void 0;
|
|
2562
|
+
const latestSignalState = createRegularAtom(store, {
|
|
2563
|
+
key: latestSignalStateKey,
|
|
2564
|
+
default: null
|
|
2565
|
+
}, familyMetaData, [`tracker:signal`]);
|
|
2566
|
+
if (store.parent?.valueMap.has(latestSignalStateKey)) {
|
|
2567
|
+
const parentValue = store.parent.valueMap.get(latestSignalStateKey);
|
|
2568
|
+
store.valueMap.set(latestSignalStateKey, parentValue);
|
|
2569
|
+
}
|
|
2570
|
+
return latestSignalState;
|
|
2571
|
+
}
|
|
2572
|
+
unsubscribeFromInnerValue;
|
|
2573
|
+
unsubscribeFromState;
|
|
2574
|
+
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
2575
|
+
const stateKey = mutableState.key;
|
|
2576
|
+
const storeName = target.config.name;
|
|
2577
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
2578
|
+
const subscriptionKey = `tracker-from-core:${storeName}:${storeStatus}:${stateKey}`;
|
|
2579
|
+
const trackerCapturesOutboundSignal = (update) => {
|
|
2580
|
+
operateOnStore(JOIN_OP, target, latestSignalState, update);
|
|
2581
|
+
};
|
|
2582
|
+
this.unsubscribeFromInnerValue = getFromStore(target, mutableState).subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
2583
|
+
this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, function trackerLooksForNewReference(update) {
|
|
2584
|
+
if (update.newValue !== update.oldValue) {
|
|
2585
|
+
this.unsubscribeFromInnerValue();
|
|
2586
|
+
this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
2587
|
+
}
|
|
2588
|
+
}.bind(this));
|
|
2589
|
+
}
|
|
2590
|
+
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
2591
|
+
const stateKey = mutableState.key;
|
|
2592
|
+
const storeName = target.config.name;
|
|
2593
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
2594
|
+
const subscriptionKey = `tracker-to-core:${storeName}:${storeStatus}:${stateKey}`;
|
|
2595
|
+
subscribeToState(target, latestSignalState, subscriptionKey, Object.assign(function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
2596
|
+
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
2597
|
+
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
2598
|
+
const unsubscribe = subscribeToTimeline(target, {
|
|
2599
|
+
key: timelineId,
|
|
2600
|
+
type: `timeline`
|
|
2601
|
+
}, subscriptionKey, function trackerWaitsForTimeTravelToFinish(update) {
|
|
2602
|
+
unsubscribe();
|
|
2603
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
2604
|
+
if (update === `redo` && newValue) transceiver.do(newValue);
|
|
2605
|
+
else if (update === `undo` && oldValue) transceiver.undo(oldValue);
|
|
2606
|
+
return transceiver;
|
|
2607
|
+
});
|
|
2608
|
+
});
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
|
|
2612
|
+
}, { inboundTracker: true }));
|
|
2613
|
+
}
|
|
2614
|
+
mutableAtomToken;
|
|
2615
|
+
latestSignalToken;
|
|
2616
|
+
[Symbol.dispose];
|
|
2617
|
+
constructor(mutableAtomToken, store) {
|
|
2618
|
+
const target = newest(store);
|
|
2619
|
+
const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target);
|
|
2620
|
+
this.mutableAtomToken = mutableAtomToken;
|
|
2621
|
+
this.latestSignalToken = latestSignalToken;
|
|
2622
|
+
this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target);
|
|
2623
|
+
this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target);
|
|
2624
|
+
target.trackers.set(mutableAtomToken.key, this);
|
|
2625
|
+
this[Symbol.dispose] = () => {
|
|
2626
|
+
this.unsubscribeFromInnerValue();
|
|
2627
|
+
this.unsubscribeFromState();
|
|
2628
|
+
target.trackers.delete(mutableAtomToken.key);
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
};
|
|
2632
|
+
|
|
1716
2633
|
//#endregion
|
|
1717
2634
|
//#region src/internal/mutable/create-mutable-atom.ts
|
|
1718
2635
|
function createMutableAtom(store, options, family) {
|
|
@@ -1855,8 +2772,7 @@ function createMutableAtomFamily(store, options, internalRoles) {
|
|
|
1855
2772
|
const getJsonFamily = (mutableAtomFamily, store) => {
|
|
1856
2773
|
const target = newest(store);
|
|
1857
2774
|
const key = `${mutableAtomFamily.key}:JSON`;
|
|
1858
|
-
|
|
1859
|
-
return jsonFamily;
|
|
2775
|
+
return target.families.get(key);
|
|
1860
2776
|
};
|
|
1861
2777
|
|
|
1862
2778
|
//#endregion
|
|
@@ -1864,21 +2780,18 @@ const getJsonFamily = (mutableAtomFamily, store) => {
|
|
|
1864
2780
|
const getJsonToken = (store, mutableAtomToken) => {
|
|
1865
2781
|
if (mutableAtomToken.family) {
|
|
1866
2782
|
const target = newest(store);
|
|
1867
|
-
const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
|
|
1868
2783
|
const jsonFamilyToken = {
|
|
1869
|
-
key:
|
|
2784
|
+
key: `${mutableAtomToken.family.key}:JSON`,
|
|
1870
2785
|
type: `writable_pure_selector_family`
|
|
1871
2786
|
};
|
|
1872
2787
|
const family = withdraw(target, jsonFamilyToken);
|
|
1873
2788
|
const subKey = parseJson(mutableAtomToken.family.subKey);
|
|
1874
|
-
|
|
1875
|
-
return jsonToken;
|
|
2789
|
+
return findInStore(store, family, subKey);
|
|
1876
2790
|
}
|
|
1877
|
-
|
|
2791
|
+
return {
|
|
1878
2792
|
type: `writable_pure_selector`,
|
|
1879
2793
|
key: `${mutableAtomToken.key}:JSON`
|
|
1880
2794
|
};
|
|
1881
|
-
return token;
|
|
1882
2795
|
};
|
|
1883
2796
|
|
|
1884
2797
|
//#endregion
|
|
@@ -1886,17 +2799,15 @@ const getJsonToken = (store, mutableAtomToken) => {
|
|
|
1886
2799
|
const getUpdateFamily = (mutableAtomFamily, store) => {
|
|
1887
2800
|
const target = newest(store);
|
|
1888
2801
|
const key = `*${mutableAtomFamily.key}`;
|
|
1889
|
-
|
|
1890
|
-
return updateFamily;
|
|
2802
|
+
return target.families.get(key);
|
|
1891
2803
|
};
|
|
1892
2804
|
|
|
1893
2805
|
//#endregion
|
|
1894
2806
|
//#region src/internal/mutable/get-update-token.ts
|
|
1895
2807
|
const getUpdateToken = (mutableAtomToken) => {
|
|
1896
|
-
const key = `*${mutableAtomToken.key}`;
|
|
1897
2808
|
const updateToken = {
|
|
1898
2809
|
type: `atom`,
|
|
1899
|
-
key
|
|
2810
|
+
key: `*${mutableAtomToken.key}`
|
|
1900
2811
|
};
|
|
1901
2812
|
if (mutableAtomToken.family) updateToken.family = {
|
|
1902
2813
|
key: `*${mutableAtomToken.family.key}`,
|
|
@@ -1905,6 +2816,177 @@ const getUpdateToken = (mutableAtomToken) => {
|
|
|
1905
2816
|
return updateToken;
|
|
1906
2817
|
};
|
|
1907
2818
|
|
|
2819
|
+
//#endregion
|
|
2820
|
+
//#region src/internal/mutable/transceiver.ts
|
|
2821
|
+
function isTransceiver(value) {
|
|
2822
|
+
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value && `READONLY_VIEW` in value && `toJSON` in value;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
//#endregion
|
|
2826
|
+
//#region src/internal/caching.ts
|
|
2827
|
+
function writeToCache(target, state, value) {
|
|
2828
|
+
const { key, subject, type } = state;
|
|
2829
|
+
const currentValue = target.valueMap.get(key);
|
|
2830
|
+
if (currentValue instanceof Future && !currentValue.done) {
|
|
2831
|
+
const future = currentValue;
|
|
2832
|
+
if (value instanceof Promise) {
|
|
2833
|
+
future.use(value);
|
|
2834
|
+
return future;
|
|
2835
|
+
}
|
|
2836
|
+
target.valueMap.set(key, value);
|
|
2837
|
+
return value;
|
|
2838
|
+
}
|
|
2839
|
+
if (value instanceof Promise) {
|
|
2840
|
+
const future = new Future(value);
|
|
2841
|
+
target.valueMap.set(key, future);
|
|
2842
|
+
future.then(function handleResolvedFuture(resolved) {
|
|
2843
|
+
if (target.valueMap.get(key) === future) {
|
|
2844
|
+
openOperation(target, state);
|
|
2845
|
+
writeToCache(target, state, resolved);
|
|
2846
|
+
switch (type) {
|
|
2847
|
+
case `atom`:
|
|
2848
|
+
evictDownstreamFromAtom(target, state);
|
|
2849
|
+
break;
|
|
2850
|
+
case `readonly_pure_selector`:
|
|
2851
|
+
case `writable_pure_selector`:
|
|
2852
|
+
evictDownstreamFromSelector(target, key);
|
|
2853
|
+
break;
|
|
2854
|
+
}
|
|
2855
|
+
closeOperation(target);
|
|
2856
|
+
subject.next({
|
|
2857
|
+
newValue: resolved,
|
|
2858
|
+
oldValue: future
|
|
2859
|
+
});
|
|
2860
|
+
}
|
|
2861
|
+
}).catch((thrown) => {
|
|
2862
|
+
target.logger.error(`💥`, state.type, key, `rejected:`, thrown);
|
|
2863
|
+
});
|
|
2864
|
+
return future;
|
|
2865
|
+
}
|
|
2866
|
+
target.logger.info(`📝`, state.type, state.key, `writing to cache`, value);
|
|
2867
|
+
target.valueMap.set(key, value);
|
|
2868
|
+
return value;
|
|
2869
|
+
}
|
|
2870
|
+
/**
|
|
2871
|
+
* @param target - the newest layer of the store
|
|
2872
|
+
* @param state - the state to read from cache
|
|
2873
|
+
* @param mut - whether the value is intended to be mutable
|
|
2874
|
+
* @returns the state's current value
|
|
2875
|
+
*/
|
|
2876
|
+
function readFromCache(target, state, mut) {
|
|
2877
|
+
target.logger.info(`📖`, state.type, state.key, `reading cached value`);
|
|
2878
|
+
let value = target.valueMap.get(state.key);
|
|
2879
|
+
if (mut === `mut` && state.type === `mutable_atom` && isChildStore(target)) {
|
|
2880
|
+
const mutableAtom$1 = state;
|
|
2881
|
+
const { parent } = target;
|
|
2882
|
+
if (target.valueMap.hasOwn(mutableAtom$1.key)) return value;
|
|
2883
|
+
const parentValue = parent.valueMap.get(mutableAtom$1.key);
|
|
2884
|
+
target.logger.info(`📃`, `atom`, mutableAtom$1.key, `copying`);
|
|
2885
|
+
const jsonValue = parentValue.toJSON();
|
|
2886
|
+
const copiedValue = mutableAtom$1.class.fromJSON(jsonValue);
|
|
2887
|
+
target.valueMap.set(mutableAtom$1.key, copiedValue);
|
|
2888
|
+
new Tracker(mutableAtom$1, parent);
|
|
2889
|
+
value = copiedValue;
|
|
2890
|
+
}
|
|
2891
|
+
return value;
|
|
2892
|
+
}
|
|
2893
|
+
function evictCachedValue(target, key) {
|
|
2894
|
+
const currentValue = target.valueMap.get(key);
|
|
2895
|
+
if (currentValue instanceof Future) {
|
|
2896
|
+
const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
|
|
2897
|
+
if (selector) selector.getFrom(target);
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
if (target.operation.open) target.operation.prev.set(key, currentValue);
|
|
2901
|
+
target.valueMap.delete(key);
|
|
2902
|
+
target.logger.info(`🗑`, `state`, key, `evicted`);
|
|
2903
|
+
}
|
|
2904
|
+
|
|
2905
|
+
//#endregion
|
|
2906
|
+
//#region src/internal/set-state/evict-downstream.ts
|
|
2907
|
+
function evictDownstreamFromAtom(store, atom) {
|
|
2908
|
+
const target = newest(store);
|
|
2909
|
+
const { key, type } = atom;
|
|
2910
|
+
const downstreamKeys = target.selectorAtoms.getRelatedKeys(key);
|
|
2911
|
+
target.logger.info(`🧹`, type, key, downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`, downstreamKeys ?? `to evict`);
|
|
2912
|
+
if (downstreamKeys) {
|
|
2913
|
+
if (target.operation.open) target.logger.info(`🧹`, type, key, `[ ${[...target.operation.done].join(`, `)} ] already done`);
|
|
2914
|
+
for (const downstreamKey of downstreamKeys) {
|
|
2915
|
+
if (isDone(target, downstreamKey)) continue;
|
|
2916
|
+
evictCachedValue(target, downstreamKey);
|
|
2917
|
+
markDone(target, downstreamKey);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
function evictDownstreamFromSelector(store, selectorKey) {
|
|
2922
|
+
const target = newest(store);
|
|
2923
|
+
const relationEntries = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: selectorKey }).filter(([_, { source }]) => source === selectorKey);
|
|
2924
|
+
for (const [downstreamSelectorKey] of relationEntries) {
|
|
2925
|
+
if (isDone(target, downstreamSelectorKey)) continue;
|
|
2926
|
+
evictCachedValue(target, downstreamSelectorKey);
|
|
2927
|
+
markDone(target, downstreamSelectorKey);
|
|
2928
|
+
evictDownstreamFromSelector(store, downstreamSelectorKey);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
//#endregion
|
|
2933
|
+
//#region src/internal/atom/create-regular-atom.ts
|
|
2934
|
+
function createRegularAtom(store, options, family, internalRoles) {
|
|
2935
|
+
const type = `atom`;
|
|
2936
|
+
const { key } = options;
|
|
2937
|
+
store.logger.info(`🔨`, type, key, `is being created`);
|
|
2938
|
+
const target = newest(store);
|
|
2939
|
+
const existing = target.atoms.get(key);
|
|
2940
|
+
if (existing && existing.type === type) {
|
|
2941
|
+
store.logger.error(`❌`, `atom`, key, `Tried to create atom, but it already exists in the store.`);
|
|
2942
|
+
return deposit(existing);
|
|
2943
|
+
}
|
|
2944
|
+
const subject = new Subject();
|
|
2945
|
+
const newAtom = {
|
|
2946
|
+
...options,
|
|
2947
|
+
type,
|
|
2948
|
+
install: (s) => {
|
|
2949
|
+
s.logger.info(`🛠️`, type, key, `installing in store "${s.config.name}"`);
|
|
2950
|
+
return createRegularAtom(s, options, family);
|
|
2951
|
+
},
|
|
2952
|
+
subject
|
|
2953
|
+
};
|
|
2954
|
+
if (family) newAtom.family = family;
|
|
2955
|
+
if (internalRoles) newAtom.internalRoles = internalRoles;
|
|
2956
|
+
target.atoms.set(key, newAtom);
|
|
2957
|
+
const token = deposit(newAtom);
|
|
2958
|
+
if (options.effects) {
|
|
2959
|
+
let effectIndex = 0;
|
|
2960
|
+
const cleanupFunctions = [];
|
|
2961
|
+
for (const effect of options.effects) {
|
|
2962
|
+
const cleanup = effect({
|
|
2963
|
+
resetSelf: () => {
|
|
2964
|
+
resetInStore(store, token);
|
|
2965
|
+
},
|
|
2966
|
+
setSelf: (next) => {
|
|
2967
|
+
setIntoStore(store, token, next);
|
|
2968
|
+
},
|
|
2969
|
+
onSet: (handle) => subscribeToState(store, token, `effect[${effectIndex}]`, handle)
|
|
2970
|
+
});
|
|
2971
|
+
if (cleanup) cleanupFunctions.push(cleanup);
|
|
2972
|
+
++effectIndex;
|
|
2973
|
+
}
|
|
2974
|
+
newAtom.cleanup = () => {
|
|
2975
|
+
for (const cleanup of cleanupFunctions) cleanup();
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
store.on.atomCreation.next(token);
|
|
2979
|
+
return token;
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
//#endregion
|
|
2983
|
+
//#region src/internal/atom/has-role.ts
|
|
2984
|
+
const INTERNAL_ROLES = [`tracker:signal`];
|
|
2985
|
+
function hasRole(atom, role) {
|
|
2986
|
+
if (`internalRoles` in atom === false) return false;
|
|
2987
|
+
return atom.internalRoles.includes(role);
|
|
2988
|
+
}
|
|
2989
|
+
|
|
1908
2990
|
//#endregion
|
|
1909
2991
|
//#region src/internal/atom/dispose-atom.ts
|
|
1910
2992
|
function disposeAtom(store, atomToken) {
|
|
@@ -1916,8 +2998,7 @@ function disposeAtom(store, atomToken) {
|
|
|
1916
2998
|
atom.cleanup?.();
|
|
1917
2999
|
const lastValue = store.valueMap.get(atom.key);
|
|
1918
3000
|
const familyToken = getFamilyOfToken(store, atomToken);
|
|
1919
|
-
const
|
|
1920
|
-
const subject = atomFamily$1.subject;
|
|
3001
|
+
const subject = withdraw(store, familyToken).subject;
|
|
1921
3002
|
const disposalEvent = {
|
|
1922
3003
|
type: `state_disposal`,
|
|
1923
3004
|
subType: `atom`,
|
|
@@ -1941,8 +3022,7 @@ function disposeAtom(store, atomToken) {
|
|
|
1941
3022
|
store.logger.info(`🔥`, `atom`, key, `deleted`);
|
|
1942
3023
|
if (isChild && target.transactionMeta.phase === `building`) {
|
|
1943
3024
|
const mostRecentUpdate = target.transactionMeta.update.subEvents.at(-1);
|
|
1944
|
-
const
|
|
1945
|
-
const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
3025
|
+
const updateAlreadyCaptured = mostRecentUpdate?.type === `molecule_disposal` && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
1946
3026
|
const isTracker = hasRole(atom, `tracker:signal`);
|
|
1947
3027
|
if (!updateAlreadyCaptured && !isTracker) target.transactionMeta.update.subEvents.push(disposalEvent);
|
|
1948
3028
|
} else store.on.atomDisposal.next(atomToken);
|
|
@@ -1976,10 +3056,7 @@ function installIntoStore(tokens, target, source) {
|
|
|
1976
3056
|
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.`);
|
|
1977
3057
|
return;
|
|
1978
3058
|
}
|
|
1979
|
-
for (const token of tokens)
|
|
1980
|
-
const resource = withdraw(source, token);
|
|
1981
|
-
resource.install(target);
|
|
1982
|
-
}
|
|
3059
|
+
for (const token of tokens) withdraw(source, token).install(target);
|
|
1983
3060
|
}
|
|
1984
3061
|
|
|
1985
3062
|
//#endregion
|
|
@@ -2046,8 +3123,7 @@ var Join = class {
|
|
|
2046
3123
|
const relationsOfAState = find(relatedKeysAtoms, a);
|
|
2047
3124
|
const currentRelationsOfA = get(relationsOfAState);
|
|
2048
3125
|
for (const currentRelationB of currentRelationsOfA) {
|
|
2049
|
-
|
|
2050
|
-
if (remainsRelated) continue;
|
|
3126
|
+
if (newRelationsOfA.includes(currentRelationB)) continue;
|
|
2051
3127
|
set(relatedKeysAtoms, currentRelationB, (relationsOfB) => {
|
|
2052
3128
|
relationsOfB.delete(a);
|
|
2053
3129
|
return relationsOfB;
|
|
@@ -2130,17 +3206,15 @@ var Join = class {
|
|
|
2130
3206
|
const setContent = ({ set }, key, content) => {
|
|
2131
3207
|
set(contentAtoms, key, content);
|
|
2132
3208
|
};
|
|
2133
|
-
|
|
3209
|
+
externalStore = Object.assign(baseExternalStoreConfiguration, {
|
|
2134
3210
|
getContent: (contentKey) => {
|
|
2135
|
-
|
|
2136
|
-
return content;
|
|
3211
|
+
return getContent(this.toolkit, contentKey);
|
|
2137
3212
|
},
|
|
2138
3213
|
setContent: (contentKey, content) => {
|
|
2139
3214
|
setContent(this.toolkit, contentKey, content);
|
|
2140
3215
|
},
|
|
2141
3216
|
deleteContent: (_) => {}
|
|
2142
|
-
};
|
|
2143
|
-
externalStore = Object.assign(baseExternalStoreConfiguration, externalStoreWithContentConfiguration);
|
|
3217
|
+
});
|
|
2144
3218
|
} else externalStore = baseExternalStoreConfiguration;
|
|
2145
3219
|
const relations = new Junction(options, {
|
|
2146
3220
|
externalStore,
|
|
@@ -2173,8 +3247,7 @@ var Join = class {
|
|
|
2173
3247
|
key: `${options.key}/multipleRelatedKeys`,
|
|
2174
3248
|
get: (key) => ({ get }) => {
|
|
2175
3249
|
const jsonFamily = getJsonFamily(relatedKeysAtoms, store);
|
|
2176
|
-
|
|
2177
|
-
return json.members;
|
|
3250
|
+
return get(jsonFamily, key).members;
|
|
2178
3251
|
}
|
|
2179
3252
|
}, [`join`, `keys`]);
|
|
2180
3253
|
};
|
|
@@ -2198,8 +3271,7 @@ var Join = class {
|
|
|
2198
3271
|
key: `${options.key}/multipleRelatedEntries`,
|
|
2199
3272
|
get: (x) => ({ get }) => {
|
|
2200
3273
|
const jsonFamily = getJsonFamily(relatedKeysAtoms, store);
|
|
2201
|
-
|
|
2202
|
-
return json.members.map((y) => {
|
|
3274
|
+
return get(jsonFamily, x).members.map((y) => {
|
|
2203
3275
|
let a = relations.isAType?.(x) ? x : void 0;
|
|
2204
3276
|
let b = a === void 0 ? x : void 0;
|
|
2205
3277
|
a ??= y;
|
|
@@ -2289,14 +3361,13 @@ var Join = class {
|
|
|
2289
3361
|
//#region src/internal/join/create-join.ts
|
|
2290
3362
|
function createJoin(store, options, defaultContent) {
|
|
2291
3363
|
store.joins.set(options.key, new Join(options, defaultContent, store));
|
|
2292
|
-
|
|
3364
|
+
return {
|
|
2293
3365
|
key: options.key,
|
|
2294
3366
|
type: `join`,
|
|
2295
3367
|
a: options.between[0],
|
|
2296
3368
|
b: options.between[1],
|
|
2297
3369
|
cardinality: options.cardinality
|
|
2298
3370
|
};
|
|
2299
|
-
return token;
|
|
2300
3371
|
}
|
|
2301
3372
|
|
|
2302
3373
|
//#endregion
|
|
@@ -2304,8 +3375,7 @@ function createJoin(store, options, defaultContent) {
|
|
|
2304
3375
|
function getJoin(token, store) {
|
|
2305
3376
|
let myJoin = store.joins.get(token.key);
|
|
2306
3377
|
if (myJoin === void 0) {
|
|
2307
|
-
const
|
|
2308
|
-
const rootJoin = rootJoinMap.get(token.key);
|
|
3378
|
+
const rootJoin = IMPLICIT.STORE.joins.get(token.key);
|
|
2309
3379
|
if (rootJoin === void 0) throw new Error(`Join "${token.key}" not found in store "${store.config.name}"`);
|
|
2310
3380
|
const root = eldest(store);
|
|
2311
3381
|
myJoin = new Join(rootJoin.options, rootJoin.defaultContent, root);
|
|
@@ -2339,13 +3409,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2339
3409
|
relations = {
|
|
2340
3410
|
get [keyAB]() {
|
|
2341
3411
|
const familyAB = myJoin.states[keyAB];
|
|
2342
|
-
|
|
2343
|
-
return state;
|
|
3412
|
+
return findInStore(store, familyAB, key);
|
|
2344
3413
|
},
|
|
2345
3414
|
get [keyBA]() {
|
|
2346
3415
|
const familyBA = myJoin.states[keyBA];
|
|
2347
|
-
|
|
2348
|
-
return state;
|
|
3416
|
+
return findInStore(store, familyBA, key);
|
|
2349
3417
|
}
|
|
2350
3418
|
};
|
|
2351
3419
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`;
|
|
@@ -2354,13 +3422,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2354
3422
|
Object.assign(relations, {
|
|
2355
3423
|
get [entryAB]() {
|
|
2356
3424
|
const familyAB = myJoin.states[entryAB];
|
|
2357
|
-
|
|
2358
|
-
return state;
|
|
3425
|
+
return findInStore(store, familyAB, key);
|
|
2359
3426
|
},
|
|
2360
3427
|
get [entryBA]() {
|
|
2361
3428
|
const familyBA = myJoin.states[entryBA];
|
|
2362
|
-
|
|
2363
|
-
return state;
|
|
3429
|
+
return findInStore(store, familyBA, key);
|
|
2364
3430
|
}
|
|
2365
3431
|
});
|
|
2366
3432
|
}
|
|
@@ -2372,13 +3438,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2372
3438
|
relations = {
|
|
2373
3439
|
get [keyAB]() {
|
|
2374
3440
|
const familyAB = myJoin.states[keyAB];
|
|
2375
|
-
|
|
2376
|
-
return state;
|
|
3441
|
+
return findInStore(store, familyAB, key);
|
|
2377
3442
|
},
|
|
2378
3443
|
get [keysBA]() {
|
|
2379
3444
|
const familyBA = myJoin.states[keysBA];
|
|
2380
|
-
|
|
2381
|
-
return state;
|
|
3445
|
+
return findInStore(store, familyBA, key);
|
|
2382
3446
|
}
|
|
2383
3447
|
};
|
|
2384
3448
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`;
|
|
@@ -2387,13 +3451,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2387
3451
|
Object.assign(relations, {
|
|
2388
3452
|
get [entryAB]() {
|
|
2389
3453
|
const familyAB = myJoin.states[entryAB];
|
|
2390
|
-
|
|
2391
|
-
return state;
|
|
3454
|
+
return findInStore(store, familyAB, key);
|
|
2392
3455
|
},
|
|
2393
3456
|
get [entriesBA]() {
|
|
2394
3457
|
const familyBA = myJoin.states[entriesBA];
|
|
2395
|
-
|
|
2396
|
-
return state;
|
|
3458
|
+
return findInStore(store, familyBA, key);
|
|
2397
3459
|
}
|
|
2398
3460
|
});
|
|
2399
3461
|
}
|
|
@@ -2405,13 +3467,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2405
3467
|
relations = {
|
|
2406
3468
|
get [keysAB]() {
|
|
2407
3469
|
const familyAB = myJoin.states[keysAB];
|
|
2408
|
-
|
|
2409
|
-
return state;
|
|
3470
|
+
return findInStore(store, familyAB, key);
|
|
2410
3471
|
},
|
|
2411
3472
|
get [keysBA]() {
|
|
2412
3473
|
const familyBA = myJoin.states[keysBA];
|
|
2413
|
-
|
|
2414
|
-
return state;
|
|
3474
|
+
return findInStore(store, familyBA, key);
|
|
2415
3475
|
}
|
|
2416
3476
|
};
|
|
2417
3477
|
const entriesAB = `${token.a}EntriesOf${capitalize(token.b)}`;
|
|
@@ -2420,13 +3480,11 @@ function findRelationsInStore(token, key, store) {
|
|
|
2420
3480
|
Object.assign(relations, {
|
|
2421
3481
|
get [entriesAB]() {
|
|
2422
3482
|
const familyAB = myJoin.states[entriesAB];
|
|
2423
|
-
|
|
2424
|
-
return state;
|
|
3483
|
+
return findInStore(store, familyAB, key);
|
|
2425
3484
|
},
|
|
2426
3485
|
get [entriesBA]() {
|
|
2427
3486
|
const familyBA = myJoin.states[entriesBA];
|
|
2428
|
-
|
|
2429
|
-
return state;
|
|
3487
|
+
return findInStore(store, familyBA, key);
|
|
2430
3488
|
}
|
|
2431
3489
|
});
|
|
2432
3490
|
}
|
|
@@ -2438,9 +3496,7 @@ function findRelationsInStore(token, key, store) {
|
|
|
2438
3496
|
//#endregion
|
|
2439
3497
|
//#region src/internal/join/get-internal-relations-from-store.ts
|
|
2440
3498
|
function getInternalRelationsFromStore(token, store) {
|
|
2441
|
-
|
|
2442
|
-
const family = myJoin.core.relatedKeysAtoms;
|
|
2443
|
-
return family;
|
|
3499
|
+
return getJoin(token, store).core.relatedKeysAtoms;
|
|
2444
3500
|
}
|
|
2445
3501
|
|
|
2446
3502
|
//#endregion
|
|
@@ -2554,11 +3610,10 @@ function addAtomFamilyToTimeline(store, atomFamilyToken, tl) {
|
|
|
2554
3610
|
function joinTransaction(store, tl, txUpdateInProgress) {
|
|
2555
3611
|
const currentTxKey = txUpdateInProgress.token.key;
|
|
2556
3612
|
const currentTxInstanceId = txUpdateInProgress.id;
|
|
2557
|
-
const
|
|
3613
|
+
const currentTransaction = withdraw(store, {
|
|
2558
3614
|
key: currentTxKey,
|
|
2559
3615
|
type: `transaction`
|
|
2560
|
-
};
|
|
2561
|
-
const currentTransaction = withdraw(store, currentTxToken);
|
|
3616
|
+
});
|
|
2562
3617
|
if (currentTxKey && tl.transactionKey === null) {
|
|
2563
3618
|
tl.transactionKey = currentTxKey;
|
|
2564
3619
|
const unsubscribe = currentTransaction.subject.subscribe(`timeline:${tl.key}`, (transactionUpdate) => {
|
|
@@ -2721,5 +3776,5 @@ const timeTravel = (store, action, token) => {
|
|
|
2721
3776
|
};
|
|
2722
3777
|
|
|
2723
3778
|
//#endregion
|
|
2724
|
-
export { CircularBuffer, FamilyTracker, Future, IMPLICIT, INTERNAL_ROLES, Join, Junction, MapOverlay, NotFoundError, RESET_STATE, RelationsOverlay, SetOverlay, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, capitalize, claimWithinStore, clearStore, closeOperation, createClaimTX, createDeallocateTX, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFamilyOfToken, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, hasRole, ingestAtomUpdateEvent, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdateEvent, ingestTransactionOutcomeEvent, installIntoStore, isAtomKey, isChildStore, isDone, isFn, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, readFromCache, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw, writeToCache };
|
|
3779
|
+
export { CircularBuffer, FamilyTracker, Future, IMPLICIT, INTERNAL_ROLES, JOIN_OP, Join, Junction, MapOverlay, NotFoundError, OWN_OP, RESET_STATE, RelationsOverlay, SetOverlay, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, capitalize, claimWithinStore, clearStore, closeOperation, createClaimTX, createDeallocateTX, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFamilyOfToken, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, hasRole, ingestAtomUpdateEvent, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdateEvent, ingestTransactionOutcomeEvent, installIntoStore, isAtomKey, isChildStore, isDone, isFn, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, operateOnStore, readFromCache, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw, writeToCache };
|
|
2725
3780
|
//# sourceMappingURL=index.js.map
|