atom.io 0.40.6 โ 0.40.8
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/README.md +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +1 -2
- package/dist/data/index.js.map +1 -1
- package/dist/employ-socket-D6wgByWh.js +12 -0
- package/dist/employ-socket-D6wgByWh.js.map +1 -0
- package/dist/eslint-plugin/index.js.map +1 -1
- package/dist/has-role-CMlaUlaf.js +1133 -0
- package/dist/has-role-CMlaUlaf.js.map +1 -0
- package/dist/internal/index.d.ts +248 -248
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +590 -1803
- package/dist/internal/index.js.map +1 -1
- package/dist/introspection/index.d.ts +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/is-fn-DY1wZ-md.js +10 -0
- package/dist/is-fn-DY1wZ-md.js.map +1 -0
- package/dist/json/index.d.ts.map +1 -1
- package/dist/json/index.js.map +1 -1
- package/dist/main/index.d.ts +33 -33
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +3 -4
- package/dist/main/index.js.map +1 -1
- package/dist/mutex-store-CSvxY9i3.js +11 -0
- package/dist/mutex-store-CSvxY9i3.js.map +1 -0
- package/dist/react/index.d.ts +5 -5
- 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 +9 -11
- package/dist/react-devtools/index.js.map +1 -1
- package/dist/realtime/index.d.ts +7 -15
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +4 -35
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-client/index.d.ts +6 -9
- package/dist/realtime-client/index.d.ts.map +1 -1
- package/dist/realtime-client/index.js +96 -88
- package/dist/realtime-client/index.js.map +1 -1
- package/dist/realtime-react/index.d.ts +17 -13
- package/dist/realtime-react/index.d.ts.map +1 -1
- package/dist/realtime-react/index.js +39 -50
- package/dist/realtime-react/index.js.map +1 -1
- package/dist/realtime-server/index.d.ts +83 -84
- package/dist/realtime-server/index.d.ts.map +1 -1
- package/dist/realtime-server/index.js +604 -543
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.d.ts +5 -4
- package/dist/realtime-testing/index.d.ts.map +1 -1
- package/dist/realtime-testing/index.js +35 -22
- package/dist/realtime-testing/index.js.map +1 -1
- package/dist/shared-room-store-BfW3nWif.js +31 -0
- package/dist/shared-room-store-BfW3nWif.js.map +1 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
- package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js +4 -8
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/web/index.d.ts +3 -3
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +4 -3
- package/dist/web/index.js.map +1 -1
- package/package.json +13 -13
- package/src/internal/atom/create-regular-atom.ts +5 -4
- package/src/internal/atom/dispose-atom.ts +7 -2
- package/src/internal/atom/has-role.ts +3 -3
- package/src/internal/caching.ts +4 -2
- package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
- package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
- package/src/internal/families/create-regular-atom-family.ts +2 -1
- package/src/internal/families/create-writable-held-selector-family.ts +2 -1
- package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
- package/src/internal/families/dispose-from-store.ts +4 -4
- package/src/internal/families/find-in-store.ts +10 -10
- package/src/internal/families/get-family-of-token.ts +2 -2
- package/src/internal/families/index.ts +1 -0
- package/src/internal/families/mint-in-store.ts +54 -19
- package/src/internal/families/seek-in-store.ts +1 -1
- package/src/internal/get-state/get-fallback.ts +2 -2
- package/src/internal/get-state/get-from-store.ts +5 -5
- package/src/internal/get-state/read-or-compute-value.ts +1 -1
- package/src/internal/get-state/reduce-reference.ts +8 -6
- package/src/internal/index.ts +2 -220
- package/src/internal/molecule.ts +1 -2
- package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
- package/src/internal/mutable/create-mutable-atom.ts +4 -2
- package/src/internal/mutable/get-json-family.ts +1 -1
- package/src/internal/mutable/get-update-family.ts +1 -1
- package/src/internal/mutable/tracker-family.ts +2 -1
- package/src/internal/mutable/tracker.ts +71 -59
- package/src/internal/safe-compute.ts +1 -1
- package/src/internal/selector/create-readonly-held-selector.ts +2 -1
- package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
- package/src/internal/selector/create-writable-held-selector.ts +2 -1
- package/src/internal/selector/create-writable-pure-selector.ts +2 -1
- package/src/internal/selector/dispose-selector.ts +3 -2
- package/src/internal/selector/register-selector.ts +8 -5
- package/src/internal/selector/trace-selector-atoms.ts +2 -1
- package/src/internal/set-state/dispatch-state-update.ts +3 -2
- package/src/internal/set-state/evict-downstream.ts +1 -1
- package/src/internal/set-state/operate-on-store.ts +16 -22
- package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
- package/src/internal/set-state/reset-in-store.ts +5 -5
- package/src/internal/set-state/set-atom-or-selector.ts +2 -2
- package/src/internal/set-state/set-atom.ts +4 -2
- package/src/internal/set-state/set-into-store.ts +21 -39
- package/src/internal/set-state/set-selector.ts +3 -2
- package/src/internal/state-types.ts +228 -0
- package/src/internal/store/deposit.ts +4 -4
- package/src/internal/store/index.ts +0 -1
- package/src/internal/store/store.ts +9 -9
- package/src/internal/store/withdraw.ts +4 -4
- package/src/internal/subscribe/recall-state.ts +1 -1
- package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
- package/src/internal/subscribe/subscribe-to-state.ts +9 -0
- package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
- package/src/internal/transaction/build-transaction.ts +3 -2
- package/src/internal/transaction/index.ts +1 -23
- package/src/internal/transaction/is-root-store.ts +4 -1
- package/src/internal/transaction/transaction-meta-progress.ts +22 -0
- package/src/main/atom.ts +1 -2
- package/src/main/find-state.ts +5 -5
- package/src/main/get-state.ts +4 -4
- package/src/main/realm.ts +2 -2
- package/src/main/set-state.ts +10 -10
- package/src/react/parse-state-overloads.ts +3 -3
- package/src/react/use-i.ts +6 -4
- package/src/react/use-loadable.ts +4 -10
- package/src/react/use-o.ts +6 -4
- package/src/react-devtools/store.ts +6 -6
- package/src/realtime/index.ts +1 -0
- package/src/realtime/mutex-store.ts +11 -0
- package/src/realtime/realtime-continuity.ts +1 -5
- package/src/realtime-client/index.ts +0 -1
- package/src/realtime-client/pull-atom-family-member.ts +14 -17
- package/src/realtime-client/pull-atom.ts +1 -1
- package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
- package/src/realtime-client/pull-selector-family-member.ts +8 -35
- package/src/realtime-client/pull-selector-roots.ts +90 -0
- package/src/realtime-client/pull-selector.ts +2 -27
- package/src/realtime-client/push-state.ts +33 -5
- package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
- package/src/realtime-react/index.ts +2 -2
- package/src/realtime-react/realtime-context.tsx +9 -5
- package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
- package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
- package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
- package/src/realtime-react/use-push.ts +7 -3
- package/src/realtime-react/use-realtime-service.ts +11 -11
- package/src/realtime-react/use-single-effect.ts +11 -14
- package/src/realtime-server/{realtime-server-stores/server-sync-store.ts โ 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} +15 -13
- package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts โ provide-perspectives.ts} +10 -8
- package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts โ provide-startup-payloads.ts} +6 -4
- package/src/realtime-server/continuity/receive-action-requests.ts +68 -0
- package/src/realtime-server/continuity/track-acknowledgements.ts +46 -0
- package/src/realtime-server/employ-socket.ts +14 -0
- package/src/realtime-server/index.ts +3 -22
- package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
- package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
- package/src/realtime-server/ipc-sockets/parent-socket.ts +98 -69
- package/src/realtime-server/realtime-family-provider.ts +78 -29
- package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
- package/src/realtime-server/realtime-mutable-provider.ts +30 -22
- package/src/realtime-server/realtime-server-stores/index.ts +0 -2
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
- package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
- package/src/realtime-server/realtime-state-provider.ts +30 -29
- package/src/realtime-server/realtime-state-receiver.ts +62 -16
- package/src/realtime-server/server-config.ts +8 -0
- package/src/realtime-server/socket-interface.ts +14 -0
- package/src/realtime-testing/setup-realtime-test.tsx +70 -31
- package/src/web/index.ts +1 -1
- package/src/web/{persist-sync.ts โ storage-sync.ts} +5 -2
- package/src/internal/store/mint-or-counterfeit.ts +0 -108
- package/src/realtime-client/server-action.ts +0 -23
- package/src/realtime-react/on-mount.ts +0 -5
- 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/continuity/prepare-to-track-client-acknowledgement.ts +0 -41
- package/src/realtime-server/realtime-action-receiver.ts +0 -40
- package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +0 -79
|
@@ -0,0 +1,1133 @@
|
|
|
1
|
+
import { isFn } from "./is-fn-DY1wZ-md.js";
|
|
2
|
+
import { PRETTY_TOKEN_TYPES } from "atom.io";
|
|
3
|
+
import { parseJson, stringifyJson } from "atom.io/json";
|
|
4
|
+
|
|
5
|
+
//#region src/internal/lineage.ts
|
|
6
|
+
function newest(scion) {
|
|
7
|
+
while (scion.child !== null) scion = scion.child;
|
|
8
|
+
return scion;
|
|
9
|
+
}
|
|
10
|
+
function eldest(scion) {
|
|
11
|
+
while (scion.parent !== null) scion = scion.parent;
|
|
12
|
+
return scion;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/internal/set-state/become.ts
|
|
17
|
+
function become(nextVersionOfThing, originalThing) {
|
|
18
|
+
if (isFn(nextVersionOfThing)) return nextVersionOfThing(originalThing);
|
|
19
|
+
return nextVersionOfThing;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/internal/future.ts
|
|
24
|
+
/**
|
|
25
|
+
* A Promise whose incoming value can be hot swapped.
|
|
26
|
+
* @internal
|
|
27
|
+
* @private
|
|
28
|
+
* @typeParam T The type of the value that the promise will resolve to.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Can be constructed like a Promise, or from an existing Promise.
|
|
32
|
+
*/
|
|
33
|
+
var Future = class extends Promise {
|
|
34
|
+
fate;
|
|
35
|
+
resolve;
|
|
36
|
+
reject;
|
|
37
|
+
done = false;
|
|
38
|
+
constructor(executor) {
|
|
39
|
+
let superResolve;
|
|
40
|
+
let superReject;
|
|
41
|
+
super((resolve, reject) => {
|
|
42
|
+
superResolve = resolve;
|
|
43
|
+
superReject = reject;
|
|
44
|
+
});
|
|
45
|
+
this.resolve = superResolve;
|
|
46
|
+
this.reject = superReject;
|
|
47
|
+
this.use(executor instanceof Promise ? executor : new Promise(executor));
|
|
48
|
+
}
|
|
49
|
+
pass(promise, value) {
|
|
50
|
+
if (promise === this.fate) {
|
|
51
|
+
this.resolve(value);
|
|
52
|
+
this.done = true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
fail(promise, reason) {
|
|
56
|
+
if (promise === this.fate) {
|
|
57
|
+
this.reject(reason);
|
|
58
|
+
this.done = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
use(value) {
|
|
62
|
+
if (this === value) return;
|
|
63
|
+
if (value instanceof Promise) {
|
|
64
|
+
const promise = value;
|
|
65
|
+
this.fate = promise;
|
|
66
|
+
promise.then((resolved) => {
|
|
67
|
+
this.pass(promise, resolved);
|
|
68
|
+
}, (reason) => {
|
|
69
|
+
this.fail(promise, reason);
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
this.resolve(value);
|
|
73
|
+
this.fate = void 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/internal/subject.ts
|
|
80
|
+
var Subject = class {
|
|
81
|
+
Subscriber;
|
|
82
|
+
subscribers = /* @__PURE__ */ new Map();
|
|
83
|
+
subscribe(key, subscriber) {
|
|
84
|
+
this.subscribers.set(key, subscriber);
|
|
85
|
+
const unsubscribe = () => {
|
|
86
|
+
this.unsubscribe(key);
|
|
87
|
+
};
|
|
88
|
+
return unsubscribe;
|
|
89
|
+
}
|
|
90
|
+
unsubscribe(key) {
|
|
91
|
+
this.subscribers.delete(key);
|
|
92
|
+
}
|
|
93
|
+
next(value) {
|
|
94
|
+
const subscribers = this.subscribers.values();
|
|
95
|
+
for (const subscriber of subscribers) subscriber(value);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
var StatefulSubject = class extends Subject {
|
|
99
|
+
state;
|
|
100
|
+
constructor(initialState) {
|
|
101
|
+
super();
|
|
102
|
+
this.state = initialState;
|
|
103
|
+
}
|
|
104
|
+
next(value) {
|
|
105
|
+
this.state = value;
|
|
106
|
+
super.next(value);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/internal/store/deposit.ts
|
|
112
|
+
function deposit(state) {
|
|
113
|
+
const token = {
|
|
114
|
+
key: state.key,
|
|
115
|
+
type: state.type
|
|
116
|
+
};
|
|
117
|
+
if (`family` in state) token.family = state.family;
|
|
118
|
+
return token;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/internal/transaction/is-root-store.ts
|
|
123
|
+
function isRootStore(store) {
|
|
124
|
+
return `epoch` in store.transactionMeta;
|
|
125
|
+
}
|
|
126
|
+
function isChildStore(store) {
|
|
127
|
+
return `phase` in store.transactionMeta;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/internal/not-found-error.ts
|
|
132
|
+
var NotFoundError = class extends Error {
|
|
133
|
+
constructor(token, store) {
|
|
134
|
+
super(`${PRETTY_TOKEN_TYPES[token.type]} ${stringifyJson(token.key)} not found in store "${store.config.name}".`);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/internal/store/withdraw.ts
|
|
140
|
+
function withdraw(store, token) {
|
|
141
|
+
let withdrawn;
|
|
142
|
+
let target = store;
|
|
143
|
+
while (target !== null) {
|
|
144
|
+
switch (token.type) {
|
|
145
|
+
case `atom`:
|
|
146
|
+
case `mutable_atom`:
|
|
147
|
+
withdrawn = target.atoms.get(token.key);
|
|
148
|
+
break;
|
|
149
|
+
case `writable_pure_selector`:
|
|
150
|
+
case `writable_held_selector`:
|
|
151
|
+
withdrawn = target.writableSelectors.get(token.key);
|
|
152
|
+
break;
|
|
153
|
+
case `readonly_pure_selector`:
|
|
154
|
+
case `readonly_held_selector`:
|
|
155
|
+
withdrawn = target.readonlySelectors.get(token.key);
|
|
156
|
+
break;
|
|
157
|
+
case `atom_family`:
|
|
158
|
+
case `mutable_atom_family`:
|
|
159
|
+
case `writable_pure_selector_family`:
|
|
160
|
+
case `readonly_pure_selector_family`:
|
|
161
|
+
case `writable_held_selector_family`:
|
|
162
|
+
case `readonly_held_selector_family`:
|
|
163
|
+
withdrawn = target.families.get(token.key);
|
|
164
|
+
break;
|
|
165
|
+
case `timeline`:
|
|
166
|
+
withdrawn = target.timelines.get(token.key);
|
|
167
|
+
break;
|
|
168
|
+
case `transaction`:
|
|
169
|
+
withdrawn = target.transactions.get(token.key);
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
if (withdrawn) return withdrawn;
|
|
173
|
+
target = target.child;
|
|
174
|
+
}
|
|
175
|
+
throw new NotFoundError(token, store);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/internal/get-state/get-fallback.ts
|
|
180
|
+
function getFallback(store, token, family, subKey) {
|
|
181
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === stringifyJson(subKey));
|
|
182
|
+
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)`);
|
|
183
|
+
switch (family.type) {
|
|
184
|
+
case `mutable_atom_family`: {
|
|
185
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
186
|
+
const defaultValue = new family.class();
|
|
187
|
+
store.defaults.set(family.key, defaultValue);
|
|
188
|
+
return defaultValue.READONLY_VIEW;
|
|
189
|
+
}
|
|
190
|
+
case `atom_family`: {
|
|
191
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
192
|
+
const def = family.default;
|
|
193
|
+
const defaultValue = def(subKey);
|
|
194
|
+
store.defaults.set(family.key, defaultValue);
|
|
195
|
+
return defaultValue;
|
|
196
|
+
}
|
|
197
|
+
case `readonly_pure_selector_family`:
|
|
198
|
+
case `writable_pure_selector_family`:
|
|
199
|
+
case `readonly_held_selector_family`:
|
|
200
|
+
case `writable_held_selector_family`: {
|
|
201
|
+
if (store.defaults.has(family.key)) return store.defaults.get(family.key);
|
|
202
|
+
const defaultValue = family.default(subKey);
|
|
203
|
+
store.defaults.set(family.key, defaultValue);
|
|
204
|
+
return defaultValue;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/internal/safe-compute.ts
|
|
211
|
+
function safeCompute(target, state) {
|
|
212
|
+
const { type, key, catch: canCatch } = state;
|
|
213
|
+
switch (type) {
|
|
214
|
+
case `readonly_pure_selector`:
|
|
215
|
+
case `writable_pure_selector`: {
|
|
216
|
+
let val;
|
|
217
|
+
target.logger.info(`๐งฎ`, type, key, `computing value`);
|
|
218
|
+
try {
|
|
219
|
+
val = state.getFrom(target);
|
|
220
|
+
if (val instanceof Promise) return val.catch((thrown) => {
|
|
221
|
+
target.logger.error(`๐ฅ`, type, key, `rejected:`, thrown);
|
|
222
|
+
if (canCatch) {
|
|
223
|
+
for (const Class of canCatch) if (thrown instanceof Class) return thrown;
|
|
224
|
+
}
|
|
225
|
+
throw thrown;
|
|
226
|
+
});
|
|
227
|
+
} catch (e) {
|
|
228
|
+
target.logger.error(`๐ฅ`, type, key, `rejected:`, e);
|
|
229
|
+
if (canCatch) {
|
|
230
|
+
for (const Class of canCatch) if (e instanceof Class) return writeToCache(target, state, e);
|
|
231
|
+
}
|
|
232
|
+
throw e;
|
|
233
|
+
}
|
|
234
|
+
return writeToCache(target, state, val);
|
|
235
|
+
}
|
|
236
|
+
case `atom`: {
|
|
237
|
+
let def;
|
|
238
|
+
if (isFn(state.default)) try {
|
|
239
|
+
def = state.default();
|
|
240
|
+
if (def instanceof Promise) def = def.catch((thrown) => {
|
|
241
|
+
target.logger.error(`๐ฅ`, type, key, `rejected:`, thrown);
|
|
242
|
+
if (canCatch) {
|
|
243
|
+
for (const Class of canCatch) if (thrown instanceof Class) return thrown;
|
|
244
|
+
}
|
|
245
|
+
throw thrown;
|
|
246
|
+
});
|
|
247
|
+
} catch (e) {
|
|
248
|
+
target.logger.error(`๐ฅ`, type, key, `rejected:`, e);
|
|
249
|
+
if (canCatch) {
|
|
250
|
+
for (const Class of canCatch) if (e instanceof Class) {
|
|
251
|
+
def = writeToCache(target, state, e);
|
|
252
|
+
target.logger.info(`โจ`, state.type, key, `computed default`, def);
|
|
253
|
+
return def;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
throw e;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
def = state.default;
|
|
260
|
+
target.logger.info(`โจ`, state.type, key, `using static default`, def);
|
|
261
|
+
}
|
|
262
|
+
return writeToCache(target, state, def);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/internal/get-state/read-or-compute-value.ts
|
|
269
|
+
function readOrComputeValue(target, state, mut) {
|
|
270
|
+
if (target.valueMap.has(state.key)) return readFromCache(target, state, mut);
|
|
271
|
+
target.logger.info(`โ`, state.type, state.key, `value not found in cache`);
|
|
272
|
+
const { key } = state;
|
|
273
|
+
switch (state.type) {
|
|
274
|
+
case `readonly_held_selector`:
|
|
275
|
+
case `writable_held_selector`:
|
|
276
|
+
target.logger.info(`๐งฎ`, state.type, key, `computing value`);
|
|
277
|
+
return state.getFrom(target);
|
|
278
|
+
case `writable_pure_selector`:
|
|
279
|
+
case `readonly_pure_selector`:
|
|
280
|
+
case `atom`: return safeCompute(target, state);
|
|
281
|
+
case `mutable_atom`: {
|
|
282
|
+
const instance = new state.class();
|
|
283
|
+
target.logger.info(`โจ`, state.type, key, `created new instance`, instance);
|
|
284
|
+
return writeToCache(target, state, instance);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region src/internal/families/get-family-of-token.ts
|
|
291
|
+
function getFamilyOfToken(store, token) {
|
|
292
|
+
return withdraw(store, {
|
|
293
|
+
key: token.family.key,
|
|
294
|
+
type: `${token.type}_family`
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/internal/families/mint-in-store.ts
|
|
300
|
+
const FAMILY_MEMBER_TOKEN_TYPES = {
|
|
301
|
+
atom_family: `atom`,
|
|
302
|
+
molecule_family: `molecule`,
|
|
303
|
+
mutable_atom_family: `mutable_atom`,
|
|
304
|
+
readonly_held_selector_family: `readonly_held_selector`,
|
|
305
|
+
readonly_pure_selector_family: `readonly_pure_selector`,
|
|
306
|
+
writable_held_selector_family: `writable_held_selector`,
|
|
307
|
+
writable_pure_selector_family: `writable_pure_selector`
|
|
308
|
+
};
|
|
309
|
+
const MUST_CREATE = Symbol(`MUST_CREATE`);
|
|
310
|
+
const DO_NOT_CREATE = Symbol(`DO_NOT_CREATE`);
|
|
311
|
+
function mintInStore(mustCreate, store, family, key) {
|
|
312
|
+
const stringKey = stringifyJson(key);
|
|
313
|
+
const molecule = store.molecules.get(stringKey);
|
|
314
|
+
if (!molecule && store.config.lifespan === `immortal`) {
|
|
315
|
+
const { type: familyType, key: familyKey } = family;
|
|
316
|
+
store.logger.warn(`๐ฃ`, `key`, stringKey, `was used to mint a counterfeit token for`, familyType, `"${familyKey}"`);
|
|
317
|
+
const fullKey = `${familyKey}(${stringKey})`;
|
|
318
|
+
const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
|
|
319
|
+
return {
|
|
320
|
+
counterfeit: true,
|
|
321
|
+
key: fullKey,
|
|
322
|
+
type,
|
|
323
|
+
family: {
|
|
324
|
+
key: familyKey,
|
|
325
|
+
subKey: stringKey
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
let token;
|
|
330
|
+
if (mustCreate === MUST_CREATE) {
|
|
331
|
+
store.logger.info(`๐ช`, family.type, family.key, `adds member`, typeof key === `string` ? `\`${key}\`` : key);
|
|
332
|
+
token = family.create(key);
|
|
333
|
+
if (molecule) store.moleculeData.set(stringKey, family.key);
|
|
334
|
+
} else {
|
|
335
|
+
const { type: familyType, key: familyKey } = family;
|
|
336
|
+
const fullKey = `${familyKey}(${stringKey})`;
|
|
337
|
+
const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
|
|
338
|
+
return {
|
|
339
|
+
key: fullKey,
|
|
340
|
+
type,
|
|
341
|
+
family: {
|
|
342
|
+
key: familyKey,
|
|
343
|
+
subKey: stringKey
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
return token;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/internal/get-state/reduce-reference.ts
|
|
352
|
+
function reduceReference(store, ...params) {
|
|
353
|
+
let existingToken;
|
|
354
|
+
let brandNewToken;
|
|
355
|
+
let family;
|
|
356
|
+
let subKey;
|
|
357
|
+
let token;
|
|
358
|
+
if (params.length === 1) {
|
|
359
|
+
token = params[0];
|
|
360
|
+
if (`family` in token) {
|
|
361
|
+
const familyToken = getFamilyOfToken(store, token);
|
|
362
|
+
family = withdraw(store, familyToken);
|
|
363
|
+
subKey = parseJson(token.family.subKey);
|
|
364
|
+
existingToken = seekInStore(store, familyToken, subKey);
|
|
365
|
+
if (`counterfeit` in token) return {
|
|
366
|
+
token,
|
|
367
|
+
family,
|
|
368
|
+
subKey,
|
|
369
|
+
isNew: false
|
|
370
|
+
};
|
|
371
|
+
if (!existingToken) {
|
|
372
|
+
brandNewToken = mintInStore(MUST_CREATE, store, familyToken, subKey);
|
|
373
|
+
token = brandNewToken;
|
|
374
|
+
} else token = existingToken;
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
family = withdraw(store, params[0]);
|
|
378
|
+
subKey = params[1];
|
|
379
|
+
existingToken = seekInStore(store, family, subKey);
|
|
380
|
+
if (!existingToken) {
|
|
381
|
+
brandNewToken = mintInStore(MUST_CREATE, store, family, subKey);
|
|
382
|
+
token = brandNewToken;
|
|
383
|
+
} else token = existingToken;
|
|
384
|
+
}
|
|
385
|
+
const isCounterfeit = `counterfeit` in token;
|
|
386
|
+
if (Boolean(brandNewToken) && isCounterfeit === false && family) {
|
|
387
|
+
let subType;
|
|
388
|
+
switch (token.type) {
|
|
389
|
+
case `readonly_pure_selector`:
|
|
390
|
+
case `readonly_held_selector`:
|
|
391
|
+
subType = `readable`;
|
|
392
|
+
break;
|
|
393
|
+
case `atom`:
|
|
394
|
+
case `mutable_atom`:
|
|
395
|
+
case `writable_pure_selector`:
|
|
396
|
+
case `writable_held_selector`:
|
|
397
|
+
subType = `writable`;
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
const stateCreationEvent = {
|
|
401
|
+
type: `state_creation`,
|
|
402
|
+
subType,
|
|
403
|
+
token,
|
|
404
|
+
timestamp: Date.now()
|
|
405
|
+
};
|
|
406
|
+
family.subject.next(stateCreationEvent);
|
|
407
|
+
const target = newest(store);
|
|
408
|
+
if (token.family) {
|
|
409
|
+
if (isRootStore(target)) switch (token.type) {
|
|
410
|
+
case `atom`:
|
|
411
|
+
case `mutable_atom`:
|
|
412
|
+
store.on.atomCreation.next(token);
|
|
413
|
+
break;
|
|
414
|
+
case `writable_pure_selector`:
|
|
415
|
+
case `readonly_pure_selector`:
|
|
416
|
+
case `writable_held_selector`:
|
|
417
|
+
case `readonly_held_selector`:
|
|
418
|
+
store.on.selectorCreation.next(token);
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
token,
|
|
426
|
+
family,
|
|
427
|
+
subKey,
|
|
428
|
+
isNew: Boolean(brandNewToken)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
//#endregion
|
|
433
|
+
//#region src/internal/get-state/get-from-store.ts
|
|
434
|
+
function getFromStore(store, ...params) {
|
|
435
|
+
const { token, family, subKey } = reduceReference(store, ...params);
|
|
436
|
+
if (`counterfeit` in token && family && subKey) return getFallback(store, token, family, subKey);
|
|
437
|
+
const state = withdraw(store, token);
|
|
438
|
+
return readOrComputeValue(store, state);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/internal/families/seek-in-store.ts
|
|
443
|
+
function seekInStore(store, token, key) {
|
|
444
|
+
const subKey = stringifyJson(key);
|
|
445
|
+
const fullKey = `${token.key}(${subKey})`;
|
|
446
|
+
const target = newest(store);
|
|
447
|
+
let state;
|
|
448
|
+
switch (token.type) {
|
|
449
|
+
case `atom_family`:
|
|
450
|
+
case `mutable_atom_family`:
|
|
451
|
+
state = target.atoms.get(fullKey);
|
|
452
|
+
break;
|
|
453
|
+
case `writable_held_selector_family`:
|
|
454
|
+
case `writable_pure_selector_family`:
|
|
455
|
+
state = target.writableSelectors.get(fullKey);
|
|
456
|
+
break;
|
|
457
|
+
case `readonly_held_selector_family`:
|
|
458
|
+
case `readonly_pure_selector_family`:
|
|
459
|
+
state = target.readonlySelectors.get(fullKey);
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
if (state) return deposit(state);
|
|
463
|
+
return state;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/internal/operation.ts
|
|
468
|
+
function openOperation(store, token) {
|
|
469
|
+
if (store.operation.open) {
|
|
470
|
+
const rejectionTime = performance.now();
|
|
471
|
+
store.logger.info(`๐ซ`, token.type, token.key, `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`);
|
|
472
|
+
return rejectionTime;
|
|
473
|
+
}
|
|
474
|
+
store.operation = {
|
|
475
|
+
open: true,
|
|
476
|
+
done: /* @__PURE__ */ new Set(),
|
|
477
|
+
prev: /* @__PURE__ */ new Map(),
|
|
478
|
+
timestamp: Date.now(),
|
|
479
|
+
token,
|
|
480
|
+
subEvents: []
|
|
481
|
+
};
|
|
482
|
+
store.logger.info(`โญ`, token.type, token.key, `operation start in store "${store.config.name}"${isChildStore(store) ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"` : ``}`);
|
|
483
|
+
return store;
|
|
484
|
+
}
|
|
485
|
+
function closeOperation(store) {
|
|
486
|
+
if (store.operation.open) store.logger.info(`๐ด`, store.operation.token.type, store.operation.token.key, `operation done in store "${store.config.name}"`);
|
|
487
|
+
store.operation = { open: false };
|
|
488
|
+
store.on.operationClose.next(store.operation);
|
|
489
|
+
}
|
|
490
|
+
const isDone = (store, key) => {
|
|
491
|
+
if (!store.operation.open) {
|
|
492
|
+
store.logger.error(`๐`, `unknown`, key, `isDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
493
|
+
return true;
|
|
494
|
+
}
|
|
495
|
+
return store.operation.done.has(key);
|
|
496
|
+
};
|
|
497
|
+
const markDone = (store, key) => {
|
|
498
|
+
if (!store.operation.open) {
|
|
499
|
+
store.logger.error(`๐`, `unknown`, key, `markDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
store.operation.done.add(key);
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
//#endregion
|
|
506
|
+
//#region src/internal/set-state/dispatch-state-update.ts
|
|
507
|
+
function dispatchOrDeferStateUpdate(target, state, { oldValue, newValue }, stateIsNewlyCreated, family) {
|
|
508
|
+
const token = deposit(state);
|
|
509
|
+
if (stateIsNewlyCreated && family) {
|
|
510
|
+
state.subject.next({ newValue });
|
|
511
|
+
const stateCreationEvent = {
|
|
512
|
+
checkpoint: true,
|
|
513
|
+
type: `state_creation`,
|
|
514
|
+
subType: `writable`,
|
|
515
|
+
token,
|
|
516
|
+
timestamp: Date.now(),
|
|
517
|
+
value: newValue
|
|
518
|
+
};
|
|
519
|
+
target.operation.subEvents.push(stateCreationEvent);
|
|
520
|
+
family.subject.next(stateCreationEvent);
|
|
521
|
+
const innerTarget = newest(target);
|
|
522
|
+
if (token.family) {
|
|
523
|
+
if (isRootStore(innerTarget)) switch (token.type) {
|
|
524
|
+
case `atom`:
|
|
525
|
+
case `mutable_atom`:
|
|
526
|
+
target.on.atomCreation.next(token);
|
|
527
|
+
break;
|
|
528
|
+
case `writable_pure_selector`:
|
|
529
|
+
case `writable_held_selector`:
|
|
530
|
+
target.on.selectorCreation.next(token);
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
else if (isChildStore(innerTarget) && innerTarget.on.transactionApplying.state === null) innerTarget.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
534
|
+
}
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const { key, subject, type } = state;
|
|
538
|
+
const update = {
|
|
539
|
+
oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
|
|
540
|
+
newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue
|
|
541
|
+
};
|
|
542
|
+
if (isRootStore(target)) {
|
|
543
|
+
switch (type) {
|
|
544
|
+
case `mutable_atom`:
|
|
545
|
+
target.logger.info(`๐ข`, type, key, `is now (`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
546
|
+
break;
|
|
547
|
+
case `atom`:
|
|
548
|
+
case `writable_pure_selector`:
|
|
549
|
+
case `writable_held_selector`: target.logger.info(`๐ข`, type, key, `went (`, oldValue, `->`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
550
|
+
}
|
|
551
|
+
subject.next(update);
|
|
552
|
+
}
|
|
553
|
+
if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
|
|
554
|
+
if (target.on.transactionApplying.state === null) {
|
|
555
|
+
if (isTransceiver(newValue)) return;
|
|
556
|
+
const { timestamp } = target.operation;
|
|
557
|
+
const atomUpdate = {
|
|
558
|
+
type: `atom_update`,
|
|
559
|
+
token,
|
|
560
|
+
timestamp,
|
|
561
|
+
update
|
|
562
|
+
};
|
|
563
|
+
target.transactionMeta.update.subEvents.push(atomUpdate);
|
|
564
|
+
target.logger.info(`๐`, `atom`, key, `stowed (`, oldValue, `->`, newValue, `)`);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (hasRole(state, `tracker:signal`)) {
|
|
568
|
+
const keyOfMutable = key.slice(1);
|
|
569
|
+
const mutable = target.atoms.get(keyOfMutable);
|
|
570
|
+
if (readOrComputeValue(target, mutable, `mut`).do(update.newValue) === null === true) evictDownstreamFromAtom(target, mutable);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
//#endregion
|
|
576
|
+
//#region src/internal/set-state/set-atom.ts
|
|
577
|
+
const setAtom = (target, atom, next) => {
|
|
578
|
+
const oldValue = readOrComputeValue(target, atom, `mut`);
|
|
579
|
+
let newValue = become(next, oldValue);
|
|
580
|
+
target.logger.info(`โญ`, `atom`, atom.key, `setting value`, newValue);
|
|
581
|
+
newValue = writeToCache(target, atom, newValue);
|
|
582
|
+
markDone(target, atom.key);
|
|
583
|
+
evictDownstreamFromAtom(target, atom);
|
|
584
|
+
return {
|
|
585
|
+
oldValue,
|
|
586
|
+
newValue
|
|
587
|
+
};
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
//#endregion
|
|
591
|
+
//#region src/internal/set-state/reset-atom-or-selector.ts
|
|
592
|
+
function resetAtom(target, atom) {
|
|
593
|
+
switch (atom.type) {
|
|
594
|
+
case `mutable_atom`: return setAtom(target, atom, new atom.class());
|
|
595
|
+
case `atom`: {
|
|
596
|
+
let def;
|
|
597
|
+
if (isFn(atom.default)) def = safeCompute(target, atom);
|
|
598
|
+
else def = atom.default;
|
|
599
|
+
return setAtom(target, atom, def);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function resetAtomOrSelector(target, state) {
|
|
604
|
+
let protoUpdate;
|
|
605
|
+
switch (state.type) {
|
|
606
|
+
case `atom`:
|
|
607
|
+
case `mutable_atom`:
|
|
608
|
+
protoUpdate = resetAtom(target, state);
|
|
609
|
+
break;
|
|
610
|
+
case `writable_held_selector`:
|
|
611
|
+
{
|
|
612
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
613
|
+
for (const atom of atoms.values()) {
|
|
614
|
+
const rootProtoUpdate = resetAtom(target, atom);
|
|
615
|
+
dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
|
|
616
|
+
}
|
|
617
|
+
const value = state.getFrom(target);
|
|
618
|
+
protoUpdate = {
|
|
619
|
+
oldValue: value,
|
|
620
|
+
newValue: value
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
break;
|
|
624
|
+
case `writable_pure_selector`:
|
|
625
|
+
{
|
|
626
|
+
const oldValue = safeCompute(target, state);
|
|
627
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
628
|
+
for (const atom of atoms.values()) {
|
|
629
|
+
const rootProtoUpdate = resetAtom(target, atom);
|
|
630
|
+
dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
|
|
631
|
+
}
|
|
632
|
+
const newValue = safeCompute(target, state);
|
|
633
|
+
protoUpdate = {
|
|
634
|
+
oldValue,
|
|
635
|
+
newValue
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
return protoUpdate;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
//#endregion
|
|
644
|
+
//#region src/internal/set-state/set-into-store.ts
|
|
645
|
+
function setIntoStore(store, ...params) {
|
|
646
|
+
operateOnStore(OWN_OP, store, ...params);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/internal/set-state/reset-in-store.ts
|
|
651
|
+
const RESET_STATE = Symbol(`RESET`);
|
|
652
|
+
function resetInStore(store, ...params) {
|
|
653
|
+
const subParams = [...params, RESET_STATE];
|
|
654
|
+
setIntoStore(store, ...subParams);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
//#endregion
|
|
658
|
+
//#region src/internal/set-state/set-selector.ts
|
|
659
|
+
function setSelector(target, selector, next) {
|
|
660
|
+
let oldValue;
|
|
661
|
+
let newValue;
|
|
662
|
+
let constant;
|
|
663
|
+
const { type, key } = selector;
|
|
664
|
+
switch (selector.type) {
|
|
665
|
+
case `writable_pure_selector`:
|
|
666
|
+
oldValue = readOrComputeValue(target, selector, `mut`);
|
|
667
|
+
newValue = become(next, oldValue);
|
|
668
|
+
newValue = writeToCache(target, selector, newValue);
|
|
669
|
+
break;
|
|
670
|
+
case `writable_held_selector`:
|
|
671
|
+
constant = selector.const;
|
|
672
|
+
become(next, constant);
|
|
673
|
+
oldValue = constant;
|
|
674
|
+
newValue = constant;
|
|
675
|
+
}
|
|
676
|
+
target.logger.info(`โญ`, type, key, `setting to`, newValue);
|
|
677
|
+
markDone(target, key);
|
|
678
|
+
selector.setSelf(newValue);
|
|
679
|
+
return {
|
|
680
|
+
oldValue,
|
|
681
|
+
newValue
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
//#endregion
|
|
686
|
+
//#region src/internal/set-state/set-atom-or-selector.ts
|
|
687
|
+
const setAtomOrSelector = (target, state, value) => {
|
|
688
|
+
let protoUpdate;
|
|
689
|
+
switch (state.type) {
|
|
690
|
+
case `atom`:
|
|
691
|
+
case `mutable_atom`:
|
|
692
|
+
protoUpdate = setAtom(target, state, value);
|
|
693
|
+
break;
|
|
694
|
+
case `writable_pure_selector`:
|
|
695
|
+
case `writable_held_selector`:
|
|
696
|
+
protoUpdate = setSelector(target, state, value);
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
return protoUpdate;
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
//#endregion
|
|
703
|
+
//#region src/internal/set-state/operate-on-store.ts
|
|
704
|
+
const OWN_OP = Symbol(`OWN_OP`);
|
|
705
|
+
const JOIN_OP = Symbol(`JOIN_OP`);
|
|
706
|
+
function operateOnStore(opMode, store, ...params) {
|
|
707
|
+
let existingToken;
|
|
708
|
+
let brandNewToken;
|
|
709
|
+
let token;
|
|
710
|
+
let family;
|
|
711
|
+
let key;
|
|
712
|
+
let value;
|
|
713
|
+
if (params.length === 2) {
|
|
714
|
+
token = params[0];
|
|
715
|
+
value = params[1];
|
|
716
|
+
if (`family` in token) {
|
|
717
|
+
family = getFamilyOfToken(store, token);
|
|
718
|
+
key = parseJson(token.family.subKey);
|
|
719
|
+
existingToken = seekInStore(store, family, key);
|
|
720
|
+
if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
721
|
+
else token = existingToken;
|
|
722
|
+
}
|
|
723
|
+
} else {
|
|
724
|
+
family = withdraw(store, params[0]);
|
|
725
|
+
key = params[1];
|
|
726
|
+
value = params[2];
|
|
727
|
+
existingToken = seekInStore(store, family, key);
|
|
728
|
+
if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
729
|
+
else token = existingToken;
|
|
730
|
+
}
|
|
731
|
+
const action = value === RESET_STATE ? `reset` : `set`;
|
|
732
|
+
let target;
|
|
733
|
+
if (opMode === OWN_OP) {
|
|
734
|
+
const result = openOperation(store, token);
|
|
735
|
+
if (typeof result === `number`) {
|
|
736
|
+
const rejectionTime = result;
|
|
737
|
+
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
738
|
+
unsubscribe();
|
|
739
|
+
store.logger.info(`๐ข`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
740
|
+
operateOnStore(opMode, store, token, value);
|
|
741
|
+
});
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
target = result;
|
|
745
|
+
} else target = store;
|
|
746
|
+
if (`counterfeit` in token && `family` in token) {
|
|
747
|
+
const subKey = token.family.subKey;
|
|
748
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
749
|
+
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)`);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const state = withdraw(target, token);
|
|
753
|
+
let protoUpdate;
|
|
754
|
+
if (value === RESET_STATE) protoUpdate = resetAtomOrSelector(target, state);
|
|
755
|
+
else protoUpdate = setAtomOrSelector(target, state, value);
|
|
756
|
+
dispatchOrDeferStateUpdate(target, state, protoUpdate, Boolean(brandNewToken), family);
|
|
757
|
+
if (opMode === OWN_OP) closeOperation(target);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
//#endregion
|
|
761
|
+
//#region src/internal/keys.ts
|
|
762
|
+
const isAtomKey = (store, key) => newest(store).atoms.has(key);
|
|
763
|
+
const isSelectorKey = (store, key) => newest(store).writableSelectors.has(key);
|
|
764
|
+
const isReadonlySelectorKey = (store, key) => newest(store).readonlySelectors.has(key);
|
|
765
|
+
const isStateKey = (store, key) => isAtomKey(store, key) || isSelectorKey(store, key) || isReadonlySelectorKey(store, key);
|
|
766
|
+
|
|
767
|
+
//#endregion
|
|
768
|
+
//#region src/internal/selector/get-selector-dependency-keys.ts
|
|
769
|
+
function getSelectorDependencyKeys(store, key) {
|
|
770
|
+
return newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(store, source));
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
//#endregion
|
|
774
|
+
//#region src/internal/selector/trace-selector-atoms.ts
|
|
775
|
+
function traceRootSelectorAtoms(store, selectorKey, covered = /* @__PURE__ */ new Set()) {
|
|
776
|
+
const dependencies = getSelectorDependencyKeys(store, selectorKey);
|
|
777
|
+
const roots = /* @__PURE__ */ new Map();
|
|
778
|
+
while (dependencies.length > 0) {
|
|
779
|
+
const dependencyKey = dependencies.pop();
|
|
780
|
+
if (covered.has(dependencyKey)) continue;
|
|
781
|
+
covered.add(dependencyKey);
|
|
782
|
+
if (isAtomKey(store, dependencyKey)) {
|
|
783
|
+
const atom = store.atoms.get(dependencyKey);
|
|
784
|
+
roots.set(atom.key, atom);
|
|
785
|
+
} else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
786
|
+
}
|
|
787
|
+
return roots;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
//#endregion
|
|
791
|
+
//#region src/internal/subscribe/recall-state.ts
|
|
792
|
+
const recallState = (store, state) => {
|
|
793
|
+
const target = newest(store);
|
|
794
|
+
if (target.operation.open) return target.operation.prev.get(state.key);
|
|
795
|
+
return target.valueMap.get(state.key);
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
//#endregion
|
|
799
|
+
//#region src/internal/subscribe/subscribe-to-root-atoms.ts
|
|
800
|
+
const subscribeToRootDependency = (target, selector, atom) => {
|
|
801
|
+
return atom.subject.subscribe(`${selector.type}:${selector.key}`, (atomChange) => {
|
|
802
|
+
target.logger.info(`๐ข`, selector.type, selector.key, `root`, atom.key, `went`, atomChange.oldValue, `->`, atomChange.newValue);
|
|
803
|
+
const oldValue = recallState(target, selector);
|
|
804
|
+
const newValue = readOrComputeValue(target, selector);
|
|
805
|
+
target.logger.info(`โจ`, selector.type, selector.key, `went`, oldValue, `->`, newValue);
|
|
806
|
+
selector.subject.next({
|
|
807
|
+
newValue,
|
|
808
|
+
oldValue
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
//#endregion
|
|
814
|
+
//#region src/internal/subscribe/subscribe-to-state.ts
|
|
815
|
+
function subscribeToState(store, token, key, handleUpdate) {
|
|
816
|
+
function safelyHandleUpdate(update) {
|
|
817
|
+
if (store.operation.open) {
|
|
818
|
+
if (state?.type === `atom` && hasRole(state, `tracker:signal`) && `*` + store.operation.token.key === token.key && `inboundTracker` in handleUpdate) return;
|
|
819
|
+
const unsubscribe$1 = store.on.operationClose.subscribe(`state subscription ${key}`, () => {
|
|
820
|
+
unsubscribe$1();
|
|
821
|
+
handleUpdate(update);
|
|
822
|
+
});
|
|
823
|
+
} else handleUpdate(update);
|
|
824
|
+
}
|
|
825
|
+
reduceReference(store, token);
|
|
826
|
+
const state = withdraw(store, token);
|
|
827
|
+
store.logger.info(`๐`, state.type, state.key, `Adding subscription "${key}"`);
|
|
828
|
+
const isSelector = state.type === `writable_pure_selector` || state.type === `readonly_pure_selector`;
|
|
829
|
+
const rootSubs = /* @__PURE__ */ new Map();
|
|
830
|
+
let updateHandler = safelyHandleUpdate;
|
|
831
|
+
if (isSelector) {
|
|
832
|
+
readOrComputeValue(store, state);
|
|
833
|
+
for (const [atomKey, atom] of traceRootSelectorAtoms(store, state.key)) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
834
|
+
updateHandler = function updateRootsBeforeHandlingUpdate(update) {
|
|
835
|
+
const dependencies = traceRootSelectorAtoms(store, state.key);
|
|
836
|
+
for (const [previousRootKey, unsub] of rootSubs) if (dependencies.get(previousRootKey)) dependencies.delete(previousRootKey);
|
|
837
|
+
else {
|
|
838
|
+
unsub();
|
|
839
|
+
rootSubs.delete(previousRootKey);
|
|
840
|
+
}
|
|
841
|
+
for (const [atomKey, atom] of dependencies) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
842
|
+
safelyHandleUpdate(update);
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
|
|
846
|
+
const unsubscribe = () => {
|
|
847
|
+
store.logger.info(`๐`, state.type, state.key, `Removing subscription "${key}"`);
|
|
848
|
+
mainUnsubFunction();
|
|
849
|
+
for (const unsubFromDependency of rootSubs.values()) unsubFromDependency();
|
|
850
|
+
};
|
|
851
|
+
return unsubscribe;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
//#endregion
|
|
855
|
+
//#region src/internal/subscribe/subscribe-to-timeline.ts
|
|
856
|
+
const subscribeToTimeline = (store, token, key, handleUpdate) => {
|
|
857
|
+
const tl = withdraw(store, token);
|
|
858
|
+
store.logger.info(`๐`, `timeline`, token.key, `Adding subscription "${key}"`);
|
|
859
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate);
|
|
860
|
+
return () => {
|
|
861
|
+
store.logger.info(`๐`, `timeline`, token.key, `Removing subscription "${key}" from timeline`);
|
|
862
|
+
unsubscribe();
|
|
863
|
+
};
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
//#endregion
|
|
867
|
+
//#region src/internal/mutable/tracker.ts
|
|
868
|
+
/**
|
|
869
|
+
* @internal Give the tracker a transceiver state and a store, and it will
|
|
870
|
+
* subscribe to the transceiver's inner value. When the inner value changes,
|
|
871
|
+
* the tracker will update its own state to reflect the change.
|
|
872
|
+
*/
|
|
873
|
+
var Tracker = class {
|
|
874
|
+
initializeSignalAtom(mutableState, store) {
|
|
875
|
+
const latestSignalStateKey = `*${mutableState.key}`;
|
|
876
|
+
store.atoms.delete(latestSignalStateKey);
|
|
877
|
+
store.valueMap.delete(latestSignalStateKey);
|
|
878
|
+
const familyMetaData = mutableState.family ? {
|
|
879
|
+
key: `*${mutableState.family.key}`,
|
|
880
|
+
subKey: mutableState.family.subKey
|
|
881
|
+
} : void 0;
|
|
882
|
+
const latestSignalState = createRegularAtom(store, {
|
|
883
|
+
key: latestSignalStateKey,
|
|
884
|
+
default: null
|
|
885
|
+
}, familyMetaData, [`tracker:signal`]);
|
|
886
|
+
if (store.parent?.valueMap.has(latestSignalStateKey)) {
|
|
887
|
+
const parentValue = store.parent.valueMap.get(latestSignalStateKey);
|
|
888
|
+
store.valueMap.set(latestSignalStateKey, parentValue);
|
|
889
|
+
}
|
|
890
|
+
return latestSignalState;
|
|
891
|
+
}
|
|
892
|
+
unsubscribeFromInnerValue;
|
|
893
|
+
unsubscribeFromState;
|
|
894
|
+
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
895
|
+
const stateKey = mutableState.key;
|
|
896
|
+
const storeName = target.config.name;
|
|
897
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
898
|
+
const subscriptionKey = `tracker-from-core:${storeName}:${storeStatus}:${stateKey}`;
|
|
899
|
+
const trackerCapturesOutboundSignal = (update) => {
|
|
900
|
+
operateOnStore(JOIN_OP, target, latestSignalState, update);
|
|
901
|
+
};
|
|
902
|
+
this.unsubscribeFromInnerValue = getFromStore(target, mutableState).subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
903
|
+
this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, function trackerLooksForNewReference(update) {
|
|
904
|
+
if (update.newValue !== update.oldValue) {
|
|
905
|
+
this.unsubscribeFromInnerValue();
|
|
906
|
+
this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
907
|
+
}
|
|
908
|
+
}.bind(this));
|
|
909
|
+
}
|
|
910
|
+
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
911
|
+
const stateKey = mutableState.key;
|
|
912
|
+
const storeName = target.config.name;
|
|
913
|
+
const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
|
|
914
|
+
const subscriptionKey = `tracker-to-core:${storeName}:${storeStatus}:${stateKey}`;
|
|
915
|
+
subscribeToState(target, latestSignalState, subscriptionKey, Object.assign(function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
916
|
+
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
917
|
+
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
918
|
+
const unsubscribe = subscribeToTimeline(target, {
|
|
919
|
+
key: timelineId,
|
|
920
|
+
type: `timeline`
|
|
921
|
+
}, subscriptionKey, function trackerWaitsForTimeTravelToFinish(update) {
|
|
922
|
+
unsubscribe();
|
|
923
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
924
|
+
if (update === `redo` && newValue) transceiver.do(newValue);
|
|
925
|
+
else if (update === `undo` && oldValue) transceiver.undo(oldValue);
|
|
926
|
+
return transceiver;
|
|
927
|
+
});
|
|
928
|
+
});
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
const mutable = getFromStore(target, mutableState);
|
|
932
|
+
const updateNumber = mutable.getUpdateNumber(newValue);
|
|
933
|
+
const eventOffset = updateNumber - mutable.cacheUpdateNumber;
|
|
934
|
+
if (newValue && eventOffset === 1) setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
|
|
935
|
+
else {
|
|
936
|
+
const expected = mutable.cacheUpdateNumber + 1;
|
|
937
|
+
target.logger.info(`โ`, `mutable_atom`, mutableState.key, `could not be updated. Expected update number`, expected, `but got`, updateNumber);
|
|
938
|
+
}
|
|
939
|
+
}, { inboundTracker: true }));
|
|
940
|
+
}
|
|
941
|
+
mutableAtomToken;
|
|
942
|
+
latestSignalToken;
|
|
943
|
+
[Symbol.dispose];
|
|
944
|
+
constructor(mutableAtomToken, store) {
|
|
945
|
+
const target = newest(store);
|
|
946
|
+
const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target);
|
|
947
|
+
this.mutableAtomToken = mutableAtomToken;
|
|
948
|
+
this.latestSignalToken = latestSignalToken;
|
|
949
|
+
this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target);
|
|
950
|
+
this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target);
|
|
951
|
+
target.trackers.set(mutableAtomToken.key, this);
|
|
952
|
+
this[Symbol.dispose] = () => {
|
|
953
|
+
this.unsubscribeFromInnerValue();
|
|
954
|
+
this.unsubscribeFromState();
|
|
955
|
+
target.trackers.delete(mutableAtomToken.key);
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
//#endregion
|
|
961
|
+
//#region src/internal/mutable/transceiver.ts
|
|
962
|
+
function isTransceiver(value) {
|
|
963
|
+
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;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
//#endregion
|
|
967
|
+
//#region src/internal/caching.ts
|
|
968
|
+
function writeToCache(target, state, value) {
|
|
969
|
+
const { key, subject, type } = state;
|
|
970
|
+
const currentValue = target.valueMap.get(key);
|
|
971
|
+
if (currentValue instanceof Future && !currentValue.done) {
|
|
972
|
+
const future = currentValue;
|
|
973
|
+
if (value instanceof Promise) {
|
|
974
|
+
future.use(value);
|
|
975
|
+
return future;
|
|
976
|
+
}
|
|
977
|
+
target.valueMap.set(key, value);
|
|
978
|
+
return value;
|
|
979
|
+
}
|
|
980
|
+
if (value instanceof Promise) {
|
|
981
|
+
const future = new Future(value);
|
|
982
|
+
target.valueMap.set(key, future);
|
|
983
|
+
future.then(function handleResolvedFuture(resolved) {
|
|
984
|
+
if (target.valueMap.get(key) === future) {
|
|
985
|
+
openOperation(target, state);
|
|
986
|
+
writeToCache(target, state, resolved);
|
|
987
|
+
switch (type) {
|
|
988
|
+
case `atom`:
|
|
989
|
+
evictDownstreamFromAtom(target, state);
|
|
990
|
+
break;
|
|
991
|
+
case `readonly_pure_selector`:
|
|
992
|
+
case `writable_pure_selector`:
|
|
993
|
+
evictDownstreamFromSelector(target, key);
|
|
994
|
+
break;
|
|
995
|
+
}
|
|
996
|
+
closeOperation(target);
|
|
997
|
+
subject.next({
|
|
998
|
+
newValue: resolved,
|
|
999
|
+
oldValue: future
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}).catch((thrown) => {
|
|
1003
|
+
target.logger.error(`๐ฅ`, state.type, key, `rejected:`, thrown);
|
|
1004
|
+
});
|
|
1005
|
+
return future;
|
|
1006
|
+
}
|
|
1007
|
+
target.logger.info(`๐`, state.type, state.key, `writing to cache`, value);
|
|
1008
|
+
target.valueMap.set(key, value);
|
|
1009
|
+
return value;
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* @param target - the newest layer of the store
|
|
1013
|
+
* @param state - the state to read from cache
|
|
1014
|
+
* @param mut - whether the value is intended to be mutable
|
|
1015
|
+
* @returns the state's current value
|
|
1016
|
+
*/
|
|
1017
|
+
function readFromCache(target, state, mut) {
|
|
1018
|
+
target.logger.info(`๐`, state.type, state.key, `reading cached value`);
|
|
1019
|
+
let value = target.valueMap.get(state.key);
|
|
1020
|
+
if (mut === `mut` && state.type === `mutable_atom` && isChildStore(target)) {
|
|
1021
|
+
const mutableAtom$1 = state;
|
|
1022
|
+
const { parent } = target;
|
|
1023
|
+
if (target.valueMap.hasOwn(mutableAtom$1.key)) return value;
|
|
1024
|
+
const parentValue = parent.valueMap.get(mutableAtom$1.key);
|
|
1025
|
+
target.logger.info(`๐`, `atom`, mutableAtom$1.key, `copying`);
|
|
1026
|
+
const jsonValue = parentValue.toJSON();
|
|
1027
|
+
const copiedValue = mutableAtom$1.class.fromJSON(jsonValue);
|
|
1028
|
+
target.valueMap.set(mutableAtom$1.key, copiedValue);
|
|
1029
|
+
new Tracker(mutableAtom$1, parent);
|
|
1030
|
+
value = copiedValue;
|
|
1031
|
+
}
|
|
1032
|
+
return value;
|
|
1033
|
+
}
|
|
1034
|
+
function evictCachedValue(target, key) {
|
|
1035
|
+
const currentValue = target.valueMap.get(key);
|
|
1036
|
+
if (currentValue instanceof Future) {
|
|
1037
|
+
const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
|
|
1038
|
+
if (selector) selector.getFrom(target);
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (target.operation.open) target.operation.prev.set(key, currentValue);
|
|
1042
|
+
target.valueMap.delete(key);
|
|
1043
|
+
target.logger.info(`๐`, `state`, key, `evicted`);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
//#endregion
|
|
1047
|
+
//#region src/internal/set-state/evict-downstream.ts
|
|
1048
|
+
function evictDownstreamFromAtom(store, atom) {
|
|
1049
|
+
const target = newest(store);
|
|
1050
|
+
const { key, type } = atom;
|
|
1051
|
+
const downstreamKeys = target.selectorAtoms.getRelatedKeys(key);
|
|
1052
|
+
target.logger.info(`๐งน`, type, key, downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`, downstreamKeys ?? `to evict`);
|
|
1053
|
+
if (downstreamKeys) {
|
|
1054
|
+
if (target.operation.open) target.logger.info(`๐งน`, type, key, `[ ${[...target.operation.done].join(`, `)} ] already done`);
|
|
1055
|
+
for (const downstreamKey of downstreamKeys) {
|
|
1056
|
+
if (isDone(target, downstreamKey)) continue;
|
|
1057
|
+
evictCachedValue(target, downstreamKey);
|
|
1058
|
+
markDone(target, downstreamKey);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
function evictDownstreamFromSelector(store, selectorKey) {
|
|
1063
|
+
const target = newest(store);
|
|
1064
|
+
const relationEntries = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: selectorKey }).filter(([_, { source }]) => source === selectorKey);
|
|
1065
|
+
for (const [downstreamSelectorKey] of relationEntries) {
|
|
1066
|
+
if (isDone(target, downstreamSelectorKey)) continue;
|
|
1067
|
+
evictCachedValue(target, downstreamSelectorKey);
|
|
1068
|
+
markDone(target, downstreamSelectorKey);
|
|
1069
|
+
evictDownstreamFromSelector(store, downstreamSelectorKey);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
//#endregion
|
|
1074
|
+
//#region src/internal/atom/create-regular-atom.ts
|
|
1075
|
+
function createRegularAtom(store, options, family, internalRoles) {
|
|
1076
|
+
const type = `atom`;
|
|
1077
|
+
const { key } = options;
|
|
1078
|
+
store.logger.info(`๐จ`, type, key, `is being created`);
|
|
1079
|
+
const target = newest(store);
|
|
1080
|
+
const existing = target.atoms.get(key);
|
|
1081
|
+
if (existing && existing.type === type) {
|
|
1082
|
+
store.logger.error(`โ`, `atom`, key, `Tried to create atom, but it already exists in the store.`);
|
|
1083
|
+
return deposit(existing);
|
|
1084
|
+
}
|
|
1085
|
+
const subject = new Subject();
|
|
1086
|
+
const newAtom = {
|
|
1087
|
+
...options,
|
|
1088
|
+
type,
|
|
1089
|
+
install: (s) => {
|
|
1090
|
+
s.logger.info(`๐ ๏ธ`, type, key, `installing in store "${s.config.name}"`);
|
|
1091
|
+
return createRegularAtom(s, options, family);
|
|
1092
|
+
},
|
|
1093
|
+
subject
|
|
1094
|
+
};
|
|
1095
|
+
if (family) newAtom.family = family;
|
|
1096
|
+
if (internalRoles) newAtom.internalRoles = internalRoles;
|
|
1097
|
+
target.atoms.set(key, newAtom);
|
|
1098
|
+
const token = deposit(newAtom);
|
|
1099
|
+
if (options.effects) {
|
|
1100
|
+
let effectIndex = 0;
|
|
1101
|
+
const cleanupFunctions = [];
|
|
1102
|
+
for (const effect of options.effects) {
|
|
1103
|
+
const cleanup = effect({
|
|
1104
|
+
resetSelf: () => {
|
|
1105
|
+
resetInStore(store, token);
|
|
1106
|
+
},
|
|
1107
|
+
setSelf: (next) => {
|
|
1108
|
+
setIntoStore(store, token, next);
|
|
1109
|
+
},
|
|
1110
|
+
onSet: (handle) => subscribeToState(store, token, `effect[${effectIndex}]`, handle)
|
|
1111
|
+
});
|
|
1112
|
+
if (cleanup) cleanupFunctions.push(cleanup);
|
|
1113
|
+
++effectIndex;
|
|
1114
|
+
}
|
|
1115
|
+
newAtom.cleanup = () => {
|
|
1116
|
+
for (const cleanup of cleanupFunctions) cleanup();
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
store.on.atomCreation.next(token);
|
|
1120
|
+
return token;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/internal/atom/has-role.ts
|
|
1125
|
+
const INTERNAL_ROLES = [`tracker:signal`];
|
|
1126
|
+
function hasRole(atom, role) {
|
|
1127
|
+
if (`internalRoles` in atom === false) return false;
|
|
1128
|
+
return atom.internalRoles.includes(role);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
//#endregion
|
|
1132
|
+
export { DO_NOT_CREATE, Future, INTERNAL_ROLES, JOIN_OP, NotFoundError, OWN_OP, 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 };
|
|
1133
|
+
//# sourceMappingURL=has-role-CMlaUlaf.js.map
|