flightdeck 0.2.14 → 0.2.15
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/bin/flightdeck.bin.js +2 -0
- package/bin/klaxon.bin.js +2 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-XIZZKICH.js +4778 -0
- package/dist/chunk-XIZZKICH.js.map +1 -0
- package/dist/chunk-ZID4FJKY.js +51 -0
- package/dist/chunk-ZID4FJKY.js.map +1 -0
- package/dist/flightdeck.x.js +122 -0
- package/dist/flightdeck.x.js.map +1 -0
- package/dist/klaxon.x.js +56 -0
- package/dist/klaxon.x.js.map +1 -0
- package/dist/lib.d.ts +46 -46
- package/dist/lib.js +5 -9
- package/dist/lib.js.map +1 -0
- package/package.json +9 -11
- package/dist/flightdeck.$configPath.schema.json +0 -64
- package/dist/flightdeck.bin.js +0 -10
- package/dist/flightdeck.main.schema.json +0 -64
- package/dist/flightdeck.schema.schema.json +0 -10
- package/dist/klaxon.bin.js +0 -5
- /package/src/{flightdeck.bin.ts → flightdeck.x.ts} +0 -0
- /package/src/{klaxon.bin.ts → klaxon.x.ts} +0 -0
|
@@ -0,0 +1,4778 @@
|
|
|
1
|
+
import { execSync, spawn } from 'node:child_process';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { inspect } from 'node:util';
|
|
6
|
+
import { CronJob } from 'cron';
|
|
7
|
+
import { FilesystemStorage } from 'safedeposit';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { createEnv } from '@t3-oss/env-core';
|
|
10
|
+
|
|
11
|
+
// src/flightdeck.lib.ts
|
|
12
|
+
|
|
13
|
+
// ../atom.io/internal/src/arbitrary.ts
|
|
14
|
+
function arbitrary(random = Math.random) {
|
|
15
|
+
return random().toString(36).slice(2);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ../atom.io/internal/src/future.ts
|
|
19
|
+
var Future = class extends Promise {
|
|
20
|
+
fate;
|
|
21
|
+
resolve;
|
|
22
|
+
reject;
|
|
23
|
+
done = false;
|
|
24
|
+
constructor(executor) {
|
|
25
|
+
let superResolve;
|
|
26
|
+
let superReject;
|
|
27
|
+
super((resolve2, reject) => {
|
|
28
|
+
superResolve = resolve2;
|
|
29
|
+
superReject = reject;
|
|
30
|
+
});
|
|
31
|
+
this.resolve = superResolve;
|
|
32
|
+
this.reject = superReject;
|
|
33
|
+
this.use(executor instanceof Promise ? executor : new Promise(executor));
|
|
34
|
+
}
|
|
35
|
+
pass(promise, value) {
|
|
36
|
+
if (promise === this.fate) {
|
|
37
|
+
this.resolve(value);
|
|
38
|
+
this.done = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
fail(promise, reason) {
|
|
42
|
+
if (promise === this.fate) {
|
|
43
|
+
this.reject(reason);
|
|
44
|
+
this.done = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
use(value) {
|
|
48
|
+
if (value instanceof Promise) {
|
|
49
|
+
const promise = value;
|
|
50
|
+
this.fate = promise;
|
|
51
|
+
promise.then(
|
|
52
|
+
(resolved) => {
|
|
53
|
+
this.pass(promise, resolved);
|
|
54
|
+
},
|
|
55
|
+
(reason) => {
|
|
56
|
+
this.fail(promise, reason);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
} else {
|
|
60
|
+
this.resolve(value);
|
|
61
|
+
this.fate = undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ../atom.io/json/src/entries.ts
|
|
67
|
+
function fromEntries(entries) {
|
|
68
|
+
return Object.fromEntries(entries);
|
|
69
|
+
}
|
|
70
|
+
function toEntries(obj) {
|
|
71
|
+
return Object.entries(obj);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ../atom.io/json/src/select-json.ts
|
|
75
|
+
var selectJson = (atom2, transform, store = IMPLICIT.STORE) => {
|
|
76
|
+
return createStandaloneSelector(store, {
|
|
77
|
+
key: `${atom2.key}:JSON`,
|
|
78
|
+
get: ({ get }) => transform.toJson(get(atom2)),
|
|
79
|
+
set: ({ set }, newValue) => {
|
|
80
|
+
set(atom2, transform.fromJson(newValue));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// ../atom.io/internal/src/lineage.ts
|
|
86
|
+
function newest(scion) {
|
|
87
|
+
while (scion.child !== null) {
|
|
88
|
+
scion = scion.child;
|
|
89
|
+
}
|
|
90
|
+
return scion;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ../atom.io/internal/src/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) {
|
|
110
|
+
subscriber(value);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var StatefulSubject = class extends Subject {
|
|
115
|
+
state;
|
|
116
|
+
constructor(initialState) {
|
|
117
|
+
super();
|
|
118
|
+
this.state = initialState;
|
|
119
|
+
}
|
|
120
|
+
next(value) {
|
|
121
|
+
this.state = value;
|
|
122
|
+
super.next(value);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// ../atom.io/internal/src/families/create-regular-atom-family.ts
|
|
127
|
+
function createRegularAtomFamily(store, options, internalRoles) {
|
|
128
|
+
const familyToken = {
|
|
129
|
+
key: options.key,
|
|
130
|
+
type: `atom_family`
|
|
131
|
+
};
|
|
132
|
+
const existing = store.families.get(options.key);
|
|
133
|
+
if (existing) {
|
|
134
|
+
store.logger.error(
|
|
135
|
+
`\u2757`,
|
|
136
|
+
`atom_family`,
|
|
137
|
+
options.key,
|
|
138
|
+
`Overwriting an existing ${prettyPrintTokenType(
|
|
139
|
+
existing
|
|
140
|
+
)} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const subject = new Subject();
|
|
144
|
+
const familyFunction = (key) => {
|
|
145
|
+
const subKey = stringifyJson(key);
|
|
146
|
+
const family = { key: options.key, subKey };
|
|
147
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
148
|
+
const target = newest(store);
|
|
149
|
+
const def = options.default;
|
|
150
|
+
const individualOptions = {
|
|
151
|
+
key: fullKey,
|
|
152
|
+
default: def instanceof Function ? def(key) : def
|
|
153
|
+
};
|
|
154
|
+
if (options.effects) {
|
|
155
|
+
individualOptions.effects = options.effects(key);
|
|
156
|
+
}
|
|
157
|
+
const token = createRegularAtom(target, individualOptions, family);
|
|
158
|
+
subject.next({ type: `state_creation`, token });
|
|
159
|
+
return token;
|
|
160
|
+
};
|
|
161
|
+
const atomFamily2 = Object.assign(familyFunction, familyToken, {
|
|
162
|
+
subject,
|
|
163
|
+
install: (s) => createRegularAtomFamily(s, options),
|
|
164
|
+
internalRoles
|
|
165
|
+
});
|
|
166
|
+
store.families.set(options.key, atomFamily2);
|
|
167
|
+
store.defaults.set(options.key, options.default);
|
|
168
|
+
return familyToken;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ../atom.io/internal/src/families/create-atom-family.ts
|
|
172
|
+
function createAtomFamily(store, options) {
|
|
173
|
+
const isMutable = `mutable` in options;
|
|
174
|
+
if (isMutable) {
|
|
175
|
+
return createMutableAtomFamily(store, options);
|
|
176
|
+
}
|
|
177
|
+
return createRegularAtomFamily(store, options);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ../atom.io/internal/src/families/create-readonly-selector-family.ts
|
|
181
|
+
function createReadonlySelectorFamily(store, options, internalRoles) {
|
|
182
|
+
const familyToken = {
|
|
183
|
+
key: options.key,
|
|
184
|
+
type: `readonly_selector_family`
|
|
185
|
+
};
|
|
186
|
+
const existing = store.families.get(options.key);
|
|
187
|
+
if (existing) {
|
|
188
|
+
store.logger.error(
|
|
189
|
+
`\u2757`,
|
|
190
|
+
`readonly_selector_family`,
|
|
191
|
+
options.key,
|
|
192
|
+
`Overwriting an existing ${prettyPrintTokenType(
|
|
193
|
+
existing
|
|
194
|
+
)} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
const subject = new Subject();
|
|
198
|
+
const familyFunction = (key) => {
|
|
199
|
+
const subKey = stringifyJson(key);
|
|
200
|
+
const family = { key: options.key, subKey };
|
|
201
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
202
|
+
const target = newest(store);
|
|
203
|
+
const token = createReadonlySelector(
|
|
204
|
+
target,
|
|
205
|
+
{
|
|
206
|
+
key: fullKey,
|
|
207
|
+
get: options.get(key)
|
|
208
|
+
},
|
|
209
|
+
family
|
|
210
|
+
);
|
|
211
|
+
subject.next({ type: `state_creation`, token });
|
|
212
|
+
return token;
|
|
213
|
+
};
|
|
214
|
+
const readonlySelectorFamily = Object.assign(familyFunction, familyToken, {
|
|
215
|
+
internalRoles,
|
|
216
|
+
subject,
|
|
217
|
+
install: (s) => createReadonlySelectorFamily(s, options),
|
|
218
|
+
default: (key) => {
|
|
219
|
+
const getFn = options.get(key);
|
|
220
|
+
return getFn({
|
|
221
|
+
get: (...ps) => getFromStore(store, ...ps),
|
|
222
|
+
find: (token, k) => findInStore(store, token, k),
|
|
223
|
+
seek: (token, k) => seekInStore(store, token, k),
|
|
224
|
+
json: (token) => getJsonToken(store, token)
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
store.families.set(options.key, readonlySelectorFamily);
|
|
229
|
+
return familyToken;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ../atom.io/internal/src/families/create-selector-family.ts
|
|
233
|
+
function createSelectorFamily(store, options) {
|
|
234
|
+
const isWritable = `set` in options;
|
|
235
|
+
if (isWritable) {
|
|
236
|
+
return createWritableSelectorFamily(store, options);
|
|
237
|
+
}
|
|
238
|
+
return createReadonlySelectorFamily(store, options);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// ../atom.io/internal/src/store/circular-buffer.ts
|
|
242
|
+
var CircularBuffer = class _CircularBuffer {
|
|
243
|
+
_buffer;
|
|
244
|
+
_index = 0;
|
|
245
|
+
constructor(lengthOrArray) {
|
|
246
|
+
let length;
|
|
247
|
+
if (typeof lengthOrArray === `number`) {
|
|
248
|
+
length = lengthOrArray;
|
|
249
|
+
} else {
|
|
250
|
+
length = lengthOrArray.length;
|
|
251
|
+
}
|
|
252
|
+
this._buffer = Array.from({ length });
|
|
253
|
+
}
|
|
254
|
+
get buffer() {
|
|
255
|
+
return this._buffer;
|
|
256
|
+
}
|
|
257
|
+
get index() {
|
|
258
|
+
return this._index;
|
|
259
|
+
}
|
|
260
|
+
add(item) {
|
|
261
|
+
this._buffer[this._index] = item;
|
|
262
|
+
this._index = (this._index + 1) % this._buffer.length;
|
|
263
|
+
}
|
|
264
|
+
copy() {
|
|
265
|
+
const copy = new _CircularBuffer([...this._buffer]);
|
|
266
|
+
copy._index = this._index;
|
|
267
|
+
return copy;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// ../atom.io/internal/src/store/counterfeit.ts
|
|
272
|
+
var FAMILY_MEMBER_TOKEN_TYPES = {
|
|
273
|
+
atom_family: `atom`,
|
|
274
|
+
mutable_atom_family: `mutable_atom`,
|
|
275
|
+
selector_family: `selector`,
|
|
276
|
+
readonly_selector_family: `readonly_selector`,
|
|
277
|
+
molecule_family: `molecule`
|
|
278
|
+
};
|
|
279
|
+
function counterfeit(token, key) {
|
|
280
|
+
const subKey = stringifyJson(key);
|
|
281
|
+
const fullKey = `${token.key}(${subKey})`;
|
|
282
|
+
const type = FAMILY_MEMBER_TOKEN_TYPES[token.type];
|
|
283
|
+
const stateToken = {
|
|
284
|
+
key: fullKey,
|
|
285
|
+
type
|
|
286
|
+
};
|
|
287
|
+
Object.assign(stateToken, {
|
|
288
|
+
family: {
|
|
289
|
+
key: token.key,
|
|
290
|
+
subKey
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
Object.assign(stateToken, { counterfeit: true });
|
|
294
|
+
return stateToken;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ../atom.io/internal/src/store/deposit.ts
|
|
298
|
+
function deposit(state) {
|
|
299
|
+
const token = {
|
|
300
|
+
key: state.key,
|
|
301
|
+
type: state.type
|
|
302
|
+
};
|
|
303
|
+
if (`family` in state) {
|
|
304
|
+
token.family = state.family;
|
|
305
|
+
}
|
|
306
|
+
return token;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// ../atom.io/src/molecule.ts
|
|
310
|
+
function makeRootMoleculeInStore(key, store = IMPLICIT.STORE) {
|
|
311
|
+
const molecule = {
|
|
312
|
+
key,
|
|
313
|
+
stringKey: stringifyJson(key),
|
|
314
|
+
dependsOn: `any`
|
|
315
|
+
};
|
|
316
|
+
store.molecules.set(stringifyJson(key), molecule);
|
|
317
|
+
return key;
|
|
318
|
+
}
|
|
319
|
+
function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
320
|
+
const origin = provenance;
|
|
321
|
+
const stringKey = stringifyJson(key);
|
|
322
|
+
const invalidKeys = [];
|
|
323
|
+
const target = newest(store);
|
|
324
|
+
if (Array.isArray(origin)) {
|
|
325
|
+
for (const formerClaim of origin) {
|
|
326
|
+
const claimString = stringifyJson(formerClaim);
|
|
327
|
+
const claim = target.molecules.get(claimString);
|
|
328
|
+
if (claim) {
|
|
329
|
+
store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
330
|
+
} else {
|
|
331
|
+
invalidKeys.push(claimString);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
const claimString = stringifyJson(origin);
|
|
336
|
+
const claim = target.molecules.get(claimString);
|
|
337
|
+
if (claim) {
|
|
338
|
+
store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
339
|
+
} else {
|
|
340
|
+
invalidKeys.push(claimString);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (invalidKeys.length === 0) {
|
|
344
|
+
target.molecules.set(stringKey, { key, stringKey, dependsOn });
|
|
345
|
+
}
|
|
346
|
+
const creationEvent = {
|
|
347
|
+
type: `molecule_creation`,
|
|
348
|
+
key,
|
|
349
|
+
provenance: origin
|
|
350
|
+
};
|
|
351
|
+
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
352
|
+
if (isTransaction) {
|
|
353
|
+
target.transactionMeta.update.updates.push(creationEvent);
|
|
354
|
+
} else {
|
|
355
|
+
target.on.moleculeCreation.next(creationEvent);
|
|
356
|
+
}
|
|
357
|
+
for (const claim of invalidKeys) {
|
|
358
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
359
|
+
(item) => item?.key === claim
|
|
360
|
+
);
|
|
361
|
+
store.logger.error(
|
|
362
|
+
`\u274C`,
|
|
363
|
+
`molecule`,
|
|
364
|
+
key,
|
|
365
|
+
`allocation failed:`,
|
|
366
|
+
`Could not allocate to ${claim} in store "${store.config.name}".`,
|
|
367
|
+
disposal ? `
|
|
368
|
+
${claim} was most recently disposed
|
|
369
|
+
${disposal.trace}` : `No previous disposal trace for ${claim} was found.`
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
return key;
|
|
373
|
+
}
|
|
374
|
+
function fuseWithinStore(store, type, sideA, sideB) {
|
|
375
|
+
const compoundKey = `T$--${type}==${sideA}++${sideB}`;
|
|
376
|
+
const above = [sideA, sideB];
|
|
377
|
+
allocateIntoStore(
|
|
378
|
+
store,
|
|
379
|
+
above,
|
|
380
|
+
compoundKey,
|
|
381
|
+
`all`
|
|
382
|
+
);
|
|
383
|
+
return compoundKey;
|
|
384
|
+
}
|
|
385
|
+
function deallocateFromStore(store, claim) {
|
|
386
|
+
const stringKey = stringifyJson(claim);
|
|
387
|
+
const molecule = store.molecules.get(stringKey);
|
|
388
|
+
if (!molecule) {
|
|
389
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
390
|
+
(item) => item?.key === stringKey
|
|
391
|
+
);
|
|
392
|
+
store.logger.error(
|
|
393
|
+
`\u274C`,
|
|
394
|
+
`molecule`,
|
|
395
|
+
claim,
|
|
396
|
+
`deallocation failed:`,
|
|
397
|
+
`Could not find allocation for ${stringKey} in store "${store.config.name}".`,
|
|
398
|
+
disposal ? `
|
|
399
|
+
This state was most recently deallocated
|
|
400
|
+
${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
|
|
401
|
+
);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const joinKeys = store.moleculeJoins.getRelatedKeys(
|
|
405
|
+
molecule.key
|
|
406
|
+
);
|
|
407
|
+
if (joinKeys) {
|
|
408
|
+
for (const joinKey of joinKeys) {
|
|
409
|
+
const join2 = store.joins.get(joinKey);
|
|
410
|
+
if (join2) {
|
|
411
|
+
join2.relations.delete(molecule.key);
|
|
412
|
+
join2.molecules.delete(molecule.stringKey);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
store.moleculeJoins.delete(molecule.stringKey);
|
|
417
|
+
const provenance = [];
|
|
418
|
+
const values = [];
|
|
419
|
+
const disposalEvent = {
|
|
420
|
+
type: `molecule_disposal`,
|
|
421
|
+
key: molecule.key,
|
|
422
|
+
values,
|
|
423
|
+
provenance
|
|
424
|
+
};
|
|
425
|
+
const target = newest(store);
|
|
426
|
+
target.molecules.delete(stringKey);
|
|
427
|
+
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
428
|
+
if (isTransaction) {
|
|
429
|
+
target.transactionMeta.update.updates.push(disposalEvent);
|
|
430
|
+
}
|
|
431
|
+
const relatedMolecules = store.moleculeGraph.getRelationEntries({
|
|
432
|
+
downstreamMoleculeKey: molecule.stringKey
|
|
433
|
+
});
|
|
434
|
+
if (relatedMolecules) {
|
|
435
|
+
for (const [relatedStringKey, { source }] of relatedMolecules) {
|
|
436
|
+
if (source === molecule.stringKey) {
|
|
437
|
+
const relatedKey = parseJson(relatedStringKey);
|
|
438
|
+
deallocateFromStore(store, relatedKey);
|
|
439
|
+
} else {
|
|
440
|
+
provenance.push(source);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const familyKeys = target.moleculeData.getRelatedKeys(molecule.stringKey);
|
|
445
|
+
if (familyKeys) {
|
|
446
|
+
for (const familyKey of familyKeys) {
|
|
447
|
+
const family = target.families.get(familyKey);
|
|
448
|
+
const token = findInStore(store, family, molecule.key);
|
|
449
|
+
values.push([family.key, token]);
|
|
450
|
+
disposeFromStore(store, token);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
target.moleculeGraph.delete(molecule.stringKey);
|
|
454
|
+
target.moleculeJoins.delete(molecule.stringKey);
|
|
455
|
+
target.moleculeData.delete(molecule.stringKey);
|
|
456
|
+
if (!isTransaction) {
|
|
457
|
+
target.on.moleculeDisposal.next(disposalEvent);
|
|
458
|
+
}
|
|
459
|
+
target.molecules.delete(molecule.stringKey);
|
|
460
|
+
const trace = getTrace(new Error());
|
|
461
|
+
store.disposalTraces.add({ key: stringKey, trace });
|
|
462
|
+
}
|
|
463
|
+
function claimWithinStore(store, newProvenance, claim, exclusive) {
|
|
464
|
+
const stringKey = stringifyJson(claim);
|
|
465
|
+
const target = newest(store);
|
|
466
|
+
const molecule = target.molecules.get(stringKey);
|
|
467
|
+
if (!molecule) {
|
|
468
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
469
|
+
(item) => item?.key === stringKey
|
|
470
|
+
);
|
|
471
|
+
store.logger.error(
|
|
472
|
+
`\u274C`,
|
|
473
|
+
`molecule`,
|
|
474
|
+
claim,
|
|
475
|
+
`claim failed:`,
|
|
476
|
+
`Could not allocate to ${stringKey} in store "${store.config.name}".`,
|
|
477
|
+
disposal ? `
|
|
478
|
+
${stringKey} was most recently disposed
|
|
479
|
+
${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
|
|
480
|
+
);
|
|
481
|
+
return claim;
|
|
482
|
+
}
|
|
483
|
+
const newProvenanceKey = stringifyJson(newProvenance);
|
|
484
|
+
const newProvenanceMolecule = target.molecules.get(newProvenanceKey);
|
|
485
|
+
if (!newProvenanceMolecule) {
|
|
486
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
487
|
+
(item) => item?.key === newProvenanceKey
|
|
488
|
+
);
|
|
489
|
+
store.logger.error(
|
|
490
|
+
`\u274C`,
|
|
491
|
+
`molecule`,
|
|
492
|
+
claim,
|
|
493
|
+
`claim failed:`,
|
|
494
|
+
`Could not allocate to ${newProvenanceKey} in store "${store.config.name}".`,
|
|
495
|
+
disposal ? `
|
|
496
|
+
${newProvenanceKey} was most recently disposed
|
|
497
|
+
${disposal.trace}` : `No previous disposal trace for ${newProvenanceKey} was found.`
|
|
498
|
+
);
|
|
499
|
+
return claim;
|
|
500
|
+
}
|
|
501
|
+
const priorProvenance = store.moleculeGraph.getRelationEntries({
|
|
502
|
+
downstreamMoleculeKey: molecule.stringKey
|
|
503
|
+
}).filter(([, { source }]) => source !== stringKey).map(([key]) => parseJson(key));
|
|
504
|
+
if (exclusive) {
|
|
505
|
+
target.moleculeGraph.delete(stringKey);
|
|
506
|
+
}
|
|
507
|
+
target.moleculeGraph.set(
|
|
508
|
+
{
|
|
509
|
+
upstreamMoleculeKey: newProvenanceMolecule.stringKey,
|
|
510
|
+
downstreamMoleculeKey: molecule.stringKey
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
source: newProvenanceMolecule.stringKey
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
const transferEvent = {
|
|
517
|
+
type: `molecule_transfer`,
|
|
518
|
+
key: molecule.key,
|
|
519
|
+
from: priorProvenance,
|
|
520
|
+
to: [newProvenanceMolecule.key]
|
|
521
|
+
};
|
|
522
|
+
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
523
|
+
if (isTransaction) {
|
|
524
|
+
target.transactionMeta.update.updates.push(transferEvent);
|
|
525
|
+
}
|
|
526
|
+
return claim;
|
|
527
|
+
}
|
|
528
|
+
var Realm = class {
|
|
529
|
+
store;
|
|
530
|
+
constructor(store = IMPLICIT.STORE) {
|
|
531
|
+
this.store = store;
|
|
532
|
+
makeRootMoleculeInStore(`root`, store);
|
|
533
|
+
}
|
|
534
|
+
allocate(provenance, key, attachmentStyle) {
|
|
535
|
+
return allocateIntoStore(
|
|
536
|
+
this.store,
|
|
537
|
+
provenance,
|
|
538
|
+
key,
|
|
539
|
+
attachmentStyle
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
fuse(type, reagentA, reagentB) {
|
|
543
|
+
return fuseWithinStore(this.store, type, reagentA, reagentB);
|
|
544
|
+
}
|
|
545
|
+
deallocate(claim) {
|
|
546
|
+
deallocateFromStore(this.store, claim);
|
|
547
|
+
}
|
|
548
|
+
claim(newProvenance, claim, exclusive) {
|
|
549
|
+
return claimWithinStore(this.store, newProvenance, claim, exclusive);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
var Anarchy = class {
|
|
553
|
+
store;
|
|
554
|
+
realm;
|
|
555
|
+
constructor(store = IMPLICIT.STORE) {
|
|
556
|
+
this.store = store;
|
|
557
|
+
this.realm = new Realm(store);
|
|
558
|
+
}
|
|
559
|
+
allocate(provenance, key, attachmentStyle) {
|
|
560
|
+
allocateIntoStore(
|
|
561
|
+
this.store,
|
|
562
|
+
provenance,
|
|
563
|
+
key,
|
|
564
|
+
attachmentStyle
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
deallocate(key) {
|
|
568
|
+
deallocateFromStore(this.store, key);
|
|
569
|
+
}
|
|
570
|
+
claim(newProvenance, key, exclusive) {
|
|
571
|
+
claimWithinStore(this.store, newProvenance, key, exclusive);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// ../atom.io/src/atom.ts
|
|
576
|
+
function atom(options) {
|
|
577
|
+
return createStandaloneAtom(IMPLICIT.STORE, options);
|
|
578
|
+
}
|
|
579
|
+
function atomFamily(options) {
|
|
580
|
+
return createAtomFamily(IMPLICIT.STORE, options);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// ../atom.io/src/logger.ts
|
|
584
|
+
var simpleLog = (logLevel) => (icon, denomination, tokenKey, message, ...rest) => {
|
|
585
|
+
console[logLevel](
|
|
586
|
+
`${icon} ${denomination} "${tokenKey}" ${message}`,
|
|
587
|
+
...rest
|
|
588
|
+
);
|
|
589
|
+
};
|
|
590
|
+
var simpleLogger = {
|
|
591
|
+
error: simpleLog(`error`),
|
|
592
|
+
info: simpleLog(`info`),
|
|
593
|
+
warn: simpleLog(`warn`)
|
|
594
|
+
};
|
|
595
|
+
var AtomIOLogger = class {
|
|
596
|
+
constructor(logLevel, filter, logger = simpleLogger) {
|
|
597
|
+
this.logLevel = logLevel;
|
|
598
|
+
this.filter = filter;
|
|
599
|
+
this.logger = logger;
|
|
600
|
+
}
|
|
601
|
+
error = (...args) => {
|
|
602
|
+
if ((this.filter?.(...args) ?? true) && this.logLevel !== null) {
|
|
603
|
+
this.logger.error(...args);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
info = (...args) => {
|
|
607
|
+
if ((this.filter?.(...args) ?? true) && this.logLevel === `info`) {
|
|
608
|
+
this.logger.info(...args);
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
warn = (...args) => {
|
|
612
|
+
if ((this.filter?.(...args) ?? true) && this.logLevel !== `error` && this.logLevel !== null) {
|
|
613
|
+
this.logger.warn(...args);
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// ../atom.io/src/selector.ts
|
|
619
|
+
function selectorFamily(options) {
|
|
620
|
+
return createSelectorFamily(IMPLICIT.STORE, options);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// ../atom.io/src/transaction.ts
|
|
624
|
+
function transaction(options) {
|
|
625
|
+
return createTransaction(options, IMPLICIT.STORE);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// ../atom.io/internal/src/junction.ts
|
|
629
|
+
var Junction = class {
|
|
630
|
+
a;
|
|
631
|
+
b;
|
|
632
|
+
cardinality;
|
|
633
|
+
relations = /* @__PURE__ */ new Map();
|
|
634
|
+
contents = /* @__PURE__ */ new Map();
|
|
635
|
+
isAType;
|
|
636
|
+
isBType;
|
|
637
|
+
isContent;
|
|
638
|
+
makeContentKey = (a, b) => `${a}:${b}`;
|
|
639
|
+
warn;
|
|
640
|
+
getRelatedKeys(key) {
|
|
641
|
+
return this.relations.get(key);
|
|
642
|
+
}
|
|
643
|
+
addRelation(a, b) {
|
|
644
|
+
let aRelations = this.relations.get(a);
|
|
645
|
+
let bRelations = this.relations.get(b);
|
|
646
|
+
if (aRelations) {
|
|
647
|
+
aRelations.add(b);
|
|
648
|
+
} else {
|
|
649
|
+
aRelations = /* @__PURE__ */ new Set([b]);
|
|
650
|
+
this.relations.set(a, aRelations);
|
|
651
|
+
}
|
|
652
|
+
if (bRelations) {
|
|
653
|
+
bRelations.add(a);
|
|
654
|
+
} else {
|
|
655
|
+
bRelations = /* @__PURE__ */ new Set([a]);
|
|
656
|
+
this.relations.set(b, bRelations);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
deleteRelation(a, b) {
|
|
660
|
+
const aRelations = this.relations.get(a);
|
|
661
|
+
if (aRelations) {
|
|
662
|
+
aRelations.delete(b);
|
|
663
|
+
if (aRelations.size === 0) {
|
|
664
|
+
this.relations.delete(a);
|
|
665
|
+
}
|
|
666
|
+
const bRelations = this.relations.get(b);
|
|
667
|
+
if (bRelations) {
|
|
668
|
+
bRelations.delete(a);
|
|
669
|
+
if (bRelations.size === 0) {
|
|
670
|
+
this.relations.delete(b);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
replaceRelationsUnsafely(x, ys) {
|
|
676
|
+
this.relations.set(x, new Set(ys));
|
|
677
|
+
for (const y of ys) {
|
|
678
|
+
const yRelations = (/* @__PURE__ */ new Set()).add(x);
|
|
679
|
+
this.relations.set(y, yRelations);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
replaceRelationsSafely(x, ys) {
|
|
683
|
+
const xRelationsPrev = this.relations.get(x);
|
|
684
|
+
let a = this.isAType?.(x) ? x : undefined;
|
|
685
|
+
let b = a === undefined ? x : undefined;
|
|
686
|
+
if (xRelationsPrev) {
|
|
687
|
+
for (const y of xRelationsPrev) {
|
|
688
|
+
a ??= y;
|
|
689
|
+
b ??= y;
|
|
690
|
+
const yRelations = this.relations.get(y);
|
|
691
|
+
if (yRelations) {
|
|
692
|
+
if (yRelations.size === 1) {
|
|
693
|
+
this.relations.delete(y);
|
|
694
|
+
} else {
|
|
695
|
+
yRelations.delete(x);
|
|
696
|
+
}
|
|
697
|
+
this.contents.delete(this.makeContentKey(a, b));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
this.relations.set(x, new Set(ys));
|
|
702
|
+
for (const y of ys) {
|
|
703
|
+
let yRelations = this.relations.get(y);
|
|
704
|
+
if (yRelations) {
|
|
705
|
+
yRelations.add(x);
|
|
706
|
+
} else {
|
|
707
|
+
yRelations = (/* @__PURE__ */ new Set()).add(x);
|
|
708
|
+
this.relations.set(y, yRelations);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
getContentInternal(contentKey) {
|
|
713
|
+
return this.contents.get(contentKey);
|
|
714
|
+
}
|
|
715
|
+
setContent(contentKey, content) {
|
|
716
|
+
this.contents.set(contentKey, content);
|
|
717
|
+
}
|
|
718
|
+
deleteContent(contentKey) {
|
|
719
|
+
this.contents.delete(contentKey);
|
|
720
|
+
}
|
|
721
|
+
constructor(data, config) {
|
|
722
|
+
this.a = data.between[0];
|
|
723
|
+
this.b = data.between[1];
|
|
724
|
+
this.cardinality = data.cardinality;
|
|
725
|
+
if (!config?.externalStore) {
|
|
726
|
+
this.relations = new Map(
|
|
727
|
+
data.relations?.map(([x, ys]) => [x, new Set(ys)])
|
|
728
|
+
);
|
|
729
|
+
this.contents = new Map(data.contents);
|
|
730
|
+
}
|
|
731
|
+
this.isAType = config?.isAType ?? null;
|
|
732
|
+
this.isBType = config?.isBType ?? null;
|
|
733
|
+
this.isContent = config?.isContent ?? null;
|
|
734
|
+
if (config?.makeContentKey) {
|
|
735
|
+
this.makeContentKey = config.makeContentKey;
|
|
736
|
+
}
|
|
737
|
+
if (config?.externalStore) {
|
|
738
|
+
const externalStore = config.externalStore;
|
|
739
|
+
this.has = (a, b) => externalStore.has(a, b);
|
|
740
|
+
this.addRelation = (a, b) => {
|
|
741
|
+
externalStore.addRelation(a, b);
|
|
742
|
+
};
|
|
743
|
+
this.deleteRelation = (a, b) => {
|
|
744
|
+
externalStore.deleteRelation(a, b);
|
|
745
|
+
};
|
|
746
|
+
this.replaceRelationsSafely = (a, bs) => {
|
|
747
|
+
externalStore.replaceRelationsSafely(a, bs);
|
|
748
|
+
};
|
|
749
|
+
this.replaceRelationsUnsafely = (a, bs) => {
|
|
750
|
+
externalStore.replaceRelationsUnsafely(a, bs);
|
|
751
|
+
};
|
|
752
|
+
this.getRelatedKeys = (key) => externalStore.getRelatedKeys(
|
|
753
|
+
key
|
|
754
|
+
);
|
|
755
|
+
if (externalStore.getContent) {
|
|
756
|
+
this.getContentInternal = (contentKey) => {
|
|
757
|
+
return externalStore.getContent(contentKey);
|
|
758
|
+
};
|
|
759
|
+
this.setContent = (contentKey, content) => {
|
|
760
|
+
externalStore.setContent(contentKey, content);
|
|
761
|
+
};
|
|
762
|
+
this.deleteContent = (contentKey) => {
|
|
763
|
+
externalStore.deleteContent(contentKey);
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
for (const [x, ys] of data.relations ?? []) {
|
|
767
|
+
let a = this.isAType?.(x) ? x : undefined;
|
|
768
|
+
let b = a === undefined ? x : undefined;
|
|
769
|
+
for (const y of ys) {
|
|
770
|
+
a ??= y;
|
|
771
|
+
b ??= y;
|
|
772
|
+
this.addRelation(a, b);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
for (const [contentKey, content] of data.contents ?? []) {
|
|
776
|
+
this.setContent(contentKey, content);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (config?.warn) {
|
|
780
|
+
this.warn = config.warn;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
toJSON() {
|
|
784
|
+
return {
|
|
785
|
+
between: [this.a, this.b],
|
|
786
|
+
cardinality: this.cardinality,
|
|
787
|
+
relations: [...this.relations.entries()].map(
|
|
788
|
+
([a, b]) => [a, [...b]]
|
|
789
|
+
),
|
|
790
|
+
contents: [...this.contents.entries()]
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
set(...params) {
|
|
794
|
+
let a;
|
|
795
|
+
let b;
|
|
796
|
+
let content;
|
|
797
|
+
switch (params.length) {
|
|
798
|
+
case 1: {
|
|
799
|
+
const relation = params[0];
|
|
800
|
+
a = relation[this.a];
|
|
801
|
+
b = relation[this.b];
|
|
802
|
+
content = undefined;
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
805
|
+
case 2: {
|
|
806
|
+
const zeroth = params[0];
|
|
807
|
+
if (typeof zeroth === `string`) {
|
|
808
|
+
[a, b] = params;
|
|
809
|
+
} else {
|
|
810
|
+
a = zeroth[this.a];
|
|
811
|
+
b = zeroth[this.b];
|
|
812
|
+
content = params[1];
|
|
813
|
+
}
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
816
|
+
default: {
|
|
817
|
+
a = params[0];
|
|
818
|
+
b = params[1];
|
|
819
|
+
content = params[2];
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
switch (this.cardinality) {
|
|
824
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
|
|
825
|
+
case `1:1`: {
|
|
826
|
+
const bPrev = this.getRelatedKey(a);
|
|
827
|
+
if (bPrev && bPrev !== b) this.delete(a, bPrev);
|
|
828
|
+
}
|
|
829
|
+
case `1:n`: {
|
|
830
|
+
const aPrev = this.getRelatedKey(b);
|
|
831
|
+
if (aPrev && aPrev !== a) this.delete(aPrev, b);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (content) {
|
|
835
|
+
const contentKey = this.makeContentKey(a, b);
|
|
836
|
+
this.setContent(contentKey, content);
|
|
837
|
+
}
|
|
838
|
+
this.addRelation(a, b);
|
|
839
|
+
return this;
|
|
840
|
+
}
|
|
841
|
+
delete(x, b) {
|
|
842
|
+
b = typeof b === `string` ? b : x[this.b];
|
|
843
|
+
const a = (
|
|
844
|
+
// @ts-expect-error we deduce that this.a may index x
|
|
845
|
+
typeof x === `string` ? x : x[this.a]
|
|
846
|
+
);
|
|
847
|
+
if (a === undefined && typeof b === `string`) {
|
|
848
|
+
const bRelations = this.getRelatedKeys(b);
|
|
849
|
+
if (bRelations) {
|
|
850
|
+
for (const bRelation of bRelations) {
|
|
851
|
+
this.delete(bRelation, b);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
if (typeof a === `string` && b === undefined) {
|
|
856
|
+
const aRelations = this.getRelatedKeys(a);
|
|
857
|
+
if (aRelations) {
|
|
858
|
+
for (const aRelation of aRelations) {
|
|
859
|
+
this.delete(a, aRelation);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (typeof a === `string` && typeof b === `string`) {
|
|
864
|
+
this.deleteRelation(a, b);
|
|
865
|
+
const contentKey = this.makeContentKey(a, b);
|
|
866
|
+
this.deleteContent(contentKey);
|
|
867
|
+
}
|
|
868
|
+
return this;
|
|
869
|
+
}
|
|
870
|
+
getRelatedKey(key) {
|
|
871
|
+
const relations = this.getRelatedKeys(key);
|
|
872
|
+
if (relations) {
|
|
873
|
+
if (relations.size > 1) {
|
|
874
|
+
this.warn?.(
|
|
875
|
+
`${relations.size} related keys were found for key "${key}": (${[
|
|
876
|
+
...relations
|
|
877
|
+
].map((k) => `"${k}"`).join(`, `)}). Only one related key was expected.`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
let singleRelation;
|
|
881
|
+
for (const relation of relations) {
|
|
882
|
+
singleRelation = relation;
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
return singleRelation;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
replaceRelations(x, relations, config) {
|
|
889
|
+
const hasContent = !Array.isArray(relations);
|
|
890
|
+
const ys = hasContent ? Object.keys(relations) : relations;
|
|
891
|
+
if (config?.reckless) {
|
|
892
|
+
this.replaceRelationsUnsafely(x, ys);
|
|
893
|
+
} else {
|
|
894
|
+
this.replaceRelationsSafely(x, ys);
|
|
895
|
+
}
|
|
896
|
+
if (hasContent) {
|
|
897
|
+
for (const y of ys) {
|
|
898
|
+
const contentKey = this.makeContentKey(x, y);
|
|
899
|
+
const content = relations[y];
|
|
900
|
+
this.setContent(contentKey, content);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
return this;
|
|
904
|
+
}
|
|
905
|
+
getContent(a, b) {
|
|
906
|
+
const contentKey = this.makeContentKey(a, b);
|
|
907
|
+
return this.getContentInternal(contentKey);
|
|
908
|
+
}
|
|
909
|
+
getRelationEntries(input) {
|
|
910
|
+
const a = input[this.a];
|
|
911
|
+
const b = input[this.b];
|
|
912
|
+
if (a !== undefined && b === undefined) {
|
|
913
|
+
const aRelations = this.getRelatedKeys(a);
|
|
914
|
+
if (aRelations) {
|
|
915
|
+
return [...aRelations].map((aRelation) => {
|
|
916
|
+
return [aRelation, this.getContent(a, aRelation)];
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
if (a === undefined && b !== undefined) {
|
|
921
|
+
const bRelations = this.getRelatedKeys(b);
|
|
922
|
+
if (bRelations) {
|
|
923
|
+
return [...bRelations].map((bRelation) => {
|
|
924
|
+
return [bRelation, this.getContent(bRelation, b)];
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return [];
|
|
929
|
+
}
|
|
930
|
+
has(a, b) {
|
|
931
|
+
if (b) {
|
|
932
|
+
const setA = this.getRelatedKeys(a);
|
|
933
|
+
return setA?.has(b) ?? false;
|
|
934
|
+
}
|
|
935
|
+
return this.relations.has(a);
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
// ../atom.io/internal/src/transaction/is-root-store.ts
|
|
940
|
+
function isRootStore(store) {
|
|
941
|
+
return `epoch` in store.transactionMeta;
|
|
942
|
+
}
|
|
943
|
+
function isChildStore(store) {
|
|
944
|
+
return `phase` in store.transactionMeta;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// ../atom.io/internal/src/transaction/abort-transaction.ts
|
|
948
|
+
var abortTransaction = (store) => {
|
|
949
|
+
const target = newest(store);
|
|
950
|
+
if (!isChildStore(target)) {
|
|
951
|
+
store.logger.warn(
|
|
952
|
+
`\u{1F41E}`,
|
|
953
|
+
`transaction`,
|
|
954
|
+
`???`,
|
|
955
|
+
`abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
|
|
956
|
+
);
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
store.logger.info(
|
|
960
|
+
`\u{1FA82}`,
|
|
961
|
+
`transaction`,
|
|
962
|
+
target.transactionMeta.update.key,
|
|
963
|
+
`Aborting transaction`
|
|
964
|
+
);
|
|
965
|
+
target.parent.child = null;
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
// ../atom.io/internal/src/pretty-print.ts
|
|
969
|
+
var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
|
|
970
|
+
function prettyPrintTokenType(token) {
|
|
971
|
+
return token.type.split(`_`).map(capitalize).join(` `);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// ../atom.io/internal/src/not-found-error.ts
|
|
975
|
+
var NotFoundError = class extends Error {
|
|
976
|
+
constructor(...params) {
|
|
977
|
+
const token = params[0];
|
|
978
|
+
const store = params.length === 2 ? params[1] : params[2];
|
|
979
|
+
if (params.length === 2) {
|
|
980
|
+
super(
|
|
981
|
+
`${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
|
|
982
|
+
);
|
|
983
|
+
} else {
|
|
984
|
+
const key = params[1];
|
|
985
|
+
super(
|
|
986
|
+
`${prettyPrintTokenType(token)} "${token.key}" member ${stringifyJson(key)} not found in store "${store.config.name}".`
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
// ../atom.io/internal/src/transaction/act-upon-store.ts
|
|
993
|
+
function actUponStore(token, id, store) {
|
|
994
|
+
return (...parameters) => {
|
|
995
|
+
const tx = withdraw(token, store);
|
|
996
|
+
if (tx) {
|
|
997
|
+
return tx.run(parameters, id);
|
|
998
|
+
}
|
|
999
|
+
throw new NotFoundError(token, store);
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// ../atom.io/internal/src/set-state/become.ts
|
|
1004
|
+
var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(originalThing) : nextVersionOfThing;
|
|
1005
|
+
|
|
1006
|
+
// ../atom.io/internal/src/get-state/read-or-compute-value.ts
|
|
1007
|
+
var readOrComputeValue = (state, target) => {
|
|
1008
|
+
if (target.valueMap.has(state.key)) {
|
|
1009
|
+
target.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
|
|
1010
|
+
return readCachedValue(state, target);
|
|
1011
|
+
}
|
|
1012
|
+
if (state.type === `selector` || state.type === `readonly_selector`) {
|
|
1013
|
+
target.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
|
|
1014
|
+
return state.get();
|
|
1015
|
+
}
|
|
1016
|
+
const fallback = state.default instanceof Function ? state.default() : state.default;
|
|
1017
|
+
target.logger.info(
|
|
1018
|
+
`\u{1F481}`,
|
|
1019
|
+
`atom`,
|
|
1020
|
+
state.key,
|
|
1021
|
+
`could not find cached value; using default`,
|
|
1022
|
+
fallback
|
|
1023
|
+
);
|
|
1024
|
+
return state.default instanceof Function ? state.default() : state.default;
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
// ../atom.io/internal/src/operation.ts
|
|
1028
|
+
var openOperation = (store, token) => {
|
|
1029
|
+
if (store.operation.open) {
|
|
1030
|
+
const rejectionTime = performance.now();
|
|
1031
|
+
store.logger.info(
|
|
1032
|
+
`\u2757`,
|
|
1033
|
+
token.type,
|
|
1034
|
+
token.key,
|
|
1035
|
+
`deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`
|
|
1036
|
+
);
|
|
1037
|
+
return rejectionTime;
|
|
1038
|
+
}
|
|
1039
|
+
store.operation = {
|
|
1040
|
+
open: true,
|
|
1041
|
+
done: /* @__PURE__ */ new Set(),
|
|
1042
|
+
prev: /* @__PURE__ */ new Map(),
|
|
1043
|
+
time: Date.now(),
|
|
1044
|
+
token
|
|
1045
|
+
};
|
|
1046
|
+
store.logger.info(
|
|
1047
|
+
`\u2B55`,
|
|
1048
|
+
token.type,
|
|
1049
|
+
token.key,
|
|
1050
|
+
`operation start in store "${store.config.name}"${!isChildStore(store) ? `` : ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`}`
|
|
1051
|
+
);
|
|
1052
|
+
};
|
|
1053
|
+
var closeOperation = (store) => {
|
|
1054
|
+
if (store.operation.open) {
|
|
1055
|
+
store.logger.info(
|
|
1056
|
+
`\u{1F534}`,
|
|
1057
|
+
store.operation.token.type,
|
|
1058
|
+
store.operation.token.key,
|
|
1059
|
+
`operation done in store "${store.config.name}"`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
store.operation = { open: false };
|
|
1063
|
+
store.on.operationClose.next(store.operation);
|
|
1064
|
+
};
|
|
1065
|
+
var isDone = (store, key) => {
|
|
1066
|
+
if (!store.operation.open) {
|
|
1067
|
+
store.logger.error(
|
|
1068
|
+
`\u{1F41E}`,
|
|
1069
|
+
`unknown`,
|
|
1070
|
+
key,
|
|
1071
|
+
`isDone called outside of an operation. This is probably a bug in AtomIO.`
|
|
1072
|
+
);
|
|
1073
|
+
return true;
|
|
1074
|
+
}
|
|
1075
|
+
return store.operation.done.has(key);
|
|
1076
|
+
};
|
|
1077
|
+
var markDone = (store, key) => {
|
|
1078
|
+
if (!store.operation.open) {
|
|
1079
|
+
store.logger.error(
|
|
1080
|
+
`\u{1F41E}`,
|
|
1081
|
+
`unknown`,
|
|
1082
|
+
key,
|
|
1083
|
+
`markDone called outside of an operation. This is probably a bug in AtomIO.`
|
|
1084
|
+
);
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
store.operation.done.add(key);
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
// ../atom.io/internal/src/set-state/emit-update.ts
|
|
1091
|
+
var emitUpdate = (state, update, store) => {
|
|
1092
|
+
switch (state.type) {
|
|
1093
|
+
case `mutable_atom`:
|
|
1094
|
+
store.logger.info(
|
|
1095
|
+
`\u{1F4E2}`,
|
|
1096
|
+
state.type,
|
|
1097
|
+
state.key,
|
|
1098
|
+
`is now (`,
|
|
1099
|
+
update.newValue,
|
|
1100
|
+
`) subscribers:`,
|
|
1101
|
+
state.subject.subscribers
|
|
1102
|
+
);
|
|
1103
|
+
break;
|
|
1104
|
+
default:
|
|
1105
|
+
store.logger.info(
|
|
1106
|
+
`\u{1F4E2}`,
|
|
1107
|
+
state.type,
|
|
1108
|
+
state.key,
|
|
1109
|
+
`went (`,
|
|
1110
|
+
update.oldValue,
|
|
1111
|
+
`->`,
|
|
1112
|
+
update.newValue,
|
|
1113
|
+
`) subscribers:`,
|
|
1114
|
+
state.subject.subscribers
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
state.subject.next(update);
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
// ../atom.io/internal/src/set-state/evict-downstream.ts
|
|
1121
|
+
var evictDownStream = (atom2, store) => {
|
|
1122
|
+
const target = newest(store);
|
|
1123
|
+
const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom2.key);
|
|
1124
|
+
target.logger.info(
|
|
1125
|
+
`\u{1F9F9}`,
|
|
1126
|
+
atom2.type,
|
|
1127
|
+
atom2.key,
|
|
1128
|
+
downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
|
|
1129
|
+
downstreamKeys ?? `to evict`
|
|
1130
|
+
);
|
|
1131
|
+
if (downstreamKeys) {
|
|
1132
|
+
if (target.operation.open) {
|
|
1133
|
+
target.logger.info(
|
|
1134
|
+
`\u{1F9F9}`,
|
|
1135
|
+
atom2.type,
|
|
1136
|
+
atom2.key,
|
|
1137
|
+
`[ ${[...target.operation.done].join(`, `)} ] already done`
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
for (const key of downstreamKeys) {
|
|
1141
|
+
if (isDone(target, key)) {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
evictCachedValue(key, target);
|
|
1145
|
+
markDone(target, key);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// ../atom.io/internal/src/set-state/stow-update.ts
|
|
1151
|
+
function shouldUpdateBeStowed(key, update) {
|
|
1152
|
+
if (isTransceiver(update.newValue)) {
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
if (key.includes(`\u{1F50D}`)) {
|
|
1156
|
+
return false;
|
|
1157
|
+
}
|
|
1158
|
+
return true;
|
|
1159
|
+
}
|
|
1160
|
+
var stowUpdate = (state, update, store) => {
|
|
1161
|
+
const { key } = state;
|
|
1162
|
+
const target = newest(store);
|
|
1163
|
+
if (!isChildStore(target) || target.transactionMeta.phase !== `building`) {
|
|
1164
|
+
store.logger.error(
|
|
1165
|
+
`\u{1F41E}`,
|
|
1166
|
+
`atom`,
|
|
1167
|
+
key,
|
|
1168
|
+
`stowUpdate called outside of a transaction. This is probably a bug.`
|
|
1169
|
+
);
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
const shouldStow = shouldUpdateBeStowed(key, update);
|
|
1173
|
+
if (!shouldStow) {
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
const atomUpdate = {
|
|
1177
|
+
type: `atom_update`,
|
|
1178
|
+
key,
|
|
1179
|
+
...update
|
|
1180
|
+
};
|
|
1181
|
+
if (state.family) {
|
|
1182
|
+
atomUpdate.family = state.family;
|
|
1183
|
+
}
|
|
1184
|
+
target.transactionMeta.update.updates.push(atomUpdate);
|
|
1185
|
+
store.logger.info(
|
|
1186
|
+
`\u{1F4C1}`,
|
|
1187
|
+
`atom`,
|
|
1188
|
+
key,
|
|
1189
|
+
`stowed (`,
|
|
1190
|
+
update.oldValue,
|
|
1191
|
+
`->`,
|
|
1192
|
+
update.newValue,
|
|
1193
|
+
`)`
|
|
1194
|
+
);
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1197
|
+
// ../atom.io/internal/src/set-state/set-atom.ts
|
|
1198
|
+
var setAtom = (atom2, next, target) => {
|
|
1199
|
+
const oldValue = readOrComputeValue(atom2, target);
|
|
1200
|
+
let newValue = oldValue;
|
|
1201
|
+
if (atom2.type === `mutable_atom` && isChildStore(target)) {
|
|
1202
|
+
const { parent } = target;
|
|
1203
|
+
const copiedValue = copyMutableIfNeeded(atom2, parent, target);
|
|
1204
|
+
newValue = copiedValue;
|
|
1205
|
+
}
|
|
1206
|
+
newValue = become(next)(newValue);
|
|
1207
|
+
target.logger.info(`\u{1F4DD}`, `atom`, atom2.key, `set to`, newValue);
|
|
1208
|
+
newValue = cacheValue(atom2.key, newValue, atom2.subject, target);
|
|
1209
|
+
if (isAtomDefault(atom2.key, target)) {
|
|
1210
|
+
markAtomAsNotDefault(atom2.key, target);
|
|
1211
|
+
}
|
|
1212
|
+
markDone(target, atom2.key);
|
|
1213
|
+
evictDownStream(atom2, target);
|
|
1214
|
+
const update = { oldValue, newValue };
|
|
1215
|
+
if (isRootStore(target)) {
|
|
1216
|
+
emitUpdate(atom2, update, target);
|
|
1217
|
+
} else if (target.parent) {
|
|
1218
|
+
if (target.on.transactionApplying.state === null) {
|
|
1219
|
+
stowUpdate(atom2, update, target);
|
|
1220
|
+
} else if (atom2.key.startsWith(`*`)) {
|
|
1221
|
+
const mutableKey = atom2.key.slice(1);
|
|
1222
|
+
const mutableAtom = target.atoms.get(mutableKey);
|
|
1223
|
+
let transceiver = target.valueMap.get(mutableKey);
|
|
1224
|
+
if (mutableAtom.type === `mutable_atom` && isChildStore(target)) {
|
|
1225
|
+
const { parent } = target;
|
|
1226
|
+
const copiedValue = copyMutableIfNeeded(mutableAtom, parent, target);
|
|
1227
|
+
transceiver = copiedValue;
|
|
1228
|
+
}
|
|
1229
|
+
const accepted = transceiver.do(update.newValue) === null;
|
|
1230
|
+
if (accepted) evictDownStream(mutableAtom, target);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
|
|
1235
|
+
// ../atom.io/internal/src/set-state/set-atom-or-selector.ts
|
|
1236
|
+
var setAtomOrSelector = (state, value, store) => {
|
|
1237
|
+
switch (state.type) {
|
|
1238
|
+
case `atom`:
|
|
1239
|
+
case `mutable_atom`:
|
|
1240
|
+
setAtom(state, value, store);
|
|
1241
|
+
break;
|
|
1242
|
+
case `selector`:
|
|
1243
|
+
state.set(value);
|
|
1244
|
+
break;
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// ../atom.io/internal/src/families/get-family-of-token.ts
|
|
1249
|
+
function getFamilyOfToken(store, token) {
|
|
1250
|
+
if (token.family) {
|
|
1251
|
+
const family = store.families.get(token.family.key);
|
|
1252
|
+
if (family) {
|
|
1253
|
+
return family;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// ../atom.io/internal/src/set-state/set-into-store.ts
|
|
1259
|
+
function setIntoStore(store, ...params) {
|
|
1260
|
+
let token;
|
|
1261
|
+
let family;
|
|
1262
|
+
let key;
|
|
1263
|
+
let value;
|
|
1264
|
+
if (params.length === 2) {
|
|
1265
|
+
token = params[0];
|
|
1266
|
+
value = params[1];
|
|
1267
|
+
family = getFamilyOfToken(store, token) ?? null;
|
|
1268
|
+
if (family) {
|
|
1269
|
+
key = token.family ? parseJson(token.family.subKey) : null;
|
|
1270
|
+
token = findInStore(store, family, key);
|
|
1271
|
+
}
|
|
1272
|
+
} else {
|
|
1273
|
+
family = params[0];
|
|
1274
|
+
key = params[1];
|
|
1275
|
+
value = params[2];
|
|
1276
|
+
token = findInStore(store, family, key);
|
|
1277
|
+
}
|
|
1278
|
+
if (`counterfeit` in token && `family` in token) {
|
|
1279
|
+
const subKey = token.family.subKey;
|
|
1280
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
1281
|
+
(item) => item?.key === subKey
|
|
1282
|
+
);
|
|
1283
|
+
store.logger.error(
|
|
1284
|
+
`\u274C`,
|
|
1285
|
+
token.type,
|
|
1286
|
+
token.key,
|
|
1287
|
+
`could not be set because it was not found in the store "${store.config.name}".`,
|
|
1288
|
+
disposal ? `This state was previously disposed:
|
|
1289
|
+
${disposal.trace}` : `No previous disposal trace was found.`
|
|
1290
|
+
);
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const rejectionTime = openOperation(store, token);
|
|
1294
|
+
if (rejectionTime) {
|
|
1295
|
+
const unsubscribe = store.on.operationClose.subscribe(
|
|
1296
|
+
`waiting to set "${token.key}" at T-${rejectionTime}`,
|
|
1297
|
+
() => {
|
|
1298
|
+
unsubscribe();
|
|
1299
|
+
store.logger.info(
|
|
1300
|
+
`\u{1F7E2}`,
|
|
1301
|
+
token.type,
|
|
1302
|
+
token.key,
|
|
1303
|
+
`resuming deferred setState from T-${rejectionTime}`
|
|
1304
|
+
);
|
|
1305
|
+
setIntoStore(store, token, value);
|
|
1306
|
+
}
|
|
1307
|
+
);
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
const state = withdraw(token, store);
|
|
1311
|
+
setAtomOrSelector(state, value, store);
|
|
1312
|
+
closeOperation(store);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// ../atom.io/internal/src/ingest-updates/ingest-atom-update.ts
|
|
1316
|
+
function ingestAtomUpdate(applying, atomUpdate, store) {
|
|
1317
|
+
const { key, newValue, oldValue } = atomUpdate;
|
|
1318
|
+
const value = newValue ;
|
|
1319
|
+
const token = { key, type: `atom` };
|
|
1320
|
+
if (atomUpdate.family) {
|
|
1321
|
+
Object.assign(token, { family: atomUpdate.family });
|
|
1322
|
+
}
|
|
1323
|
+
setIntoStore(store, token, value);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// ../atom.io/internal/src/ingest-updates/ingest-creation-disposal.ts
|
|
1327
|
+
function ingestCreationEvent(update, applying, store) {
|
|
1328
|
+
switch (applying) {
|
|
1329
|
+
case `newValue`: {
|
|
1330
|
+
createInStore(update, store);
|
|
1331
|
+
break;
|
|
1332
|
+
}
|
|
1333
|
+
case `oldValue`: {
|
|
1334
|
+
disposeFromStore(store, update.token);
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
function ingestDisposalEvent(update, applying, store) {
|
|
1340
|
+
switch (applying) {
|
|
1341
|
+
case `newValue`: {
|
|
1342
|
+
disposeFromStore(store, update.token);
|
|
1343
|
+
break;
|
|
1344
|
+
}
|
|
1345
|
+
case `oldValue`: {
|
|
1346
|
+
createInStore(update, store);
|
|
1347
|
+
if (update.subType === `atom`) {
|
|
1348
|
+
store.valueMap.set(update.token.key, update.value);
|
|
1349
|
+
}
|
|
1350
|
+
break;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
function createInStore(update, store) {
|
|
1355
|
+
const { family: familyMeta } = update.token;
|
|
1356
|
+
if (familyMeta) {
|
|
1357
|
+
const family = store.families.get(familyMeta.key);
|
|
1358
|
+
if (family) {
|
|
1359
|
+
findInStore(store, family, parseJson(familyMeta.subKey));
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
function ingestMoleculeCreationEvent(update, applying, store) {
|
|
1364
|
+
switch (applying) {
|
|
1365
|
+
case `newValue`:
|
|
1366
|
+
allocateIntoStore(store, update.provenance, update.key);
|
|
1367
|
+
break;
|
|
1368
|
+
case `oldValue`:
|
|
1369
|
+
deallocateFromStore(store, update.key);
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
function ingestMoleculeDisposalEvent(update, applying, store) {
|
|
1374
|
+
switch (applying) {
|
|
1375
|
+
case `newValue`:
|
|
1376
|
+
deallocateFromStore(store, update.key);
|
|
1377
|
+
break;
|
|
1378
|
+
case `oldValue`:
|
|
1379
|
+
{
|
|
1380
|
+
const provenanceJson = update.provenance.map(parseJson);
|
|
1381
|
+
allocateIntoStore(store, provenanceJson, update.key);
|
|
1382
|
+
for (const [familyKey, value] of update.values) {
|
|
1383
|
+
const family = store.families.get(familyKey);
|
|
1384
|
+
if (family) {
|
|
1385
|
+
findInStore(store, family, update.key);
|
|
1386
|
+
const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
|
|
1387
|
+
store.valueMap.set(memberKey, value);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
break;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
function ingestMoleculeTransferEvent(update, applying, store) {
|
|
1395
|
+
switch (applying) {
|
|
1396
|
+
case `newValue`:
|
|
1397
|
+
{
|
|
1398
|
+
const provenance = update.to.length === 1 ? update.to[0] : update.to;
|
|
1399
|
+
claimWithinStore(
|
|
1400
|
+
store,
|
|
1401
|
+
provenance,
|
|
1402
|
+
update.key,
|
|
1403
|
+
`exclusive`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
break;
|
|
1407
|
+
case `oldValue`:
|
|
1408
|
+
{
|
|
1409
|
+
const provenance = update.from.length === 1 ? update.from[0] : update.from;
|
|
1410
|
+
claimWithinStore(
|
|
1411
|
+
store,
|
|
1412
|
+
provenance,
|
|
1413
|
+
update.key,
|
|
1414
|
+
`exclusive`
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
break;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// ../atom.io/internal/src/ingest-updates/ingest-transaction-update.ts
|
|
1422
|
+
function ingestTransactionUpdate(applying, transactionUpdate, store) {
|
|
1423
|
+
const updates = transactionUpdate.updates ;
|
|
1424
|
+
for (const updateFromTransaction of updates) {
|
|
1425
|
+
switch (updateFromTransaction.type) {
|
|
1426
|
+
case `atom_update`:
|
|
1427
|
+
case `selector_update`:
|
|
1428
|
+
ingestAtomUpdate(applying, updateFromTransaction, store);
|
|
1429
|
+
break;
|
|
1430
|
+
case `state_creation`:
|
|
1431
|
+
ingestCreationEvent(updateFromTransaction, applying, store);
|
|
1432
|
+
break;
|
|
1433
|
+
case `state_disposal`:
|
|
1434
|
+
ingestDisposalEvent(updateFromTransaction, applying, store);
|
|
1435
|
+
break;
|
|
1436
|
+
case `molecule_creation`:
|
|
1437
|
+
ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
|
|
1438
|
+
break;
|
|
1439
|
+
case `molecule_disposal`:
|
|
1440
|
+
ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
|
|
1441
|
+
break;
|
|
1442
|
+
case `molecule_transfer`:
|
|
1443
|
+
ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
|
|
1444
|
+
break;
|
|
1445
|
+
case `transaction_update`:
|
|
1446
|
+
ingestTransactionUpdate(applying, updateFromTransaction, store);
|
|
1447
|
+
break;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
// ../atom.io/internal/src/transaction/set-epoch-number.ts
|
|
1453
|
+
function setEpochNumberOfAction(transactionKey, newEpoch, store) {
|
|
1454
|
+
const isRoot = isRootStore(store);
|
|
1455
|
+
if (!isRoot) {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
|
|
1459
|
+
if (continuityKey !== undefined) {
|
|
1460
|
+
store.transactionMeta.epoch.set(continuityKey, newEpoch);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
// ../atom.io/internal/src/transaction/apply-transaction.ts
|
|
1465
|
+
var applyTransaction = (output, store) => {
|
|
1466
|
+
const child = newest(store);
|
|
1467
|
+
const { parent } = child;
|
|
1468
|
+
if (parent === null || !isChildStore(child) || child.transactionMeta?.phase !== `building`) {
|
|
1469
|
+
store.logger.warn(
|
|
1470
|
+
`\u{1F41E}`,
|
|
1471
|
+
`transaction`,
|
|
1472
|
+
`???`,
|
|
1473
|
+
`applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
|
|
1474
|
+
);
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
child.transactionMeta.phase = `applying`;
|
|
1478
|
+
child.transactionMeta.update.output = output;
|
|
1479
|
+
parent.child = null;
|
|
1480
|
+
parent.on.transactionApplying.next(child.transactionMeta);
|
|
1481
|
+
const { updates } = child.transactionMeta.update;
|
|
1482
|
+
store.logger.info(
|
|
1483
|
+
`\u{1F6C4}`,
|
|
1484
|
+
`transaction`,
|
|
1485
|
+
child.transactionMeta.update.key,
|
|
1486
|
+
`Applying transaction with ${updates.length} updates:`,
|
|
1487
|
+
updates
|
|
1488
|
+
);
|
|
1489
|
+
ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
|
|
1490
|
+
if (isRootStore(parent)) {
|
|
1491
|
+
setEpochNumberOfAction(
|
|
1492
|
+
child.transactionMeta.update.key,
|
|
1493
|
+
child.transactionMeta.update.epoch,
|
|
1494
|
+
parent
|
|
1495
|
+
);
|
|
1496
|
+
const myTransaction = withdraw(
|
|
1497
|
+
{ key: child.transactionMeta.update.key, type: `transaction` },
|
|
1498
|
+
store
|
|
1499
|
+
);
|
|
1500
|
+
myTransaction?.subject.next(child.transactionMeta.update);
|
|
1501
|
+
store.logger.info(
|
|
1502
|
+
`\u{1F6EC}`,
|
|
1503
|
+
`transaction`,
|
|
1504
|
+
child.transactionMeta.update.key,
|
|
1505
|
+
`Finished applying transaction.`
|
|
1506
|
+
);
|
|
1507
|
+
} else if (isChildStore(parent)) {
|
|
1508
|
+
parent.transactionMeta.update.updates.push(child.transactionMeta.update);
|
|
1509
|
+
}
|
|
1510
|
+
parent.on.transactionApplying.next(null);
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1513
|
+
// ../atom.io/internal/src/get-environment-data.ts
|
|
1514
|
+
function getEnvironmentData(store) {
|
|
1515
|
+
return {
|
|
1516
|
+
store
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// ../atom.io/internal/src/get-state/get-from-store.ts
|
|
1521
|
+
function getFromStore(store, ...params) {
|
|
1522
|
+
let token;
|
|
1523
|
+
let family;
|
|
1524
|
+
let key;
|
|
1525
|
+
if (params.length === 1) {
|
|
1526
|
+
token = params[0];
|
|
1527
|
+
} else {
|
|
1528
|
+
family = params[0];
|
|
1529
|
+
key = params[1];
|
|
1530
|
+
token = findInStore(store, family, key);
|
|
1531
|
+
}
|
|
1532
|
+
if (`counterfeit` in token && `family` in token) {
|
|
1533
|
+
family = store.families.get(token.family.key);
|
|
1534
|
+
const subKey = token.family.subKey;
|
|
1535
|
+
const disposal = store.disposalTraces.buffer.find(
|
|
1536
|
+
(item) => item?.key === subKey
|
|
1537
|
+
);
|
|
1538
|
+
store.logger.error(
|
|
1539
|
+
`\u274C`,
|
|
1540
|
+
token.type,
|
|
1541
|
+
token.key,
|
|
1542
|
+
`could not be retrieved because it was not found in the store "${store.config.name}".`,
|
|
1543
|
+
disposal ? `This state was previously disposed:
|
|
1544
|
+
${disposal.trace}` : `No previous disposal trace was found.`
|
|
1545
|
+
);
|
|
1546
|
+
switch (family.type) {
|
|
1547
|
+
case `atom_family`:
|
|
1548
|
+
case `mutable_atom_family`:
|
|
1549
|
+
return store.defaults.get(family.key);
|
|
1550
|
+
case `selector_family`:
|
|
1551
|
+
case `readonly_selector_family`: {
|
|
1552
|
+
if (store.defaults.has(family.key)) {
|
|
1553
|
+
return store.defaults.get(token.family.key);
|
|
1554
|
+
}
|
|
1555
|
+
const defaultValue = withdraw(family, store).default(subKey);
|
|
1556
|
+
store.defaults.set(family.key, defaultValue);
|
|
1557
|
+
return defaultValue;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
return readOrComputeValue(withdraw(token, store), store);
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
// ../atom.io/internal/src/lazy-map.ts
|
|
1565
|
+
var LazyMap = class extends Map {
|
|
1566
|
+
constructor(source) {
|
|
1567
|
+
super();
|
|
1568
|
+
this.source = source;
|
|
1569
|
+
}
|
|
1570
|
+
deleted = /* @__PURE__ */ new Set();
|
|
1571
|
+
get(key) {
|
|
1572
|
+
const has = super.has(key);
|
|
1573
|
+
if (has) {
|
|
1574
|
+
return super.get(key);
|
|
1575
|
+
}
|
|
1576
|
+
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
1577
|
+
const value = this.source.get(key);
|
|
1578
|
+
return value;
|
|
1579
|
+
}
|
|
1580
|
+
return undefined;
|
|
1581
|
+
}
|
|
1582
|
+
set(key, value) {
|
|
1583
|
+
this.deleted.delete(key);
|
|
1584
|
+
return super.set(key, value);
|
|
1585
|
+
}
|
|
1586
|
+
hasOwn(key) {
|
|
1587
|
+
return super.has(key);
|
|
1588
|
+
}
|
|
1589
|
+
has(key) {
|
|
1590
|
+
return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
|
|
1591
|
+
}
|
|
1592
|
+
delete(key) {
|
|
1593
|
+
this.deleted.add(key);
|
|
1594
|
+
return super.delete(key);
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
|
|
1598
|
+
// ../atom.io/internal/src/transaction/build-transaction.ts
|
|
1599
|
+
var buildTransaction = (key, params, store, id) => {
|
|
1600
|
+
const parent = newest(store);
|
|
1601
|
+
const childBase = {
|
|
1602
|
+
parent,
|
|
1603
|
+
child: null,
|
|
1604
|
+
on: parent.on,
|
|
1605
|
+
loggers: parent.loggers,
|
|
1606
|
+
logger: parent.logger,
|
|
1607
|
+
config: parent.config,
|
|
1608
|
+
atoms: new LazyMap(parent.atoms),
|
|
1609
|
+
atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
|
|
1610
|
+
families: new LazyMap(parent.families),
|
|
1611
|
+
joins: new LazyMap(parent.joins),
|
|
1612
|
+
operation: { open: false },
|
|
1613
|
+
readonlySelectors: new LazyMap(parent.readonlySelectors),
|
|
1614
|
+
timelines: new LazyMap(parent.timelines),
|
|
1615
|
+
timelineTopics: new Junction(parent.timelineTopics.toJSON()),
|
|
1616
|
+
trackers: /* @__PURE__ */ new Map(),
|
|
1617
|
+
transactions: new LazyMap(parent.transactions),
|
|
1618
|
+
selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
|
|
1619
|
+
selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
|
|
1620
|
+
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
1621
|
+
}),
|
|
1622
|
+
selectors: new LazyMap(parent.selectors),
|
|
1623
|
+
valueMap: new LazyMap(parent.valueMap),
|
|
1624
|
+
defaults: parent.defaults,
|
|
1625
|
+
disposalTraces: store.disposalTraces.copy(),
|
|
1626
|
+
molecules: new LazyMap(parent.molecules),
|
|
1627
|
+
moleculeGraph: new Junction(parent.moleculeGraph.toJSON(), {
|
|
1628
|
+
makeContentKey: parent.moleculeGraph.makeContentKey
|
|
1629
|
+
}),
|
|
1630
|
+
moleculeData: new Junction(parent.moleculeData.toJSON(), {
|
|
1631
|
+
makeContentKey: parent.moleculeData.makeContentKey
|
|
1632
|
+
}),
|
|
1633
|
+
moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), {
|
|
1634
|
+
makeContentKey: parent.moleculeJoins.makeContentKey
|
|
1635
|
+
}),
|
|
1636
|
+
miscResources: new LazyMap(parent.miscResources)
|
|
1637
|
+
};
|
|
1638
|
+
const epoch = getEpochNumberOfAction(key, store);
|
|
1639
|
+
const transactionMeta = {
|
|
1640
|
+
phase: `building`,
|
|
1641
|
+
update: {
|
|
1642
|
+
type: `transaction_update`,
|
|
1643
|
+
key,
|
|
1644
|
+
id,
|
|
1645
|
+
epoch: epoch === undefined ? Number.NaN : epoch + 1,
|
|
1646
|
+
updates: [],
|
|
1647
|
+
params,
|
|
1648
|
+
output: undefined
|
|
1649
|
+
},
|
|
1650
|
+
toolkit: {
|
|
1651
|
+
get: (...ps) => getFromStore(child, ...ps),
|
|
1652
|
+
set: (...ps) => {
|
|
1653
|
+
setIntoStore(child, ...ps);
|
|
1654
|
+
},
|
|
1655
|
+
run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
|
|
1656
|
+
find: (token, k) => findInStore(child, token, k),
|
|
1657
|
+
seek: (token, k) => seekInStore(child, token, k),
|
|
1658
|
+
json: (token) => getJsonToken(child, token),
|
|
1659
|
+
dispose: (...ps) => {
|
|
1660
|
+
disposeFromStore(child, ...ps);
|
|
1661
|
+
},
|
|
1662
|
+
env: () => getEnvironmentData(child)
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
const child = Object.assign(childBase, {
|
|
1666
|
+
transactionMeta
|
|
1667
|
+
});
|
|
1668
|
+
parent.child = child;
|
|
1669
|
+
store.logger.info(
|
|
1670
|
+
`\u{1F6EB}`,
|
|
1671
|
+
`transaction`,
|
|
1672
|
+
key,
|
|
1673
|
+
`Building transaction with params:`,
|
|
1674
|
+
params
|
|
1675
|
+
);
|
|
1676
|
+
return child;
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
// ../atom.io/internal/src/transaction/create-transaction.ts
|
|
1680
|
+
function createTransaction(options, store) {
|
|
1681
|
+
const newTransaction = {
|
|
1682
|
+
key: options.key,
|
|
1683
|
+
type: `transaction`,
|
|
1684
|
+
run: (params, id) => {
|
|
1685
|
+
const childStore = buildTransaction(options.key, params, store, id);
|
|
1686
|
+
try {
|
|
1687
|
+
const target2 = newest(store);
|
|
1688
|
+
const { toolkit } = childStore.transactionMeta;
|
|
1689
|
+
const output = options.do(toolkit, ...params);
|
|
1690
|
+
applyTransaction(output, target2);
|
|
1691
|
+
return output;
|
|
1692
|
+
} catch (thrown) {
|
|
1693
|
+
abortTransaction(target);
|
|
1694
|
+
store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
|
|
1695
|
+
throw thrown;
|
|
1696
|
+
}
|
|
1697
|
+
},
|
|
1698
|
+
install: (s) => createTransaction(options, s),
|
|
1699
|
+
subject: new Subject()
|
|
1700
|
+
};
|
|
1701
|
+
const target = newest(store);
|
|
1702
|
+
target.transactions.set(newTransaction.key, newTransaction);
|
|
1703
|
+
const token = deposit(newTransaction);
|
|
1704
|
+
store.on.transactionCreation.next(token);
|
|
1705
|
+
return token;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// ../atom.io/internal/src/transaction/get-epoch-number.ts
|
|
1709
|
+
function getEpochNumberOfAction(transactionKey, store) {
|
|
1710
|
+
const isRoot = isRootStore(store);
|
|
1711
|
+
const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : undefined;
|
|
1712
|
+
const epoch = isRoot && continuity !== undefined ? store.transactionMeta.epoch.get(continuity) : undefined;
|
|
1713
|
+
return epoch;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// ../atom.io/internal/src/store/store.ts
|
|
1717
|
+
var Store = class {
|
|
1718
|
+
parent = null;
|
|
1719
|
+
child = null;
|
|
1720
|
+
valueMap = /* @__PURE__ */ new Map();
|
|
1721
|
+
defaults = /* @__PURE__ */ new Map();
|
|
1722
|
+
atoms = /* @__PURE__ */ new Map();
|
|
1723
|
+
selectors = /* @__PURE__ */ new Map();
|
|
1724
|
+
readonlySelectors = /* @__PURE__ */ new Map();
|
|
1725
|
+
atomsThatAreDefault = /* @__PURE__ */ new Set();
|
|
1726
|
+
selectorAtoms = new Junction({
|
|
1727
|
+
between: [`selectorKey`, `atomKey`],
|
|
1728
|
+
cardinality: `n:n`
|
|
1729
|
+
});
|
|
1730
|
+
selectorGraph = new Junction(
|
|
1731
|
+
{
|
|
1732
|
+
between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
|
|
1733
|
+
cardinality: `n:n`
|
|
1734
|
+
},
|
|
1735
|
+
{
|
|
1736
|
+
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
1737
|
+
}
|
|
1738
|
+
);
|
|
1739
|
+
trackers = /* @__PURE__ */ new Map();
|
|
1740
|
+
families = /* @__PURE__ */ new Map();
|
|
1741
|
+
joins = /* @__PURE__ */ new Map();
|
|
1742
|
+
transactions = /* @__PURE__ */ new Map();
|
|
1743
|
+
transactionMeta = {
|
|
1744
|
+
epoch: /* @__PURE__ */ new Map(),
|
|
1745
|
+
actionContinuities: new Junction({
|
|
1746
|
+
between: [`continuity`, `action`],
|
|
1747
|
+
cardinality: `1:n`
|
|
1748
|
+
})
|
|
1749
|
+
};
|
|
1750
|
+
timelines = /* @__PURE__ */ new Map();
|
|
1751
|
+
timelineTopics = new Junction({
|
|
1752
|
+
between: [`timelineKey`, `topicKey`],
|
|
1753
|
+
cardinality: `1:n`
|
|
1754
|
+
});
|
|
1755
|
+
disposalTraces = new CircularBuffer(100);
|
|
1756
|
+
molecules = /* @__PURE__ */ new Map();
|
|
1757
|
+
moleculeJoins = new Junction(
|
|
1758
|
+
{
|
|
1759
|
+
between: [`moleculeKey`, `joinKey`],
|
|
1760
|
+
cardinality: `n:n`
|
|
1761
|
+
},
|
|
1762
|
+
{
|
|
1763
|
+
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
1764
|
+
}
|
|
1765
|
+
);
|
|
1766
|
+
moleculeGraph = new Junction(
|
|
1767
|
+
{
|
|
1768
|
+
between: [`upstreamMoleculeKey`, `downstreamMoleculeKey`],
|
|
1769
|
+
cardinality: `n:n`
|
|
1770
|
+
},
|
|
1771
|
+
{
|
|
1772
|
+
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
1773
|
+
}
|
|
1774
|
+
);
|
|
1775
|
+
moleculeData = new Junction(
|
|
1776
|
+
{
|
|
1777
|
+
between: [`moleculeKey`, `stateFamilyKey`],
|
|
1778
|
+
cardinality: `n:n`
|
|
1779
|
+
},
|
|
1780
|
+
{
|
|
1781
|
+
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
1782
|
+
}
|
|
1783
|
+
);
|
|
1784
|
+
miscResources = /* @__PURE__ */ new Map();
|
|
1785
|
+
on = {
|
|
1786
|
+
atomCreation: new Subject(),
|
|
1787
|
+
atomDisposal: new Subject(),
|
|
1788
|
+
selectorCreation: new Subject(),
|
|
1789
|
+
selectorDisposal: new Subject(),
|
|
1790
|
+
timelineCreation: new Subject(),
|
|
1791
|
+
transactionCreation: new Subject(),
|
|
1792
|
+
transactionApplying: new StatefulSubject(
|
|
1793
|
+
null
|
|
1794
|
+
),
|
|
1795
|
+
operationClose: new Subject(),
|
|
1796
|
+
moleculeCreation: new Subject(),
|
|
1797
|
+
moleculeDisposal: new Subject()
|
|
1798
|
+
};
|
|
1799
|
+
operation = { open: false };
|
|
1800
|
+
config = {
|
|
1801
|
+
name: `IMPLICIT_STORE`,
|
|
1802
|
+
lifespan: `ephemeral`
|
|
1803
|
+
};
|
|
1804
|
+
loggers = [
|
|
1805
|
+
new AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F50D}`))
|
|
1806
|
+
];
|
|
1807
|
+
logger = {
|
|
1808
|
+
error: (...messages) => {
|
|
1809
|
+
for (const logger of this.loggers) logger.error(...messages);
|
|
1810
|
+
},
|
|
1811
|
+
info: (...messages) => {
|
|
1812
|
+
for (const logger of this.loggers) logger.info(...messages);
|
|
1813
|
+
},
|
|
1814
|
+
warn: (...messages) => {
|
|
1815
|
+
for (const logger of this.loggers) logger.warn(...messages);
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
constructor(config, store = null) {
|
|
1819
|
+
this.config = {
|
|
1820
|
+
...store?.config,
|
|
1821
|
+
...config
|
|
1822
|
+
};
|
|
1823
|
+
if (store !== null) {
|
|
1824
|
+
this.valueMap = new Map(store?.valueMap);
|
|
1825
|
+
this.operation = { ...store?.operation };
|
|
1826
|
+
if (isRootStore(store)) {
|
|
1827
|
+
this.transactionMeta = {
|
|
1828
|
+
epoch: new Map(store?.transactionMeta.epoch),
|
|
1829
|
+
actionContinuities: new Junction(
|
|
1830
|
+
store?.transactionMeta.actionContinuities.toJSON()
|
|
1831
|
+
)
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
for (const [, family] of store.families) {
|
|
1835
|
+
if (family.internalRoles?.includes(`mutable`) || family.internalRoles?.includes(`join`)) {
|
|
1836
|
+
continue;
|
|
1837
|
+
}
|
|
1838
|
+
family.install(this);
|
|
1839
|
+
}
|
|
1840
|
+
const mutableHelpers = /* @__PURE__ */ new Set();
|
|
1841
|
+
for (const [, atom2] of store.atoms) {
|
|
1842
|
+
if (mutableHelpers.has(atom2.key)) {
|
|
1843
|
+
continue;
|
|
1844
|
+
}
|
|
1845
|
+
atom2.install(this);
|
|
1846
|
+
if (atom2.type === `mutable_atom`) {
|
|
1847
|
+
const originalJsonToken = getJsonToken(store, atom2);
|
|
1848
|
+
const originalUpdateToken = getUpdateToken(atom2);
|
|
1849
|
+
mutableHelpers.add(originalJsonToken.key);
|
|
1850
|
+
mutableHelpers.add(originalUpdateToken.key);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
for (const [, selector] of store.readonlySelectors) {
|
|
1854
|
+
selector.install(this);
|
|
1855
|
+
}
|
|
1856
|
+
for (const [, selector] of store.selectors) {
|
|
1857
|
+
if (mutableHelpers.has(selector.key)) {
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
selector.install(this);
|
|
1861
|
+
}
|
|
1862
|
+
for (const [, tx] of store.transactions) {
|
|
1863
|
+
tx.install(this);
|
|
1864
|
+
}
|
|
1865
|
+
for (const [, timeline] of store.timelines) {
|
|
1866
|
+
timeline.install(this);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
};
|
|
1871
|
+
var IMPLICIT = {
|
|
1872
|
+
get STORE() {
|
|
1873
|
+
if (!globalThis.ATOM_IO_IMPLICIT_STORE) {
|
|
1874
|
+
globalThis.ATOM_IO_IMPLICIT_STORE = new Store({
|
|
1875
|
+
name: `IMPLICIT_STORE`,
|
|
1876
|
+
lifespan: `ephemeral`
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
return globalThis.ATOM_IO_IMPLICIT_STORE;
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1883
|
+
// ../atom.io/internal/src/store/withdraw.ts
|
|
1884
|
+
function withdraw(token, store) {
|
|
1885
|
+
let withdrawn;
|
|
1886
|
+
let target = store;
|
|
1887
|
+
while (target !== null) {
|
|
1888
|
+
switch (token.type) {
|
|
1889
|
+
case `atom`:
|
|
1890
|
+
case `mutable_atom`:
|
|
1891
|
+
withdrawn = target.atoms.get(token.key);
|
|
1892
|
+
break;
|
|
1893
|
+
case `selector`:
|
|
1894
|
+
withdrawn = target.selectors.get(token.key);
|
|
1895
|
+
break;
|
|
1896
|
+
case `readonly_selector`:
|
|
1897
|
+
withdrawn = target.readonlySelectors.get(token.key);
|
|
1898
|
+
break;
|
|
1899
|
+
case `atom_family`:
|
|
1900
|
+
case `mutable_atom_family`:
|
|
1901
|
+
case `selector_family`:
|
|
1902
|
+
case `readonly_selector_family`:
|
|
1903
|
+
withdrawn = target.families.get(token.key);
|
|
1904
|
+
break;
|
|
1905
|
+
case `timeline`:
|
|
1906
|
+
withdrawn = target.timelines.get(token.key);
|
|
1907
|
+
break;
|
|
1908
|
+
case `transaction`:
|
|
1909
|
+
withdrawn = target.transactions.get(token.key);
|
|
1910
|
+
break;
|
|
1911
|
+
}
|
|
1912
|
+
if (withdrawn) {
|
|
1913
|
+
return withdrawn;
|
|
1914
|
+
}
|
|
1915
|
+
target = target.child;
|
|
1916
|
+
}
|
|
1917
|
+
throw new NotFoundError(token, store);
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
// ../atom.io/internal/src/families/init-family-member.ts
|
|
1921
|
+
function initFamilyMemberInStore(store, token, key) {
|
|
1922
|
+
const family = store.families.get(token.key);
|
|
1923
|
+
if (family === undefined) {
|
|
1924
|
+
throw new NotFoundError(token, store);
|
|
1925
|
+
}
|
|
1926
|
+
const state = family(key);
|
|
1927
|
+
const target = newest(store);
|
|
1928
|
+
if (state.family) {
|
|
1929
|
+
if (isRootStore(target)) {
|
|
1930
|
+
switch (state.type) {
|
|
1931
|
+
case `atom`:
|
|
1932
|
+
case `mutable_atom`:
|
|
1933
|
+
store.on.atomCreation.next(state);
|
|
1934
|
+
break;
|
|
1935
|
+
case `selector`:
|
|
1936
|
+
case `readonly_selector`:
|
|
1937
|
+
store.on.selectorCreation.next(state);
|
|
1938
|
+
break;
|
|
1939
|
+
}
|
|
1940
|
+
} else if (isChildStore(target) && target.on.transactionApplying.state === null) {
|
|
1941
|
+
target.transactionMeta.update.updates.push({
|
|
1942
|
+
type: `state_creation`,
|
|
1943
|
+
token: state
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return state;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
// ../atom.io/internal/src/families/seek-in-store.ts
|
|
1951
|
+
function seekInStore(store, token, key) {
|
|
1952
|
+
const subKey = stringifyJson(key);
|
|
1953
|
+
const fullKey = `${token.key}(${subKey})`;
|
|
1954
|
+
const target = newest(store);
|
|
1955
|
+
let state;
|
|
1956
|
+
switch (token.type) {
|
|
1957
|
+
case `atom_family`:
|
|
1958
|
+
case `mutable_atom_family`:
|
|
1959
|
+
state = target.atoms.get(fullKey);
|
|
1960
|
+
break;
|
|
1961
|
+
case `selector_family`:
|
|
1962
|
+
state = target.selectors.get(fullKey);
|
|
1963
|
+
break;
|
|
1964
|
+
case `readonly_selector_family`:
|
|
1965
|
+
state = target.readonlySelectors.get(fullKey);
|
|
1966
|
+
break;
|
|
1967
|
+
}
|
|
1968
|
+
if (state) {
|
|
1969
|
+
return deposit(state);
|
|
1970
|
+
}
|
|
1971
|
+
return state;
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// ../atom.io/internal/src/families/find-in-store.ts
|
|
1975
|
+
function findInStore(store, token, key) {
|
|
1976
|
+
let state = seekInStore(store, token, key);
|
|
1977
|
+
if (state) {
|
|
1978
|
+
return state;
|
|
1979
|
+
}
|
|
1980
|
+
const stringKey = stringifyJson(key);
|
|
1981
|
+
const molecule = store.molecules.get(stringKey);
|
|
1982
|
+
if (!molecule && store.config.lifespan === `immortal`) {
|
|
1983
|
+
const fakeToken = counterfeit(token, key);
|
|
1984
|
+
store.logger.error(
|
|
1985
|
+
`\u274C`,
|
|
1986
|
+
fakeToken.type,
|
|
1987
|
+
fakeToken.key,
|
|
1988
|
+
`was not found in store "${store.config.name}"; returned a counterfeit token.`
|
|
1989
|
+
);
|
|
1990
|
+
return fakeToken;
|
|
1991
|
+
}
|
|
1992
|
+
state = initFamilyMemberInStore(store, token, key);
|
|
1993
|
+
if (molecule) {
|
|
1994
|
+
const target = newest(store);
|
|
1995
|
+
target.moleculeData.set(stringKey, token.key);
|
|
1996
|
+
}
|
|
1997
|
+
return state;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
// ../atom.io/internal/src/families/dispose-from-store.ts
|
|
2001
|
+
function disposeFromStore(store, ...params) {
|
|
2002
|
+
let token;
|
|
2003
|
+
if (params.length === 1) {
|
|
2004
|
+
token = params[0];
|
|
2005
|
+
} else {
|
|
2006
|
+
const family = params[0];
|
|
2007
|
+
const key = params[1];
|
|
2008
|
+
const maybeToken = findInStore(store, family, key);
|
|
2009
|
+
token = maybeToken;
|
|
2010
|
+
}
|
|
2011
|
+
try {
|
|
2012
|
+
withdraw(token, store);
|
|
2013
|
+
} catch (thrown) {
|
|
2014
|
+
store.logger.error(
|
|
2015
|
+
`\u274C`,
|
|
2016
|
+
token.type,
|
|
2017
|
+
token.key,
|
|
2018
|
+
`could not be disposed because it was not found in the store "${store.config.name}".`
|
|
2019
|
+
// disposal
|
|
2020
|
+
// ? `\n This state was most recently disposed\n${disposal.trace}`
|
|
2021
|
+
// : `No previous disposal trace was found.`,
|
|
2022
|
+
);
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
switch (token.type) {
|
|
2026
|
+
case `atom`:
|
|
2027
|
+
case `mutable_atom`:
|
|
2028
|
+
disposeAtom(token, store);
|
|
2029
|
+
break;
|
|
2030
|
+
case `selector`:
|
|
2031
|
+
case `readonly_selector`:
|
|
2032
|
+
disposeSelector(token, store);
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
// ../atom.io/internal/src/keys.ts
|
|
2038
|
+
var isAtomKey = (key, store) => newest(store).atoms.has(key);
|
|
2039
|
+
var isSelectorKey = (key, store) => newest(store).selectors.has(key);
|
|
2040
|
+
var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
|
|
2041
|
+
var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
|
|
2042
|
+
|
|
2043
|
+
// ../atom.io/internal/src/selector/get-selector-dependency-keys.ts
|
|
2044
|
+
var getSelectorDependencyKeys = (key, store) => {
|
|
2045
|
+
const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
|
|
2046
|
+
return sources;
|
|
2047
|
+
};
|
|
2048
|
+
|
|
2049
|
+
// ../atom.io/internal/src/selector/trace-selector-atoms.ts
|
|
2050
|
+
var traceSelectorAtoms = (directDependencyKey, covered, store) => {
|
|
2051
|
+
const rootKeys = [];
|
|
2052
|
+
const indirectDependencyKeys = getSelectorDependencyKeys(
|
|
2053
|
+
directDependencyKey,
|
|
2054
|
+
store
|
|
2055
|
+
);
|
|
2056
|
+
while (indirectDependencyKeys.length > 0) {
|
|
2057
|
+
const indirectDependencyKey = indirectDependencyKeys.shift();
|
|
2058
|
+
if (covered.has(indirectDependencyKey)) {
|
|
2059
|
+
continue;
|
|
2060
|
+
}
|
|
2061
|
+
covered.add(indirectDependencyKey);
|
|
2062
|
+
if (!isAtomKey(indirectDependencyKey, store)) {
|
|
2063
|
+
indirectDependencyKeys.push(
|
|
2064
|
+
...getSelectorDependencyKeys(indirectDependencyKey, store)
|
|
2065
|
+
);
|
|
2066
|
+
} else if (!rootKeys.includes(indirectDependencyKey)) {
|
|
2067
|
+
rootKeys.push(indirectDependencyKey);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
return rootKeys;
|
|
2071
|
+
};
|
|
2072
|
+
var traceAllSelectorAtoms = (selector, store) => {
|
|
2073
|
+
const selectorKey = selector.key;
|
|
2074
|
+
const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
|
|
2075
|
+
const covered = /* @__PURE__ */ new Set();
|
|
2076
|
+
return directDependencyKeys.flatMap(
|
|
2077
|
+
(depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(depKey, covered, store)
|
|
2078
|
+
);
|
|
2079
|
+
};
|
|
2080
|
+
|
|
2081
|
+
// ../atom.io/internal/src/selector/update-selector-atoms.ts
|
|
2082
|
+
var updateSelectorAtoms = (selectorKey, dependency, covered, store) => {
|
|
2083
|
+
const target = newest(store);
|
|
2084
|
+
if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
|
|
2085
|
+
target.selectorAtoms.set({
|
|
2086
|
+
selectorKey,
|
|
2087
|
+
atomKey: dependency.key
|
|
2088
|
+
});
|
|
2089
|
+
store.logger.info(
|
|
2090
|
+
`\u{1F50D}`,
|
|
2091
|
+
`selector`,
|
|
2092
|
+
selectorKey,
|
|
2093
|
+
`discovers root atom "${dependency.key}"`
|
|
2094
|
+
);
|
|
2095
|
+
} else {
|
|
2096
|
+
const rootKeys = traceSelectorAtoms(dependency.key, covered, store);
|
|
2097
|
+
store.logger.info(
|
|
2098
|
+
`\u{1F50D}`,
|
|
2099
|
+
`selector`,
|
|
2100
|
+
selectorKey,
|
|
2101
|
+
`discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
|
|
2102
|
+
);
|
|
2103
|
+
for (const atomKey of rootKeys) {
|
|
2104
|
+
target.selectorAtoms = target.selectorAtoms.set({
|
|
2105
|
+
selectorKey,
|
|
2106
|
+
atomKey
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
covered.add(dependency.key);
|
|
2111
|
+
};
|
|
2112
|
+
|
|
2113
|
+
// ../atom.io/internal/src/selector/register-selector.ts
|
|
2114
|
+
var registerSelector = (selectorKey, covered, store) => ({
|
|
2115
|
+
get: (...params) => {
|
|
2116
|
+
const target = newest(store);
|
|
2117
|
+
let dependency;
|
|
2118
|
+
if (params.length === 2) {
|
|
2119
|
+
const [family, key] = params;
|
|
2120
|
+
dependency = findInStore(store, family, key);
|
|
2121
|
+
} else {
|
|
2122
|
+
[dependency] = params;
|
|
2123
|
+
}
|
|
2124
|
+
const dependencyState = withdraw(dependency, store);
|
|
2125
|
+
const dependencyValue = readOrComputeValue(dependencyState, store);
|
|
2126
|
+
store.logger.info(
|
|
2127
|
+
`\u{1F50C}`,
|
|
2128
|
+
`selector`,
|
|
2129
|
+
selectorKey,
|
|
2130
|
+
`registers dependency ( "${dependency.key}" =`,
|
|
2131
|
+
dependencyValue,
|
|
2132
|
+
`)`
|
|
2133
|
+
);
|
|
2134
|
+
target.selectorGraph.set(
|
|
2135
|
+
{
|
|
2136
|
+
upstreamSelectorKey: dependency.key,
|
|
2137
|
+
downstreamSelectorKey: selectorKey
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
source: dependency.key
|
|
2141
|
+
}
|
|
2142
|
+
);
|
|
2143
|
+
updateSelectorAtoms(selectorKey, dependency, covered, store);
|
|
2144
|
+
return dependencyValue;
|
|
2145
|
+
},
|
|
2146
|
+
set: (...params) => {
|
|
2147
|
+
let token;
|
|
2148
|
+
let value;
|
|
2149
|
+
if (params.length === 2) {
|
|
2150
|
+
token = params[0];
|
|
2151
|
+
value = params[1];
|
|
2152
|
+
} else {
|
|
2153
|
+
const family = params[0];
|
|
2154
|
+
const key = params[1];
|
|
2155
|
+
value = params[2];
|
|
2156
|
+
const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(store, family, key) : seekInStore(store, family, key);
|
|
2157
|
+
if (!maybeToken) {
|
|
2158
|
+
throw new NotFoundError(family, key, store);
|
|
2159
|
+
}
|
|
2160
|
+
token = maybeToken;
|
|
2161
|
+
}
|
|
2162
|
+
const target = newest(store);
|
|
2163
|
+
const state = withdraw(token, target);
|
|
2164
|
+
setAtomOrSelector(state, value, target);
|
|
2165
|
+
},
|
|
2166
|
+
find: (token, key) => findInStore(store, token, key),
|
|
2167
|
+
seek: (token, key) => seekInStore(store, token, key),
|
|
2168
|
+
json: (token) => getJsonToken(store, token)
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
// ../atom.io/internal/src/selector/create-readonly-selector.ts
|
|
2172
|
+
var createReadonlySelector = (store, options, family) => {
|
|
2173
|
+
const target = newest(store);
|
|
2174
|
+
const subject = new Subject();
|
|
2175
|
+
const covered = /* @__PURE__ */ new Set();
|
|
2176
|
+
const { get, find, seek, json } = registerSelector(
|
|
2177
|
+
options.key,
|
|
2178
|
+
covered,
|
|
2179
|
+
target
|
|
2180
|
+
);
|
|
2181
|
+
const getSelf = () => {
|
|
2182
|
+
const value = options.get({ get, find, seek, json });
|
|
2183
|
+
cacheValue(options.key, value, subject, newest(store));
|
|
2184
|
+
covered.clear();
|
|
2185
|
+
return value;
|
|
2186
|
+
};
|
|
2187
|
+
const readonlySelector = {
|
|
2188
|
+
...options,
|
|
2189
|
+
subject,
|
|
2190
|
+
install: (s) => createReadonlySelector(s, options, family),
|
|
2191
|
+
get: getSelf,
|
|
2192
|
+
type: `readonly_selector`,
|
|
2193
|
+
...family && { family }
|
|
2194
|
+
};
|
|
2195
|
+
target.readonlySelectors.set(options.key, readonlySelector);
|
|
2196
|
+
const initialValue = getSelf();
|
|
2197
|
+
store.logger.info(
|
|
2198
|
+
`\u2728`,
|
|
2199
|
+
readonlySelector.type,
|
|
2200
|
+
readonlySelector.key,
|
|
2201
|
+
`=`,
|
|
2202
|
+
initialValue
|
|
2203
|
+
);
|
|
2204
|
+
const token = {
|
|
2205
|
+
key: options.key,
|
|
2206
|
+
type: `readonly_selector`
|
|
2207
|
+
};
|
|
2208
|
+
if (family) {
|
|
2209
|
+
token.family = family;
|
|
2210
|
+
}
|
|
2211
|
+
return token;
|
|
2212
|
+
};
|
|
2213
|
+
|
|
2214
|
+
// ../atom.io/internal/src/selector/create-writable-selector.ts
|
|
2215
|
+
var createWritableSelector = (store, options, family) => {
|
|
2216
|
+
const target = newest(store);
|
|
2217
|
+
const subject = new Subject();
|
|
2218
|
+
const covered = /* @__PURE__ */ new Set();
|
|
2219
|
+
const setterToolkit = registerSelector(options.key, covered, target);
|
|
2220
|
+
const { find, get, seek, json } = setterToolkit;
|
|
2221
|
+
const getterToolkit = { find, get, seek, json };
|
|
2222
|
+
const getSelf = (getFn = options.get, innerTarget = newest(store)) => {
|
|
2223
|
+
const value = getFn(getterToolkit);
|
|
2224
|
+
cacheValue(options.key, value, subject, innerTarget);
|
|
2225
|
+
covered.clear();
|
|
2226
|
+
return value;
|
|
2227
|
+
};
|
|
2228
|
+
const setSelf = (next) => {
|
|
2229
|
+
const innerTarget = newest(store);
|
|
2230
|
+
const oldValue = getSelf(options.get, innerTarget);
|
|
2231
|
+
const newValue = become(next)(oldValue);
|
|
2232
|
+
store.logger.info(
|
|
2233
|
+
`\u{1F4DD}`,
|
|
2234
|
+
`selector`,
|
|
2235
|
+
options.key,
|
|
2236
|
+
`set (`,
|
|
2237
|
+
oldValue,
|
|
2238
|
+
`->`,
|
|
2239
|
+
newValue,
|
|
2240
|
+
`)`
|
|
2241
|
+
);
|
|
2242
|
+
cacheValue(options.key, newValue, subject, innerTarget);
|
|
2243
|
+
markDone(innerTarget, options.key);
|
|
2244
|
+
if (isRootStore(innerTarget)) {
|
|
2245
|
+
subject.next({ newValue, oldValue });
|
|
2246
|
+
}
|
|
2247
|
+
options.set(setterToolkit, newValue);
|
|
2248
|
+
};
|
|
2249
|
+
const mySelector = {
|
|
2250
|
+
...options,
|
|
2251
|
+
subject,
|
|
2252
|
+
install: (s) => createWritableSelector(s, options, family),
|
|
2253
|
+
get: getSelf,
|
|
2254
|
+
set: setSelf,
|
|
2255
|
+
type: `selector`,
|
|
2256
|
+
...family && { family }
|
|
2257
|
+
};
|
|
2258
|
+
target.selectors.set(options.key, mySelector);
|
|
2259
|
+
const initialValue = getSelf();
|
|
2260
|
+
store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
|
|
2261
|
+
const token = {
|
|
2262
|
+
key: options.key,
|
|
2263
|
+
type: `selector`
|
|
2264
|
+
};
|
|
2265
|
+
if (family) {
|
|
2266
|
+
token.family = family;
|
|
2267
|
+
}
|
|
2268
|
+
return token;
|
|
2269
|
+
};
|
|
2270
|
+
|
|
2271
|
+
// ../atom.io/internal/src/selector/create-standalone-selector.ts
|
|
2272
|
+
function createStandaloneSelector(store, options) {
|
|
2273
|
+
const isWritable = `set` in options;
|
|
2274
|
+
if (isWritable) {
|
|
2275
|
+
const state2 = createWritableSelector(store, options, undefined);
|
|
2276
|
+
store.on.selectorCreation.next(state2);
|
|
2277
|
+
return state2;
|
|
2278
|
+
}
|
|
2279
|
+
const state = createReadonlySelector(store, options, undefined);
|
|
2280
|
+
store.on.selectorCreation.next(state);
|
|
2281
|
+
return state;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// ../atom.io/internal/src/selector/dispose-selector.ts
|
|
2285
|
+
function disposeSelector(selectorToken, store) {
|
|
2286
|
+
const target = newest(store);
|
|
2287
|
+
const { key } = selectorToken;
|
|
2288
|
+
const selector = withdraw(selectorToken, target);
|
|
2289
|
+
if (!selector.family) {
|
|
2290
|
+
store.logger.error(
|
|
2291
|
+
`\u274C`,
|
|
2292
|
+
`selector`,
|
|
2293
|
+
key,
|
|
2294
|
+
`Standalone selectors cannot be disposed.`
|
|
2295
|
+
);
|
|
2296
|
+
} else {
|
|
2297
|
+
const molecule = target.molecules.get(selector.family.subKey);
|
|
2298
|
+
if (molecule) {
|
|
2299
|
+
target.moleculeData.delete(selector.family.subKey, selector.family.key);
|
|
2300
|
+
}
|
|
2301
|
+
switch (selectorToken.type) {
|
|
2302
|
+
case `selector`:
|
|
2303
|
+
{
|
|
2304
|
+
target.selectors.delete(key);
|
|
2305
|
+
withdraw(
|
|
2306
|
+
{ key: selector.family.key, type: `selector_family` },
|
|
2307
|
+
store
|
|
2308
|
+
);
|
|
2309
|
+
}
|
|
2310
|
+
break;
|
|
2311
|
+
case `readonly_selector`:
|
|
2312
|
+
{
|
|
2313
|
+
target.readonlySelectors.delete(key);
|
|
2314
|
+
const family = withdraw(
|
|
2315
|
+
{ key: selector.family.key, type: `readonly_selector_family` },
|
|
2316
|
+
store
|
|
2317
|
+
);
|
|
2318
|
+
family.subject.next({
|
|
2319
|
+
type: `state_disposal`,
|
|
2320
|
+
subType: `selector`,
|
|
2321
|
+
token: selectorToken
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
break;
|
|
2325
|
+
}
|
|
2326
|
+
target.valueMap.delete(key);
|
|
2327
|
+
target.selectorAtoms.delete(key);
|
|
2328
|
+
target.selectorGraph.delete(key);
|
|
2329
|
+
store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
|
|
2330
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`) {
|
|
2331
|
+
target.transactionMeta.update.updates.push({
|
|
2332
|
+
type: `state_disposal`,
|
|
2333
|
+
subType: `selector`,
|
|
2334
|
+
token: selectorToken
|
|
2335
|
+
});
|
|
2336
|
+
} else {
|
|
2337
|
+
store.on.selectorDisposal.next(selectorToken);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
// ../atom.io/internal/src/families/create-writable-selector-family.ts
|
|
2343
|
+
function createWritableSelectorFamily(store, options, internalRoles) {
|
|
2344
|
+
const familyToken = {
|
|
2345
|
+
key: options.key,
|
|
2346
|
+
type: `selector_family`
|
|
2347
|
+
};
|
|
2348
|
+
const existing = store.families.get(options.key);
|
|
2349
|
+
if (existing) {
|
|
2350
|
+
store.logger.error(
|
|
2351
|
+
`\u2757`,
|
|
2352
|
+
`selector_family`,
|
|
2353
|
+
options.key,
|
|
2354
|
+
`Overwriting an existing ${prettyPrintTokenType(
|
|
2355
|
+
existing
|
|
2356
|
+
)} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
const subject = new Subject();
|
|
2360
|
+
const familyFunction = (key) => {
|
|
2361
|
+
const subKey = stringifyJson(key);
|
|
2362
|
+
const family = { key: options.key, subKey };
|
|
2363
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
2364
|
+
const target = newest(store);
|
|
2365
|
+
const token = createWritableSelector(
|
|
2366
|
+
target,
|
|
2367
|
+
{
|
|
2368
|
+
key: fullKey,
|
|
2369
|
+
get: options.get(key),
|
|
2370
|
+
set: options.set(key)
|
|
2371
|
+
},
|
|
2372
|
+
family
|
|
2373
|
+
);
|
|
2374
|
+
subject.next({ type: `state_creation`, token });
|
|
2375
|
+
return token;
|
|
2376
|
+
};
|
|
2377
|
+
const selectorFamily2 = Object.assign(familyFunction, familyToken, {
|
|
2378
|
+
internalRoles,
|
|
2379
|
+
subject,
|
|
2380
|
+
install: (s) => createWritableSelectorFamily(s, options),
|
|
2381
|
+
default: (key) => {
|
|
2382
|
+
const getFn = options.get(key);
|
|
2383
|
+
return getFn({
|
|
2384
|
+
get: (...ps) => getFromStore(store, ...ps),
|
|
2385
|
+
find: (token, k) => findInStore(store, token, k),
|
|
2386
|
+
seek: (token, k) => seekInStore(store, token, k),
|
|
2387
|
+
json: (token) => getJsonToken(store, token)
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
store.families.set(options.key, selectorFamily2);
|
|
2392
|
+
return familyToken;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
// ../atom.io/json/src/select-json-family.ts
|
|
2396
|
+
function selectJsonFamily(atomFamilyToken, transform, store = IMPLICIT.STORE) {
|
|
2397
|
+
const jsonFamily = createWritableSelectorFamily(
|
|
2398
|
+
store,
|
|
2399
|
+
{
|
|
2400
|
+
key: `${atomFamilyToken.key}:JSON`,
|
|
2401
|
+
get: (key) => ({ get }) => {
|
|
2402
|
+
const baseState = get(atomFamilyToken, key);
|
|
2403
|
+
return transform.toJson(baseState);
|
|
2404
|
+
},
|
|
2405
|
+
set: (key) => ({ set }, newValue) => {
|
|
2406
|
+
set(atomFamilyToken, key, transform.fromJson(newValue));
|
|
2407
|
+
}
|
|
2408
|
+
},
|
|
2409
|
+
[`mutable`, `json`]
|
|
2410
|
+
);
|
|
2411
|
+
const atomFamily2 = withdraw(atomFamilyToken, store);
|
|
2412
|
+
atomFamily2.subject.subscribe(
|
|
2413
|
+
`store=${store.config.name}::json-selector-family`,
|
|
2414
|
+
(event) => {
|
|
2415
|
+
if (event.token.family) {
|
|
2416
|
+
seekInStore(store, jsonFamily, parseJson(event.token.family.subKey));
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
);
|
|
2420
|
+
return jsonFamily;
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
// ../atom.io/json/src/index.ts
|
|
2424
|
+
var parseJson = (str) => JSON.parse(str);
|
|
2425
|
+
var stringifyJson = (json) => JSON.stringify(json);
|
|
2426
|
+
|
|
2427
|
+
// ../atom.io/internal/src/subscribe/recall-state.ts
|
|
2428
|
+
var recallState = (state, store) => {
|
|
2429
|
+
const target = newest(store);
|
|
2430
|
+
if (target.operation.open) {
|
|
2431
|
+
return target.operation.prev.get(state.key);
|
|
2432
|
+
}
|
|
2433
|
+
return target.valueMap.get(state.key);
|
|
2434
|
+
};
|
|
2435
|
+
|
|
2436
|
+
// ../atom.io/internal/src/subscribe/subscribe-to-root-atoms.ts
|
|
2437
|
+
var subscribeToRootAtoms = (selector, store) => {
|
|
2438
|
+
const target = newest(store);
|
|
2439
|
+
const dependencySubscriptions = traceAllSelectorAtoms(selector, store).map(
|
|
2440
|
+
(atomKey) => {
|
|
2441
|
+
const atom2 = target.atoms.get(atomKey);
|
|
2442
|
+
if (atom2 === undefined) {
|
|
2443
|
+
throw new Error(
|
|
2444
|
+
`Atom "${atomKey}", a dependency of selector "${selector.key}", not found in store "${store.config.name}".`
|
|
2445
|
+
);
|
|
2446
|
+
}
|
|
2447
|
+
return atom2.subject.subscribe(
|
|
2448
|
+
`${selector.type}:${selector.key}`,
|
|
2449
|
+
(atomChange) => {
|
|
2450
|
+
store.logger.info(
|
|
2451
|
+
`\u{1F4E2}`,
|
|
2452
|
+
selector.type,
|
|
2453
|
+
selector.key,
|
|
2454
|
+
`root`,
|
|
2455
|
+
atomKey,
|
|
2456
|
+
`went`,
|
|
2457
|
+
atomChange.oldValue,
|
|
2458
|
+
`->`,
|
|
2459
|
+
atomChange.newValue
|
|
2460
|
+
);
|
|
2461
|
+
const oldValue = recallState(selector, target);
|
|
2462
|
+
const newValue = readOrComputeValue(selector, target);
|
|
2463
|
+
store.logger.info(
|
|
2464
|
+
`\u2728`,
|
|
2465
|
+
selector.type,
|
|
2466
|
+
selector.key,
|
|
2467
|
+
`went`,
|
|
2468
|
+
oldValue,
|
|
2469
|
+
`->`,
|
|
2470
|
+
newValue
|
|
2471
|
+
);
|
|
2472
|
+
selector.subject.next({ newValue, oldValue });
|
|
2473
|
+
}
|
|
2474
|
+
);
|
|
2475
|
+
}
|
|
2476
|
+
);
|
|
2477
|
+
return dependencySubscriptions;
|
|
2478
|
+
};
|
|
2479
|
+
|
|
2480
|
+
// ../atom.io/internal/src/subscribe/subscribe-to-state.ts
|
|
2481
|
+
function subscribeToState(token, handleUpdate, key, store) {
|
|
2482
|
+
function safelyHandleUpdate(update) {
|
|
2483
|
+
if (store.operation.open) {
|
|
2484
|
+
const unsubscribe2 = store.on.operationClose.subscribe(
|
|
2485
|
+
`state subscription ${key}`,
|
|
2486
|
+
() => {
|
|
2487
|
+
unsubscribe2();
|
|
2488
|
+
handleUpdate(update);
|
|
2489
|
+
}
|
|
2490
|
+
);
|
|
2491
|
+
} else {
|
|
2492
|
+
handleUpdate(update);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
const state = withdraw(token, store);
|
|
2496
|
+
store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
|
|
2497
|
+
const isSelector = state.type === `selector` || state.type === `readonly_selector`;
|
|
2498
|
+
let dependencyUnsubFunctions = null;
|
|
2499
|
+
let updateHandler = safelyHandleUpdate;
|
|
2500
|
+
if (isSelector) {
|
|
2501
|
+
dependencyUnsubFunctions = subscribeToRootAtoms(state, store);
|
|
2502
|
+
updateHandler = (update) => {
|
|
2503
|
+
if (dependencyUnsubFunctions) {
|
|
2504
|
+
dependencyUnsubFunctions.length = 0;
|
|
2505
|
+
dependencyUnsubFunctions.push(...subscribeToRootAtoms(state, store));
|
|
2506
|
+
}
|
|
2507
|
+
safelyHandleUpdate(update);
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
|
|
2511
|
+
const unsubscribe = () => {
|
|
2512
|
+
store.logger.info(
|
|
2513
|
+
`\u{1F648}`,
|
|
2514
|
+
state.type,
|
|
2515
|
+
state.key,
|
|
2516
|
+
`Removing subscription "${key}"`
|
|
2517
|
+
);
|
|
2518
|
+
mainUnsubFunction();
|
|
2519
|
+
if (dependencyUnsubFunctions) {
|
|
2520
|
+
for (const unsubFromDependency of dependencyUnsubFunctions) {
|
|
2521
|
+
unsubFromDependency();
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
return unsubscribe;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
// ../atom.io/internal/src/subscribe/subscribe-to-timeline.ts
|
|
2529
|
+
var subscribeToTimeline = (token, handleUpdate, key, store) => {
|
|
2530
|
+
const tl = withdraw(token, store);
|
|
2531
|
+
store.logger.info(`\u{1F440}`, `timeline`, token.key, `Adding subscription "${key}"`);
|
|
2532
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate);
|
|
2533
|
+
return () => {
|
|
2534
|
+
store.logger.info(
|
|
2535
|
+
`\u{1F648}`,
|
|
2536
|
+
`timeline`,
|
|
2537
|
+
token.key,
|
|
2538
|
+
`Removing subscription "${key}" from timeline`
|
|
2539
|
+
);
|
|
2540
|
+
unsubscribe();
|
|
2541
|
+
};
|
|
2542
|
+
};
|
|
2543
|
+
|
|
2544
|
+
// ../atom.io/internal/src/mutable/tracker.ts
|
|
2545
|
+
var Tracker = class {
|
|
2546
|
+
Update;
|
|
2547
|
+
initializeState(mutableState, store) {
|
|
2548
|
+
const latestUpdateStateKey = `*${mutableState.key}`;
|
|
2549
|
+
store.atoms.delete(latestUpdateStateKey);
|
|
2550
|
+
store.valueMap.delete(latestUpdateStateKey);
|
|
2551
|
+
const familyMetaData = mutableState.family ? {
|
|
2552
|
+
key: `*${mutableState.family.key}`,
|
|
2553
|
+
subKey: mutableState.family.subKey
|
|
2554
|
+
} : undefined;
|
|
2555
|
+
const latestUpdateState = createRegularAtom(
|
|
2556
|
+
store,
|
|
2557
|
+
{
|
|
2558
|
+
key: latestUpdateStateKey,
|
|
2559
|
+
default: null
|
|
2560
|
+
},
|
|
2561
|
+
familyMetaData
|
|
2562
|
+
);
|
|
2563
|
+
if (store.parent?.valueMap.has(latestUpdateStateKey)) {
|
|
2564
|
+
const parentValue = store.parent.valueMap.get(latestUpdateStateKey);
|
|
2565
|
+
store.valueMap.set(latestUpdateStateKey, parentValue);
|
|
2566
|
+
}
|
|
2567
|
+
return latestUpdateState;
|
|
2568
|
+
}
|
|
2569
|
+
unsubscribeFromInnerValue;
|
|
2570
|
+
unsubscribeFromState;
|
|
2571
|
+
observeCore(mutableState, latestUpdateState, target) {
|
|
2572
|
+
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
|
|
2573
|
+
const originalInnerValue = getFromStore(target, mutableState);
|
|
2574
|
+
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
2575
|
+
subscriptionKey,
|
|
2576
|
+
(update) => {
|
|
2577
|
+
setIntoStore(target, latestUpdateState, update);
|
|
2578
|
+
}
|
|
2579
|
+
);
|
|
2580
|
+
this.unsubscribeFromState = subscribeToState(
|
|
2581
|
+
mutableState,
|
|
2582
|
+
(update) => {
|
|
2583
|
+
if (update.newValue !== update.oldValue) {
|
|
2584
|
+
this.unsubscribeFromInnerValue();
|
|
2585
|
+
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
2586
|
+
subscriptionKey,
|
|
2587
|
+
(transceiverUpdate) => {
|
|
2588
|
+
setIntoStore(target, latestUpdateState, transceiverUpdate);
|
|
2589
|
+
}
|
|
2590
|
+
);
|
|
2591
|
+
}
|
|
2592
|
+
},
|
|
2593
|
+
subscriptionKey,
|
|
2594
|
+
target
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
updateCore(mutableState, latestUpdateState, target) {
|
|
2598
|
+
const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
|
|
2599
|
+
subscribeToState(
|
|
2600
|
+
latestUpdateState,
|
|
2601
|
+
({ newValue, oldValue }) => {
|
|
2602
|
+
const timelineId = target.timelineTopics.getRelatedKey(
|
|
2603
|
+
latestUpdateState.key
|
|
2604
|
+
);
|
|
2605
|
+
if (timelineId) {
|
|
2606
|
+
const timelineData = target.timelines.get(timelineId);
|
|
2607
|
+
if (timelineData?.timeTraveling) {
|
|
2608
|
+
const unsubscribe2 = subscribeToTimeline(
|
|
2609
|
+
{ key: timelineId, type: `timeline` },
|
|
2610
|
+
(update) => {
|
|
2611
|
+
unsubscribe2();
|
|
2612
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
2613
|
+
if (update === `redo` && newValue) {
|
|
2614
|
+
transceiver.do(newValue);
|
|
2615
|
+
} else if (update === `undo` && oldValue) {
|
|
2616
|
+
transceiver.undo(oldValue);
|
|
2617
|
+
}
|
|
2618
|
+
return transceiver;
|
|
2619
|
+
});
|
|
2620
|
+
},
|
|
2621
|
+
subscriptionKey,
|
|
2622
|
+
target
|
|
2623
|
+
);
|
|
2624
|
+
return;
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
const unsubscribe = target.on.operationClose.subscribe(
|
|
2628
|
+
subscriptionKey,
|
|
2629
|
+
() => {
|
|
2630
|
+
unsubscribe();
|
|
2631
|
+
const mutable = getFromStore(target, mutableState);
|
|
2632
|
+
const updateNumber = newValue === null ? -1 : mutable.getUpdateNumber(newValue);
|
|
2633
|
+
const eventOffset = updateNumber - mutable.cacheUpdateNumber;
|
|
2634
|
+
if (newValue && eventOffset === 1) {
|
|
2635
|
+
setIntoStore(
|
|
2636
|
+
target,
|
|
2637
|
+
mutableState,
|
|
2638
|
+
(transceiver) => (transceiver.do(newValue), transceiver)
|
|
2639
|
+
);
|
|
2640
|
+
} else {
|
|
2641
|
+
target.logger.info(
|
|
2642
|
+
`\u274C`,
|
|
2643
|
+
`mutable_atom`,
|
|
2644
|
+
mutableState.key,
|
|
2645
|
+
`could not be updated. Expected update number ${mutable.cacheUpdateNumber + 1}, but got ${updateNumber}`
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
);
|
|
2650
|
+
},
|
|
2651
|
+
subscriptionKey,
|
|
2652
|
+
target
|
|
2653
|
+
);
|
|
2654
|
+
}
|
|
2655
|
+
mutableState;
|
|
2656
|
+
latestUpdateState;
|
|
2657
|
+
dispose;
|
|
2658
|
+
constructor(mutableState, store) {
|
|
2659
|
+
this.mutableState = mutableState;
|
|
2660
|
+
const target = newest(store);
|
|
2661
|
+
this.latestUpdateState = this.initializeState(mutableState, target);
|
|
2662
|
+
this.observeCore(mutableState, this.latestUpdateState, target);
|
|
2663
|
+
this.updateCore(mutableState, this.latestUpdateState, target);
|
|
2664
|
+
target.trackers.set(mutableState.key, this);
|
|
2665
|
+
this.dispose = () => {
|
|
2666
|
+
this.unsubscribeFromInnerValue();
|
|
2667
|
+
this.unsubscribeFromState();
|
|
2668
|
+
target.trackers.delete(mutableState.key);
|
|
2669
|
+
};
|
|
2670
|
+
}
|
|
2671
|
+
};
|
|
2672
|
+
|
|
2673
|
+
// ../atom.io/internal/src/mutable/create-mutable-atom.ts
|
|
2674
|
+
function createMutableAtom(store, options, family) {
|
|
2675
|
+
store.logger.info(
|
|
2676
|
+
`\u{1F528}`,
|
|
2677
|
+
`atom`,
|
|
2678
|
+
options.key,
|
|
2679
|
+
`creating in store "${store.config.name}"`
|
|
2680
|
+
);
|
|
2681
|
+
const target = newest(store);
|
|
2682
|
+
const existing = target.atoms.get(options.key);
|
|
2683
|
+
if (existing && existing.type === `mutable_atom`) {
|
|
2684
|
+
store.logger.error(
|
|
2685
|
+
`\u274C`,
|
|
2686
|
+
`atom`,
|
|
2687
|
+
options.key,
|
|
2688
|
+
`Tried to create atom, but it already exists in the store.`
|
|
2689
|
+
);
|
|
2690
|
+
return deposit(existing);
|
|
2691
|
+
}
|
|
2692
|
+
const subject = new Subject();
|
|
2693
|
+
const newAtom = {
|
|
2694
|
+
...options,
|
|
2695
|
+
type: `mutable_atom`,
|
|
2696
|
+
install: (s) => {
|
|
2697
|
+
s.logger.info(
|
|
2698
|
+
`\u{1F6E0}\uFE0F`,
|
|
2699
|
+
`atom`,
|
|
2700
|
+
options.key,
|
|
2701
|
+
`installing in store "${s.config.name}"`
|
|
2702
|
+
);
|
|
2703
|
+
return createMutableAtom(s, options, family);
|
|
2704
|
+
},
|
|
2705
|
+
subject
|
|
2706
|
+
};
|
|
2707
|
+
if (family) {
|
|
2708
|
+
newAtom.family = family;
|
|
2709
|
+
}
|
|
2710
|
+
const initialValue = options.default();
|
|
2711
|
+
target.atoms.set(newAtom.key, newAtom);
|
|
2712
|
+
markAtomAsDefault(options.key, store);
|
|
2713
|
+
cacheValue(options.key, initialValue, subject, target);
|
|
2714
|
+
const token = deposit(newAtom);
|
|
2715
|
+
if (options.effects) {
|
|
2716
|
+
let effectIndex = 0;
|
|
2717
|
+
const cleanupFunctions = [];
|
|
2718
|
+
for (const effect of options.effects) {
|
|
2719
|
+
const cleanup = effect({
|
|
2720
|
+
setSelf: (next) => {
|
|
2721
|
+
setIntoStore(store, token, next);
|
|
2722
|
+
},
|
|
2723
|
+
onSet: (handle) => subscribeToState(token, handle, `effect[${effectIndex}]`, store)
|
|
2724
|
+
});
|
|
2725
|
+
if (cleanup) {
|
|
2726
|
+
cleanupFunctions.push(cleanup);
|
|
2727
|
+
}
|
|
2728
|
+
++effectIndex;
|
|
2729
|
+
}
|
|
2730
|
+
newAtom.cleanup = () => {
|
|
2731
|
+
for (const cleanup of cleanupFunctions) {
|
|
2732
|
+
cleanup();
|
|
2733
|
+
}
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
new Tracker(token, store);
|
|
2737
|
+
if (!family) {
|
|
2738
|
+
selectJson(token, options, store);
|
|
2739
|
+
}
|
|
2740
|
+
return token;
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
// ../atom.io/internal/src/mutable/tracker-family.ts
|
|
2744
|
+
var FamilyTracker = class {
|
|
2745
|
+
Update;
|
|
2746
|
+
latestUpdateAtoms;
|
|
2747
|
+
mutableAtoms;
|
|
2748
|
+
constructor(mutableAtoms, store) {
|
|
2749
|
+
const updateAtoms = createRegularAtomFamily(
|
|
2750
|
+
store,
|
|
2751
|
+
{
|
|
2752
|
+
key: `*${mutableAtoms.key}`,
|
|
2753
|
+
default: null
|
|
2754
|
+
},
|
|
2755
|
+
[`mutable`, `updates`]
|
|
2756
|
+
);
|
|
2757
|
+
this.latestUpdateAtoms = withdraw(updateAtoms, store);
|
|
2758
|
+
this.mutableAtoms = mutableAtoms;
|
|
2759
|
+
this.mutableAtoms.subject.subscribe(
|
|
2760
|
+
`store=${store.config.name}::tracker-atom-family`,
|
|
2761
|
+
(event) => {
|
|
2762
|
+
if (event.token.family) {
|
|
2763
|
+
const key = parseJson(event.token.family.subKey);
|
|
2764
|
+
seekInStore(store, this.latestUpdateAtoms, key);
|
|
2765
|
+
new Tracker(event.token, store);
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
);
|
|
2769
|
+
this.latestUpdateAtoms.subject.subscribe(
|
|
2770
|
+
`store=${store.config.name}::tracker-atom-family`,
|
|
2771
|
+
(event) => {
|
|
2772
|
+
if (event.token.family) {
|
|
2773
|
+
const key = parseJson(event.token.family.subKey);
|
|
2774
|
+
const mutableAtomToken = seekInStore(store, this.mutableAtoms, key);
|
|
2775
|
+
if (mutableAtomToken) {
|
|
2776
|
+
new Tracker(mutableAtomToken, store);
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
);
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
|
|
2784
|
+
// ../atom.io/internal/src/mutable/create-mutable-atom-family.ts
|
|
2785
|
+
function createMutableAtomFamily(store, options, internalRoles) {
|
|
2786
|
+
const familyToken = {
|
|
2787
|
+
key: options.key,
|
|
2788
|
+
type: `mutable_atom_family`
|
|
2789
|
+
};
|
|
2790
|
+
const existing = store.families.get(options.key);
|
|
2791
|
+
if (existing) {
|
|
2792
|
+
store.logger.error(
|
|
2793
|
+
`\u2757`,
|
|
2794
|
+
`mutable_atom_family`,
|
|
2795
|
+
options.key,
|
|
2796
|
+
`Overwriting an existing ${prettyPrintTokenType(
|
|
2797
|
+
existing
|
|
2798
|
+
)} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2801
|
+
const subject = new Subject();
|
|
2802
|
+
const familyFunction = (key) => {
|
|
2803
|
+
const subKey = stringifyJson(key);
|
|
2804
|
+
const family = { key: options.key, subKey };
|
|
2805
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
2806
|
+
const target = newest(store);
|
|
2807
|
+
const individualOptions = {
|
|
2808
|
+
key: fullKey,
|
|
2809
|
+
default: () => options.default(key),
|
|
2810
|
+
toJson: options.toJson,
|
|
2811
|
+
fromJson: options.fromJson,
|
|
2812
|
+
mutable: true
|
|
2813
|
+
};
|
|
2814
|
+
if (options.effects) {
|
|
2815
|
+
individualOptions.effects = options.effects(key);
|
|
2816
|
+
}
|
|
2817
|
+
const token = createMutableAtom(target, individualOptions, family);
|
|
2818
|
+
subject.next({ type: `state_creation`, token });
|
|
2819
|
+
return token;
|
|
2820
|
+
};
|
|
2821
|
+
const atomFamily2 = Object.assign(familyFunction, familyToken, {
|
|
2822
|
+
subject,
|
|
2823
|
+
install: (s) => createMutableAtomFamily(s, options),
|
|
2824
|
+
toJson: options.toJson,
|
|
2825
|
+
fromJson: options.fromJson,
|
|
2826
|
+
internalRoles
|
|
2827
|
+
});
|
|
2828
|
+
store.families.set(options.key, atomFamily2);
|
|
2829
|
+
selectJsonFamily(atomFamily2, options, store);
|
|
2830
|
+
new FamilyTracker(atomFamily2, store);
|
|
2831
|
+
return familyToken;
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// ../atom.io/internal/src/mutable/get-json-family.ts
|
|
2835
|
+
var getJsonFamily = (mutableAtomFamily, store) => {
|
|
2836
|
+
const target = newest(store);
|
|
2837
|
+
const key = `${mutableAtomFamily.key}:JSON`;
|
|
2838
|
+
const jsonFamily = target.families.get(key);
|
|
2839
|
+
return jsonFamily;
|
|
2840
|
+
};
|
|
2841
|
+
|
|
2842
|
+
// ../atom.io/internal/src/mutable/get-json-token.ts
|
|
2843
|
+
var getJsonToken = (store, mutableAtomToken) => {
|
|
2844
|
+
if (mutableAtomToken.family) {
|
|
2845
|
+
const target = newest(store);
|
|
2846
|
+
const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
|
|
2847
|
+
const jsonFamilyToken = {
|
|
2848
|
+
key: jsonFamilyKey,
|
|
2849
|
+
type: `selector_family`
|
|
2850
|
+
};
|
|
2851
|
+
const family = withdraw(jsonFamilyToken, target);
|
|
2852
|
+
const subKey = JSON.parse(mutableAtomToken.family.subKey);
|
|
2853
|
+
const jsonToken = findInStore(store, family, subKey);
|
|
2854
|
+
return jsonToken;
|
|
2855
|
+
}
|
|
2856
|
+
const token = {
|
|
2857
|
+
type: `selector`,
|
|
2858
|
+
key: `${mutableAtomToken.key}:JSON`
|
|
2859
|
+
};
|
|
2860
|
+
return token;
|
|
2861
|
+
};
|
|
2862
|
+
|
|
2863
|
+
// ../atom.io/internal/src/mutable/get-update-token.ts
|
|
2864
|
+
var getUpdateToken = (mutableAtomToken) => {
|
|
2865
|
+
const key = `*${mutableAtomToken.key}`;
|
|
2866
|
+
const updateToken = { type: `atom`, key };
|
|
2867
|
+
if (mutableAtomToken.family) {
|
|
2868
|
+
updateToken.family = {
|
|
2869
|
+
key: `*${mutableAtomToken.family.key}`,
|
|
2870
|
+
subKey: mutableAtomToken.family.subKey
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
return updateToken;
|
|
2874
|
+
};
|
|
2875
|
+
|
|
2876
|
+
// ../atom.io/internal/src/mutable/transceiver.ts
|
|
2877
|
+
function isTransceiver(value) {
|
|
2878
|
+
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
// ../atom.io/internal/src/set-state/copy-mutable-if-needed.ts
|
|
2882
|
+
function copyMutableIfNeeded(atom2, origin, target) {
|
|
2883
|
+
const originValue = origin.valueMap.get(atom2.key);
|
|
2884
|
+
const targetValue = target.valueMap.get(atom2.key);
|
|
2885
|
+
if (originValue === targetValue) {
|
|
2886
|
+
if (originValue === undefined) {
|
|
2887
|
+
return typeof atom2.default === `function` ? atom2.default() : atom2.default;
|
|
2888
|
+
}
|
|
2889
|
+
origin.logger.info(`\u{1F4C3}`, `atom`, atom2.key, `copying`);
|
|
2890
|
+
const jsonValue = atom2.toJson(originValue);
|
|
2891
|
+
const copiedValue = atom2.fromJson(jsonValue);
|
|
2892
|
+
target.valueMap.set(atom2.key, copiedValue);
|
|
2893
|
+
new Tracker(atom2, origin);
|
|
2894
|
+
return copiedValue;
|
|
2895
|
+
}
|
|
2896
|
+
return targetValue;
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// ../atom.io/internal/src/caching.ts
|
|
2900
|
+
function cacheValue(key, value, subject, target) {
|
|
2901
|
+
const currentValue = target.valueMap.get(key);
|
|
2902
|
+
if (currentValue instanceof Future) {
|
|
2903
|
+
const future = currentValue;
|
|
2904
|
+
future.use(value);
|
|
2905
|
+
}
|
|
2906
|
+
if (value instanceof Promise) {
|
|
2907
|
+
const future = new Future(value);
|
|
2908
|
+
target.valueMap.set(key, future);
|
|
2909
|
+
future.then((resolved) => {
|
|
2910
|
+
cacheValue(key, resolved, subject, target);
|
|
2911
|
+
subject.next({ newValue: resolved, oldValue: future });
|
|
2912
|
+
}).catch((thrown) => {
|
|
2913
|
+
target.logger.error(`\u{1F4A5}`, `state`, key, `rejected:`, thrown);
|
|
2914
|
+
});
|
|
2915
|
+
return future;
|
|
2916
|
+
}
|
|
2917
|
+
target.valueMap.set(key, value);
|
|
2918
|
+
return value;
|
|
2919
|
+
}
|
|
2920
|
+
var readCachedValue = (token, target) => {
|
|
2921
|
+
let value = target.valueMap.get(token.key);
|
|
2922
|
+
if (token.type === `mutable_atom` && isChildStore(target)) {
|
|
2923
|
+
const { parent } = target;
|
|
2924
|
+
const copiedValue = copyMutableIfNeeded(token, parent, target);
|
|
2925
|
+
value = copiedValue;
|
|
2926
|
+
}
|
|
2927
|
+
return value;
|
|
2928
|
+
};
|
|
2929
|
+
var evictCachedValue = (key, target) => {
|
|
2930
|
+
const currentValue = target.valueMap.get(key);
|
|
2931
|
+
if (currentValue instanceof Future) {
|
|
2932
|
+
const future = currentValue;
|
|
2933
|
+
const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key);
|
|
2934
|
+
if (selector) {
|
|
2935
|
+
future.use(selector.get());
|
|
2936
|
+
}
|
|
2937
|
+
return;
|
|
2938
|
+
}
|
|
2939
|
+
if (target.operation.open) {
|
|
2940
|
+
target.operation.prev.set(key, currentValue);
|
|
2941
|
+
}
|
|
2942
|
+
target.valueMap.delete(key);
|
|
2943
|
+
target.logger.info(`\u{1F5D1}`, `state`, key, `evicted`);
|
|
2944
|
+
};
|
|
2945
|
+
|
|
2946
|
+
// ../atom.io/internal/src/atom/is-default.ts
|
|
2947
|
+
var isAtomDefault = (key, store) => {
|
|
2948
|
+
const core = newest(store);
|
|
2949
|
+
return core.atomsThatAreDefault.has(key);
|
|
2950
|
+
};
|
|
2951
|
+
var markAtomAsDefault = (key, store) => {
|
|
2952
|
+
const core = newest(store);
|
|
2953
|
+
core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
|
|
2954
|
+
};
|
|
2955
|
+
var markAtomAsNotDefault = (key, store) => {
|
|
2956
|
+
const core = newest(store);
|
|
2957
|
+
core.atomsThatAreDefault = new Set(newest(store).atomsThatAreDefault);
|
|
2958
|
+
core.atomsThatAreDefault.delete(key);
|
|
2959
|
+
};
|
|
2960
|
+
|
|
2961
|
+
// ../atom.io/internal/src/atom/create-regular-atom.ts
|
|
2962
|
+
function createRegularAtom(store, options, family) {
|
|
2963
|
+
store.logger.info(
|
|
2964
|
+
`\u{1F528}`,
|
|
2965
|
+
`atom`,
|
|
2966
|
+
options.key,
|
|
2967
|
+
`creating in store "${store.config.name}"`
|
|
2968
|
+
);
|
|
2969
|
+
const target = newest(store);
|
|
2970
|
+
const existing = target.atoms.get(options.key);
|
|
2971
|
+
if (existing && existing.type === `atom`) {
|
|
2972
|
+
store.logger.error(
|
|
2973
|
+
`\u274C`,
|
|
2974
|
+
`atom`,
|
|
2975
|
+
options.key,
|
|
2976
|
+
`Tried to create atom, but it already exists in the store.`
|
|
2977
|
+
);
|
|
2978
|
+
return deposit(existing);
|
|
2979
|
+
}
|
|
2980
|
+
const subject = new Subject();
|
|
2981
|
+
const newAtom = {
|
|
2982
|
+
...options,
|
|
2983
|
+
type: `atom`,
|
|
2984
|
+
install: (s) => {
|
|
2985
|
+
s.logger.info(
|
|
2986
|
+
`\u{1F6E0}\uFE0F`,
|
|
2987
|
+
`atom`,
|
|
2988
|
+
options.key,
|
|
2989
|
+
`installing in store "${s.config.name}"`
|
|
2990
|
+
);
|
|
2991
|
+
return createRegularAtom(s, options, family);
|
|
2992
|
+
},
|
|
2993
|
+
subject
|
|
2994
|
+
};
|
|
2995
|
+
if (family) {
|
|
2996
|
+
newAtom.family = family;
|
|
2997
|
+
}
|
|
2998
|
+
let initialValue = options.default;
|
|
2999
|
+
if (options.default instanceof Function) {
|
|
3000
|
+
initialValue = options.default();
|
|
3001
|
+
}
|
|
3002
|
+
target.atoms.set(newAtom.key, newAtom);
|
|
3003
|
+
markAtomAsDefault(options.key, store);
|
|
3004
|
+
cacheValue(options.key, initialValue, subject, target);
|
|
3005
|
+
const token = deposit(newAtom);
|
|
3006
|
+
if (options.effects) {
|
|
3007
|
+
let effectIndex = 0;
|
|
3008
|
+
const cleanupFunctions = [];
|
|
3009
|
+
for (const effect of options.effects) {
|
|
3010
|
+
const cleanup = effect({
|
|
3011
|
+
setSelf: (next) => {
|
|
3012
|
+
setIntoStore(store, token, next);
|
|
3013
|
+
},
|
|
3014
|
+
onSet: (handle) => subscribeToState(token, handle, `effect[${effectIndex}]`, store)
|
|
3015
|
+
});
|
|
3016
|
+
if (cleanup) {
|
|
3017
|
+
cleanupFunctions.push(cleanup);
|
|
3018
|
+
}
|
|
3019
|
+
++effectIndex;
|
|
3020
|
+
}
|
|
3021
|
+
newAtom.cleanup = () => {
|
|
3022
|
+
for (const cleanup of cleanupFunctions) {
|
|
3023
|
+
cleanup();
|
|
3024
|
+
}
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
return token;
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
// ../atom.io/internal/src/atom/create-standalone-atom.ts
|
|
3031
|
+
function createStandaloneAtom(store, options) {
|
|
3032
|
+
const isMutable = `mutable` in options;
|
|
3033
|
+
if (isMutable) {
|
|
3034
|
+
const state2 = createMutableAtom(store, options, undefined);
|
|
3035
|
+
store.on.atomCreation.next(state2);
|
|
3036
|
+
return state2;
|
|
3037
|
+
}
|
|
3038
|
+
const state = createRegularAtom(store, options, undefined);
|
|
3039
|
+
store.on.atomCreation.next(state);
|
|
3040
|
+
return state;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
// ../atom.io/internal/src/atom/dispose-atom.ts
|
|
3044
|
+
function disposeAtom(atomToken, store) {
|
|
3045
|
+
const target = newest(store);
|
|
3046
|
+
const { key, family } = atomToken;
|
|
3047
|
+
const atom2 = withdraw(atomToken, target);
|
|
3048
|
+
if (!family) {
|
|
3049
|
+
store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
|
|
3050
|
+
} else {
|
|
3051
|
+
atom2.cleanup?.();
|
|
3052
|
+
const lastValue = store.valueMap.get(atom2.key);
|
|
3053
|
+
const atomFamily2 = withdraw({ key: family.key, type: `atom_family` }, store);
|
|
3054
|
+
const disposal = {
|
|
3055
|
+
type: `state_disposal`,
|
|
3056
|
+
subType: `atom`,
|
|
3057
|
+
token: atomToken,
|
|
3058
|
+
value: lastValue
|
|
3059
|
+
};
|
|
3060
|
+
atomFamily2.subject.next(disposal);
|
|
3061
|
+
const isChild = isChildStore(target);
|
|
3062
|
+
target.atoms.delete(key);
|
|
3063
|
+
target.valueMap.delete(key);
|
|
3064
|
+
target.selectorAtoms.delete(key);
|
|
3065
|
+
target.atomsThatAreDefault.delete(key);
|
|
3066
|
+
store.timelineTopics.delete(key);
|
|
3067
|
+
if (atomToken.type === `mutable_atom`) {
|
|
3068
|
+
const updateToken = getUpdateToken(atomToken);
|
|
3069
|
+
disposeAtom(updateToken, store);
|
|
3070
|
+
store.trackers.delete(key);
|
|
3071
|
+
}
|
|
3072
|
+
store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
|
|
3073
|
+
if (isChild && target.transactionMeta.phase === `building`) {
|
|
3074
|
+
const mostRecentUpdate = target.transactionMeta.update.updates.at(-1);
|
|
3075
|
+
const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
|
|
3076
|
+
const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom2.family?.key);
|
|
3077
|
+
if (!updateAlreadyCaptured) {
|
|
3078
|
+
target.transactionMeta.update.updates.push(disposal);
|
|
3079
|
+
}
|
|
3080
|
+
} else {
|
|
3081
|
+
store.on.atomDisposal.next(atomToken);
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
// ../atom.io/internal/src/get-trace.ts
|
|
3087
|
+
function getTrace(error) {
|
|
3088
|
+
const { stack } = error;
|
|
3089
|
+
if (stack) {
|
|
3090
|
+
return `
|
|
3091
|
+
` + stack.split(`
|
|
3092
|
+
`)?.slice(1)?.join(`
|
|
3093
|
+
`);
|
|
3094
|
+
}
|
|
3095
|
+
return ``;
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
// ../atom.io/introspection/src/refinery.ts
|
|
3099
|
+
var Refinery = class {
|
|
3100
|
+
supported;
|
|
3101
|
+
constructor(supported) {
|
|
3102
|
+
this.supported = supported;
|
|
3103
|
+
}
|
|
3104
|
+
refine(input) {
|
|
3105
|
+
for (const [key, refiner] of Object.entries(this.supported)) {
|
|
3106
|
+
try {
|
|
3107
|
+
if (
|
|
3108
|
+
// @ts-expect-error that's the point
|
|
3109
|
+
refiner(input) === true && refiner !== Boolean
|
|
3110
|
+
) {
|
|
3111
|
+
return { type: key, data: input };
|
|
3112
|
+
}
|
|
3113
|
+
} catch (_) {
|
|
3114
|
+
try {
|
|
3115
|
+
if (input instanceof refiner) {
|
|
3116
|
+
return { type: key, data: input };
|
|
3117
|
+
}
|
|
3118
|
+
} catch (__) {
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
return null;
|
|
3123
|
+
}
|
|
3124
|
+
};
|
|
3125
|
+
var primitiveRefinery = new Refinery({
|
|
3126
|
+
number: (input) => typeof input === `number`,
|
|
3127
|
+
string: (input) => typeof input === `string`,
|
|
3128
|
+
boolean: (input) => typeof input === `boolean`,
|
|
3129
|
+
null: (input) => input === null
|
|
3130
|
+
});
|
|
3131
|
+
function isPlainObject(input) {
|
|
3132
|
+
if (!input) {
|
|
3133
|
+
return false;
|
|
3134
|
+
}
|
|
3135
|
+
const prototype = Object.getPrototypeOf(input);
|
|
3136
|
+
return prototype === Object.prototype;
|
|
3137
|
+
}
|
|
3138
|
+
var jsonTreeRefinery = new Refinery({
|
|
3139
|
+
object: isPlainObject,
|
|
3140
|
+
array: (input) => Array.isArray(input)
|
|
3141
|
+
});
|
|
3142
|
+
var jsonRefinery = new Refinery({
|
|
3143
|
+
...primitiveRefinery.supported,
|
|
3144
|
+
...jsonTreeRefinery.supported
|
|
3145
|
+
});
|
|
3146
|
+
var discoverType = (input) => {
|
|
3147
|
+
if (input === undefined) {
|
|
3148
|
+
return `undefined`;
|
|
3149
|
+
}
|
|
3150
|
+
const refined = jsonRefinery.refine(input);
|
|
3151
|
+
if (refined) {
|
|
3152
|
+
return refined.type;
|
|
3153
|
+
}
|
|
3154
|
+
return Object.getPrototypeOf(input).constructor.name;
|
|
3155
|
+
};
|
|
3156
|
+
|
|
3157
|
+
// ../atom.io/introspection/src/sprawl.ts
|
|
3158
|
+
var sprawl = (tree, inspector) => {
|
|
3159
|
+
const walk = (path, node) => {
|
|
3160
|
+
const inspect2 = (p, n) => {
|
|
3161
|
+
const result2 = inspector(p, n);
|
|
3162
|
+
if (result2) return result2;
|
|
3163
|
+
return null;
|
|
3164
|
+
};
|
|
3165
|
+
const result = inspect2(path, node);
|
|
3166
|
+
if (result?.jobComplete ?? result?.pathComplete) {
|
|
3167
|
+
return result;
|
|
3168
|
+
}
|
|
3169
|
+
const childEntries = Array.isArray(node) ? node.map((v, i) => [i, v]) : isPlainObject(node) ? Object.entries(node) : [];
|
|
3170
|
+
for (const [k, v] of childEntries) {
|
|
3171
|
+
const subResult = walk([...path, k], v);
|
|
3172
|
+
if (subResult?.jobComplete) {
|
|
3173
|
+
return subResult;
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
return {};
|
|
3177
|
+
};
|
|
3178
|
+
walk([], tree);
|
|
3179
|
+
};
|
|
3180
|
+
|
|
3181
|
+
// ../atom.io/introspection/src/differ.ts
|
|
3182
|
+
function diffNumber(a, b) {
|
|
3183
|
+
const sign = a < b ? `+` : `-`;
|
|
3184
|
+
return {
|
|
3185
|
+
summary: `${sign}${Math.abs(a - b)} (${a} \u2192 ${b})`
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
function diffString(a, b) {
|
|
3189
|
+
const sign = a.length < b.length ? `+` : `-`;
|
|
3190
|
+
return {
|
|
3191
|
+
summary: `${sign}${Math.abs(a.length - b.length)} ("${a}" \u2192 "${b}")`
|
|
3192
|
+
};
|
|
3193
|
+
}
|
|
3194
|
+
function diffBoolean(a, b) {
|
|
3195
|
+
return {
|
|
3196
|
+
summary: `${a} \u2192 ${b}`
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
function diffObject(a, b, recurse) {
|
|
3200
|
+
let summary = ``;
|
|
3201
|
+
const added = [];
|
|
3202
|
+
const removed = [];
|
|
3203
|
+
const changed = [];
|
|
3204
|
+
sprawl(a, (path, nodeA) => {
|
|
3205
|
+
let key;
|
|
3206
|
+
for (key of path) {
|
|
3207
|
+
const nodeB = b[key];
|
|
3208
|
+
if (nodeB === undefined) {
|
|
3209
|
+
removed.push([key, JSON.stringify(nodeA)]);
|
|
3210
|
+
} else {
|
|
3211
|
+
const delta = recurse(nodeA, nodeB);
|
|
3212
|
+
if (delta.summary !== `No Change`) {
|
|
3213
|
+
changed.push([key, delta]);
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
});
|
|
3218
|
+
sprawl(b, (path, nodeB) => {
|
|
3219
|
+
let key;
|
|
3220
|
+
for (key of path) {
|
|
3221
|
+
const nodeA = a[key];
|
|
3222
|
+
if (nodeA === undefined) {
|
|
3223
|
+
added.push([key, JSON.stringify(nodeB)]);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
});
|
|
3227
|
+
summary = `\uFF5E${changed.length} \uFF0B${added.length} \uFF0D${removed.length}`;
|
|
3228
|
+
return {
|
|
3229
|
+
summary,
|
|
3230
|
+
added,
|
|
3231
|
+
removed,
|
|
3232
|
+
changed
|
|
3233
|
+
};
|
|
3234
|
+
}
|
|
3235
|
+
function diffArray(a, b, recurse) {
|
|
3236
|
+
return diffObject(a, b, recurse);
|
|
3237
|
+
}
|
|
3238
|
+
var Differ = class {
|
|
3239
|
+
leafRefinery;
|
|
3240
|
+
treeRefinery;
|
|
3241
|
+
leafDiffers;
|
|
3242
|
+
treeDiffers;
|
|
3243
|
+
constructor(leafRefinery, treeRefinery, diffFunctions) {
|
|
3244
|
+
this.leafRefinery = leafRefinery;
|
|
3245
|
+
this.treeRefinery = treeRefinery;
|
|
3246
|
+
this.leafDiffers = {};
|
|
3247
|
+
this.treeDiffers = {};
|
|
3248
|
+
for (const key of Object.keys(leafRefinery.supported)) {
|
|
3249
|
+
const diffFunction = diffFunctions[key];
|
|
3250
|
+
this.leafDiffers[key] = diffFunction;
|
|
3251
|
+
}
|
|
3252
|
+
for (const key of Object.keys(treeRefinery.supported)) {
|
|
3253
|
+
const diffFunction = diffFunctions[key];
|
|
3254
|
+
this.treeDiffers[key] = diffFunction;
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
diff(a, b) {
|
|
3258
|
+
if (a === b) {
|
|
3259
|
+
return { summary: `No Change` };
|
|
3260
|
+
}
|
|
3261
|
+
const aRefined = this.leafRefinery.refine(a) ?? this.treeRefinery.refine(a);
|
|
3262
|
+
const bRefined = this.leafRefinery.refine(b) ?? this.treeRefinery.refine(b);
|
|
3263
|
+
if (aRefined !== null && bRefined !== null) {
|
|
3264
|
+
if (aRefined.type === bRefined.type) {
|
|
3265
|
+
if (aRefined.type in this.leafDiffers) {
|
|
3266
|
+
const delta = this.leafDiffers[aRefined.type](
|
|
3267
|
+
aRefined.data,
|
|
3268
|
+
bRefined.data
|
|
3269
|
+
);
|
|
3270
|
+
return delta;
|
|
3271
|
+
}
|
|
3272
|
+
if (aRefined.type in this.treeDiffers) {
|
|
3273
|
+
const delta = this.treeDiffers[aRefined.type](
|
|
3274
|
+
aRefined.data,
|
|
3275
|
+
bRefined.data,
|
|
3276
|
+
(x, y) => this.diff(x, y)
|
|
3277
|
+
);
|
|
3278
|
+
return delta;
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
const typeA = discoverType(a);
|
|
3283
|
+
const typeB = discoverType(b);
|
|
3284
|
+
if (typeA === typeB) {
|
|
3285
|
+
return {
|
|
3286
|
+
summary: `${typeA} \u2192 ${typeB}`
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
return {
|
|
3290
|
+
summary: `Type change: ${typeA} \u2192 ${typeB}`
|
|
3291
|
+
};
|
|
3292
|
+
}
|
|
3293
|
+
};
|
|
3294
|
+
new Differ(primitiveRefinery, jsonTreeRefinery, {
|
|
3295
|
+
number: diffNumber,
|
|
3296
|
+
string: diffString,
|
|
3297
|
+
boolean: diffBoolean,
|
|
3298
|
+
null: () => ({ summary: `No Change` }),
|
|
3299
|
+
object: diffObject,
|
|
3300
|
+
array: diffArray
|
|
3301
|
+
});
|
|
3302
|
+
|
|
3303
|
+
// ../atom.io/transceivers/set-rtx/src/set-rtx.ts
|
|
3304
|
+
var SetRTX = class _SetRTX extends Set {
|
|
3305
|
+
mode = `record`;
|
|
3306
|
+
subject = new Subject();
|
|
3307
|
+
cacheLimit = 0;
|
|
3308
|
+
cache = [];
|
|
3309
|
+
cacheIdx = -1;
|
|
3310
|
+
cacheUpdateNumber = -1;
|
|
3311
|
+
constructor(values, cacheLimit = 0) {
|
|
3312
|
+
super(values);
|
|
3313
|
+
if (values instanceof _SetRTX) {
|
|
3314
|
+
this.parent = values;
|
|
3315
|
+
this.cacheUpdateNumber = values.cacheUpdateNumber;
|
|
3316
|
+
}
|
|
3317
|
+
if (cacheLimit) {
|
|
3318
|
+
this.cacheLimit = cacheLimit;
|
|
3319
|
+
this.cache = new Array(cacheLimit);
|
|
3320
|
+
this.subscribe(`auto cache`, (update) => {
|
|
3321
|
+
this.cacheIdx++;
|
|
3322
|
+
this.cacheIdx %= this.cacheLimit;
|
|
3323
|
+
this.cache[this.cacheIdx] = update;
|
|
3324
|
+
});
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
toJSON() {
|
|
3328
|
+
return {
|
|
3329
|
+
members: [...this],
|
|
3330
|
+
cache: this.cache,
|
|
3331
|
+
cacheLimit: this.cacheLimit,
|
|
3332
|
+
cacheIdx: this.cacheIdx,
|
|
3333
|
+
cacheUpdateNumber: this.cacheUpdateNumber
|
|
3334
|
+
};
|
|
3335
|
+
}
|
|
3336
|
+
static fromJSON(json) {
|
|
3337
|
+
const set = new _SetRTX(json.members, json.cacheLimit);
|
|
3338
|
+
set.cache = json.cache;
|
|
3339
|
+
set.cacheIdx = json.cacheIdx;
|
|
3340
|
+
set.cacheUpdateNumber = json.cacheUpdateNumber;
|
|
3341
|
+
return set;
|
|
3342
|
+
}
|
|
3343
|
+
add(value) {
|
|
3344
|
+
const result = super.add(value);
|
|
3345
|
+
if (this.mode === `record`) {
|
|
3346
|
+
this.cacheUpdateNumber++;
|
|
3347
|
+
this.emit(`add:${stringifyJson(value)}`);
|
|
3348
|
+
}
|
|
3349
|
+
return result;
|
|
3350
|
+
}
|
|
3351
|
+
clear() {
|
|
3352
|
+
const capturedContents = this.mode === `record` ? [...this] : null;
|
|
3353
|
+
super.clear();
|
|
3354
|
+
if (capturedContents) {
|
|
3355
|
+
this.cacheUpdateNumber++;
|
|
3356
|
+
this.emit(`clear:${JSON.stringify(capturedContents)}`);
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
delete(value) {
|
|
3360
|
+
const result = super.delete(value);
|
|
3361
|
+
if (this.mode === `record`) {
|
|
3362
|
+
this.cacheUpdateNumber++;
|
|
3363
|
+
this.emit(`del:${stringifyJson(value)}`);
|
|
3364
|
+
}
|
|
3365
|
+
return result;
|
|
3366
|
+
}
|
|
3367
|
+
parent;
|
|
3368
|
+
child = null;
|
|
3369
|
+
transactionUpdates = null;
|
|
3370
|
+
transaction(run) {
|
|
3371
|
+
this.mode = `transaction`;
|
|
3372
|
+
this.transactionUpdates = [];
|
|
3373
|
+
this.child = new _SetRTX(this);
|
|
3374
|
+
const unsubscribe = this.child._subscribe(`transaction`, (update) => {
|
|
3375
|
+
this.transactionUpdates?.push(update);
|
|
3376
|
+
});
|
|
3377
|
+
try {
|
|
3378
|
+
const shouldCommit = run(this.child);
|
|
3379
|
+
if (shouldCommit) {
|
|
3380
|
+
for (const update of this.transactionUpdates) {
|
|
3381
|
+
this.doStep(update);
|
|
3382
|
+
}
|
|
3383
|
+
this.cacheUpdateNumber++;
|
|
3384
|
+
this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
|
|
3385
|
+
}
|
|
3386
|
+
} catch (thrown) {
|
|
3387
|
+
console.error(`Failed to apply transaction to SetRTX:`, thrown);
|
|
3388
|
+
throw thrown;
|
|
3389
|
+
} finally {
|
|
3390
|
+
unsubscribe();
|
|
3391
|
+
this.child = null;
|
|
3392
|
+
this.transactionUpdates = null;
|
|
3393
|
+
this.mode = `record`;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
_subscribe(key, fn) {
|
|
3397
|
+
return this.subject.subscribe(key, fn);
|
|
3398
|
+
}
|
|
3399
|
+
subscribe(key, fn) {
|
|
3400
|
+
return this.subject.subscribe(key, (update) => {
|
|
3401
|
+
fn(`${this.cacheUpdateNumber}=${update}`);
|
|
3402
|
+
});
|
|
3403
|
+
}
|
|
3404
|
+
emit(update) {
|
|
3405
|
+
this.subject.next(update);
|
|
3406
|
+
}
|
|
3407
|
+
doStep(update) {
|
|
3408
|
+
const typeValueBreak = update.indexOf(`:`);
|
|
3409
|
+
const type = update.substring(0, typeValueBreak);
|
|
3410
|
+
const value = update.substring(typeValueBreak + 1);
|
|
3411
|
+
switch (type) {
|
|
3412
|
+
case `add`:
|
|
3413
|
+
this.add(JSON.parse(value));
|
|
3414
|
+
break;
|
|
3415
|
+
case `clear`:
|
|
3416
|
+
this.clear();
|
|
3417
|
+
break;
|
|
3418
|
+
case `del`:
|
|
3419
|
+
this.delete(JSON.parse(value));
|
|
3420
|
+
break;
|
|
3421
|
+
case `tx`:
|
|
3422
|
+
for (const subUpdate of value.split(`;`)) {
|
|
3423
|
+
this.doStep(subUpdate);
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
getUpdateNumber(update) {
|
|
3428
|
+
const breakpoint = update.indexOf(`=`);
|
|
3429
|
+
return Number(update.substring(0, breakpoint));
|
|
3430
|
+
}
|
|
3431
|
+
do(update) {
|
|
3432
|
+
const breakpoint = update.indexOf(`=`);
|
|
3433
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
3434
|
+
const eventOffset = updateNumber - this.cacheUpdateNumber;
|
|
3435
|
+
const isFuture = eventOffset > 0;
|
|
3436
|
+
if (isFuture) {
|
|
3437
|
+
if (eventOffset === 1) {
|
|
3438
|
+
this.mode = `playback`;
|
|
3439
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
3440
|
+
this.doStep(innerUpdate);
|
|
3441
|
+
this.mode = `record`;
|
|
3442
|
+
this.cacheUpdateNumber = updateNumber;
|
|
3443
|
+
return null;
|
|
3444
|
+
}
|
|
3445
|
+
return this.cacheUpdateNumber + 1;
|
|
3446
|
+
}
|
|
3447
|
+
if (Math.abs(eventOffset) < this.cacheLimit) {
|
|
3448
|
+
const eventIdx = this.cacheIdx + eventOffset;
|
|
3449
|
+
const cachedUpdate = this.cache[eventIdx];
|
|
3450
|
+
if (cachedUpdate === update) {
|
|
3451
|
+
return null;
|
|
3452
|
+
}
|
|
3453
|
+
this.mode = `playback`;
|
|
3454
|
+
let done = false;
|
|
3455
|
+
while (!done) {
|
|
3456
|
+
this.cacheIdx %= this.cacheLimit;
|
|
3457
|
+
const u = this.cache[this.cacheIdx];
|
|
3458
|
+
this.cacheIdx--;
|
|
3459
|
+
if (!u) {
|
|
3460
|
+
return `OUT_OF_RANGE`;
|
|
3461
|
+
}
|
|
3462
|
+
this.undo(u);
|
|
3463
|
+
done = this.cacheIdx === eventIdx - 1;
|
|
3464
|
+
}
|
|
3465
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
3466
|
+
this.doStep(innerUpdate);
|
|
3467
|
+
this.mode = `record`;
|
|
3468
|
+
this.cacheUpdateNumber = updateNumber;
|
|
3469
|
+
return null;
|
|
3470
|
+
}
|
|
3471
|
+
return `OUT_OF_RANGE`;
|
|
3472
|
+
}
|
|
3473
|
+
undoStep(update) {
|
|
3474
|
+
const breakpoint = update.indexOf(`:`);
|
|
3475
|
+
const type = update.substring(0, breakpoint);
|
|
3476
|
+
const value = update.substring(breakpoint + 1);
|
|
3477
|
+
switch (type) {
|
|
3478
|
+
case `add`:
|
|
3479
|
+
this.delete(JSON.parse(value));
|
|
3480
|
+
break;
|
|
3481
|
+
case `del`:
|
|
3482
|
+
this.add(JSON.parse(value));
|
|
3483
|
+
break;
|
|
3484
|
+
case `clear`: {
|
|
3485
|
+
const values = JSON.parse(value);
|
|
3486
|
+
for (const v of values) this.add(v);
|
|
3487
|
+
break;
|
|
3488
|
+
}
|
|
3489
|
+
case `tx`: {
|
|
3490
|
+
const updates = value.split(`;`);
|
|
3491
|
+
for (let i = updates.length - 1; i >= 0; i--) {
|
|
3492
|
+
this.undoStep(updates[i]);
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
undo(update) {
|
|
3498
|
+
const breakpoint = update.indexOf(`=`);
|
|
3499
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
3500
|
+
if (updateNumber === this.cacheUpdateNumber) {
|
|
3501
|
+
this.mode = `playback`;
|
|
3502
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
3503
|
+
this.undoStep(innerUpdate);
|
|
3504
|
+
this.mode = `record`;
|
|
3505
|
+
this.cacheUpdateNumber--;
|
|
3506
|
+
return null;
|
|
3507
|
+
}
|
|
3508
|
+
return this.cacheUpdateNumber;
|
|
3509
|
+
}
|
|
3510
|
+
};
|
|
3511
|
+
|
|
3512
|
+
// ../atom.io/data/src/join.ts
|
|
3513
|
+
function capitalize2(string) {
|
|
3514
|
+
return string[0].toUpperCase() + string.slice(1);
|
|
3515
|
+
}
|
|
3516
|
+
var Join = class {
|
|
3517
|
+
toolkit;
|
|
3518
|
+
options;
|
|
3519
|
+
defaultContent;
|
|
3520
|
+
molecules = /* @__PURE__ */ new Map();
|
|
3521
|
+
relations;
|
|
3522
|
+
states;
|
|
3523
|
+
core;
|
|
3524
|
+
transact(toolkit, run) {
|
|
3525
|
+
const originalToolkit = this.toolkit;
|
|
3526
|
+
this.toolkit = toolkit;
|
|
3527
|
+
run(this);
|
|
3528
|
+
this.toolkit = originalToolkit;
|
|
3529
|
+
}
|
|
3530
|
+
store;
|
|
3531
|
+
realm;
|
|
3532
|
+
[Symbol.dispose]() {
|
|
3533
|
+
}
|
|
3534
|
+
constructor(options, defaultContent, store = IMPLICIT.STORE) {
|
|
3535
|
+
this.store = store;
|
|
3536
|
+
this.realm = new Anarchy(store);
|
|
3537
|
+
this.options = options;
|
|
3538
|
+
this.defaultContent = defaultContent;
|
|
3539
|
+
this.store.miscResources.set(`join:${options.key}`, this);
|
|
3540
|
+
this.realm.allocate(`root`, options.key);
|
|
3541
|
+
this.toolkit = {
|
|
3542
|
+
get: (...ps) => getFromStore(store, ...ps),
|
|
3543
|
+
set: (...ps) => {
|
|
3544
|
+
setIntoStore(store, ...ps);
|
|
3545
|
+
},
|
|
3546
|
+
find: (...ps) => findInStore(store, ...ps),
|
|
3547
|
+
seek: (...ps) => seekInStore(store, ...ps),
|
|
3548
|
+
json: (token) => getJsonToken(store, token)
|
|
3549
|
+
};
|
|
3550
|
+
const aSide = options.between[0];
|
|
3551
|
+
const bSide = options.between[1];
|
|
3552
|
+
const relatedKeysAtoms = createMutableAtomFamily(
|
|
3553
|
+
store,
|
|
3554
|
+
{
|
|
3555
|
+
key: `${options.key}/relatedKeys`,
|
|
3556
|
+
default: () => new SetRTX(),
|
|
3557
|
+
mutable: true,
|
|
3558
|
+
fromJson: (json) => SetRTX.fromJSON(json),
|
|
3559
|
+
toJson: (set) => set.toJSON()
|
|
3560
|
+
},
|
|
3561
|
+
[`join`, `relations`]
|
|
3562
|
+
);
|
|
3563
|
+
this.core = { relatedKeysAtoms };
|
|
3564
|
+
const getRelatedKeys = ({ get }, key) => get(relatedKeysAtoms, key);
|
|
3565
|
+
const addRelation = ({ set }, a, b) => {
|
|
3566
|
+
if (!this.store.molecules.has(stringifyJson(a))) {
|
|
3567
|
+
this.realm.allocate(options.key, a);
|
|
3568
|
+
}
|
|
3569
|
+
set(relatedKeysAtoms, a, (aKeys) => aKeys.add(b));
|
|
3570
|
+
set(relatedKeysAtoms, b, (bKeys) => bKeys.add(a));
|
|
3571
|
+
};
|
|
3572
|
+
const deleteRelation = ({ set }, a, b) => {
|
|
3573
|
+
set(relatedKeysAtoms, a, (aKeys) => {
|
|
3574
|
+
aKeys.delete(b);
|
|
3575
|
+
return aKeys;
|
|
3576
|
+
});
|
|
3577
|
+
set(relatedKeysAtoms, b, (bKeys) => {
|
|
3578
|
+
bKeys.delete(a);
|
|
3579
|
+
return bKeys;
|
|
3580
|
+
});
|
|
3581
|
+
};
|
|
3582
|
+
const replaceRelationsSafely = (toolkit, a, newRelationsOfA) => {
|
|
3583
|
+
const { find, get, set } = toolkit;
|
|
3584
|
+
const relationsOfAState = find(relatedKeysAtoms, a);
|
|
3585
|
+
const currentRelationsOfA = get(relationsOfAState);
|
|
3586
|
+
for (const currentRelationB of currentRelationsOfA) {
|
|
3587
|
+
const remainsRelated = newRelationsOfA.includes(currentRelationB);
|
|
3588
|
+
if (remainsRelated) {
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
set(relatedKeysAtoms, currentRelationB, (relationsOfB) => {
|
|
3592
|
+
relationsOfB.delete(a);
|
|
3593
|
+
return relationsOfB;
|
|
3594
|
+
});
|
|
3595
|
+
}
|
|
3596
|
+
set(relationsOfAState, (relationsOfA) => {
|
|
3597
|
+
relationsOfA.transaction((nextRelationsOfA) => {
|
|
3598
|
+
nextRelationsOfA.clear();
|
|
3599
|
+
for (const newRelationB of newRelationsOfA) {
|
|
3600
|
+
const relationsOfB = getRelatedKeys(toolkit, newRelationB);
|
|
3601
|
+
const newRelationBIsAlreadyRelated = relationsOfB.has(a);
|
|
3602
|
+
if (this.relations.cardinality === `1:n`) {
|
|
3603
|
+
const previousOwnersToDispose = [];
|
|
3604
|
+
for (const previousOwner of relationsOfB) {
|
|
3605
|
+
if (previousOwner === a) {
|
|
3606
|
+
continue;
|
|
3607
|
+
}
|
|
3608
|
+
const previousOwnerRelations = getRelatedKeys(
|
|
3609
|
+
toolkit,
|
|
3610
|
+
previousOwner
|
|
3611
|
+
);
|
|
3612
|
+
previousOwnerRelations.delete(newRelationB);
|
|
3613
|
+
if (previousOwnerRelations.size === 0) {
|
|
3614
|
+
previousOwnersToDispose.push(previousOwner);
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0) {
|
|
3618
|
+
relationsOfB.clear();
|
|
3619
|
+
}
|
|
3620
|
+
for (const previousOwner of previousOwnersToDispose) {
|
|
3621
|
+
const sorted = [newRelationB, previousOwner].sort();
|
|
3622
|
+
const compositeKey = `"${sorted[0]}:${sorted[1]}"`;
|
|
3623
|
+
this.molecules.delete(compositeKey);
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
if (!newRelationBIsAlreadyRelated) {
|
|
3627
|
+
relationsOfB.add(a);
|
|
3628
|
+
}
|
|
3629
|
+
nextRelationsOfA.add(newRelationB);
|
|
3630
|
+
}
|
|
3631
|
+
return true;
|
|
3632
|
+
});
|
|
3633
|
+
return relationsOfA;
|
|
3634
|
+
});
|
|
3635
|
+
};
|
|
3636
|
+
const replaceRelationsUnsafely = (toolkit, a, newRelationsOfA) => {
|
|
3637
|
+
const { set } = toolkit;
|
|
3638
|
+
set(relatedKeysAtoms, a, (relationsOfA) => {
|
|
3639
|
+
relationsOfA.transaction((nextRelationsOfA) => {
|
|
3640
|
+
for (const newRelationB of newRelationsOfA) {
|
|
3641
|
+
nextRelationsOfA.add(newRelationB);
|
|
3642
|
+
}
|
|
3643
|
+
return true;
|
|
3644
|
+
});
|
|
3645
|
+
return relationsOfA;
|
|
3646
|
+
});
|
|
3647
|
+
for (const newRelationB of newRelationsOfA) {
|
|
3648
|
+
set(relatedKeysAtoms, newRelationB, (newRelationsB) => {
|
|
3649
|
+
newRelationsB.add(a);
|
|
3650
|
+
return newRelationsB;
|
|
3651
|
+
});
|
|
3652
|
+
}
|
|
3653
|
+
return true;
|
|
3654
|
+
};
|
|
3655
|
+
const has = (toolkit, a, b) => {
|
|
3656
|
+
const aKeys = getRelatedKeys(toolkit, a);
|
|
3657
|
+
return b ? aKeys.has(b) : aKeys.size > 0;
|
|
3658
|
+
};
|
|
3659
|
+
const baseExternalStoreConfiguration = {
|
|
3660
|
+
getRelatedKeys: (key) => getRelatedKeys(this.toolkit, key),
|
|
3661
|
+
addRelation: (a, b) => {
|
|
3662
|
+
this.store.moleculeJoins.set(
|
|
3663
|
+
a,
|
|
3664
|
+
options.key
|
|
3665
|
+
);
|
|
3666
|
+
this.store.moleculeJoins.set(
|
|
3667
|
+
b,
|
|
3668
|
+
options.key
|
|
3669
|
+
);
|
|
3670
|
+
addRelation(this.toolkit, a, b);
|
|
3671
|
+
},
|
|
3672
|
+
deleteRelation: (a, b) => {
|
|
3673
|
+
deleteRelation(this.toolkit, a, b);
|
|
3674
|
+
},
|
|
3675
|
+
replaceRelationsSafely: (a, bs) => {
|
|
3676
|
+
replaceRelationsSafely(this.toolkit, a, bs);
|
|
3677
|
+
},
|
|
3678
|
+
replaceRelationsUnsafely: (a, bs) => {
|
|
3679
|
+
replaceRelationsUnsafely(this.toolkit, a, bs);
|
|
3680
|
+
},
|
|
3681
|
+
has: (a, b) => has(this.toolkit, a, b)
|
|
3682
|
+
};
|
|
3683
|
+
let externalStore;
|
|
3684
|
+
let contentAtoms;
|
|
3685
|
+
if (defaultContent) {
|
|
3686
|
+
contentAtoms = createRegularAtomFamily(
|
|
3687
|
+
store,
|
|
3688
|
+
{
|
|
3689
|
+
key: `${options.key}/content`,
|
|
3690
|
+
default: defaultContent
|
|
3691
|
+
},
|
|
3692
|
+
[`join`, `content`]
|
|
3693
|
+
);
|
|
3694
|
+
const getContent = ({ get }, key) => get(contentAtoms, key);
|
|
3695
|
+
const setContent = ({ set }, key, content) => {
|
|
3696
|
+
set(contentAtoms, key, content);
|
|
3697
|
+
};
|
|
3698
|
+
const externalStoreWithContentConfiguration = {
|
|
3699
|
+
getContent: (contentKey) => {
|
|
3700
|
+
const content = getContent(this.toolkit, contentKey);
|
|
3701
|
+
return content;
|
|
3702
|
+
},
|
|
3703
|
+
setContent: (contentKey, content) => {
|
|
3704
|
+
setContent(this.toolkit, contentKey, content);
|
|
3705
|
+
},
|
|
3706
|
+
deleteContent: (contentKey) => {
|
|
3707
|
+
this.realm.deallocate(contentKey);
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
externalStore = Object.assign(
|
|
3711
|
+
baseExternalStoreConfiguration,
|
|
3712
|
+
externalStoreWithContentConfiguration
|
|
3713
|
+
);
|
|
3714
|
+
} else {
|
|
3715
|
+
externalStore = baseExternalStoreConfiguration;
|
|
3716
|
+
}
|
|
3717
|
+
const relations = new Junction(
|
|
3718
|
+
options,
|
|
3719
|
+
{
|
|
3720
|
+
externalStore,
|
|
3721
|
+
isAType: options.isAType,
|
|
3722
|
+
isBType: options.isBType,
|
|
3723
|
+
makeContentKey: (...args) => {
|
|
3724
|
+
const [a, b] = args;
|
|
3725
|
+
const sorted = args.sort();
|
|
3726
|
+
const compositeKey = `${sorted[0]}:${sorted[1]}`;
|
|
3727
|
+
const aMolecule = store.molecules.get(stringifyJson(a));
|
|
3728
|
+
const bMolecule = store.molecules.get(stringifyJson(b));
|
|
3729
|
+
if (!aMolecule) {
|
|
3730
|
+
this.realm.allocate(options.key, a);
|
|
3731
|
+
}
|
|
3732
|
+
if (!bMolecule) {
|
|
3733
|
+
this.realm.allocate(options.key, b);
|
|
3734
|
+
}
|
|
3735
|
+
this.realm.allocate(a, compositeKey, `all`);
|
|
3736
|
+
this.realm.claim(b, compositeKey);
|
|
3737
|
+
this.store.moleculeJoins.set(compositeKey, options.key);
|
|
3738
|
+
return compositeKey;
|
|
3739
|
+
}
|
|
3740
|
+
}
|
|
3741
|
+
);
|
|
3742
|
+
const createSingleKeySelectorFamily = () => createReadonlySelectorFamily(
|
|
3743
|
+
store,
|
|
3744
|
+
{
|
|
3745
|
+
key: `${options.key}/singleRelatedKey`,
|
|
3746
|
+
get: (key) => ({ get }) => {
|
|
3747
|
+
const relatedKeys = get(relatedKeysAtoms, key);
|
|
3748
|
+
for (const relatedKey of relatedKeys) {
|
|
3749
|
+
return relatedKey;
|
|
3750
|
+
}
|
|
3751
|
+
return null;
|
|
3752
|
+
}
|
|
3753
|
+
},
|
|
3754
|
+
[`join`, `keys`]
|
|
3755
|
+
);
|
|
3756
|
+
const getMultipleKeySelectorFamily = () => {
|
|
3757
|
+
return createReadonlySelectorFamily(
|
|
3758
|
+
store,
|
|
3759
|
+
{
|
|
3760
|
+
key: `${options.key}/multipleRelatedKeys`,
|
|
3761
|
+
get: (key) => ({ get }) => {
|
|
3762
|
+
const jsonFamily = getJsonFamily(relatedKeysAtoms, store);
|
|
3763
|
+
const json = get(jsonFamily, key);
|
|
3764
|
+
return json.members;
|
|
3765
|
+
}
|
|
3766
|
+
},
|
|
3767
|
+
[`join`, `keys`]
|
|
3768
|
+
);
|
|
3769
|
+
};
|
|
3770
|
+
const createSingleEntrySelectorFamily = () => createReadonlySelectorFamily(
|
|
3771
|
+
store,
|
|
3772
|
+
{
|
|
3773
|
+
key: `${options.key}/singleRelatedEntry`,
|
|
3774
|
+
get: (x) => ({ get }) => {
|
|
3775
|
+
const relatedKeys = get(relatedKeysAtoms, x);
|
|
3776
|
+
for (const y of relatedKeys) {
|
|
3777
|
+
let a = relations.isAType?.(x) ? x : undefined;
|
|
3778
|
+
let b = a === undefined ? x : undefined;
|
|
3779
|
+
a ??= y;
|
|
3780
|
+
b ??= y;
|
|
3781
|
+
const contentKey = relations.makeContentKey(a, b);
|
|
3782
|
+
const content = get(contentAtoms, contentKey);
|
|
3783
|
+
return [y, content];
|
|
3784
|
+
}
|
|
3785
|
+
return null;
|
|
3786
|
+
}
|
|
3787
|
+
},
|
|
3788
|
+
[`join`, `entries`]
|
|
3789
|
+
);
|
|
3790
|
+
const getMultipleEntrySelectorFamily = () => createReadonlySelectorFamily(
|
|
3791
|
+
store,
|
|
3792
|
+
{
|
|
3793
|
+
key: `${options.key}/multipleRelatedEntries`,
|
|
3794
|
+
get: (x) => ({ get }) => {
|
|
3795
|
+
const jsonFamily = getJsonFamily(relatedKeysAtoms, store);
|
|
3796
|
+
const json = get(jsonFamily, x);
|
|
3797
|
+
return json.members.map((y) => {
|
|
3798
|
+
let a = relations.isAType?.(x) ? x : undefined;
|
|
3799
|
+
let b = a === undefined ? x : undefined;
|
|
3800
|
+
a ??= y;
|
|
3801
|
+
b ??= y;
|
|
3802
|
+
const contentKey = relations.makeContentKey(a, b);
|
|
3803
|
+
const content = get(contentAtoms, contentKey);
|
|
3804
|
+
return [y, content];
|
|
3805
|
+
});
|
|
3806
|
+
}
|
|
3807
|
+
},
|
|
3808
|
+
[`join`, `entries`]
|
|
3809
|
+
);
|
|
3810
|
+
switch (options.cardinality) {
|
|
3811
|
+
case `1:1`: {
|
|
3812
|
+
const singleRelatedKeySelectors = createSingleKeySelectorFamily();
|
|
3813
|
+
const stateKeyA = `${aSide}KeyOf${capitalize2(bSide)}`;
|
|
3814
|
+
const stateKeyB = `${bSide}KeyOf${capitalize2(aSide)}`;
|
|
3815
|
+
const baseStates = {
|
|
3816
|
+
[stateKeyA]: singleRelatedKeySelectors,
|
|
3817
|
+
[stateKeyB]: singleRelatedKeySelectors
|
|
3818
|
+
};
|
|
3819
|
+
let states;
|
|
3820
|
+
if (defaultContent) {
|
|
3821
|
+
const singleEntrySelectors = createSingleEntrySelectorFamily();
|
|
3822
|
+
const entriesStateKeyA = `${aSide}EntryOf${capitalize2(bSide)}`;
|
|
3823
|
+
const entriesStateKeyB = `${bSide}EntryOf${capitalize2(aSide)}`;
|
|
3824
|
+
const contentStates = {
|
|
3825
|
+
[entriesStateKeyA]: singleEntrySelectors,
|
|
3826
|
+
[entriesStateKeyB]: singleEntrySelectors
|
|
3827
|
+
};
|
|
3828
|
+
states = Object.assign(baseStates, contentStates);
|
|
3829
|
+
} else {
|
|
3830
|
+
states = baseStates;
|
|
3831
|
+
}
|
|
3832
|
+
this.relations = relations;
|
|
3833
|
+
this.states = states;
|
|
3834
|
+
break;
|
|
3835
|
+
}
|
|
3836
|
+
case `1:n`: {
|
|
3837
|
+
const singleRelatedKeySelectors = createSingleKeySelectorFamily();
|
|
3838
|
+
const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily();
|
|
3839
|
+
const stateKeyA = `${aSide}KeyOf${capitalize2(bSide)}`;
|
|
3840
|
+
const stateKeyB = `${bSide}KeysOf${capitalize2(aSide)}`;
|
|
3841
|
+
const baseStates = {
|
|
3842
|
+
[stateKeyA]: singleRelatedKeySelectors,
|
|
3843
|
+
[stateKeyB]: multipleRelatedKeysSelectors
|
|
3844
|
+
};
|
|
3845
|
+
let states;
|
|
3846
|
+
if (defaultContent) {
|
|
3847
|
+
const singleRelatedEntrySelectors = createSingleEntrySelectorFamily();
|
|
3848
|
+
const multipleRelatedEntriesSelectors = getMultipleEntrySelectorFamily();
|
|
3849
|
+
const entriesStateKeyA = `${aSide}EntryOf${capitalize2(bSide)}`;
|
|
3850
|
+
const entriesStateKeyB = `${bSide}EntriesOf${capitalize2(
|
|
3851
|
+
aSide
|
|
3852
|
+
)}`;
|
|
3853
|
+
const contentStates = {
|
|
3854
|
+
[entriesStateKeyA]: singleRelatedEntrySelectors,
|
|
3855
|
+
[entriesStateKeyB]: multipleRelatedEntriesSelectors
|
|
3856
|
+
};
|
|
3857
|
+
states = Object.assign(baseStates, contentStates);
|
|
3858
|
+
} else {
|
|
3859
|
+
states = baseStates;
|
|
3860
|
+
}
|
|
3861
|
+
this.relations = relations;
|
|
3862
|
+
this.states = states;
|
|
3863
|
+
break;
|
|
3864
|
+
}
|
|
3865
|
+
default: {
|
|
3866
|
+
const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily();
|
|
3867
|
+
const stateKeyA = `${aSide}KeysOf${capitalize2(bSide)}`;
|
|
3868
|
+
const stateKeyB = `${bSide}KeysOf${capitalize2(aSide)}`;
|
|
3869
|
+
const baseStates = {
|
|
3870
|
+
[stateKeyA]: multipleRelatedKeysSelectors,
|
|
3871
|
+
[stateKeyB]: multipleRelatedKeysSelectors
|
|
3872
|
+
};
|
|
3873
|
+
let states;
|
|
3874
|
+
if (defaultContent) {
|
|
3875
|
+
const multipleRelatedEntriesSelectors = getMultipleEntrySelectorFamily();
|
|
3876
|
+
const entriesStateKeyA = `${aSide}EntriesOf${capitalize2(
|
|
3877
|
+
bSide
|
|
3878
|
+
)}`;
|
|
3879
|
+
const entriesStateKeyB = `${bSide}EntriesOf${capitalize2(
|
|
3880
|
+
aSide
|
|
3881
|
+
)}`;
|
|
3882
|
+
const contentStates = {
|
|
3883
|
+
[entriesStateKeyA]: multipleRelatedEntriesSelectors,
|
|
3884
|
+
[entriesStateKeyB]: multipleRelatedEntriesSelectors
|
|
3885
|
+
};
|
|
3886
|
+
states = Object.assign(baseStates, contentStates);
|
|
3887
|
+
} else {
|
|
3888
|
+
states = baseStates;
|
|
3889
|
+
}
|
|
3890
|
+
this.relations = relations;
|
|
3891
|
+
this.states = states;
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
};
|
|
3896
|
+
function join(options, defaultContent, store = IMPLICIT.STORE) {
|
|
3897
|
+
store.joins.set(options.key, new Join(options, defaultContent, store));
|
|
3898
|
+
const token = {
|
|
3899
|
+
key: options.key,
|
|
3900
|
+
type: `join`,
|
|
3901
|
+
a: options.between[0],
|
|
3902
|
+
b: options.between[1],
|
|
3903
|
+
cardinality: options.cardinality
|
|
3904
|
+
};
|
|
3905
|
+
return token;
|
|
3906
|
+
}
|
|
3907
|
+
function getJoin(token, store) {
|
|
3908
|
+
let myJoin = store.joins.get(token.key);
|
|
3909
|
+
if (myJoin === undefined) {
|
|
3910
|
+
const rootJoinMap = IMPLICIT.STORE.joins;
|
|
3911
|
+
const rootJoin = rootJoinMap.get(token.key);
|
|
3912
|
+
if (rootJoin === undefined) {
|
|
3913
|
+
throw new Error(
|
|
3914
|
+
`Join "${token.key}" not found in store "${store.config.name}"`
|
|
3915
|
+
);
|
|
3916
|
+
}
|
|
3917
|
+
myJoin = new Join(rootJoin.options, rootJoin.defaultContent, store);
|
|
3918
|
+
store.joins.set(token.key, myJoin);
|
|
3919
|
+
}
|
|
3920
|
+
return myJoin;
|
|
3921
|
+
}
|
|
3922
|
+
function editRelationsInStore(token, change, store) {
|
|
3923
|
+
const myJoin = getJoin(token, store);
|
|
3924
|
+
const target = newest(store);
|
|
3925
|
+
if (isChildStore(target)) {
|
|
3926
|
+
const { toolkit } = target.transactionMeta;
|
|
3927
|
+
myJoin.transact(toolkit, ({ relations }) => {
|
|
3928
|
+
change(relations);
|
|
3929
|
+
});
|
|
3930
|
+
} else {
|
|
3931
|
+
change(myJoin.relations);
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
function getInternalRelationsFromStore(token, store) {
|
|
3935
|
+
const myJoin = getJoin(token, store);
|
|
3936
|
+
const family = myJoin.core.relatedKeysAtoms;
|
|
3937
|
+
return family;
|
|
3938
|
+
}
|
|
3939
|
+
function getInternalRelations(token) {
|
|
3940
|
+
return getInternalRelationsFromStore(token, IMPLICIT.STORE);
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
// ../atom.io/realtime/src/shared-room-store.ts
|
|
3944
|
+
atom({
|
|
3945
|
+
key: `usersInRoomIndex`,
|
|
3946
|
+
mutable: true,
|
|
3947
|
+
default: () => new SetRTX(),
|
|
3948
|
+
toJson: (set) => set.toJSON(),
|
|
3949
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
3950
|
+
});
|
|
3951
|
+
var roomIndex = atom({
|
|
3952
|
+
key: `roomIndex`,
|
|
3953
|
+
default: () => new SetRTX(),
|
|
3954
|
+
mutable: true,
|
|
3955
|
+
toJson: (set) => set.toJSON(),
|
|
3956
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
3957
|
+
});
|
|
3958
|
+
var DEFAULT_USER_IN_ROOM_META = {
|
|
3959
|
+
enteredAtEpoch: 0
|
|
3960
|
+
};
|
|
3961
|
+
var usersInRooms = join(
|
|
3962
|
+
{
|
|
3963
|
+
key: `usersInRooms`,
|
|
3964
|
+
between: [`room`, `user`],
|
|
3965
|
+
cardinality: `1:n`,
|
|
3966
|
+
isAType: (input) => typeof input === `string`,
|
|
3967
|
+
isBType: (input) => typeof input === `string`
|
|
3968
|
+
},
|
|
3969
|
+
DEFAULT_USER_IN_ROOM_META
|
|
3970
|
+
);
|
|
3971
|
+
selectorFamily({
|
|
3972
|
+
key: `usersInMyRoomView`,
|
|
3973
|
+
get: (myUsername) => ({ find }) => {
|
|
3974
|
+
const usersInRoomsAtoms = getInternalRelations(usersInRooms);
|
|
3975
|
+
const myRoomIndex = find(usersInRoomsAtoms, myUsername);
|
|
3976
|
+
return [myRoomIndex];
|
|
3977
|
+
}
|
|
3978
|
+
});
|
|
3979
|
+
|
|
3980
|
+
// ../atom.io/realtime-server/src/ipc-sockets/custom-socket.ts
|
|
3981
|
+
var CustomSocket = class {
|
|
3982
|
+
constructor(emit) {
|
|
3983
|
+
this.emit = emit;
|
|
3984
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
3985
|
+
this.globalListeners = /* @__PURE__ */ new Set();
|
|
3986
|
+
}
|
|
3987
|
+
listeners;
|
|
3988
|
+
globalListeners;
|
|
3989
|
+
handleEvent(event, ...args) {
|
|
3990
|
+
for (const listener of this.globalListeners) {
|
|
3991
|
+
listener(event, ...args);
|
|
3992
|
+
}
|
|
3993
|
+
const listeners = this.listeners.get(event);
|
|
3994
|
+
if (listeners) {
|
|
3995
|
+
for (const listener of listeners) {
|
|
3996
|
+
listener(...args);
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
}
|
|
4000
|
+
id = `no_id_retrieved`;
|
|
4001
|
+
on(event, listener) {
|
|
4002
|
+
const listeners = this.listeners.get(event);
|
|
4003
|
+
if (listeners) {
|
|
4004
|
+
listeners.add(listener);
|
|
4005
|
+
} else {
|
|
4006
|
+
this.listeners.set(event, /* @__PURE__ */ new Set([listener]));
|
|
4007
|
+
}
|
|
4008
|
+
return this;
|
|
4009
|
+
}
|
|
4010
|
+
onAny(listener) {
|
|
4011
|
+
this.globalListeners.add(listener);
|
|
4012
|
+
return this;
|
|
4013
|
+
}
|
|
4014
|
+
off(event, listener) {
|
|
4015
|
+
const listeners = this.listeners.get(event);
|
|
4016
|
+
if (listeners) {
|
|
4017
|
+
if (listener) {
|
|
4018
|
+
listeners.delete(listener);
|
|
4019
|
+
} else {
|
|
4020
|
+
this.listeners.delete(event);
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
return this;
|
|
4024
|
+
}
|
|
4025
|
+
offAny(listener) {
|
|
4026
|
+
this.globalListeners.delete(listener);
|
|
4027
|
+
return this;
|
|
4028
|
+
}
|
|
4029
|
+
};
|
|
4030
|
+
|
|
4031
|
+
// ../atom.io/realtime-server/src/ipc-sockets/child-socket.ts
|
|
4032
|
+
var ChildSocket = class extends CustomSocket {
|
|
4033
|
+
incompleteData = ``;
|
|
4034
|
+
unprocessedEvents = [];
|
|
4035
|
+
incompleteLog = ``;
|
|
4036
|
+
unprocessedLogs = [];
|
|
4037
|
+
id = `#####`;
|
|
4038
|
+
process;
|
|
4039
|
+
key;
|
|
4040
|
+
logger;
|
|
4041
|
+
handleLog(arg) {
|
|
4042
|
+
if (Array.isArray(arg)) {
|
|
4043
|
+
const [level, ...rest] = arg;
|
|
4044
|
+
switch (level) {
|
|
4045
|
+
case `i`:
|
|
4046
|
+
this.logger.info(...rest);
|
|
4047
|
+
break;
|
|
4048
|
+
case `w`:
|
|
4049
|
+
this.logger.warn(...rest);
|
|
4050
|
+
break;
|
|
4051
|
+
case `e`:
|
|
4052
|
+
this.logger.error(...rest);
|
|
4053
|
+
break;
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
constructor(process2, key, logger) {
|
|
4058
|
+
super((event, ...args) => {
|
|
4059
|
+
const stringifiedEvent = JSON.stringify([event, ...args]) + ``;
|
|
4060
|
+
const errorHandler = (err) => {
|
|
4061
|
+
if (err.code === `EPIPE`) {
|
|
4062
|
+
console.error(`EPIPE error during write`, this.process.stdin);
|
|
4063
|
+
}
|
|
4064
|
+
this.process.stdin.removeListener(`error`, errorHandler);
|
|
4065
|
+
};
|
|
4066
|
+
this.process.stdin.once(`error`, errorHandler);
|
|
4067
|
+
this.process.stdin.write(stringifiedEvent);
|
|
4068
|
+
return this;
|
|
4069
|
+
});
|
|
4070
|
+
this.process = process2;
|
|
4071
|
+
this.key = key;
|
|
4072
|
+
this.logger = logger ?? {
|
|
4073
|
+
info: (...args) => {
|
|
4074
|
+
console.info(this.id, this.key, ...args);
|
|
4075
|
+
},
|
|
4076
|
+
warn: (...args) => {
|
|
4077
|
+
console.warn(this.id, this.key, ...args);
|
|
4078
|
+
},
|
|
4079
|
+
error: (...args) => {
|
|
4080
|
+
console.error(this.id, this.key, ...args);
|
|
4081
|
+
}
|
|
4082
|
+
};
|
|
4083
|
+
this.process.stdout.on(
|
|
4084
|
+
`data`,
|
|
4085
|
+
(buffer) => {
|
|
4086
|
+
const chunk = buffer.toString();
|
|
4087
|
+
if (chunk === `ALIVE`) {
|
|
4088
|
+
return;
|
|
4089
|
+
}
|
|
4090
|
+
this.unprocessedEvents.push(...chunk.split(``));
|
|
4091
|
+
const newInput = this.unprocessedEvents.shift();
|
|
4092
|
+
this.incompleteData += newInput ?? ``;
|
|
4093
|
+
try {
|
|
4094
|
+
if (this.incompleteData.startsWith(`error`)) {
|
|
4095
|
+
console.log(`\u2757`, this.incompleteData);
|
|
4096
|
+
}
|
|
4097
|
+
let parsedEvent = parseJson(this.incompleteData);
|
|
4098
|
+
this.handleEvent(...parsedEvent);
|
|
4099
|
+
while (this.unprocessedEvents.length > 0) {
|
|
4100
|
+
const event = this.unprocessedEvents.shift();
|
|
4101
|
+
if (event) {
|
|
4102
|
+
if (this.unprocessedEvents.length === 0) {
|
|
4103
|
+
this.incompleteData = event;
|
|
4104
|
+
}
|
|
4105
|
+
parsedEvent = parseJson(event);
|
|
4106
|
+
this.handleEvent(...parsedEvent);
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
this.incompleteData = ``;
|
|
4110
|
+
} catch (error) {
|
|
4111
|
+
console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
|
|
4112
|
+
console.warn(this.incompleteData);
|
|
4113
|
+
console.warn(`\u26A0\uFE0F----------------\u26A0\uFE0F`);
|
|
4114
|
+
console.error(error);
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
);
|
|
4118
|
+
this.process.stderr.on(`data`, (buf) => {
|
|
4119
|
+
const chunk = buf.toString();
|
|
4120
|
+
this.unprocessedLogs.push(...chunk.split(``));
|
|
4121
|
+
const newInput = this.unprocessedLogs.shift();
|
|
4122
|
+
this.incompleteLog += newInput ?? ``;
|
|
4123
|
+
try {
|
|
4124
|
+
let parsedLog = parseJson(this.incompleteLog);
|
|
4125
|
+
this.handleLog(parsedLog);
|
|
4126
|
+
while (this.unprocessedLogs.length > 0) {
|
|
4127
|
+
this.incompleteLog = this.unprocessedLogs.shift() ?? ``;
|
|
4128
|
+
if (this.incompleteLog) {
|
|
4129
|
+
parsedLog = parseJson(this.incompleteLog);
|
|
4130
|
+
this.handleLog(parsedLog);
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
} catch (error) {
|
|
4134
|
+
console.error(`\u274C\u274C\u274C`);
|
|
4135
|
+
console.error(this.incompleteLog);
|
|
4136
|
+
console.error(error);
|
|
4137
|
+
console.error(`\u274C\u274C\u274C\uFE0F`);
|
|
4138
|
+
}
|
|
4139
|
+
});
|
|
4140
|
+
if (process2.pid) {
|
|
4141
|
+
this.id = process2.pid.toString();
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
};
|
|
4145
|
+
|
|
4146
|
+
// ../atom.io/realtime-server/src/realtime-server-stores/server-room-external-store.ts
|
|
4147
|
+
var roomArgumentsAtoms = atomFamily({
|
|
4148
|
+
key: `roomArguments`,
|
|
4149
|
+
default: [`echo`, [`Hello World!`]]
|
|
4150
|
+
});
|
|
4151
|
+
var roomSelectors = selectorFamily({
|
|
4152
|
+
key: `room`,
|
|
4153
|
+
get: (roomId) => async ({ get, find }) => {
|
|
4154
|
+
const argumentsState = find(roomArgumentsAtoms, roomId);
|
|
4155
|
+
const args = get(argumentsState);
|
|
4156
|
+
const [script, options] = args;
|
|
4157
|
+
const child = await new Promise(
|
|
4158
|
+
(resolve2) => {
|
|
4159
|
+
const room = spawn(script, options, { env: process.env });
|
|
4160
|
+
const resolver = (data) => {
|
|
4161
|
+
if (data.toString() === `ALIVE`) {
|
|
4162
|
+
room.stdout.off(`data`, resolver);
|
|
4163
|
+
resolve2(room);
|
|
4164
|
+
}
|
|
4165
|
+
};
|
|
4166
|
+
room.stdout.on(`data`, resolver);
|
|
4167
|
+
}
|
|
4168
|
+
);
|
|
4169
|
+
return new ChildSocket(child, roomId);
|
|
4170
|
+
}
|
|
4171
|
+
});
|
|
4172
|
+
|
|
4173
|
+
// ../atom.io/realtime-server/src/realtime-server-stores/server-room-external-actions.ts
|
|
4174
|
+
transaction({
|
|
4175
|
+
key: `createRoom`,
|
|
4176
|
+
do: ({ get, set, find }, roomId, script, options) => {
|
|
4177
|
+
const args = options ? [script, options] : [script];
|
|
4178
|
+
const roomArgumentsState = find(roomArgumentsAtoms, roomId);
|
|
4179
|
+
set(roomArgumentsState, args);
|
|
4180
|
+
set(roomIndex, (s) => s.add(roomId));
|
|
4181
|
+
const roomState = find(roomSelectors, roomId);
|
|
4182
|
+
const room = get(roomState);
|
|
4183
|
+
return room;
|
|
4184
|
+
}
|
|
4185
|
+
});
|
|
4186
|
+
transaction({
|
|
4187
|
+
key: `joinRoom`,
|
|
4188
|
+
do: (tools, roomId, userId, enteredAtEpoch) => {
|
|
4189
|
+
const meta = { enteredAtEpoch };
|
|
4190
|
+
editRelationsInStore(
|
|
4191
|
+
usersInRooms,
|
|
4192
|
+
(relations) => {
|
|
4193
|
+
relations.set({ room: roomId, user: userId }, meta);
|
|
4194
|
+
},
|
|
4195
|
+
tools.env().store
|
|
4196
|
+
);
|
|
4197
|
+
return meta;
|
|
4198
|
+
}
|
|
4199
|
+
});
|
|
4200
|
+
transaction({
|
|
4201
|
+
key: `leaveRoom`,
|
|
4202
|
+
do: (tools, roomId, userId) => {
|
|
4203
|
+
editRelationsInStore(
|
|
4204
|
+
usersInRooms,
|
|
4205
|
+
(relations) => {
|
|
4206
|
+
relations.delete({ room: roomId, user: userId });
|
|
4207
|
+
},
|
|
4208
|
+
tools.env().store
|
|
4209
|
+
);
|
|
4210
|
+
}
|
|
4211
|
+
});
|
|
4212
|
+
transaction({
|
|
4213
|
+
key: `destroyRoom`,
|
|
4214
|
+
do: (tools, roomId) => {
|
|
4215
|
+
editRelationsInStore(
|
|
4216
|
+
usersInRooms,
|
|
4217
|
+
(relations) => {
|
|
4218
|
+
relations.delete({ room: roomId });
|
|
4219
|
+
},
|
|
4220
|
+
tools.env().store
|
|
4221
|
+
);
|
|
4222
|
+
tools.set(roomIndex, (s) => (s.delete(roomId), s));
|
|
4223
|
+
}
|
|
4224
|
+
});
|
|
4225
|
+
|
|
4226
|
+
// ../atom.io/realtime-server/src/realtime-server-stores/server-sync-store.ts
|
|
4227
|
+
atomFamily({
|
|
4228
|
+
key: `redactor`,
|
|
4229
|
+
default: { occlude: (updates) => updates }
|
|
4230
|
+
});
|
|
4231
|
+
atomFamily({
|
|
4232
|
+
key: `unacknowledgedUpdates`,
|
|
4233
|
+
default: () => []
|
|
4234
|
+
});
|
|
4235
|
+
|
|
4236
|
+
// ../atom.io/realtime-server/src/realtime-server-stores/server-user-store.ts
|
|
4237
|
+
atomFamily({
|
|
4238
|
+
key: `sockets`,
|
|
4239
|
+
default: null
|
|
4240
|
+
});
|
|
4241
|
+
atom({
|
|
4242
|
+
key: `socketsIndex`,
|
|
4243
|
+
mutable: true,
|
|
4244
|
+
default: () => new SetRTX(),
|
|
4245
|
+
toJson: (set) => set.toJSON(),
|
|
4246
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
4247
|
+
});
|
|
4248
|
+
atom({
|
|
4249
|
+
key: `usersIndex`,
|
|
4250
|
+
mutable: true,
|
|
4251
|
+
default: () => new SetRTX(),
|
|
4252
|
+
toJson: (set) => set.toJSON(),
|
|
4253
|
+
fromJson: (json) => SetRTX.fromJSON(json)
|
|
4254
|
+
});
|
|
4255
|
+
join({
|
|
4256
|
+
key: `usersOfSockets`,
|
|
4257
|
+
between: [`user`, `socket`],
|
|
4258
|
+
cardinality: `1:1`,
|
|
4259
|
+
isAType: (s) => s.startsWith(`user::`),
|
|
4260
|
+
isBType: (s) => s.startsWith(`socket::`)
|
|
4261
|
+
});
|
|
4262
|
+
var env = createEnv({
|
|
4263
|
+
server: { FLIGHTDECK_SECRET: z.string().optional() },
|
|
4264
|
+
clientPrefix: `NEVER`,
|
|
4265
|
+
client: {},
|
|
4266
|
+
runtimeEnv: import.meta.env,
|
|
4267
|
+
emptyStringAsUndefined: true
|
|
4268
|
+
});
|
|
4269
|
+
|
|
4270
|
+
// src/flightdeck.lib.ts
|
|
4271
|
+
var FLIGHTDECK_SETUP_PHASES = [`downloaded`, `installed`];
|
|
4272
|
+
var FLIGHTDECK_UPDATE_PHASES = [`notified`, `confirmed`];
|
|
4273
|
+
function isVersionNumber(version) {
|
|
4274
|
+
return /^\d+\.\d+\.\d+$/.test(version) || !Number.isNaN(Number.parseFloat(version));
|
|
4275
|
+
}
|
|
4276
|
+
var FlightDeck = class {
|
|
4277
|
+
constructor(options) {
|
|
4278
|
+
this.options = options;
|
|
4279
|
+
const { FLIGHTDECK_SECRET } = env;
|
|
4280
|
+
const { flightdeckRootDir = resolve(homedir(), `.flightdeck`) } = options;
|
|
4281
|
+
const port = options.port ?? 8080;
|
|
4282
|
+
const origin = `http://localhost:${port}`;
|
|
4283
|
+
const servicesEntries = toEntries(options.services);
|
|
4284
|
+
this.services = fromEntries(
|
|
4285
|
+
servicesEntries.map(([serviceName]) => [serviceName, null])
|
|
4286
|
+
);
|
|
4287
|
+
this.serviceIdx = fromEntries(
|
|
4288
|
+
servicesEntries.map(([serviceName], idx) => [serviceName, idx])
|
|
4289
|
+
);
|
|
4290
|
+
this.defaultServicesReadyToUpdate = fromEntries(
|
|
4291
|
+
servicesEntries.map(([serviceName, { waitFor }]) => [
|
|
4292
|
+
serviceName,
|
|
4293
|
+
!waitFor
|
|
4294
|
+
])
|
|
4295
|
+
);
|
|
4296
|
+
this.servicesReadyToUpdate = { ...this.defaultServicesReadyToUpdate };
|
|
4297
|
+
this.autoRespawnDeadServices = true;
|
|
4298
|
+
this.logger = new FlightDeckLogger(
|
|
4299
|
+
this.options.packageName,
|
|
4300
|
+
process.pid,
|
|
4301
|
+
undefined,
|
|
4302
|
+
{ jsonLogging: this.options.jsonLogging ?? false }
|
|
4303
|
+
);
|
|
4304
|
+
this.serviceLoggers = fromEntries(
|
|
4305
|
+
servicesEntries.map(([serviceName]) => [
|
|
4306
|
+
serviceName,
|
|
4307
|
+
new FlightDeckLogger(
|
|
4308
|
+
this.options.packageName,
|
|
4309
|
+
process.pid,
|
|
4310
|
+
serviceName,
|
|
4311
|
+
{ jsonLogging: this.options.jsonLogging ?? false }
|
|
4312
|
+
)
|
|
4313
|
+
])
|
|
4314
|
+
);
|
|
4315
|
+
this.servicesLive = servicesEntries.map(() => new Future(() => {
|
|
4316
|
+
}));
|
|
4317
|
+
this.servicesDead = servicesEntries.map(() => new Future(() => {
|
|
4318
|
+
}));
|
|
4319
|
+
this.live.use(Promise.all(this.servicesLive));
|
|
4320
|
+
this.dead.use(Promise.all(this.servicesDead));
|
|
4321
|
+
this.storage = new FilesystemStorage({
|
|
4322
|
+
path: resolve(flightdeckRootDir, `storage`, options.packageName)
|
|
4323
|
+
});
|
|
4324
|
+
if (FLIGHTDECK_SECRET === undefined) {
|
|
4325
|
+
this.logger.warn(
|
|
4326
|
+
`No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.`
|
|
4327
|
+
);
|
|
4328
|
+
} else {
|
|
4329
|
+
createServer((req, res) => {
|
|
4330
|
+
let data = [];
|
|
4331
|
+
req.on(`data`, (chunk) => {
|
|
4332
|
+
data.push(chunk instanceof Buffer ? chunk : Buffer.from(chunk));
|
|
4333
|
+
}).on(`end`, () => {
|
|
4334
|
+
const authHeader = req.headers.authorization;
|
|
4335
|
+
try {
|
|
4336
|
+
if (typeof req.url === `undefined`) throw 400;
|
|
4337
|
+
const expectedAuthHeader = `Bearer ${FLIGHTDECK_SECRET}`;
|
|
4338
|
+
if (authHeader !== `Bearer ${FLIGHTDECK_SECRET}`) {
|
|
4339
|
+
this.logger.info(
|
|
4340
|
+
`Unauthorized: needed \`${expectedAuthHeader}\`, got \`${authHeader}\``
|
|
4341
|
+
);
|
|
4342
|
+
throw 401;
|
|
4343
|
+
}
|
|
4344
|
+
const url = new URL(req.url, origin);
|
|
4345
|
+
this.logger.info(req.method, url.pathname);
|
|
4346
|
+
const versionForeignInput = Buffer.concat(data).toString();
|
|
4347
|
+
if (!isVersionNumber(versionForeignInput)) {
|
|
4348
|
+
throw 400;
|
|
4349
|
+
}
|
|
4350
|
+
res.writeHead(200);
|
|
4351
|
+
res.end();
|
|
4352
|
+
this.storage.setItem(`updatePhase`, `notified`);
|
|
4353
|
+
this.storage.setItem(`updateAwaitedVersion`, versionForeignInput);
|
|
4354
|
+
const { checkAvailability } = options.scripts;
|
|
4355
|
+
if (checkAvailability) {
|
|
4356
|
+
this.updateAvailabilityChecker?.stop();
|
|
4357
|
+
this.seekUpdate(versionForeignInput);
|
|
4358
|
+
const updatePhase = this.storage.getItem(`updatePhase`);
|
|
4359
|
+
this.logger.info(`> storage("updatePhase") >`, updatePhase);
|
|
4360
|
+
if (updatePhase === `notified`) {
|
|
4361
|
+
this.updateAvailabilityChecker = new CronJob(
|
|
4362
|
+
`30 * * * * *`,
|
|
4363
|
+
() => {
|
|
4364
|
+
this.seekUpdate(versionForeignInput);
|
|
4365
|
+
}
|
|
4366
|
+
);
|
|
4367
|
+
this.updateAvailabilityChecker.start();
|
|
4368
|
+
}
|
|
4369
|
+
} else {
|
|
4370
|
+
this.downloadPackage();
|
|
4371
|
+
}
|
|
4372
|
+
} catch (thrown) {
|
|
4373
|
+
this.logger.error(thrown, req.url);
|
|
4374
|
+
if (typeof thrown === `number`) {
|
|
4375
|
+
res.writeHead(thrown);
|
|
4376
|
+
res.end();
|
|
4377
|
+
}
|
|
4378
|
+
} finally {
|
|
4379
|
+
data = [];
|
|
4380
|
+
}
|
|
4381
|
+
});
|
|
4382
|
+
}).listen(port, () => {
|
|
4383
|
+
this.logger.info(`Server started on port ${port}`);
|
|
4384
|
+
});
|
|
4385
|
+
}
|
|
4386
|
+
this.startAllServices().then(() => {
|
|
4387
|
+
this.logger.info(`All services started.`);
|
|
4388
|
+
}).catch((thrown) => {
|
|
4389
|
+
if (thrown instanceof Error) {
|
|
4390
|
+
this.logger.error(`Failed to start all services:`, thrown.message);
|
|
4391
|
+
}
|
|
4392
|
+
});
|
|
4393
|
+
}
|
|
4394
|
+
safety = 0;
|
|
4395
|
+
storage;
|
|
4396
|
+
webhookServer;
|
|
4397
|
+
services;
|
|
4398
|
+
serviceIdx;
|
|
4399
|
+
defaultServicesReadyToUpdate;
|
|
4400
|
+
servicesReadyToUpdate;
|
|
4401
|
+
autoRespawnDeadServices;
|
|
4402
|
+
logger;
|
|
4403
|
+
serviceLoggers;
|
|
4404
|
+
updateAvailabilityChecker = null;
|
|
4405
|
+
servicesLive;
|
|
4406
|
+
servicesDead;
|
|
4407
|
+
live = new Future(() => {
|
|
4408
|
+
});
|
|
4409
|
+
dead = new Future(() => {
|
|
4410
|
+
});
|
|
4411
|
+
restartTimes = [];
|
|
4412
|
+
seekUpdate(version) {
|
|
4413
|
+
this.logger.info(`Checking for updates...`);
|
|
4414
|
+
const { checkAvailability } = this.options.scripts;
|
|
4415
|
+
if (!checkAvailability) {
|
|
4416
|
+
this.logger.info(`No checkAvailability script found.`);
|
|
4417
|
+
return;
|
|
4418
|
+
}
|
|
4419
|
+
try {
|
|
4420
|
+
const out = execSync(`${checkAvailability} ${version}`);
|
|
4421
|
+
this.logger.info(`Check stdout:`, out.toString());
|
|
4422
|
+
this.updateAvailabilityChecker?.stop();
|
|
4423
|
+
this.storage.setItem(`updatePhase`, `confirmed`);
|
|
4424
|
+
this.downloadPackage();
|
|
4425
|
+
this.announceUpdate();
|
|
4426
|
+
} catch (thrown) {
|
|
4427
|
+
if (thrown instanceof Error) {
|
|
4428
|
+
this.logger.error(`Check failed:`, thrown.message);
|
|
4429
|
+
} else {
|
|
4430
|
+
const thrownType = discoverType(thrown);
|
|
4431
|
+
this.logger.error(`Check threw`, thrownType, thrown);
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
announceUpdate() {
|
|
4436
|
+
for (const entry of toEntries(this.services)) {
|
|
4437
|
+
const [serviceName, service] = entry;
|
|
4438
|
+
if (service) {
|
|
4439
|
+
if (this.options.services[serviceName].waitFor) {
|
|
4440
|
+
service.emit(`updatesReady`);
|
|
4441
|
+
}
|
|
4442
|
+
} else {
|
|
4443
|
+
this.startService(serviceName);
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
}
|
|
4447
|
+
tryUpdate() {
|
|
4448
|
+
if (toEntries(this.servicesReadyToUpdate).every(([, isReady]) => isReady)) {
|
|
4449
|
+
this.logger.info(`All services are ready to update.`);
|
|
4450
|
+
this.stopAllServices().then(() => {
|
|
4451
|
+
this.logger.info(`All services stopped; starting up fresh...`);
|
|
4452
|
+
this.startAllServices().then(() => {
|
|
4453
|
+
this.logger.info(`All services started; we're back online.`);
|
|
4454
|
+
}).catch((thrown) => {
|
|
4455
|
+
if (thrown instanceof Error) {
|
|
4456
|
+
this.logger.error(
|
|
4457
|
+
`Failed to start all services:`,
|
|
4458
|
+
thrown.message
|
|
4459
|
+
);
|
|
4460
|
+
}
|
|
4461
|
+
});
|
|
4462
|
+
}).catch((thrown) => {
|
|
4463
|
+
if (thrown instanceof Error) {
|
|
4464
|
+
this.logger.error(`Failed to stop all services:`, thrown.message);
|
|
4465
|
+
}
|
|
4466
|
+
});
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
startAllServices() {
|
|
4470
|
+
this.logger.info(`Starting all services...`);
|
|
4471
|
+
this.autoRespawnDeadServices = true;
|
|
4472
|
+
const setupPhase = this.storage.getItem(`setupPhase`);
|
|
4473
|
+
this.logger.info(`> storage("setupPhase") >`, setupPhase);
|
|
4474
|
+
switch (setupPhase) {
|
|
4475
|
+
case null:
|
|
4476
|
+
this.logger.info(`Starting from scratch.`);
|
|
4477
|
+
this.downloadPackage();
|
|
4478
|
+
this.installPackage();
|
|
4479
|
+
return this.startAllServices();
|
|
4480
|
+
case `downloaded`:
|
|
4481
|
+
this.logger.info(`Found package downloaded but not installed.`);
|
|
4482
|
+
this.installPackage();
|
|
4483
|
+
return this.startAllServices();
|
|
4484
|
+
case `installed`: {
|
|
4485
|
+
for (const [serviceName] of toEntries(this.services)) {
|
|
4486
|
+
this.startService(serviceName);
|
|
4487
|
+
}
|
|
4488
|
+
return this.live;
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
startService(serviceName) {
|
|
4493
|
+
this.logger.info(
|
|
4494
|
+
`Starting service ${this.options.packageName}::${serviceName}, try ${this.safety}/2...`
|
|
4495
|
+
);
|
|
4496
|
+
if (this.safety >= 2) {
|
|
4497
|
+
throw new Error(`Out of tries...`);
|
|
4498
|
+
}
|
|
4499
|
+
this.safety++;
|
|
4500
|
+
const [exe, ...args] = this.options.services[serviceName].run.split(` `);
|
|
4501
|
+
const serviceProcess = spawn(exe, args, {
|
|
4502
|
+
cwd: this.options.flightdeckRootDir,
|
|
4503
|
+
env: import.meta.env
|
|
4504
|
+
});
|
|
4505
|
+
const serviceLogger = this.serviceLoggers[serviceName];
|
|
4506
|
+
const service = this.services[serviceName] = new ChildSocket(
|
|
4507
|
+
serviceProcess,
|
|
4508
|
+
`${this.options.packageName}::${serviceName}`,
|
|
4509
|
+
serviceLogger
|
|
4510
|
+
);
|
|
4511
|
+
serviceLogger.processCode = service.process.pid ?? -1;
|
|
4512
|
+
this.services[serviceName].onAny((...messages) => {
|
|
4513
|
+
serviceLogger.info(`\u{1F4AC}`, ...messages);
|
|
4514
|
+
});
|
|
4515
|
+
this.services[serviceName].on(`readyToUpdate`, () => {
|
|
4516
|
+
this.logger.info(`Service "${serviceName}" is ready to update.`);
|
|
4517
|
+
this.servicesReadyToUpdate[serviceName] = true;
|
|
4518
|
+
this.tryUpdate();
|
|
4519
|
+
});
|
|
4520
|
+
this.services[serviceName].on(`alive`, () => {
|
|
4521
|
+
this.servicesLive[this.serviceIdx[serviceName]].use(Promise.resolve());
|
|
4522
|
+
this.servicesDead[this.serviceIdx[serviceName]] = new Future(() => {
|
|
4523
|
+
});
|
|
4524
|
+
if (this.dead.done) {
|
|
4525
|
+
this.dead = new Future(() => {
|
|
4526
|
+
});
|
|
4527
|
+
}
|
|
4528
|
+
this.dead.use(Promise.all(this.servicesDead));
|
|
4529
|
+
});
|
|
4530
|
+
this.services[serviceName].process.once(`close`, (exitCode) => {
|
|
4531
|
+
this.logger.info(
|
|
4532
|
+
`Auto-respawn saw "${serviceName}" exit with code ${exitCode}`
|
|
4533
|
+
);
|
|
4534
|
+
this.services[serviceName] = null;
|
|
4535
|
+
if (!this.autoRespawnDeadServices) {
|
|
4536
|
+
this.logger.info(`Auto-respawn is off; "${serviceName}" rests.`);
|
|
4537
|
+
return;
|
|
4538
|
+
}
|
|
4539
|
+
const updatePhase = this.storage.getItem(`updatePhase`);
|
|
4540
|
+
this.logger.info(`> storage("updatePhase") >`, updatePhase);
|
|
4541
|
+
const updatesAreReady = updatePhase === `confirmed`;
|
|
4542
|
+
if (updatesAreReady) {
|
|
4543
|
+
this.serviceLoggers[serviceName].info(`Updating before startup...`);
|
|
4544
|
+
this.restartTimes = [];
|
|
4545
|
+
this.installPackage();
|
|
4546
|
+
this.startService(serviceName);
|
|
4547
|
+
} else {
|
|
4548
|
+
const now = Date.now();
|
|
4549
|
+
const fiveMinutesAgo = now - 5 * 60 * 1e3;
|
|
4550
|
+
this.restartTimes = this.restartTimes.filter(
|
|
4551
|
+
(time) => time > fiveMinutesAgo
|
|
4552
|
+
);
|
|
4553
|
+
this.restartTimes.push(now);
|
|
4554
|
+
if (this.restartTimes.length < 5) {
|
|
4555
|
+
this.serviceLoggers[serviceName].info(`Crashed. Restarting...`);
|
|
4556
|
+
this.startService(serviceName);
|
|
4557
|
+
} else {
|
|
4558
|
+
this.serviceLoggers[serviceName].info(
|
|
4559
|
+
`Crashed 5 times in 5 minutes. Not restarting.`
|
|
4560
|
+
);
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
});
|
|
4564
|
+
this.safety = 0;
|
|
4565
|
+
}
|
|
4566
|
+
downloadPackage() {
|
|
4567
|
+
this.logger.info(`Downloading...`);
|
|
4568
|
+
try {
|
|
4569
|
+
const out = execSync(this.options.scripts.download);
|
|
4570
|
+
this.logger.info(`Download stdout:`, out.toString());
|
|
4571
|
+
this.storage.setItem(`setupPhase`, `downloaded`);
|
|
4572
|
+
this.logger.info(`Downloaded!`);
|
|
4573
|
+
} catch (thrown) {
|
|
4574
|
+
if (thrown instanceof Error) {
|
|
4575
|
+
this.logger.error(`Failed to get the latest release: ${thrown.message}`);
|
|
4576
|
+
}
|
|
4577
|
+
return;
|
|
4578
|
+
}
|
|
4579
|
+
}
|
|
4580
|
+
installPackage() {
|
|
4581
|
+
this.logger.info(`Installing...`);
|
|
4582
|
+
try {
|
|
4583
|
+
const out = execSync(this.options.scripts.install);
|
|
4584
|
+
this.logger.info(`Install stdout:`, out.toString());
|
|
4585
|
+
this.storage.setItem(`setupPhase`, `installed`);
|
|
4586
|
+
this.logger.info(`Installed!`);
|
|
4587
|
+
} catch (thrown) {
|
|
4588
|
+
if (thrown instanceof Error) {
|
|
4589
|
+
this.logger.error(`Failed to get the latest release: ${thrown.message}`);
|
|
4590
|
+
}
|
|
4591
|
+
return;
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
stopAllServices() {
|
|
4595
|
+
this.logger.info(`Stopping all services... auto-respawn disabled.`);
|
|
4596
|
+
this.autoRespawnDeadServices = false;
|
|
4597
|
+
for (const [serviceName] of toEntries(this.services)) {
|
|
4598
|
+
this.stopService(serviceName);
|
|
4599
|
+
}
|
|
4600
|
+
return this.dead;
|
|
4601
|
+
}
|
|
4602
|
+
stopService(serviceName) {
|
|
4603
|
+
const service = this.services[serviceName];
|
|
4604
|
+
if (service) {
|
|
4605
|
+
this.logger.info(`Stopping service "${serviceName}"...`);
|
|
4606
|
+
this.servicesDead[this.serviceIdx[serviceName]].use(
|
|
4607
|
+
new Promise((pass) => {
|
|
4608
|
+
service.emit(`timeToStop`);
|
|
4609
|
+
service.process.once(`close`, (exitCode) => {
|
|
4610
|
+
this.logger.info(
|
|
4611
|
+
`Stopped service "${serviceName}"; exited with code ${exitCode}`
|
|
4612
|
+
);
|
|
4613
|
+
this.services[serviceName] = null;
|
|
4614
|
+
pass();
|
|
4615
|
+
});
|
|
4616
|
+
})
|
|
4617
|
+
);
|
|
4618
|
+
this.dead.use(Promise.all(this.servicesDead));
|
|
4619
|
+
this.servicesLive[this.serviceIdx[serviceName]] = new Future(() => {
|
|
4620
|
+
});
|
|
4621
|
+
if (this.live.done) {
|
|
4622
|
+
this.live = new Future(() => {
|
|
4623
|
+
});
|
|
4624
|
+
}
|
|
4625
|
+
this.live.use(Promise.all(this.servicesLive));
|
|
4626
|
+
} else {
|
|
4627
|
+
this.serviceLoggers[serviceName].error(
|
|
4628
|
+
`Tried to stop service, but it wasn't running.`
|
|
4629
|
+
);
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
};
|
|
4633
|
+
var FLIGHTDECK_INFO = `info`;
|
|
4634
|
+
var FLIGHTDECK_WARN = `warn`;
|
|
4635
|
+
var FLIGHTDECK_ERROR = `ERR!`;
|
|
4636
|
+
var flightDeckLogSchema = z.object({
|
|
4637
|
+
level: z.union([
|
|
4638
|
+
z.literal(FLIGHTDECK_INFO),
|
|
4639
|
+
z.literal(FLIGHTDECK_WARN),
|
|
4640
|
+
z.literal(FLIGHTDECK_ERROR)
|
|
4641
|
+
]),
|
|
4642
|
+
timestamp: z.number(),
|
|
4643
|
+
package: z.string(),
|
|
4644
|
+
service: z.string().optional(),
|
|
4645
|
+
process: z.number(),
|
|
4646
|
+
body: z.string()
|
|
4647
|
+
});
|
|
4648
|
+
var LINE_FORMAT = `line-format`;
|
|
4649
|
+
var VALUE = `value`;
|
|
4650
|
+
var FLIGHTDECK_LNAV_FORMAT = {
|
|
4651
|
+
title: `FlightDeck Log`,
|
|
4652
|
+
description: `Format for events logged by the FlightDeck process manager.`,
|
|
4653
|
+
"file-type": `json`,
|
|
4654
|
+
"timestamp-field": `timestamp`,
|
|
4655
|
+
"timestamp-divisor": 1e3,
|
|
4656
|
+
"module-field": `package`,
|
|
4657
|
+
"opid-field": `service`,
|
|
4658
|
+
"level-field": `level`,
|
|
4659
|
+
level: {
|
|
4660
|
+
info: FLIGHTDECK_INFO,
|
|
4661
|
+
warning: FLIGHTDECK_WARN,
|
|
4662
|
+
error: FLIGHTDECK_ERROR
|
|
4663
|
+
},
|
|
4664
|
+
[LINE_FORMAT]: [
|
|
4665
|
+
{
|
|
4666
|
+
field: `level`
|
|
4667
|
+
},
|
|
4668
|
+
{
|
|
4669
|
+
prefix: ` `,
|
|
4670
|
+
field: `__timestamp__`,
|
|
4671
|
+
"timestamp-format": `%Y-%m-%dT%H:%M:%S.%L%Z`
|
|
4672
|
+
},
|
|
4673
|
+
{
|
|
4674
|
+
prefix: ` `,
|
|
4675
|
+
field: `process`,
|
|
4676
|
+
"min-width": 5
|
|
4677
|
+
},
|
|
4678
|
+
{
|
|
4679
|
+
prefix: `:`,
|
|
4680
|
+
field: `package`
|
|
4681
|
+
},
|
|
4682
|
+
{
|
|
4683
|
+
prefix: `:`,
|
|
4684
|
+
field: `service`,
|
|
4685
|
+
"default-value": ``
|
|
4686
|
+
},
|
|
4687
|
+
{
|
|
4688
|
+
prefix: `: `,
|
|
4689
|
+
field: `body`
|
|
4690
|
+
}
|
|
4691
|
+
],
|
|
4692
|
+
[VALUE]: {
|
|
4693
|
+
timestamp: {
|
|
4694
|
+
kind: `integer`
|
|
4695
|
+
},
|
|
4696
|
+
level: {
|
|
4697
|
+
kind: `string`
|
|
4698
|
+
},
|
|
4699
|
+
package: {
|
|
4700
|
+
kind: `string`
|
|
4701
|
+
},
|
|
4702
|
+
service: {
|
|
4703
|
+
kind: `string`
|
|
4704
|
+
},
|
|
4705
|
+
process: {
|
|
4706
|
+
kind: `integer`
|
|
4707
|
+
},
|
|
4708
|
+
body: {
|
|
4709
|
+
kind: `string`
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
};
|
|
4713
|
+
var FlightDeckLogger = class {
|
|
4714
|
+
packageName;
|
|
4715
|
+
serviceName;
|
|
4716
|
+
jsonLogging;
|
|
4717
|
+
processCode;
|
|
4718
|
+
constructor(packageName, processCode, serviceName, options) {
|
|
4719
|
+
this.packageName = packageName;
|
|
4720
|
+
if (serviceName) {
|
|
4721
|
+
this.serviceName = serviceName;
|
|
4722
|
+
}
|
|
4723
|
+
this.processCode = processCode;
|
|
4724
|
+
this.jsonLogging = options?.jsonLogging ?? false;
|
|
4725
|
+
}
|
|
4726
|
+
log(level, ...messages) {
|
|
4727
|
+
if (this.jsonLogging) {
|
|
4728
|
+
let body = messages.map(
|
|
4729
|
+
(message) => typeof message === `string` ? message : inspect(message, false, null, true)
|
|
4730
|
+
).join(` `);
|
|
4731
|
+
if (body.includes(`
|
|
4732
|
+
`)) {
|
|
4733
|
+
body = `
|
|
4734
|
+
${body.split(`
|
|
4735
|
+
`).join(`
|
|
4736
|
+
`)}`;
|
|
4737
|
+
}
|
|
4738
|
+
const log = {
|
|
4739
|
+
timestamp: Date.now(),
|
|
4740
|
+
level,
|
|
4741
|
+
process: this.processCode,
|
|
4742
|
+
package: this.packageName,
|
|
4743
|
+
body
|
|
4744
|
+
};
|
|
4745
|
+
if (this.serviceName) {
|
|
4746
|
+
log.service = this.serviceName;
|
|
4747
|
+
}
|
|
4748
|
+
process.stdout.write(JSON.stringify(log) + `
|
|
4749
|
+
`);
|
|
4750
|
+
} else {
|
|
4751
|
+
const source = this.serviceName ? `${this.packageName}:${this.serviceName}` : this.packageName;
|
|
4752
|
+
switch (level) {
|
|
4753
|
+
case FLIGHTDECK_INFO:
|
|
4754
|
+
console.log(`${source}:`, ...messages);
|
|
4755
|
+
break;
|
|
4756
|
+
case FLIGHTDECK_WARN:
|
|
4757
|
+
console.warn(`${source}:`, ...messages);
|
|
4758
|
+
break;
|
|
4759
|
+
case FLIGHTDECK_ERROR:
|
|
4760
|
+
console.error(`${source}:`, ...messages);
|
|
4761
|
+
break;
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
info(...messages) {
|
|
4766
|
+
this.log(FLIGHTDECK_INFO, ...messages);
|
|
4767
|
+
}
|
|
4768
|
+
warn(...messages) {
|
|
4769
|
+
this.log(FLIGHTDECK_WARN, ...messages);
|
|
4770
|
+
}
|
|
4771
|
+
error(...messages) {
|
|
4772
|
+
this.log(FLIGHTDECK_ERROR, ...messages);
|
|
4773
|
+
}
|
|
4774
|
+
};
|
|
4775
|
+
|
|
4776
|
+
export { FLIGHTDECK_ERROR, FLIGHTDECK_INFO, FLIGHTDECK_LNAV_FORMAT, FLIGHTDECK_SETUP_PHASES, FLIGHTDECK_UPDATE_PHASES, FLIGHTDECK_WARN, FlightDeck, FlightDeckLogger, flightDeckLogSchema, isVersionNumber };
|
|
4777
|
+
//# sourceMappingURL=chunk-XIZZKICH.js.map
|
|
4778
|
+
//# sourceMappingURL=chunk-XIZZKICH.js.map
|