atom.io 0.27.2 → 0.27.4

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.
Files changed (52) hide show
  1. package/data/dist/index.d.ts +12 -12
  2. package/data/dist/index.js +20 -14
  3. package/data/src/dict.ts +4 -4
  4. package/data/src/join.ts +23 -18
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/chunk-JRENM6KL.js +3148 -0
  7. package/dist/index.d.ts +3 -30
  8. package/eslint-plugin/dist/index.js +8 -0
  9. package/eslint-plugin/src/walk.ts +8 -0
  10. package/internal/dist/index.d.ts +55 -25
  11. package/internal/dist/index.js +2 -3044
  12. package/internal/src/families/create-atom-family.ts +6 -5
  13. package/internal/src/families/create-readonly-selector-family.ts +54 -28
  14. package/internal/src/families/create-regular-atom-family.ts +41 -31
  15. package/internal/src/families/create-selector-family.ts +6 -5
  16. package/internal/src/families/create-writable-selector-family.ts +55 -29
  17. package/internal/src/families/dispose-from-store.ts +11 -2
  18. package/internal/src/families/seek-in-store.ts +0 -3
  19. package/internal/src/families/throw-in-case-of-conflicting-family.ts +18 -0
  20. package/internal/src/get-state/get-from-store.ts +26 -2
  21. package/internal/src/get-state/read-or-compute-value.ts +1 -1
  22. package/internal/src/index.ts +78 -2
  23. package/internal/src/ingest-updates/ingest-creation-disposal.ts +0 -1
  24. package/internal/src/ingest-updates/ingest-selector-update.ts +1 -1
  25. package/internal/src/molecule/dispose-molecule.ts +0 -1
  26. package/internal/src/molecule/grow-molecule-in-store.ts +27 -17
  27. package/internal/src/mutable/create-mutable-atom-family.ts +41 -32
  28. package/internal/src/mutable/get-json-family.ts +2 -1
  29. package/internal/src/mutable/get-update-family.ts +23 -0
  30. package/internal/src/mutable/index.ts +1 -0
  31. package/internal/src/mutable/tracker-family.ts +5 -3
  32. package/internal/src/not-found-error.ts +2 -35
  33. package/internal/src/pretty-print.ts +37 -0
  34. package/internal/src/selector/create-writable-selector.ts +6 -6
  35. package/internal/src/set-state/set-into-store.ts +13 -2
  36. package/internal/src/store/deposit.ts +11 -10
  37. package/internal/src/store/store.ts +11 -4
  38. package/internal/src/store/withdraw.ts +8 -8
  39. package/internal/src/transaction/build-transaction.ts +1 -0
  40. package/introspection/dist/index.js +3 -3
  41. package/introspection/src/attach-timeline-family.ts +1 -1
  42. package/introspection/src/attach-transaction-logs.ts +2 -2
  43. package/json/dist/index.d.ts +2 -2
  44. package/json/dist/index.js +16 -12
  45. package/json/src/select-json-family.ts +21 -18
  46. package/package.json +7 -7
  47. package/realtime-server/dist/index.d.ts +1 -1
  48. package/src/atom.ts +2 -32
  49. package/src/index.ts +1 -10
  50. package/src/logger.ts +4 -0
  51. package/src/selector.ts +1 -26
  52. package/src/silo.ts +7 -5
@@ -0,0 +1,3148 @@
1
+ import { Junction } from './chunk-IBTHB2PI.js';
2
+ import { stringifyJson, parseJson, selectJson, selectJsonFamily } from 'atom.io/json';
3
+ import { AtomIOLogger } from 'atom.io';
4
+ import { getJoin, findRelations } from 'atom.io/data';
5
+
6
+ // internal/src/arbitrary.ts
7
+ function arbitrary(random = Math.random) {
8
+ return random().toString(36).slice(2);
9
+ }
10
+
11
+ // internal/src/future.ts
12
+ var Future = class extends Promise {
13
+ fate;
14
+ resolve;
15
+ reject;
16
+ constructor(executor) {
17
+ let superResolve;
18
+ let superReject;
19
+ super((resolve, reject) => {
20
+ superResolve = resolve;
21
+ superReject = reject;
22
+ });
23
+ this.resolve = superResolve;
24
+ this.reject = superReject;
25
+ this.use(executor instanceof Promise ? executor : new Promise(executor));
26
+ }
27
+ pass(promise, value) {
28
+ if (promise === this.fate) {
29
+ this.resolve(value);
30
+ }
31
+ }
32
+ fail(promise, reason) {
33
+ if (promise === this.fate) {
34
+ this.reject(reason);
35
+ }
36
+ }
37
+ use(value) {
38
+ if (value instanceof Promise) {
39
+ const promise = value;
40
+ this.fate = promise;
41
+ promise.then(
42
+ (resolved) => {
43
+ this.pass(promise, resolved);
44
+ },
45
+ (reason) => {
46
+ this.fail(promise, reason);
47
+ }
48
+ );
49
+ } else {
50
+ this.resolve(value);
51
+ this.fate = void 0;
52
+ }
53
+ }
54
+ };
55
+
56
+ // internal/src/lineage.ts
57
+ function newest(scion) {
58
+ while (scion.child !== null) {
59
+ scion = scion.child;
60
+ }
61
+ return scion;
62
+ }
63
+ function eldest(scion) {
64
+ while (scion.parent !== null) {
65
+ scion = scion.parent;
66
+ }
67
+ return scion;
68
+ }
69
+
70
+ // internal/src/store/deposit.ts
71
+ function deposit(state) {
72
+ const token = {
73
+ key: state.key,
74
+ type: state.type
75
+ };
76
+ if (`family` in state) {
77
+ token.family = state.family;
78
+ }
79
+ return token;
80
+ }
81
+
82
+ // internal/src/subject.ts
83
+ var Subject = class {
84
+ Subscriber;
85
+ subscribers = /* @__PURE__ */ new Map();
86
+ subscribe(key, subscriber) {
87
+ this.subscribers.set(key, subscriber);
88
+ const unsubscribe = () => {
89
+ this.unsubscribe(key);
90
+ };
91
+ return unsubscribe;
92
+ }
93
+ unsubscribe(key) {
94
+ this.subscribers.delete(key);
95
+ }
96
+ next(value) {
97
+ const subscribers = this.subscribers.values();
98
+ for (const subscriber of subscribers) {
99
+ subscriber(value);
100
+ }
101
+ }
102
+ };
103
+ var StatefulSubject = class extends Subject {
104
+ state;
105
+ constructor(initialState) {
106
+ super();
107
+ this.state = initialState;
108
+ }
109
+ next(value) {
110
+ this.state = value;
111
+ super.next(value);
112
+ }
113
+ };
114
+
115
+ // internal/src/transaction/is-root-store.ts
116
+ function isRootStore(store) {
117
+ return `epoch` in store.transactionMeta;
118
+ }
119
+ function isChildStore(store) {
120
+ return `phase` in store.transactionMeta;
121
+ }
122
+
123
+ // internal/src/transaction/abort-transaction.ts
124
+ var abortTransaction = (store) => {
125
+ const target = newest(store);
126
+ if (!isChildStore(target)) {
127
+ store.logger.warn(
128
+ `\u{1F41E}`,
129
+ `transaction`,
130
+ `???`,
131
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
132
+ );
133
+ return;
134
+ }
135
+ store.logger.info(
136
+ `\u{1FA82}`,
137
+ `transaction`,
138
+ target.transactionMeta.update.key,
139
+ `Aborting transaction`
140
+ );
141
+ target.parent.child = null;
142
+ };
143
+
144
+ // internal/src/pretty-print.ts
145
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
146
+ function prettyPrintTokenType(token) {
147
+ switch (token.type) {
148
+ case `atom_family`:
149
+ return `Atom Family`;
150
+ case `molecule_family`:
151
+ return `Molecule Family`;
152
+ case `mutable_atom_family`:
153
+ return `Mutable Atom Family`;
154
+ case `readonly_selector`:
155
+ return `Readonly Selector`;
156
+ case `readonly_selector_family`:
157
+ return `Readonly Selector Family`;
158
+ case `selector_family`:
159
+ return `Selector Family`;
160
+ default:
161
+ return capitalize(token.type);
162
+ }
163
+ }
164
+
165
+ // internal/src/not-found-error.ts
166
+ var NotFoundError = class extends Error {
167
+ constructor(...params) {
168
+ const token = params[0];
169
+ const store = params.length === 2 ? params[1] : params[2];
170
+ if (params.length === 2) {
171
+ super(
172
+ `${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
173
+ );
174
+ } else {
175
+ const key = params[1];
176
+ super(
177
+ `${prettyPrintTokenType(token)} "${token.key}" member ${stringifyJson(key)} not found in store "${store.config.name}".`
178
+ );
179
+ }
180
+ }
181
+ };
182
+
183
+ // internal/src/transaction/act-upon-store.ts
184
+ function actUponStore(token, id, store) {
185
+ return (...parameters) => {
186
+ const tx = withdraw(token, store);
187
+ if (tx) {
188
+ return tx.run(parameters, id);
189
+ }
190
+ throw new NotFoundError(token, store);
191
+ };
192
+ }
193
+
194
+ // internal/src/set-state/become.ts
195
+ var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
196
+ originalThing instanceof Function ? originalThing() : originalThing
197
+ ) : nextVersionOfThing;
198
+
199
+ // internal/src/get-state/read-or-compute-value.ts
200
+ var readOrComputeValue = (state, target) => {
201
+ if (target.valueMap.has(state.key)) {
202
+ target.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
203
+ return readCachedValue(state, target);
204
+ }
205
+ if (state.type === `selector` || state.type === `readonly_selector`) {
206
+ target.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
207
+ return state.get();
208
+ }
209
+ const fallback = state.default instanceof Function ? state.default() : state.default;
210
+ target.logger.info(
211
+ `\u{1F481}`,
212
+ `atom`,
213
+ state.key,
214
+ `could not find cached value; using default`,
215
+ fallback
216
+ );
217
+ return state.default instanceof Function ? state.default() : state.default;
218
+ };
219
+
220
+ // internal/src/operation.ts
221
+ var openOperation = (token, store) => {
222
+ if (store.operation.open) {
223
+ const rejectionTime = performance.now();
224
+ store.logger.info(
225
+ `\u2757`,
226
+ token.type,
227
+ token.key,
228
+ `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`
229
+ );
230
+ return rejectionTime;
231
+ }
232
+ store.operation = {
233
+ open: true,
234
+ done: /* @__PURE__ */ new Set(),
235
+ prev: /* @__PURE__ */ new Map(),
236
+ time: Date.now(),
237
+ token
238
+ };
239
+ store.logger.info(
240
+ `\u2B55`,
241
+ token.type,
242
+ token.key,
243
+ `operation start in store "${store.config.name}"${!isChildStore(store) ? `` : ` ${store.transactionMeta.phase} "${store.transactionMeta.update.key}"`}`
244
+ );
245
+ };
246
+ var closeOperation = (store) => {
247
+ if (store.operation.open) {
248
+ store.logger.info(
249
+ `\u{1F534}`,
250
+ store.operation.token.type,
251
+ store.operation.token.key,
252
+ `operation done in store "${store.config.name}"`
253
+ );
254
+ }
255
+ store.operation = { open: false };
256
+ store.on.operationClose.next(store.operation);
257
+ };
258
+ var isDone = (key, store) => {
259
+ if (!store.operation.open) {
260
+ store.logger.warn(
261
+ `\u{1F41E}`,
262
+ `unknown`,
263
+ key,
264
+ `isDone called outside of an operation. This is probably a bug.`
265
+ );
266
+ return true;
267
+ }
268
+ return store.operation.done.has(key);
269
+ };
270
+ var markDone = (key, store) => {
271
+ if (!store.operation.open) {
272
+ store.logger.warn(
273
+ `\u{1F41E}`,
274
+ `unknown`,
275
+ key,
276
+ `markDone called outside of an operation. This is probably a bug.`
277
+ );
278
+ return;
279
+ }
280
+ store.operation.done.add(key);
281
+ };
282
+
283
+ // internal/src/set-state/emit-update.ts
284
+ var emitUpdate = (state, update, store) => {
285
+ switch (state.type) {
286
+ case `mutable_atom`:
287
+ store.logger.info(
288
+ `\u{1F4E2}`,
289
+ state.type,
290
+ state.key,
291
+ `is now (`,
292
+ update.newValue,
293
+ `) subscribers:`,
294
+ state.subject.subscribers
295
+ );
296
+ break;
297
+ default:
298
+ store.logger.info(
299
+ `\u{1F4E2}`,
300
+ state.type,
301
+ state.key,
302
+ `went (`,
303
+ update.oldValue,
304
+ `->`,
305
+ update.newValue,
306
+ `) subscribers:`,
307
+ state.subject.subscribers
308
+ );
309
+ }
310
+ state.subject.next(update);
311
+ };
312
+
313
+ // internal/src/set-state/evict-downstream.ts
314
+ var evictDownStream = (atom, store) => {
315
+ const target = newest(store);
316
+ const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom.key);
317
+ target.logger.info(
318
+ `\u{1F9F9}`,
319
+ atom.type,
320
+ atom.key,
321
+ downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
322
+ downstreamKeys ?? `to evict`
323
+ );
324
+ if (downstreamKeys) {
325
+ if (target.operation.open) {
326
+ target.logger.info(
327
+ `\u{1F9F9}`,
328
+ atom.type,
329
+ atom.key,
330
+ `[ ${[...target.operation.done].join(`, `)} ] already done`
331
+ );
332
+ }
333
+ for (const key of downstreamKeys) {
334
+ if (isDone(key, target)) {
335
+ continue;
336
+ }
337
+ evictCachedValue(key, target);
338
+ markDone(key, target);
339
+ }
340
+ }
341
+ };
342
+
343
+ // internal/src/set-state/stow-update.ts
344
+ function shouldUpdateBeStowed(key, update) {
345
+ if (isTransceiver(update.newValue)) {
346
+ return false;
347
+ }
348
+ if (key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
349
+ return false;
350
+ }
351
+ return true;
352
+ }
353
+ var stowUpdate = (state, update, store) => {
354
+ const { key } = state;
355
+ const target = newest(store);
356
+ if (!isChildStore(target) || target.transactionMeta.phase !== `building`) {
357
+ store.logger.error(
358
+ `\u{1F41E}`,
359
+ `atom`,
360
+ key,
361
+ `stowUpdate called outside of a transaction. This is probably a bug.`
362
+ );
363
+ return;
364
+ }
365
+ const shouldStow = shouldUpdateBeStowed(key, update);
366
+ if (!shouldStow) {
367
+ return;
368
+ }
369
+ const atomUpdate = {
370
+ type: `atom_update`,
371
+ key,
372
+ ...update
373
+ };
374
+ if (state.family) {
375
+ atomUpdate.family = state.family;
376
+ }
377
+ target.transactionMeta.update.updates.push(atomUpdate);
378
+ store.logger.info(
379
+ `\u{1F4C1}`,
380
+ `atom`,
381
+ key,
382
+ `stowed (`,
383
+ update.oldValue,
384
+ `->`,
385
+ update.newValue,
386
+ `)`
387
+ );
388
+ };
389
+
390
+ // internal/src/set-state/set-atom.ts
391
+ var setAtom = (atom, next, target) => {
392
+ const oldValue = readOrComputeValue(atom, target);
393
+ let newValue = oldValue;
394
+ if (atom.type === `mutable_atom` && isChildStore(target)) {
395
+ const { parent } = target;
396
+ const copiedValue = copyMutableIfNeeded(atom, parent, target);
397
+ newValue = copiedValue;
398
+ }
399
+ newValue = become(next)(newValue);
400
+ target.logger.info(`\u{1F4DD}`, `atom`, atom.key, `set to`, newValue);
401
+ newValue = cacheValue(atom.key, newValue, atom.subject, target);
402
+ if (isAtomDefault(atom.key, target)) {
403
+ markAtomAsNotDefault(atom.key, target);
404
+ }
405
+ markDone(atom.key, target);
406
+ evictDownStream(atom, target);
407
+ const update = { oldValue, newValue };
408
+ if (isRootStore(target)) {
409
+ emitUpdate(atom, update, target);
410
+ } else if (target.parent) {
411
+ if (target.on.transactionApplying.state === null) {
412
+ stowUpdate(atom, update, target);
413
+ } else if (atom.key.startsWith(`*`)) {
414
+ const mutableKey = atom.key.slice(1);
415
+ const mutableAtom = target.atoms.get(mutableKey);
416
+ let transceiver = target.valueMap.get(mutableKey);
417
+ if (mutableAtom.type === `mutable_atom` && isChildStore(target)) {
418
+ const { parent } = target;
419
+ const copiedValue = copyMutableIfNeeded(mutableAtom, parent, target);
420
+ transceiver = copiedValue;
421
+ }
422
+ const accepted = transceiver.do(update.newValue) === null;
423
+ if (accepted) evictDownStream(mutableAtom, target);
424
+ }
425
+ }
426
+ };
427
+
428
+ // internal/src/set-state/set-atom-or-selector.ts
429
+ var setAtomOrSelector = (state, value, store) => {
430
+ switch (state.type) {
431
+ case `atom`:
432
+ case `mutable_atom`:
433
+ setAtom(state, value, store);
434
+ break;
435
+ case `selector`:
436
+ state.set(value);
437
+ break;
438
+ }
439
+ };
440
+
441
+ // internal/src/families/throw-in-case-of-conflicting-family.ts
442
+ function throwInCaseOfConflictingFamily(family, store) {
443
+ const existingFamily = store.families.get(family.key);
444
+ if (existingFamily) {
445
+ throw new Error(
446
+ `Tried to create ${family.type === `atom_family` ? `an` : `a`} ${prettyPrintTokenType(family)} with key "${family.key}", but "${family.key}" already exists in store "${store.config.name}" as ${existingFamily.type === `atom_family` ? `an` : `a`} ${prettyPrintTokenType(
447
+ existingFamily
448
+ )}`
449
+ );
450
+ }
451
+ }
452
+
453
+ // internal/src/families/create-regular-atom-family.ts
454
+ function createRegularAtomFamily(options, store, internalRoles) {
455
+ const familyToken = {
456
+ key: options.key,
457
+ type: `atom_family`
458
+ };
459
+ throwInCaseOfConflictingFamily(familyToken, store);
460
+ const subject = new Subject();
461
+ const familyFunction = (key) => {
462
+ const subKey = stringifyJson(key);
463
+ const family = { key: options.key, subKey };
464
+ const fullKey = `${options.key}(${subKey})`;
465
+ const target = newest(store);
466
+ const def = options.default;
467
+ const individualOptions = {
468
+ key: fullKey,
469
+ default: def instanceof Function ? def(key) : def
470
+ };
471
+ if (options.effects) {
472
+ individualOptions.effects = options.effects(key);
473
+ }
474
+ const token = createRegularAtom(individualOptions, family, target);
475
+ subject.next({ type: `state_creation`, token });
476
+ return token;
477
+ };
478
+ const atomFamily = Object.assign(familyFunction, familyToken, {
479
+ subject,
480
+ install: (s) => createRegularAtomFamily(options, s),
481
+ internalRoles
482
+ });
483
+ store.families.set(options.key, atomFamily);
484
+ store.defaults.set(options.key, options.default);
485
+ return familyToken;
486
+ }
487
+
488
+ // internal/src/families/create-atom-family.ts
489
+ function createAtomFamily(options, store) {
490
+ const isMutable = `mutable` in options;
491
+ if (isMutable) {
492
+ return createMutableAtomFamily(options, store);
493
+ }
494
+ return createRegularAtomFamily(options, store);
495
+ }
496
+ function getFromStore(...params) {
497
+ let token;
498
+ let store;
499
+ if (params.length === 2) {
500
+ token = params[0];
501
+ store = params[1];
502
+ } else {
503
+ const family = params[0];
504
+ const key = params[1];
505
+ store = params[2];
506
+ const maybeToken = family.type === `molecule_family` ? seekInStore(family, key, store) : store.config.lifespan === `immortal` ? seekInStore(family, key, store) : findInStore(family, key, store);
507
+ if (!maybeToken) {
508
+ store.logger.error(
509
+ `\u2757`,
510
+ family.type,
511
+ family.key,
512
+ `tried to get member`,
513
+ stringifyJson(key),
514
+ `but it was not found in store`,
515
+ store.config.name
516
+ );
517
+ switch (family.type) {
518
+ case `atom_family`:
519
+ case `mutable_atom_family`:
520
+ return store.defaults.get(family.key);
521
+ case `selector_family`:
522
+ case `readonly_selector_family`: {
523
+ if (store.defaults.has(family.key)) {
524
+ return store.defaults.get(family.key);
525
+ }
526
+ const defaultValue = withdraw(family, store).default(key);
527
+ store.defaults.set(family.key, defaultValue);
528
+ return defaultValue;
529
+ }
530
+ case `molecule_family`:
531
+ throw new NotFoundError(family, key, store);
532
+ }
533
+ }
534
+ token = maybeToken;
535
+ }
536
+ switch (token.type) {
537
+ case `atom`:
538
+ case `mutable_atom`:
539
+ case `selector`:
540
+ case `readonly_selector`:
541
+ return readOrComputeValue(withdraw(token, store), store);
542
+ case `molecule`:
543
+ return withdraw(token, store).instance;
544
+ }
545
+ }
546
+
547
+ // internal/src/keys.ts
548
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
549
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
550
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
551
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
552
+
553
+ // internal/src/selector/get-selector-dependency-keys.ts
554
+ var getSelectorDependencyKeys = (key, store) => {
555
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
556
+ return sources;
557
+ };
558
+
559
+ // internal/src/selector/trace-selector-atoms.ts
560
+ var traceSelectorAtoms = (directDependencyKey, covered, store) => {
561
+ const rootKeys = [];
562
+ const indirectDependencyKeys = getSelectorDependencyKeys(
563
+ directDependencyKey,
564
+ store
565
+ );
566
+ while (indirectDependencyKeys.length > 0) {
567
+ const indirectDependencyKey = indirectDependencyKeys.shift();
568
+ if (covered.has(indirectDependencyKey)) {
569
+ continue;
570
+ }
571
+ covered.add(indirectDependencyKey);
572
+ if (!isAtomKey(indirectDependencyKey, store)) {
573
+ indirectDependencyKeys.push(
574
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
575
+ );
576
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
577
+ rootKeys.push(indirectDependencyKey);
578
+ }
579
+ }
580
+ return rootKeys;
581
+ };
582
+ var traceAllSelectorAtoms = (selector, store) => {
583
+ const selectorKey = selector.key;
584
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
585
+ const covered = /* @__PURE__ */ new Set();
586
+ return directDependencyKeys.flatMap(
587
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(depKey, covered, store)
588
+ );
589
+ };
590
+
591
+ // internal/src/selector/update-selector-atoms.ts
592
+ var updateSelectorAtoms = (selectorKey, dependency, covered, store) => {
593
+ const target = newest(store);
594
+ if (dependency.type === `atom` || dependency.type === `mutable_atom`) {
595
+ target.selectorAtoms.set({
596
+ selectorKey,
597
+ atomKey: dependency.key
598
+ });
599
+ store.logger.info(
600
+ `\u{1F50D}`,
601
+ `selector`,
602
+ selectorKey,
603
+ `discovers root atom "${dependency.key}"`
604
+ );
605
+ } else {
606
+ const rootKeys = traceSelectorAtoms(dependency.key, covered, store);
607
+ store.logger.info(
608
+ `\u{1F50D}`,
609
+ `selector`,
610
+ selectorKey,
611
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
612
+ );
613
+ for (const atomKey of rootKeys) {
614
+ target.selectorAtoms = target.selectorAtoms.set({
615
+ selectorKey,
616
+ atomKey
617
+ });
618
+ }
619
+ }
620
+ covered.add(dependency.key);
621
+ };
622
+
623
+ // internal/src/selector/register-selector.ts
624
+ var registerSelector = (selectorKey, covered, store) => ({
625
+ get: (...params) => {
626
+ const target = newest(store);
627
+ let dependency;
628
+ if (params.length === 2) {
629
+ const [family, key] = params;
630
+ switch (family.type) {
631
+ case `molecule_family`:
632
+ return getFromStore(family, key, store);
633
+ default:
634
+ if (store.config.lifespan === `ephemeral`) {
635
+ dependency = findInStore(family, key, store);
636
+ } else {
637
+ const maybeDependency = seekInStore(family, key, store);
638
+ if (maybeDependency) {
639
+ dependency = maybeDependency;
640
+ } else {
641
+ throw new NotFoundError(family, key, store);
642
+ }
643
+ }
644
+ }
645
+ } else {
646
+ [dependency] = params;
647
+ }
648
+ if (dependency.type === `molecule`) {
649
+ return getFromStore(dependency, store);
650
+ }
651
+ const dependencyState = withdraw(dependency, store);
652
+ const dependencyValue = readOrComputeValue(dependencyState, store);
653
+ store.logger.info(
654
+ `\u{1F50C}`,
655
+ `selector`,
656
+ selectorKey,
657
+ `registers dependency ( "${dependency.key}" =`,
658
+ dependencyValue,
659
+ `)`
660
+ );
661
+ target.selectorGraph.set(
662
+ {
663
+ upstreamSelectorKey: dependency.key,
664
+ downstreamSelectorKey: selectorKey
665
+ },
666
+ {
667
+ source: dependency.key
668
+ }
669
+ );
670
+ updateSelectorAtoms(selectorKey, dependency, covered, store);
671
+ return dependencyValue;
672
+ },
673
+ set: (...params) => {
674
+ let token;
675
+ let value;
676
+ if (params.length === 2) {
677
+ token = params[0];
678
+ value = params[1];
679
+ } else {
680
+ const family = params[0];
681
+ const key = params[1];
682
+ value = params[2];
683
+ const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(family, key, store) : seekInStore(family, key, store);
684
+ if (!maybeToken) {
685
+ throw new NotFoundError(family, key, store);
686
+ }
687
+ token = maybeToken;
688
+ }
689
+ const target = newest(store);
690
+ const state = withdraw(token, target);
691
+ setAtomOrSelector(state, value, target);
692
+ },
693
+ find: (token, key) => findInStore(token, key, store),
694
+ seek: (token, key) => seekInStore(token, key, store),
695
+ json: (token) => getJsonToken(token, store)
696
+ });
697
+
698
+ // internal/src/selector/create-readonly-selector.ts
699
+ var createReadonlySelector = (options, family, store) => {
700
+ const target = newest(store);
701
+ const subject = new Subject();
702
+ const covered = /* @__PURE__ */ new Set();
703
+ const { get, find, seek, json } = registerSelector(
704
+ options.key,
705
+ covered,
706
+ target
707
+ );
708
+ const getSelf = () => {
709
+ const value = options.get({ get, find, seek, json });
710
+ cacheValue(options.key, value, subject, newest(store));
711
+ covered.clear();
712
+ return value;
713
+ };
714
+ const readonlySelector = {
715
+ ...options,
716
+ subject,
717
+ install: (s) => createReadonlySelector(options, family, s),
718
+ get: getSelf,
719
+ type: `readonly_selector`,
720
+ ...family && { family }
721
+ };
722
+ target.readonlySelectors.set(options.key, readonlySelector);
723
+ const initialValue = getSelf();
724
+ store.logger.info(
725
+ `\u2728`,
726
+ readonlySelector.type,
727
+ readonlySelector.key,
728
+ `=`,
729
+ initialValue
730
+ );
731
+ const token = {
732
+ key: options.key,
733
+ type: `readonly_selector`
734
+ };
735
+ if (family) {
736
+ token.family = family;
737
+ }
738
+ return token;
739
+ };
740
+
741
+ // internal/src/selector/create-writable-selector.ts
742
+ var createWritableSelector = (options, family, store) => {
743
+ const target = newest(store);
744
+ const subject = new Subject();
745
+ const covered = /* @__PURE__ */ new Set();
746
+ const setterToolkit = registerSelector(options.key, covered, target);
747
+ const { find, get, seek, json } = setterToolkit;
748
+ const getterToolkit = { find, get, seek, json };
749
+ const getSelf = (getFn = options.get, innerTarget = newest(store)) => {
750
+ const value = getFn(getterToolkit);
751
+ cacheValue(options.key, value, subject, innerTarget);
752
+ covered.clear();
753
+ return value;
754
+ };
755
+ const setSelf = (next) => {
756
+ const innerTarget = newest(store);
757
+ const oldValue = getSelf(options.get, innerTarget);
758
+ const newValue = become(next)(oldValue);
759
+ store.logger.info(
760
+ `\u{1F4DD}`,
761
+ `selector`,
762
+ options.key,
763
+ `set (`,
764
+ oldValue,
765
+ `->`,
766
+ newValue,
767
+ `)`
768
+ );
769
+ cacheValue(options.key, newValue, subject, innerTarget);
770
+ markDone(options.key, innerTarget);
771
+ if (isRootStore(innerTarget)) {
772
+ subject.next({ newValue, oldValue });
773
+ }
774
+ options.set(setterToolkit, newValue);
775
+ };
776
+ const mySelector = {
777
+ ...options,
778
+ subject,
779
+ install: (s) => createWritableSelector(options, family, s),
780
+ get: getSelf,
781
+ set: setSelf,
782
+ type: `selector`,
783
+ ...family && { family }
784
+ };
785
+ target.selectors.set(options.key, mySelector);
786
+ const initialValue = getSelf();
787
+ store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
788
+ const token = {
789
+ key: options.key,
790
+ type: `selector`
791
+ };
792
+ if (family) {
793
+ token.family = family;
794
+ }
795
+ return token;
796
+ };
797
+
798
+ // internal/src/selector/create-standalone-selector.ts
799
+ function createStandaloneSelector(options, store) {
800
+ const isWritable = `set` in options;
801
+ if (isWritable) {
802
+ const state2 = createWritableSelector(options, void 0, store);
803
+ store.on.selectorCreation.next(state2);
804
+ return state2;
805
+ }
806
+ const state = createReadonlySelector(options, void 0, store);
807
+ store.on.selectorCreation.next(state);
808
+ return state;
809
+ }
810
+
811
+ // internal/src/selector/dispose-selector.ts
812
+ function disposeSelector(selectorToken, store) {
813
+ const target = newest(store);
814
+ const { key } = selectorToken;
815
+ const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key);
816
+ if (!selector) {
817
+ store.logger.info(
818
+ `\u274C`,
819
+ `selector`,
820
+ key,
821
+ `Tried to dispose selector, but it does not exist in the store.`
822
+ );
823
+ } else if (!selector.family) {
824
+ store.logger.error(
825
+ `\u274C`,
826
+ `selector`,
827
+ key,
828
+ `Standalone selectors cannot be disposed.`
829
+ );
830
+ } else {
831
+ const molecule = target.molecules.get(selector.family.subKey);
832
+ if (molecule) {
833
+ molecule.tokens.delete(key);
834
+ }
835
+ switch (selectorToken.type) {
836
+ case `selector`:
837
+ {
838
+ target.selectors.delete(key);
839
+ const family = withdraw(
840
+ { key: selector.family.key, type: `selector_family` },
841
+ store
842
+ );
843
+ family.subject.next({
844
+ type: `state_disposal`,
845
+ token: selectorToken
846
+ });
847
+ }
848
+ break;
849
+ case `readonly_selector`:
850
+ {
851
+ target.readonlySelectors.delete(key);
852
+ const family = withdraw(
853
+ { key: selector.family.key, type: `readonly_selector_family` },
854
+ store
855
+ );
856
+ family.subject.next({
857
+ type: `state_disposal`,
858
+ token: selectorToken
859
+ });
860
+ }
861
+ break;
862
+ }
863
+ target.valueMap.delete(key);
864
+ target.selectorAtoms.delete(key);
865
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
866
+ ([downstreamSelectorKey]) => target.selectors.get(downstreamSelectorKey) ?? target.readonlySelectors.get(downstreamSelectorKey)
867
+ );
868
+ for (const downstreamToken of downstreamTokens) {
869
+ if (downstreamToken) {
870
+ disposeSelector(downstreamToken, store);
871
+ }
872
+ }
873
+ target.selectorGraph.delete(key);
874
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
875
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
876
+ target.transactionMeta.update.updates.push({
877
+ type: `state_disposal`,
878
+ token: selectorToken
879
+ });
880
+ } else {
881
+ store.on.selectorDisposal.next(selectorToken);
882
+ }
883
+ }
884
+ }
885
+
886
+ // internal/src/families/create-readonly-selector-family.ts
887
+ function createReadonlySelectorFamily(options, store, internalRoles) {
888
+ const familyToken = {
889
+ key: options.key,
890
+ type: `readonly_selector_family`
891
+ };
892
+ throwInCaseOfConflictingFamily(familyToken, store);
893
+ const subject = new Subject();
894
+ const familyFunction = (key) => {
895
+ const subKey = stringifyJson(key);
896
+ const family = { key: options.key, subKey };
897
+ const fullKey = `${options.key}(${subKey})`;
898
+ const target = newest(store);
899
+ const token = createReadonlySelector(
900
+ {
901
+ key: fullKey,
902
+ get: options.get(key)
903
+ },
904
+ family,
905
+ target
906
+ );
907
+ subject.next({ type: `state_creation`, token });
908
+ return token;
909
+ };
910
+ const readonlySelectorFamily = Object.assign(familyFunction, familyToken, {
911
+ internalRoles,
912
+ subject,
913
+ install: (s) => createReadonlySelectorFamily(options, s),
914
+ default: (key) => {
915
+ const getFn = options.get(key);
916
+ return getFn({
917
+ get: (token) => getFromStore(token, store),
918
+ find: (token, k) => findInStore(token, k, store),
919
+ seek: (token, k) => seekInStore(token, k, store),
920
+ json: (token) => getJsonToken(token, store)
921
+ });
922
+ }
923
+ });
924
+ store.families.set(options.key, readonlySelectorFamily);
925
+ return familyToken;
926
+ }
927
+ function createWritableSelectorFamily(options, store, internalRoles) {
928
+ const familyToken = {
929
+ key: options.key,
930
+ type: `selector_family`
931
+ };
932
+ throwInCaseOfConflictingFamily(familyToken, store);
933
+ const subject = new Subject();
934
+ const familyFunction = (key) => {
935
+ const subKey = stringifyJson(key);
936
+ const family = { key: options.key, subKey };
937
+ const fullKey = `${options.key}(${subKey})`;
938
+ const target = newest(store);
939
+ const token = createWritableSelector(
940
+ {
941
+ key: fullKey,
942
+ get: options.get(key),
943
+ set: options.set(key)
944
+ },
945
+ family,
946
+ target
947
+ );
948
+ subject.next({ type: `state_creation`, token });
949
+ return token;
950
+ };
951
+ const selectorFamily = Object.assign(familyFunction, familyToken, {
952
+ internalRoles,
953
+ subject,
954
+ install: (s) => createWritableSelectorFamily(options, s),
955
+ default: (key) => {
956
+ const getFn = options.get(key);
957
+ return getFn({
958
+ get: (...params) => getFromStore(...params, store),
959
+ // TODO: make store zero-arg
960
+ find: (token, k) => findInStore(token, k, store),
961
+ seek: (token, k) => seekInStore(token, k, store),
962
+ json: (token) => getJsonToken(token, store)
963
+ });
964
+ }
965
+ });
966
+ store.families.set(options.key, selectorFamily);
967
+ return familyToken;
968
+ }
969
+
970
+ // internal/src/families/create-selector-family.ts
971
+ function createSelectorFamily(options, store) {
972
+ const isWritable = `set` in options;
973
+ if (isWritable) {
974
+ return createWritableSelectorFamily(options, store);
975
+ }
976
+ return createReadonlySelectorFamily(options, store);
977
+ }
978
+
979
+ // internal/src/molecule/dispose-molecule.ts
980
+ function disposeMolecule(token, store) {
981
+ let molecule;
982
+ try {
983
+ molecule = withdraw(token, store);
984
+ } catch (thrown) {
985
+ if (thrown instanceof Error) {
986
+ store.logger.error(
987
+ `\u{1F41E}`,
988
+ `molecule`,
989
+ JSON.stringify(token.key),
990
+ `Failed to dispose molecule, because it was not found in the store.`,
991
+ thrown.message
992
+ );
993
+ }
994
+ return;
995
+ }
996
+ const { family } = token;
997
+ const context = [];
998
+ for (const above of molecule.above.values()) {
999
+ context.push(deposit(above));
1000
+ }
1001
+ const values = [];
1002
+ for (const stateToken of molecule.tokens.values()) {
1003
+ const tokenFamily = stateToken.family;
1004
+ values.push([tokenFamily.key, store.valueMap.get(stateToken.key)]);
1005
+ }
1006
+ if (family) {
1007
+ const Formula = withdraw(family, store);
1008
+ const disposalEvent = {
1009
+ type: `molecule_disposal`,
1010
+ token,
1011
+ family,
1012
+ context,
1013
+ values
1014
+ };
1015
+ if (token.family) {
1016
+ disposalEvent.family = token.family;
1017
+ }
1018
+ for (const state of molecule.tokens.values()) {
1019
+ disposeFromStore(state, store);
1020
+ }
1021
+ for (const child of molecule.below.values()) {
1022
+ if (child.family?.dependsOn === `all`) {
1023
+ disposeMolecule(child, store);
1024
+ } else {
1025
+ child.above.delete(molecule.stringKey);
1026
+ if (child.above.size === 0) {
1027
+ disposeMolecule(child, store);
1028
+ }
1029
+ }
1030
+ }
1031
+ molecule.below.clear();
1032
+ const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1033
+ if (isTransaction) {
1034
+ store.transactionMeta.update.updates.push(disposalEvent);
1035
+ } else {
1036
+ Formula.subject.next(disposalEvent);
1037
+ }
1038
+ store.molecules.delete(molecule.stringKey);
1039
+ }
1040
+ for (const join of molecule.joins.values()) {
1041
+ join.molecules.delete(molecule.stringKey);
1042
+ }
1043
+ for (const parent of molecule.above.values()) {
1044
+ parent.below.delete(molecule.stringKey);
1045
+ }
1046
+ }
1047
+
1048
+ // internal/src/families/init-family-member.ts
1049
+ function initFamilyMemberInStore(token, key, store) {
1050
+ const familyKey = token.key;
1051
+ const family = store.families.get(familyKey);
1052
+ if (family === void 0) {
1053
+ throw new NotFoundError(token, store);
1054
+ }
1055
+ const state = family(key);
1056
+ const target = newest(store);
1057
+ if (state.family && target.moleculeInProgress === null) {
1058
+ if (isRootStore(target)) {
1059
+ switch (state.type) {
1060
+ case `atom`:
1061
+ case `mutable_atom`:
1062
+ store.on.atomCreation.next(state);
1063
+ break;
1064
+ case `selector`:
1065
+ case `readonly_selector`:
1066
+ store.on.selectorCreation.next(state);
1067
+ break;
1068
+ }
1069
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1070
+ target.transactionMeta.update.updates.push({
1071
+ type: `state_creation`,
1072
+ token: state
1073
+ });
1074
+ }
1075
+ }
1076
+ return state;
1077
+ }
1078
+ function seekInStore(token, key, store) {
1079
+ const subKey = stringifyJson(key);
1080
+ const fullKey = `${token.key}(${subKey})`;
1081
+ const target = newest(store);
1082
+ let state;
1083
+ switch (token.type) {
1084
+ case `atom_family`:
1085
+ case `mutable_atom_family`:
1086
+ state = target.atoms.get(fullKey);
1087
+ break;
1088
+ case `selector_family`:
1089
+ state = target.selectors.get(fullKey);
1090
+ break;
1091
+ case `readonly_selector_family`:
1092
+ state = target.readonlySelectors.get(fullKey);
1093
+ break;
1094
+ case `molecule_family`:
1095
+ state = target.molecules.get(stringifyJson(key));
1096
+ }
1097
+ if (state) {
1098
+ return deposit(state);
1099
+ }
1100
+ return state;
1101
+ }
1102
+
1103
+ // internal/src/families/find-in-store.ts
1104
+ function findInStore(token, key, store) {
1105
+ if (store.config.lifespan === `immortal`) {
1106
+ throw new Error(
1107
+ `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
1108
+ );
1109
+ }
1110
+ let state = seekInStore(token, key, store);
1111
+ if (state) {
1112
+ return state;
1113
+ }
1114
+ state = initFamilyMemberInStore(token, key, store);
1115
+ return state;
1116
+ }
1117
+
1118
+ // internal/src/families/dispose-from-store.ts
1119
+ function disposeFromStore(...params) {
1120
+ let token;
1121
+ let store;
1122
+ if (params.length === 2) {
1123
+ token = params[0];
1124
+ store = params[1];
1125
+ } else {
1126
+ const family = params[0];
1127
+ const key = params[1];
1128
+ store = params[2];
1129
+ const maybeToken = family.type === `molecule_family` ? seekInStore(family, key, store) : store.config.lifespan === `immortal` ? seekInStore(family, key, store) : findInStore(family, key, store);
1130
+ if (!maybeToken) {
1131
+ store.logger.error(
1132
+ `\u2757`,
1133
+ family.type,
1134
+ family.key,
1135
+ `tried to dispose of member`,
1136
+ stringifyJson(key),
1137
+ `but it was not found in store`,
1138
+ store.config.name
1139
+ );
1140
+ return;
1141
+ }
1142
+ token = maybeToken;
1143
+ }
1144
+ switch (token.type) {
1145
+ case `atom`:
1146
+ case `mutable_atom`:
1147
+ disposeAtom(token, store);
1148
+ break;
1149
+ case `selector`:
1150
+ case `readonly_selector`:
1151
+ disposeSelector(token, store);
1152
+ break;
1153
+ case `molecule`:
1154
+ disposeMolecule(token, store);
1155
+ break;
1156
+ }
1157
+ }
1158
+
1159
+ // internal/src/set-state/set-into-store.ts
1160
+ function setIntoStore(...params) {
1161
+ let token;
1162
+ let value;
1163
+ let store;
1164
+ if (params.length === 3) {
1165
+ token = params[0];
1166
+ value = params[1];
1167
+ store = params[2];
1168
+ } else {
1169
+ const family = params[0];
1170
+ const key = params[1];
1171
+ value = params[2];
1172
+ store = params[3];
1173
+ const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(family, key, store) : seekInStore(family, key, store);
1174
+ if (!maybeToken) {
1175
+ store.logger.error(
1176
+ `\u2757`,
1177
+ family.type,
1178
+ family.key,
1179
+ `tried to set member`,
1180
+ stringifyJson(key),
1181
+ `to`,
1182
+ value,
1183
+ `but it was not found in store`,
1184
+ store.config.name
1185
+ );
1186
+ return;
1187
+ }
1188
+ token = maybeToken;
1189
+ }
1190
+ const rejectionTime = openOperation(token, store);
1191
+ if (rejectionTime) {
1192
+ const unsubscribe = store.on.operationClose.subscribe(
1193
+ `waiting to set "${token.key}" at T-${rejectionTime}`,
1194
+ () => {
1195
+ unsubscribe();
1196
+ store.logger.info(
1197
+ `\u{1F7E2}`,
1198
+ token.type,
1199
+ token.key,
1200
+ `resuming deferred setState from T-${rejectionTime}`
1201
+ );
1202
+ setIntoStore(token, value, store);
1203
+ }
1204
+ );
1205
+ return;
1206
+ }
1207
+ const state = withdraw(token, store);
1208
+ setAtomOrSelector(state, value, store);
1209
+ closeOperation(store);
1210
+ }
1211
+
1212
+ // internal/src/ingest-updates/ingest-atom-update.ts
1213
+ function ingestAtomUpdate(applying, atomUpdate, store) {
1214
+ const { key, newValue, oldValue } = atomUpdate;
1215
+ const value = applying === `newValue` ? newValue : oldValue;
1216
+ const token = { key, type: `atom` };
1217
+ if (atomUpdate.family) {
1218
+ Object.assign(token, { family: atomUpdate.family });
1219
+ }
1220
+ setIntoStore(token, value, store);
1221
+ }
1222
+
1223
+ // internal/src/molecule/create-molecule-family.ts
1224
+ function createMoleculeFamily(options, store) {
1225
+ const subject = new Subject();
1226
+ const token = {
1227
+ type: `molecule_family`,
1228
+ key: options.key,
1229
+ dependsOn: options.dependsOn ?? `all`
1230
+ };
1231
+ const family = {
1232
+ ...token,
1233
+ subject,
1234
+ new: options.new
1235
+ };
1236
+ store.moleculeFamilies.set(options.key, family);
1237
+ return token;
1238
+ }
1239
+
1240
+ // internal/src/molecule/grow-molecule-in-store.ts
1241
+ function growMoleculeInStore(molecule, family, store) {
1242
+ const stateToken = initFamilyMemberInStore(family, molecule.key, store);
1243
+ molecule.tokens.set(stateToken.key, stateToken);
1244
+ const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1245
+ const moleculeInProgress = store.moleculeInProgress === molecule.key;
1246
+ if (!isTransaction && !moleculeInProgress) {
1247
+ molecule.subject.next({ type: `state_creation`, token: stateToken });
1248
+ }
1249
+ return stateToken;
1250
+ }
1251
+
1252
+ // internal/src/get-environment-data.ts
1253
+ function getEnvironmentData(store) {
1254
+ return {
1255
+ store
1256
+ };
1257
+ }
1258
+ var Molecule = class {
1259
+ constructor(ctx, key, family) {
1260
+ this.key = key;
1261
+ this.stringKey = stringifyJson(key);
1262
+ if (family) {
1263
+ this.family = family;
1264
+ }
1265
+ if (ctx) {
1266
+ if (Array.isArray(ctx)) {
1267
+ for (const molecule of ctx) {
1268
+ this.above.set(molecule.stringKey, molecule);
1269
+ }
1270
+ } else {
1271
+ this.above.set(ctx.stringKey, ctx);
1272
+ }
1273
+ }
1274
+ }
1275
+ type = `molecule`;
1276
+ stringKey;
1277
+ family;
1278
+ subject = new Subject();
1279
+ tokens = /* @__PURE__ */ new Map();
1280
+ above = /* @__PURE__ */ new Map();
1281
+ below = /* @__PURE__ */ new Map();
1282
+ joins = /* @__PURE__ */ new Map();
1283
+ instance;
1284
+ };
1285
+
1286
+ // internal/src/molecule/make-molecule-in-store.ts
1287
+ function capitalize2(string) {
1288
+ return string[0].toUpperCase() + string.slice(1);
1289
+ }
1290
+ function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1291
+ const rootStore = eldest(store);
1292
+ const target = newest(store);
1293
+ const stringKey = stringifyJson(key);
1294
+ target.moleculeInProgress = stringKey;
1295
+ const contextArray = Array.isArray(context) ? context : [context];
1296
+ const owners = contextArray.map((ctx) => {
1297
+ if (ctx instanceof Molecule) {
1298
+ return ctx;
1299
+ }
1300
+ const ctxStringKey = stringifyJson(ctx.key);
1301
+ const molecule2 = store.molecules.get(ctxStringKey);
1302
+ if (!molecule2) {
1303
+ throw new Error(
1304
+ `Molecule ${ctxStringKey} not found in store "${store.config.name}"`
1305
+ );
1306
+ }
1307
+ return molecule2;
1308
+ });
1309
+ const molecule = new Molecule(owners, key, familyToken);
1310
+ target.molecules.set(stringKey, molecule);
1311
+ for (const owner of owners) {
1312
+ owner.below.set(molecule.stringKey, molecule);
1313
+ }
1314
+ const toolkit = {
1315
+ get: (...ps) => getFromStore(...ps, newest(rootStore)),
1316
+ set: (...ps) => {
1317
+ setIntoStore(...ps, newest(rootStore));
1318
+ },
1319
+ seek: (t, k) => seekInStore(t, k, newest(rootStore)),
1320
+ json: (t) => getJsonToken(t, newest(rootStore)),
1321
+ run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
1322
+ make: (ctx, f, k, ...args) => makeMoleculeInStore(newest(rootStore), ctx, f, k, ...args),
1323
+ dispose: (t) => {
1324
+ disposeFromStore(t, newest(rootStore));
1325
+ },
1326
+ env: () => getEnvironmentData(newest(rootStore)),
1327
+ bond: (token2, maybeRole) => {
1328
+ if (token2.type === `join`) {
1329
+ const { as: role } = maybeRole;
1330
+ const join = getJoin(token2, rootStore);
1331
+ join.molecules.set(stringKey, molecule);
1332
+ molecule.joins.set(token2.key, join);
1333
+ const unsubFromFamily = family.subject.subscribe(
1334
+ `join:${token2.key}-${stringKey}`,
1335
+ (event) => {
1336
+ if (event.type === `molecule_disposal` && stringifyJson(event.token.key) === stringKey) {
1337
+ unsubFromFamily();
1338
+ join.molecules.delete(stringKey);
1339
+ }
1340
+ }
1341
+ );
1342
+ if (role === null) {
1343
+ return;
1344
+ }
1345
+ const otherRole = token2.a === role ? token2.b : token2.a;
1346
+ const relations = findRelations(token2, key);
1347
+ const relatedKeys = relations[`${otherRole}KeysOf${capitalize2(role)}`];
1348
+ const relatedEntries = relations[`${otherRole}EntriesOf${capitalize2(role)}`];
1349
+ let tokens = { relatedKeys };
1350
+ if (relatedEntries) {
1351
+ tokens = Object.assign(tokens, { relatedEntries });
1352
+ }
1353
+ return tokens;
1354
+ }
1355
+ return growMoleculeInStore(
1356
+ molecule,
1357
+ withdraw(token2, rootStore),
1358
+ newest(rootStore)
1359
+ );
1360
+ },
1361
+ claim: (below, options) => {
1362
+ const { exclusive } = options;
1363
+ const belowMolecule = newest(store).molecules.get(stringifyJson(below.key));
1364
+ if (belowMolecule) {
1365
+ if (exclusive) {
1366
+ for (const value of belowMolecule.above.values()) {
1367
+ value.below.delete(belowMolecule.stringKey);
1368
+ }
1369
+ belowMolecule.above.clear();
1370
+ belowMolecule.above.set(molecule.stringKey, molecule);
1371
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1372
+ } else {
1373
+ belowMolecule.above.set(molecule.stringKey, molecule);
1374
+ molecule.below.set(belowMolecule.stringKey, belowMolecule);
1375
+ }
1376
+ }
1377
+ },
1378
+ spawn: (f, k, ...p) => makeMoleculeInStore(
1379
+ newest(store),
1380
+ [molecule],
1381
+ withdraw(f, store),
1382
+ k,
1383
+ ...p
1384
+ )
1385
+ };
1386
+ const family = withdraw(familyToken, store);
1387
+ const Constructor = family.new;
1388
+ molecule.instance = new Constructor(toolkit, key, ...params);
1389
+ const token = {
1390
+ type: `molecule`,
1391
+ key,
1392
+ family: familyToken
1393
+ };
1394
+ const update = {
1395
+ type: `molecule_creation`,
1396
+ token,
1397
+ family: familyToken,
1398
+ context: contextArray,
1399
+ params
1400
+ };
1401
+ if (isRootStore(target)) {
1402
+ family.subject.next(update);
1403
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1404
+ target.transactionMeta.update.updates.push(update);
1405
+ }
1406
+ target.moleculeInProgress = null;
1407
+ return token;
1408
+ }
1409
+
1410
+ // internal/src/ingest-updates/ingest-creation-disposal.ts
1411
+ function ingestCreationEvent(update, applying, store) {
1412
+ switch (applying) {
1413
+ case `newValue`: {
1414
+ createInStore(update.token, store);
1415
+ break;
1416
+ }
1417
+ case `oldValue`: {
1418
+ disposeFromStore(update.token, store);
1419
+ break;
1420
+ }
1421
+ }
1422
+ }
1423
+ function ingestDisposalEvent(update, applying, store) {
1424
+ switch (applying) {
1425
+ case `newValue`: {
1426
+ disposeFromStore(update.token, store);
1427
+ break;
1428
+ }
1429
+ case `oldValue`: {
1430
+ createInStore(update.token, store);
1431
+ store.valueMap.set(update.token.key, update.value);
1432
+ break;
1433
+ }
1434
+ }
1435
+ }
1436
+ function createInStore(token, store) {
1437
+ if (token.family) {
1438
+ const family = store.families.get(token.family.key);
1439
+ if (family) {
1440
+ const molecule = store.molecules.get(token.family.subKey);
1441
+ if (molecule) {
1442
+ growMoleculeInStore(molecule, family, store);
1443
+ return;
1444
+ }
1445
+ if (store.config.lifespan === `immortal`) {
1446
+ throw new Error(`No molecule found for key "${token.family.subKey}"`);
1447
+ }
1448
+ initFamilyMemberInStore(family, parseJson(token.family.subKey), store);
1449
+ }
1450
+ }
1451
+ }
1452
+ function ingestMoleculeCreationEvent(update, applying, store) {
1453
+ switch (applying) {
1454
+ case `newValue`:
1455
+ makeMoleculeInStore(
1456
+ store,
1457
+ update.context,
1458
+ update.family,
1459
+ update.token.key,
1460
+ ...update.params
1461
+ );
1462
+ break;
1463
+ case `oldValue`:
1464
+ disposeFromStore(update.token, store);
1465
+ break;
1466
+ }
1467
+ }
1468
+ function ingestMoleculeDisposalEvent(update, applying, store) {
1469
+ switch (applying) {
1470
+ case `newValue`:
1471
+ disposeFromStore(update.token, store);
1472
+ break;
1473
+ case `oldValue`:
1474
+ {
1475
+ const moleculeToken = makeMoleculeInStore(
1476
+ store,
1477
+ update.context,
1478
+ update.family,
1479
+ update.token.key
1480
+ );
1481
+ for (const [familyKey, value] of update.values) {
1482
+ const memberKey = `${familyKey}(${stringifyJson(moleculeToken.key)})`;
1483
+ const molecule = withdraw(moleculeToken, store);
1484
+ const alreadyCreated = molecule.tokens.has(memberKey);
1485
+ const family = store.families.get(familyKey);
1486
+ if (family && !alreadyCreated) {
1487
+ growMoleculeInStore(molecule, family, store);
1488
+ }
1489
+ store.valueMap.set(memberKey, value);
1490
+ }
1491
+ }
1492
+ break;
1493
+ }
1494
+ }
1495
+
1496
+ // internal/src/ingest-updates/ingest-selector-update.ts
1497
+ function ingestSelectorUpdate(applying, selectorUpdate, store) {
1498
+ const updates = applying === `newValue` ? selectorUpdate.atomUpdates : selectorUpdate.atomUpdates.toReversed();
1499
+ for (const atomUpdate of updates) {
1500
+ ingestAtomUpdate(applying, atomUpdate, store);
1501
+ }
1502
+ }
1503
+
1504
+ // internal/src/ingest-updates/ingest-transaction-update.ts
1505
+ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1506
+ const updates = applying === `newValue` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1507
+ for (const updateFromTransaction of updates) {
1508
+ switch (updateFromTransaction.type) {
1509
+ case `atom_update`:
1510
+ case `selector_update`:
1511
+ ingestAtomUpdate(applying, updateFromTransaction, store);
1512
+ break;
1513
+ case `state_creation`:
1514
+ ingestCreationEvent(updateFromTransaction, applying, store);
1515
+ break;
1516
+ case `state_disposal`:
1517
+ ingestDisposalEvent(updateFromTransaction, applying, store);
1518
+ break;
1519
+ case `molecule_creation`:
1520
+ ingestMoleculeCreationEvent(updateFromTransaction, applying, store);
1521
+ break;
1522
+ case `molecule_disposal`:
1523
+ ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1524
+ break;
1525
+ case `transaction_update`:
1526
+ ingestTransactionUpdate(applying, updateFromTransaction, store);
1527
+ break;
1528
+ }
1529
+ }
1530
+ }
1531
+
1532
+ // internal/src/transaction/set-epoch-number.ts
1533
+ function setEpochNumberOfContinuity(continuityKey, newEpoch, store) {
1534
+ const isRoot = isRootStore(store);
1535
+ if (isRoot && continuityKey) {
1536
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1537
+ }
1538
+ }
1539
+ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1540
+ const isRoot = isRootStore(store);
1541
+ if (!isRoot) {
1542
+ return;
1543
+ }
1544
+ const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1545
+ if (continuityKey !== void 0) {
1546
+ store.transactionMeta.epoch.set(continuityKey, newEpoch);
1547
+ }
1548
+ }
1549
+
1550
+ // internal/src/transaction/apply-transaction.ts
1551
+ var applyTransaction = (output, store) => {
1552
+ const child = newest(store);
1553
+ const { parent } = child;
1554
+ if (parent === null || !isChildStore(child) || child.transactionMeta?.phase !== `building`) {
1555
+ store.logger.warn(
1556
+ `\u{1F41E}`,
1557
+ `transaction`,
1558
+ `???`,
1559
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
1560
+ );
1561
+ return;
1562
+ }
1563
+ child.transactionMeta.phase = `applying`;
1564
+ child.transactionMeta.update.output = output;
1565
+ parent.child = null;
1566
+ parent.on.transactionApplying.next(child.transactionMeta);
1567
+ const { updates } = child.transactionMeta.update;
1568
+ store.logger.info(
1569
+ `\u{1F6C4}`,
1570
+ `transaction`,
1571
+ child.transactionMeta.update.key,
1572
+ `Applying transaction with ${updates.length} updates:`,
1573
+ updates
1574
+ );
1575
+ ingestTransactionUpdate(`newValue`, child.transactionMeta.update, parent);
1576
+ if (isRootStore(parent)) {
1577
+ setEpochNumberOfAction(
1578
+ child.transactionMeta.update.key,
1579
+ child.transactionMeta.update.epoch,
1580
+ parent
1581
+ );
1582
+ const myTransaction = withdraw(
1583
+ { key: child.transactionMeta.update.key, type: `transaction` },
1584
+ store
1585
+ );
1586
+ myTransaction?.subject.next(child.transactionMeta.update);
1587
+ store.logger.info(
1588
+ `\u{1F6EC}`,
1589
+ `transaction`,
1590
+ child.transactionMeta.update.key,
1591
+ `Finished applying transaction.`
1592
+ );
1593
+ } else if (isChildStore(parent)) {
1594
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
1595
+ }
1596
+ parent.on.transactionApplying.next(null);
1597
+ };
1598
+
1599
+ // internal/src/transaction/assign-transaction-to-continuity.ts
1600
+ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
1601
+ const isRoot = isRootStore(store);
1602
+ if (!isRoot) {
1603
+ return;
1604
+ }
1605
+ const { epoch, actionContinuities } = store.transactionMeta;
1606
+ actionContinuities.set(continuityKey, transactionKey);
1607
+ if (!epoch.has(continuityKey)) {
1608
+ epoch.set(continuityKey, -1);
1609
+ }
1610
+ }
1611
+
1612
+ // internal/src/lazy-map.ts
1613
+ var LazyMap = class extends Map {
1614
+ constructor(source) {
1615
+ super();
1616
+ this.source = source;
1617
+ }
1618
+ deleted = /* @__PURE__ */ new Set();
1619
+ get(key) {
1620
+ const has = super.has(key);
1621
+ if (has) {
1622
+ return super.get(key);
1623
+ }
1624
+ if (!this.deleted.has(key) && this.source.has(key)) {
1625
+ const value = this.source.get(key);
1626
+ return value;
1627
+ }
1628
+ return void 0;
1629
+ }
1630
+ set(key, value) {
1631
+ this.deleted.delete(key);
1632
+ return super.set(key, value);
1633
+ }
1634
+ hasOwn(key) {
1635
+ return super.has(key);
1636
+ }
1637
+ has(key) {
1638
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1639
+ }
1640
+ delete(key) {
1641
+ this.deleted.add(key);
1642
+ return super.delete(key);
1643
+ }
1644
+ };
1645
+
1646
+ // internal/src/transaction/build-transaction.ts
1647
+ var buildTransaction = (key, params, store, id) => {
1648
+ const parent = newest(store);
1649
+ const childBase = {
1650
+ parent,
1651
+ child: null,
1652
+ on: parent.on,
1653
+ loggers: parent.loggers,
1654
+ logger: parent.logger,
1655
+ config: parent.config,
1656
+ atoms: new LazyMap(parent.atoms),
1657
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
1658
+ families: new LazyMap(parent.families),
1659
+ operation: { open: false },
1660
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
1661
+ timelines: new LazyMap(parent.timelines),
1662
+ timelineTopics: new Junction(parent.timelineTopics.toJSON()),
1663
+ trackers: /* @__PURE__ */ new Map(),
1664
+ transactions: new LazyMap(parent.transactions),
1665
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
1666
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
1667
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1668
+ }),
1669
+ selectors: new LazyMap(parent.selectors),
1670
+ valueMap: new LazyMap(parent.valueMap),
1671
+ defaults: parent.defaults,
1672
+ molecules: new LazyMap(parent.molecules),
1673
+ moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1674
+ moleculeInProgress: parent.moleculeInProgress,
1675
+ miscResources: new LazyMap(parent.miscResources)
1676
+ };
1677
+ const epoch = getEpochNumberOfAction(key, store);
1678
+ const transactionMeta = {
1679
+ phase: `building`,
1680
+ update: {
1681
+ type: `transaction_update`,
1682
+ key,
1683
+ id,
1684
+ epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1685
+ updates: [],
1686
+ params,
1687
+ output: void 0
1688
+ },
1689
+ toolkit: {
1690
+ get: (...ps) => getFromStore(...ps, child),
1691
+ set: (...ps) => {
1692
+ setIntoStore(...ps, child);
1693
+ },
1694
+ run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
1695
+ find: (token, k) => findInStore(token, k, child),
1696
+ seek: (token, k) => seekInStore(token, k, child),
1697
+ json: (token) => getJsonToken(token, child),
1698
+ make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
1699
+ dispose: (...ps) => {
1700
+ disposeFromStore(...ps, child);
1701
+ },
1702
+ env: () => getEnvironmentData(child)
1703
+ }
1704
+ };
1705
+ const child = Object.assign(childBase, {
1706
+ transactionMeta
1707
+ });
1708
+ parent.child = child;
1709
+ store.logger.info(
1710
+ `\u{1F6EB}`,
1711
+ `transaction`,
1712
+ key,
1713
+ `Building transaction with params:`,
1714
+ params
1715
+ );
1716
+ return child;
1717
+ };
1718
+
1719
+ // internal/src/transaction/create-transaction.ts
1720
+ function createTransaction(options, store) {
1721
+ const newTransaction = {
1722
+ key: options.key,
1723
+ type: `transaction`,
1724
+ run: (params, id) => {
1725
+ const childStore = buildTransaction(options.key, params, store, id);
1726
+ try {
1727
+ const target2 = newest(store);
1728
+ const { toolkit } = childStore.transactionMeta;
1729
+ const output = options.do(toolkit, ...params);
1730
+ applyTransaction(output, target2);
1731
+ return output;
1732
+ } catch (thrown) {
1733
+ abortTransaction(target);
1734
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
1735
+ throw thrown;
1736
+ }
1737
+ },
1738
+ install: (s) => createTransaction(options, s),
1739
+ subject: new Subject()
1740
+ };
1741
+ const target = newest(store);
1742
+ target.transactions.set(newTransaction.key, newTransaction);
1743
+ const token = deposit(newTransaction);
1744
+ store.on.transactionCreation.next(token);
1745
+ return token;
1746
+ }
1747
+
1748
+ // internal/src/transaction/get-epoch-number.ts
1749
+ function getContinuityKey(transactionKey, store) {
1750
+ const isRoot = isRootStore(store);
1751
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1752
+ return continuity;
1753
+ }
1754
+ function getEpochNumberOfContinuity(continuityKey, store) {
1755
+ const isRoot = isRootStore(store);
1756
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1757
+ return epoch;
1758
+ }
1759
+ function getEpochNumberOfAction(transactionKey, store) {
1760
+ const isRoot = isRootStore(store);
1761
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1762
+ const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1763
+ return epoch;
1764
+ }
1765
+
1766
+ // internal/src/transaction/index.ts
1767
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1768
+
1769
+ // internal/src/store/store.ts
1770
+ var Store = class {
1771
+ parent = null;
1772
+ child = null;
1773
+ valueMap = /* @__PURE__ */ new Map();
1774
+ defaults = /* @__PURE__ */ new Map();
1775
+ atoms = /* @__PURE__ */ new Map();
1776
+ selectors = /* @__PURE__ */ new Map();
1777
+ readonlySelectors = /* @__PURE__ */ new Map();
1778
+ atomsThatAreDefault = /* @__PURE__ */ new Set();
1779
+ selectorAtoms = new Junction({
1780
+ between: [`selectorKey`, `atomKey`],
1781
+ cardinality: `n:n`
1782
+ });
1783
+ selectorGraph = new Junction(
1784
+ {
1785
+ between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
1786
+ cardinality: `n:n`
1787
+ },
1788
+ {
1789
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1790
+ }
1791
+ );
1792
+ trackers = /* @__PURE__ */ new Map();
1793
+ families = /* @__PURE__ */ new Map();
1794
+ transactions = /* @__PURE__ */ new Map();
1795
+ transactionMeta = {
1796
+ epoch: /* @__PURE__ */ new Map(),
1797
+ actionContinuities: new Junction({
1798
+ between: [`continuity`, `action`],
1799
+ cardinality: `1:n`
1800
+ })
1801
+ };
1802
+ timelines = /* @__PURE__ */ new Map();
1803
+ timelineTopics = new Junction({
1804
+ between: [`timelineKey`, `topicKey`],
1805
+ cardinality: `1:n`
1806
+ });
1807
+ molecules = /* @__PURE__ */ new Map();
1808
+ moleculeFamilies = /* @__PURE__ */ new Map();
1809
+ moleculeInProgress = null;
1810
+ miscResources = /* @__PURE__ */ new Map();
1811
+ on = {
1812
+ atomCreation: new Subject(),
1813
+ atomDisposal: new Subject(),
1814
+ selectorCreation: new Subject(),
1815
+ selectorDisposal: new Subject(),
1816
+ timelineCreation: new Subject(),
1817
+ transactionCreation: new Subject(),
1818
+ transactionApplying: new StatefulSubject(
1819
+ null
1820
+ ),
1821
+ operationClose: new Subject(),
1822
+ moleculeCreationStart: new Subject(),
1823
+ moleculeCreationDone: new Subject(),
1824
+ moleculeDisposal: new Subject()
1825
+ };
1826
+ operation = { open: false };
1827
+ config = {
1828
+ name: `IMPLICIT_STORE`,
1829
+ lifespan: `ephemeral`
1830
+ };
1831
+ loggers = [
1832
+ new AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
1833
+ ];
1834
+ logger = {
1835
+ error: (...messages) => {
1836
+ for (const logger of this.loggers) logger.error(...messages);
1837
+ },
1838
+ info: (...messages) => {
1839
+ for (const logger of this.loggers) logger.info(...messages);
1840
+ },
1841
+ warn: (...messages) => {
1842
+ for (const logger of this.loggers) logger.warn(...messages);
1843
+ }
1844
+ };
1845
+ constructor(config, store = null) {
1846
+ this.config = {
1847
+ ...store?.config,
1848
+ ...config
1849
+ };
1850
+ if (store !== null) {
1851
+ this.valueMap = new Map(store?.valueMap);
1852
+ this.operation = { ...store?.operation };
1853
+ if (isRootStore(store)) {
1854
+ this.transactionMeta = {
1855
+ epoch: new Map(store?.transactionMeta.epoch),
1856
+ actionContinuities: new Junction(
1857
+ store?.transactionMeta.actionContinuities.toJSON()
1858
+ )
1859
+ };
1860
+ }
1861
+ for (const [, family] of store.families) {
1862
+ if (family.internalRoles?.includes(`mutable`) || family.internalRoles?.includes(`join`)) {
1863
+ continue;
1864
+ }
1865
+ family.install(this);
1866
+ }
1867
+ const mutableHelpers = /* @__PURE__ */ new Set();
1868
+ for (const [, atom] of store.atoms) {
1869
+ if (mutableHelpers.has(atom.key)) {
1870
+ continue;
1871
+ }
1872
+ atom.install(this);
1873
+ if (atom.type === `mutable_atom`) {
1874
+ const originalJsonToken = getJsonToken(atom, store);
1875
+ const originalUpdateToken = getUpdateToken(atom);
1876
+ mutableHelpers.add(originalJsonToken.key);
1877
+ mutableHelpers.add(originalUpdateToken.key);
1878
+ }
1879
+ }
1880
+ for (const [, selector] of store.readonlySelectors) {
1881
+ selector.install(this);
1882
+ }
1883
+ for (const [, selector] of store.selectors) {
1884
+ if (mutableHelpers.has(selector.key)) {
1885
+ continue;
1886
+ }
1887
+ selector.install(this);
1888
+ }
1889
+ for (const [, tx] of store.transactions) {
1890
+ tx.install(this);
1891
+ }
1892
+ for (const [, timeline] of store.timelines) {
1893
+ timeline.install(this);
1894
+ }
1895
+ }
1896
+ }
1897
+ };
1898
+ var IMPLICIT = {
1899
+ get STORE() {
1900
+ if (!globalThis.ATOM_IO_IMPLICIT_STORE) {
1901
+ globalThis.ATOM_IO_IMPLICIT_STORE = new Store({
1902
+ name: `IMPLICIT_STORE`,
1903
+ lifespan: `ephemeral`
1904
+ });
1905
+ }
1906
+ return globalThis.ATOM_IO_IMPLICIT_STORE;
1907
+ }
1908
+ };
1909
+ var clearStore = (store) => {
1910
+ const { config } = store;
1911
+ for (const disposable of store.miscResources.values()) {
1912
+ disposable[Symbol.dispose]();
1913
+ }
1914
+ Object.assign(store, new Store(config));
1915
+ store.config = config;
1916
+ };
1917
+ function withdraw(token, store) {
1918
+ let withdrawn;
1919
+ let target = store;
1920
+ while (target !== null) {
1921
+ switch (token.type) {
1922
+ case `atom`:
1923
+ case `mutable_atom`:
1924
+ withdrawn = target.atoms.get(token.key);
1925
+ break;
1926
+ case `selector`:
1927
+ withdrawn = target.selectors.get(token.key);
1928
+ break;
1929
+ case `readonly_selector`:
1930
+ withdrawn = target.readonlySelectors.get(token.key);
1931
+ break;
1932
+ case `atom_family`:
1933
+ case `mutable_atom_family`:
1934
+ case `selector_family`:
1935
+ case `readonly_selector_family`:
1936
+ withdrawn = target.families.get(token.key);
1937
+ break;
1938
+ case `timeline`:
1939
+ withdrawn = target.timelines.get(token.key);
1940
+ break;
1941
+ case `transaction`:
1942
+ withdrawn = target.transactions.get(token.key);
1943
+ break;
1944
+ case `molecule`:
1945
+ withdrawn = target.molecules.get(stringifyJson(token.key));
1946
+ break;
1947
+ case `molecule_family`:
1948
+ withdrawn = target.moleculeFamilies.get(token.key);
1949
+ break;
1950
+ }
1951
+ if (withdrawn) {
1952
+ return withdrawn;
1953
+ }
1954
+ target = target.child;
1955
+ }
1956
+ throw new NotFoundError(token, store);
1957
+ }
1958
+
1959
+ // internal/src/subscribe/recall-state.ts
1960
+ var recallState = (state, store) => {
1961
+ const target = newest(store);
1962
+ if (target.operation.open) {
1963
+ return target.operation.prev.get(state.key);
1964
+ }
1965
+ return target.valueMap.get(state.key);
1966
+ };
1967
+
1968
+ // internal/src/subscribe/subscribe-to-root-atoms.ts
1969
+ var subscribeToRootAtoms = (selector, store) => {
1970
+ const target = newest(store);
1971
+ const dependencySubscriptions = traceAllSelectorAtoms(selector, store).map(
1972
+ (atomKey) => {
1973
+ const atom = target.atoms.get(atomKey);
1974
+ if (atom === void 0) {
1975
+ throw new Error(
1976
+ `Atom "${atomKey}", a dependency of selector "${selector.key}", not found in store "${store.config.name}".`
1977
+ );
1978
+ }
1979
+ return atom.subject.subscribe(
1980
+ `${selector.type}:${selector.key}`,
1981
+ (atomChange) => {
1982
+ store.logger.info(
1983
+ `\u{1F4E2}`,
1984
+ selector.type,
1985
+ selector.key,
1986
+ `root`,
1987
+ atomKey,
1988
+ `went`,
1989
+ atomChange.oldValue,
1990
+ `->`,
1991
+ atomChange.newValue
1992
+ );
1993
+ const oldValue = recallState(selector, target);
1994
+ const newValue = readOrComputeValue(selector, target);
1995
+ store.logger.info(
1996
+ `\u2728`,
1997
+ selector.type,
1998
+ selector.key,
1999
+ `went`,
2000
+ oldValue,
2001
+ `->`,
2002
+ newValue
2003
+ );
2004
+ selector.subject.next({ newValue, oldValue });
2005
+ }
2006
+ );
2007
+ }
2008
+ );
2009
+ return dependencySubscriptions;
2010
+ };
2011
+
2012
+ // internal/src/subscribe/subscribe-to-state.ts
2013
+ function subscribeToState(token, handleUpdate, key, store) {
2014
+ function safelyHandleUpdate(update) {
2015
+ if (store.operation.open) {
2016
+ const unsubscribe2 = store.on.operationClose.subscribe(
2017
+ `state subscription ${key}`,
2018
+ () => {
2019
+ unsubscribe2();
2020
+ handleUpdate(update);
2021
+ }
2022
+ );
2023
+ } else {
2024
+ handleUpdate(update);
2025
+ }
2026
+ }
2027
+ const state = withdraw(token, store);
2028
+ store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
2029
+ const isSelector = state.type === `selector` || state.type === `readonly_selector`;
2030
+ let dependencyUnsubFunctions = null;
2031
+ let updateHandler = safelyHandleUpdate;
2032
+ if (isSelector) {
2033
+ dependencyUnsubFunctions = subscribeToRootAtoms(state, store);
2034
+ updateHandler = (update) => {
2035
+ if (dependencyUnsubFunctions) {
2036
+ dependencyUnsubFunctions.length = 0;
2037
+ dependencyUnsubFunctions.push(...subscribeToRootAtoms(state, store));
2038
+ }
2039
+ safelyHandleUpdate(update);
2040
+ };
2041
+ }
2042
+ const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
2043
+ const unsubscribe = () => {
2044
+ store.logger.info(
2045
+ `\u{1F648}`,
2046
+ state.type,
2047
+ state.key,
2048
+ `Removing subscription "${key}"`
2049
+ );
2050
+ mainUnsubFunction();
2051
+ if (dependencyUnsubFunctions) {
2052
+ for (const unsubFromDependency of dependencyUnsubFunctions) {
2053
+ unsubFromDependency();
2054
+ }
2055
+ }
2056
+ };
2057
+ return unsubscribe;
2058
+ }
2059
+
2060
+ // internal/src/subscribe/subscribe-to-timeline.ts
2061
+ var subscribeToTimeline = (token, handleUpdate, key, store) => {
2062
+ const tl = withdraw(token, store);
2063
+ store.logger.info(`\u{1F440}`, `timeline`, token.key, `Adding subscription "${key}"`);
2064
+ const unsubscribe = tl.subject.subscribe(key, handleUpdate);
2065
+ return () => {
2066
+ store.logger.info(
2067
+ `\u{1F648}`,
2068
+ `timeline`,
2069
+ token.key,
2070
+ `Removing subscription "${key}" from timeline`
2071
+ );
2072
+ unsubscribe();
2073
+ };
2074
+ };
2075
+
2076
+ // internal/src/subscribe/subscribe-to-transaction.ts
2077
+ var subscribeToTransaction = (token, handleUpdate, key, store) => {
2078
+ const tx = withdraw(token, store);
2079
+ store.logger.info(
2080
+ `\u{1F440}`,
2081
+ `transaction`,
2082
+ token.key,
2083
+ `Adding subscription "${key}"`
2084
+ );
2085
+ const unsubscribe = tx.subject.subscribe(key, handleUpdate);
2086
+ return () => {
2087
+ store.logger.info(
2088
+ `\u{1F648}`,
2089
+ `transaction`,
2090
+ token.key,
2091
+ `Removing subscription "${key}"`
2092
+ );
2093
+ unsubscribe();
2094
+ };
2095
+ };
2096
+
2097
+ // internal/src/mutable/tracker.ts
2098
+ var Tracker = class {
2099
+ Update;
2100
+ initializeState(mutableState, store) {
2101
+ const latestUpdateStateKey = `*${mutableState.key}`;
2102
+ store.atoms.delete(latestUpdateStateKey);
2103
+ store.valueMap.delete(latestUpdateStateKey);
2104
+ const familyMetaData = mutableState.family ? {
2105
+ key: `*${mutableState.family.key}`,
2106
+ subKey: mutableState.family.subKey
2107
+ } : void 0;
2108
+ const latestUpdateState = createRegularAtom(
2109
+ {
2110
+ key: latestUpdateStateKey,
2111
+ default: null
2112
+ },
2113
+ familyMetaData,
2114
+ store
2115
+ );
2116
+ if (store.parent?.valueMap.has(latestUpdateStateKey)) {
2117
+ const parentValue = store.parent.valueMap.get(latestUpdateStateKey);
2118
+ store.valueMap.set(latestUpdateStateKey, parentValue);
2119
+ }
2120
+ return latestUpdateState;
2121
+ }
2122
+ unsubscribeFromInnerValue;
2123
+ unsubscribeFromState;
2124
+ observeCore(mutableState, latestUpdateState, target) {
2125
+ const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
2126
+ const originalInnerValue = getFromStore(mutableState, target);
2127
+ this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
2128
+ subscriptionKey,
2129
+ (update) => {
2130
+ setIntoStore(latestUpdateState, update, target);
2131
+ }
2132
+ );
2133
+ this.unsubscribeFromState = subscribeToState(
2134
+ mutableState,
2135
+ (update) => {
2136
+ if (update.newValue !== update.oldValue) {
2137
+ this.unsubscribeFromInnerValue();
2138
+ this.unsubscribeFromInnerValue = update.newValue.subscribe(
2139
+ subscriptionKey,
2140
+ (transceiverUpdate) => {
2141
+ setIntoStore(latestUpdateState, transceiverUpdate, target);
2142
+ }
2143
+ );
2144
+ }
2145
+ },
2146
+ subscriptionKey,
2147
+ target
2148
+ );
2149
+ }
2150
+ updateCore(mutableState, latestUpdateState, target) {
2151
+ const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
2152
+ subscribeToState(
2153
+ latestUpdateState,
2154
+ ({ newValue, oldValue }) => {
2155
+ const timelineId = target.timelineTopics.getRelatedKey(
2156
+ latestUpdateState.key
2157
+ );
2158
+ if (timelineId) {
2159
+ const timelineData = target.timelines.get(timelineId);
2160
+ if (timelineData?.timeTraveling) {
2161
+ const unsubscribe2 = subscribeToTimeline(
2162
+ { key: timelineId, type: `timeline` },
2163
+ (update) => {
2164
+ unsubscribe2();
2165
+ setIntoStore(
2166
+ mutableState,
2167
+ (transceiver) => {
2168
+ if (update === `redo` && newValue) {
2169
+ transceiver.do(newValue);
2170
+ } else if (update === `undo` && oldValue) {
2171
+ transceiver.undo(oldValue);
2172
+ }
2173
+ return transceiver;
2174
+ },
2175
+ target
2176
+ );
2177
+ },
2178
+ subscriptionKey,
2179
+ target
2180
+ );
2181
+ return;
2182
+ }
2183
+ }
2184
+ const unsubscribe = target.on.operationClose.subscribe(
2185
+ subscriptionKey,
2186
+ () => {
2187
+ unsubscribe();
2188
+ const mutable = getFromStore(mutableState, target);
2189
+ const updateNumber = newValue === null ? -1 : mutable.getUpdateNumber(newValue);
2190
+ const eventOffset = updateNumber - mutable.cacheUpdateNumber;
2191
+ if (newValue && eventOffset === 1) {
2192
+ setIntoStore(
2193
+ mutableState,
2194
+ (transceiver) => (transceiver.do(newValue), transceiver),
2195
+ target
2196
+ );
2197
+ } else {
2198
+ target.logger.info(
2199
+ `\u274C`,
2200
+ `mutable_atom`,
2201
+ mutableState.key,
2202
+ `could not be updated. Expected update number ${mutable.cacheUpdateNumber + 1}, but got ${updateNumber}`
2203
+ );
2204
+ }
2205
+ }
2206
+ );
2207
+ },
2208
+ subscriptionKey,
2209
+ target
2210
+ );
2211
+ }
2212
+ mutableState;
2213
+ latestUpdateState;
2214
+ dispose;
2215
+ constructor(mutableState, store) {
2216
+ this.mutableState = mutableState;
2217
+ const target = newest(store);
2218
+ this.latestUpdateState = this.initializeState(mutableState, target);
2219
+ this.observeCore(mutableState, this.latestUpdateState, target);
2220
+ this.updateCore(mutableState, this.latestUpdateState, target);
2221
+ target.trackers.set(mutableState.key, this);
2222
+ this.dispose = () => {
2223
+ this.unsubscribeFromInnerValue();
2224
+ this.unsubscribeFromState();
2225
+ target.trackers.delete(mutableState.key);
2226
+ };
2227
+ }
2228
+ };
2229
+
2230
+ // internal/src/mutable/create-mutable-atom.ts
2231
+ function createMutableAtom(options, family, store) {
2232
+ store.logger.info(
2233
+ `\u{1F528}`,
2234
+ `atom`,
2235
+ options.key,
2236
+ `creating in store "${store.config.name}"`
2237
+ );
2238
+ const target = newest(store);
2239
+ const existing = target.atoms.get(options.key);
2240
+ if (existing && existing.type === `mutable_atom`) {
2241
+ store.logger.error(
2242
+ `\u274C`,
2243
+ `atom`,
2244
+ options.key,
2245
+ `Tried to create atom, but it already exists in the store.`
2246
+ );
2247
+ return deposit(existing);
2248
+ }
2249
+ const subject = new Subject();
2250
+ const newAtom = {
2251
+ ...options,
2252
+ type: `mutable_atom`,
2253
+ install: (s) => {
2254
+ s.logger.info(
2255
+ `\u{1F6E0}\uFE0F`,
2256
+ `atom`,
2257
+ options.key,
2258
+ `installing in store "${s.config.name}"`
2259
+ );
2260
+ return createMutableAtom(options, family, s);
2261
+ },
2262
+ subject
2263
+ };
2264
+ if (family) {
2265
+ newAtom.family = family;
2266
+ }
2267
+ const initialValue = options.default();
2268
+ target.atoms.set(newAtom.key, newAtom);
2269
+ markAtomAsDefault(options.key, store);
2270
+ cacheValue(options.key, initialValue, subject, target);
2271
+ const token = deposit(newAtom);
2272
+ if (options.effects) {
2273
+ let effectIndex = 0;
2274
+ const cleanupFunctions = [];
2275
+ for (const effect of options.effects) {
2276
+ const cleanup = effect({
2277
+ setSelf: (next) => {
2278
+ setIntoStore(token, next, store);
2279
+ },
2280
+ onSet: (handle) => subscribeToState(token, handle, `effect[${effectIndex}]`, store)
2281
+ });
2282
+ if (cleanup) {
2283
+ cleanupFunctions.push(cleanup);
2284
+ }
2285
+ ++effectIndex;
2286
+ }
2287
+ newAtom.cleanup = () => {
2288
+ for (const cleanup of cleanupFunctions) {
2289
+ cleanup();
2290
+ }
2291
+ };
2292
+ }
2293
+ new Tracker(token, store);
2294
+ if (!family) {
2295
+ selectJson(token, options, store);
2296
+ }
2297
+ return token;
2298
+ }
2299
+ var FamilyTracker = class {
2300
+ Update;
2301
+ latestUpdateAtoms;
2302
+ mutableAtoms;
2303
+ constructor(mutableAtoms, store) {
2304
+ const updateAtoms = createRegularAtomFamily(
2305
+ {
2306
+ key: `*${mutableAtoms.key}`,
2307
+ default: null
2308
+ },
2309
+ store,
2310
+ [`mutable`, `updates`]
2311
+ );
2312
+ this.latestUpdateAtoms = withdraw(updateAtoms, store);
2313
+ this.mutableAtoms = mutableAtoms;
2314
+ this.mutableAtoms.subject.subscribe(
2315
+ `store=${store.config.name}::tracker-atom-family`,
2316
+ (event) => {
2317
+ if (event.token.family) {
2318
+ const key = parseJson(event.token.family.subKey);
2319
+ seekInStore(this.latestUpdateAtoms, key, store);
2320
+ new Tracker(event.token, store);
2321
+ }
2322
+ }
2323
+ );
2324
+ this.latestUpdateAtoms.subject.subscribe(
2325
+ `store=${store.config.name}::tracker-atom-family`,
2326
+ (event) => {
2327
+ if (event.token.family) {
2328
+ const key = parseJson(event.token.family.subKey);
2329
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
2330
+ if (mutableAtomToken) {
2331
+ new Tracker(mutableAtomToken, store);
2332
+ }
2333
+ }
2334
+ }
2335
+ );
2336
+ }
2337
+ };
2338
+
2339
+ // internal/src/mutable/create-mutable-atom-family.ts
2340
+ function createMutableAtomFamily(options, store, internalRoles) {
2341
+ const familyToken = {
2342
+ key: options.key,
2343
+ type: `mutable_atom_family`
2344
+ };
2345
+ throwInCaseOfConflictingFamily(familyToken, store);
2346
+ const subject = new Subject();
2347
+ const familyFunction = (key) => {
2348
+ const subKey = stringifyJson(key);
2349
+ const family = { key: options.key, subKey };
2350
+ const fullKey = `${options.key}(${subKey})`;
2351
+ const target = newest(store);
2352
+ const individualOptions = {
2353
+ key: fullKey,
2354
+ default: () => options.default(key),
2355
+ toJson: options.toJson,
2356
+ fromJson: options.fromJson,
2357
+ mutable: true
2358
+ };
2359
+ if (options.effects) {
2360
+ individualOptions.effects = options.effects(key);
2361
+ }
2362
+ const token = createMutableAtom(individualOptions, family, target);
2363
+ subject.next({ type: `state_creation`, token });
2364
+ return token;
2365
+ };
2366
+ const atomFamily = Object.assign(familyFunction, familyToken, {
2367
+ subject,
2368
+ install: (s) => createMutableAtomFamily(options, s),
2369
+ toJson: options.toJson,
2370
+ fromJson: options.fromJson,
2371
+ internalRoles
2372
+ });
2373
+ store.families.set(options.key, atomFamily);
2374
+ selectJsonFamily(atomFamily, options, store);
2375
+ new FamilyTracker(atomFamily, store);
2376
+ return familyToken;
2377
+ }
2378
+
2379
+ // internal/src/mutable/get-json-family.ts
2380
+ var getJsonFamily = (mutableAtomFamily, store) => {
2381
+ const target = newest(store);
2382
+ const key = `${mutableAtomFamily.key}:JSON`;
2383
+ const jsonFamily = target.families.get(key);
2384
+ return jsonFamily;
2385
+ };
2386
+
2387
+ // internal/src/mutable/get-json-token.ts
2388
+ var getJsonToken = (mutableAtomToken, store) => {
2389
+ if (mutableAtomToken.family) {
2390
+ const target = newest(store);
2391
+ const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
2392
+ const jsonFamilyToken = {
2393
+ key: jsonFamilyKey,
2394
+ type: `selector_family`
2395
+ };
2396
+ const family = withdraw(jsonFamilyToken, target);
2397
+ const subKey = JSON.parse(mutableAtomToken.family.subKey);
2398
+ const jsonToken = findInStore(family, subKey, store);
2399
+ return jsonToken;
2400
+ }
2401
+ const token = {
2402
+ type: `selector`,
2403
+ key: `${mutableAtomToken.key}:JSON`
2404
+ };
2405
+ return token;
2406
+ };
2407
+
2408
+ // internal/src/mutable/get-update-family.ts
2409
+ var getUpdateFamily = (mutableAtomFamily, store) => {
2410
+ const target = newest(store);
2411
+ const key = `*${mutableAtomFamily.key}`;
2412
+ const updateFamily = target.families.get(
2413
+ key
2414
+ );
2415
+ return updateFamily;
2416
+ };
2417
+
2418
+ // internal/src/mutable/get-update-token.ts
2419
+ var getUpdateToken = (mutableAtomToken) => {
2420
+ const key = `*${mutableAtomToken.key}`;
2421
+ const updateToken = { type: `atom`, key };
2422
+ if (mutableAtomToken.family) {
2423
+ updateToken.family = {
2424
+ key: `*${mutableAtomToken.family.key}`,
2425
+ subKey: mutableAtomToken.family.subKey
2426
+ };
2427
+ }
2428
+ return updateToken;
2429
+ };
2430
+
2431
+ // internal/src/mutable/transceiver.ts
2432
+ function isTransceiver(value) {
2433
+ return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
2434
+ }
2435
+
2436
+ // internal/src/set-state/copy-mutable-if-needed.ts
2437
+ function copyMutableIfNeeded(atom, origin, target) {
2438
+ const originValue = origin.valueMap.get(atom.key);
2439
+ const targetValue = target.valueMap.get(atom.key);
2440
+ if (originValue === targetValue) {
2441
+ if (originValue === void 0) {
2442
+ return typeof atom.default === `function` ? atom.default() : atom.default;
2443
+ }
2444
+ origin.logger.info(`\u{1F4C3}`, `atom`, atom.key, `copying`);
2445
+ const jsonValue = atom.toJson(originValue);
2446
+ const copiedValue = atom.fromJson(jsonValue);
2447
+ target.valueMap.set(atom.key, copiedValue);
2448
+ new Tracker(atom, origin);
2449
+ return copiedValue;
2450
+ }
2451
+ return targetValue;
2452
+ }
2453
+
2454
+ // internal/src/caching.ts
2455
+ function cacheValue(key, value, subject, target) {
2456
+ const currentValue = target.valueMap.get(key);
2457
+ if (currentValue instanceof Future) {
2458
+ const future = currentValue;
2459
+ future.use(value);
2460
+ }
2461
+ if (value instanceof Promise) {
2462
+ const future = new Future(value);
2463
+ target.valueMap.set(key, future);
2464
+ future.then((resolved) => {
2465
+ cacheValue(key, resolved, subject, target);
2466
+ subject.next({ newValue: resolved, oldValue: future });
2467
+ }).catch((thrown) => {
2468
+ target.logger.error(`\u{1F4A5}`, `state`, key, `rejected:`, thrown);
2469
+ });
2470
+ return future;
2471
+ }
2472
+ target.valueMap.set(key, value);
2473
+ return value;
2474
+ }
2475
+ var readCachedValue = (token, target) => {
2476
+ let value = target.valueMap.get(token.key);
2477
+ if (token.type === `mutable_atom` && isChildStore(target)) {
2478
+ const { parent } = target;
2479
+ const copiedValue = copyMutableIfNeeded(token, parent, target);
2480
+ value = copiedValue;
2481
+ }
2482
+ return value;
2483
+ };
2484
+ var evictCachedValue = (key, target) => {
2485
+ const currentValue = target.valueMap.get(key);
2486
+ if (currentValue instanceof Future) {
2487
+ const future = currentValue;
2488
+ const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key);
2489
+ if (selector) {
2490
+ future.use(selector.get());
2491
+ }
2492
+ return;
2493
+ }
2494
+ if (target.operation.open) {
2495
+ target.operation.prev.set(key, currentValue);
2496
+ }
2497
+ target.valueMap.delete(key);
2498
+ target.logger.info(`\u{1F5D1}`, `state`, key, `evicted`);
2499
+ };
2500
+
2501
+ // internal/src/atom/is-default.ts
2502
+ var isAtomDefault = (key, store) => {
2503
+ const core = newest(store);
2504
+ return core.atomsThatAreDefault.has(key);
2505
+ };
2506
+ var markAtomAsDefault = (key, store) => {
2507
+ const core = newest(store);
2508
+ core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
2509
+ };
2510
+ var markAtomAsNotDefault = (key, store) => {
2511
+ const core = newest(store);
2512
+ core.atomsThatAreDefault = new Set(newest(store).atomsThatAreDefault);
2513
+ core.atomsThatAreDefault.delete(key);
2514
+ };
2515
+
2516
+ // internal/src/atom/create-regular-atom.ts
2517
+ function createRegularAtom(options, family, store) {
2518
+ store.logger.info(
2519
+ `\u{1F528}`,
2520
+ `atom`,
2521
+ options.key,
2522
+ `creating in store "${store.config.name}"`
2523
+ );
2524
+ const target = newest(store);
2525
+ const existing = target.atoms.get(options.key);
2526
+ if (existing && existing.type === `atom`) {
2527
+ store.logger.error(
2528
+ `\u274C`,
2529
+ `atom`,
2530
+ options.key,
2531
+ `Tried to create atom, but it already exists in the store.`
2532
+ );
2533
+ return deposit(existing);
2534
+ }
2535
+ const subject = new Subject();
2536
+ const newAtom = {
2537
+ ...options,
2538
+ type: `atom`,
2539
+ install: (s) => {
2540
+ s.logger.info(
2541
+ `\u{1F6E0}\uFE0F`,
2542
+ `atom`,
2543
+ options.key,
2544
+ `installing in store "${s.config.name}"`
2545
+ );
2546
+ return createRegularAtom(options, family, s);
2547
+ },
2548
+ subject
2549
+ };
2550
+ if (family) {
2551
+ newAtom.family = family;
2552
+ }
2553
+ let initialValue = options.default;
2554
+ if (options.default instanceof Function) {
2555
+ initialValue = options.default();
2556
+ }
2557
+ target.atoms.set(newAtom.key, newAtom);
2558
+ markAtomAsDefault(options.key, store);
2559
+ cacheValue(options.key, initialValue, subject, target);
2560
+ const token = deposit(newAtom);
2561
+ if (options.effects) {
2562
+ let effectIndex = 0;
2563
+ const cleanupFunctions = [];
2564
+ for (const effect of options.effects) {
2565
+ const cleanup = effect({
2566
+ setSelf: (next) => {
2567
+ setIntoStore(token, next, store);
2568
+ },
2569
+ onSet: (handle) => subscribeToState(token, handle, `effect[${effectIndex}]`, store)
2570
+ });
2571
+ if (cleanup) {
2572
+ cleanupFunctions.push(cleanup);
2573
+ }
2574
+ ++effectIndex;
2575
+ }
2576
+ newAtom.cleanup = () => {
2577
+ for (const cleanup of cleanupFunctions) {
2578
+ cleanup();
2579
+ }
2580
+ };
2581
+ }
2582
+ return token;
2583
+ }
2584
+
2585
+ // internal/src/atom/create-standalone-atom.ts
2586
+ function createStandaloneAtom(options, store) {
2587
+ const isMutable = `mutable` in options;
2588
+ if (isMutable) {
2589
+ const state2 = createMutableAtom(options, void 0, store);
2590
+ store.on.atomCreation.next(state2);
2591
+ return state2;
2592
+ }
2593
+ const state = createRegularAtom(options, void 0, store);
2594
+ store.on.atomCreation.next(state);
2595
+ return state;
2596
+ }
2597
+
2598
+ // internal/src/atom/dispose-atom.ts
2599
+ function disposeAtom(atomToken, store) {
2600
+ const target = newest(store);
2601
+ const { key } = atomToken;
2602
+ const atom = target.atoms.get(key);
2603
+ if (!atom) {
2604
+ store.logger.error(
2605
+ `\u274C`,
2606
+ `atom`,
2607
+ key,
2608
+ `Tried to dispose atom, but it does not exist in the store.`
2609
+ );
2610
+ } else if (!atom.family) {
2611
+ store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
2612
+ } else {
2613
+ atom.cleanup?.();
2614
+ const lastValue = store.valueMap.get(atom.key);
2615
+ const family = withdraw({ key: atom.family.key, type: `atom_family` }, store);
2616
+ family.subject.next({
2617
+ type: `state_disposal`,
2618
+ token: atomToken,
2619
+ value: lastValue
2620
+ });
2621
+ const molecule = target.molecules.get(atom.family.subKey);
2622
+ if (molecule) {
2623
+ molecule.tokens.delete(key);
2624
+ }
2625
+ target.atoms.delete(key);
2626
+ target.valueMap.delete(key);
2627
+ const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
2628
+ if (selectorKeys) {
2629
+ for (const selectorKey of selectorKeys) {
2630
+ const token = target.selectors.get(selectorKey) ?? target.readonlySelectors.get(selectorKey);
2631
+ if (token) {
2632
+ disposeSelector(token, store);
2633
+ }
2634
+ }
2635
+ }
2636
+ target.selectorAtoms.delete(key);
2637
+ target.atomsThatAreDefault.delete(key);
2638
+ target.timelineTopics.delete(key);
2639
+ if (atomToken.type === `mutable_atom`) {
2640
+ const updateToken = getUpdateToken(atomToken);
2641
+ disposeAtom(updateToken, store);
2642
+ store.trackers.delete(key);
2643
+ }
2644
+ store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
2645
+ if (isChildStore(target) && target.transactionMeta.phase === `building`) {
2646
+ target.transactionMeta.update.updates.push({
2647
+ type: `state_disposal`,
2648
+ token: atomToken
2649
+ });
2650
+ } else {
2651
+ store.on.atomDisposal.next(atomToken);
2652
+ }
2653
+ }
2654
+ }
2655
+ function createTimeline(options, store, data) {
2656
+ const tl = {
2657
+ type: `timeline`,
2658
+ key: options.key,
2659
+ at: 0,
2660
+ timeTraveling: null,
2661
+ selectorTime: null,
2662
+ transactionKey: null,
2663
+ ...data,
2664
+ history: data?.history.map((update) => ({ ...update })) ?? [],
2665
+ install: (s) => createTimeline(options, s, tl),
2666
+ subject: new Subject(),
2667
+ subscriptions: /* @__PURE__ */ new Map()
2668
+ };
2669
+ if (options.shouldCapture) {
2670
+ tl.shouldCapture = options.shouldCapture;
2671
+ }
2672
+ const timelineKey = options.key;
2673
+ const target = newest(store);
2674
+ for (const initialTopic of options.scope) {
2675
+ switch (initialTopic.type) {
2676
+ case `atom`:
2677
+ case `mutable_atom`:
2678
+ {
2679
+ const atomToken = initialTopic;
2680
+ const atomKey = atomToken.key;
2681
+ let existingTimelineKey = target.timelineTopics.getRelatedKey(atomKey);
2682
+ if (`family` in atomToken) {
2683
+ const familyKey = atomToken.family.key;
2684
+ existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2685
+ if (existingTimelineKey) {
2686
+ store.logger.error(
2687
+ `\u274C`,
2688
+ `timeline`,
2689
+ options.key,
2690
+ `Failed to add atom "${atomKey}" because its family "${familyKey}" already belongs to timeline "${existingTimelineKey}"`
2691
+ );
2692
+ continue;
2693
+ }
2694
+ }
2695
+ if (existingTimelineKey) {
2696
+ store.logger.error(
2697
+ `\u274C`,
2698
+ `timeline`,
2699
+ options.key,
2700
+ `Failed to add atom "${atomKey}" because it already belongs to timeline "${existingTimelineKey}"`
2701
+ );
2702
+ continue;
2703
+ }
2704
+ addAtomToTimeline(atomToken, tl, store);
2705
+ }
2706
+ break;
2707
+ case `atom_family`:
2708
+ case `mutable_atom_family`:
2709
+ {
2710
+ const familyToken = initialTopic;
2711
+ const familyKey = familyToken.key;
2712
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2713
+ if (existingTimelineKey) {
2714
+ store.logger.error(
2715
+ `\u274C`,
2716
+ `timeline`,
2717
+ options.key,
2718
+ `Failed to add atom family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2719
+ );
2720
+ continue;
2721
+ }
2722
+ addAtomFamilyToTimeline(familyToken, tl, store);
2723
+ }
2724
+ break;
2725
+ case `molecule_family`:
2726
+ {
2727
+ const familyToken = initialTopic;
2728
+ const familyKey = familyToken.key;
2729
+ const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
2730
+ if (existingTimelineKey) {
2731
+ store.logger.error(
2732
+ `\u274C`,
2733
+ `timeline`,
2734
+ options.key,
2735
+ `Failed to add molecule family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
2736
+ );
2737
+ continue;
2738
+ }
2739
+ addMoleculeFamilyToTimeline(familyToken, tl, store);
2740
+ }
2741
+ break;
2742
+ }
2743
+ }
2744
+ store.timelines.set(options.key, tl);
2745
+ const token = {
2746
+ key: timelineKey,
2747
+ type: `timeline`
2748
+ };
2749
+ store.on.timelineCreation.next(token);
2750
+ return token;
2751
+ }
2752
+ function addAtomToTimeline(atomToken, tl, store) {
2753
+ let maybeAtom = withdraw(atomToken, store);
2754
+ if (maybeAtom.type === `mutable_atom`) {
2755
+ const updateToken = getUpdateToken(maybeAtom);
2756
+ maybeAtom = withdraw(updateToken, store);
2757
+ }
2758
+ const atom = maybeAtom;
2759
+ store.timelineTopics.set(
2760
+ { topicKey: atom.key, timelineKey: tl.key },
2761
+ { topicType: `atom` }
2762
+ );
2763
+ tl.subscriptions.set(
2764
+ atom.key,
2765
+ atom.subject.subscribe(`timeline`, (update) => {
2766
+ const target = newest(store);
2767
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2768
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2769
+ const txUpdateInProgress = target.on.transactionApplying.state?.update;
2770
+ store.logger.info(
2771
+ `\u23F3`,
2772
+ `timeline`,
2773
+ tl.key,
2774
+ `atom`,
2775
+ atomToken.key,
2776
+ `went`,
2777
+ update.oldValue,
2778
+ `->`,
2779
+ update.newValue,
2780
+ txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2781
+ );
2782
+ if (tl.timeTraveling === null) {
2783
+ if (txUpdateInProgress) {
2784
+ joinTransaction(tl, txUpdateInProgress, store);
2785
+ } else if (currentSelectorKey && currentSelectorTime) {
2786
+ let latestUpdate = tl.history.at(-1);
2787
+ if (currentSelectorTime !== tl.selectorTime) {
2788
+ latestUpdate = {
2789
+ type: `selector_update`,
2790
+ timestamp: currentSelectorTime,
2791
+ key: currentSelectorKey,
2792
+ atomUpdates: []
2793
+ };
2794
+ latestUpdate.atomUpdates.push({
2795
+ key: atom.key,
2796
+ type: `atom_update`,
2797
+ ...update
2798
+ });
2799
+ if (tl.at !== tl.history.length) {
2800
+ tl.history.splice(tl.at);
2801
+ }
2802
+ tl.history.push(latestUpdate);
2803
+ store.logger.info(
2804
+ `\u231B`,
2805
+ `timeline`,
2806
+ tl.key,
2807
+ `got a selector_update "${currentSelectorKey}" with`,
2808
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
2809
+ );
2810
+ tl.at = tl.history.length;
2811
+ tl.selectorTime = currentSelectorTime;
2812
+ } else {
2813
+ if (latestUpdate?.type === `selector_update`) {
2814
+ latestUpdate.atomUpdates.push({
2815
+ key: atom.key,
2816
+ type: `atom_update`,
2817
+ ...update
2818
+ });
2819
+ store.logger.info(
2820
+ `\u231B`,
2821
+ `timeline`,
2822
+ tl.key,
2823
+ `set selector_update "${currentSelectorKey}" to`,
2824
+ latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
2825
+ );
2826
+ }
2827
+ }
2828
+ if (latestUpdate) {
2829
+ const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
2830
+ if (willCaptureSelectorUpdate) {
2831
+ tl.subject.next(latestUpdate);
2832
+ } else {
2833
+ tl.history.pop();
2834
+ tl.at = tl.history.length;
2835
+ }
2836
+ }
2837
+ } else {
2838
+ const timestamp = Date.now();
2839
+ tl.selectorTime = null;
2840
+ if (tl.at !== tl.history.length) {
2841
+ tl.history.splice(tl.at);
2842
+ }
2843
+ const atomUpdate = {
2844
+ type: `atom_update`,
2845
+ timestamp,
2846
+ key: atom.key,
2847
+ oldValue: update.oldValue,
2848
+ newValue: update.newValue
2849
+ };
2850
+ if (atom.family) {
2851
+ atomUpdate.family = atom.family;
2852
+ }
2853
+ const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
2854
+ store.logger.info(
2855
+ `\u231B`,
2856
+ `timeline`,
2857
+ tl.key,
2858
+ `got an atom_update to "${atom.key}"`
2859
+ );
2860
+ if (willCapture) {
2861
+ tl.history.push(atomUpdate);
2862
+ tl.at = tl.history.length;
2863
+ tl.subject.next(atomUpdate);
2864
+ }
2865
+ }
2866
+ }
2867
+ })
2868
+ );
2869
+ }
2870
+ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
2871
+ const family = withdraw(atomFamilyToken, store);
2872
+ store.timelineTopics.set(
2873
+ { topicKey: family.key, timelineKey: tl.key },
2874
+ { topicType: `atom_family` }
2875
+ );
2876
+ tl.subscriptions.set(
2877
+ family.key,
2878
+ family.subject.subscribe(`timeline`, (creationOrDisposal) => {
2879
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
2880
+ })
2881
+ );
2882
+ for (const atom of store.atoms.values()) {
2883
+ if (atom.family?.key === family.key) {
2884
+ addAtomToTimeline(atom, tl, store);
2885
+ }
2886
+ }
2887
+ }
2888
+ function addMoleculeFamilyToTimeline(familyToken, tl, store) {
2889
+ store.timelineTopics.set(
2890
+ { topicKey: familyToken.key, timelineKey: tl.key },
2891
+ { topicType: `molecule_family` }
2892
+ );
2893
+ const family = store.moleculeFamilies.get(familyToken.key);
2894
+ if (family) {
2895
+ tl.subscriptions.set(
2896
+ familyToken.key,
2897
+ family.subject.subscribe(`timeline:${tl.key}`, (creationOrDisposal) => {
2898
+ store.logger.info(
2899
+ `\u{1F41E}`,
2900
+ `timeline`,
2901
+ tl.key,
2902
+ `got a molecule creation or disposal`,
2903
+ creationOrDisposal
2904
+ );
2905
+ switch (creationOrDisposal.type) {
2906
+ case `molecule_creation`:
2907
+ {
2908
+ store.timelineTopics.set(
2909
+ {
2910
+ topicKey: creationOrDisposal.token.key,
2911
+ timelineKey: tl.key
2912
+ },
2913
+ { topicType: `molecule` }
2914
+ );
2915
+ const txUpdateInProgress = newest(store).on.transactionApplying.state?.update;
2916
+ if (txUpdateInProgress) {
2917
+ joinTransaction(tl, txUpdateInProgress, store);
2918
+ } else if (tl.timeTraveling === null) {
2919
+ const event = Object.assign(creationOrDisposal, {
2920
+ timestamp: Date.now()
2921
+ });
2922
+ tl.history.push(event);
2923
+ tl.at = tl.history.length;
2924
+ tl.subject.next(event);
2925
+ }
2926
+ const molecule = withdraw(creationOrDisposal.token, store);
2927
+ for (const token of molecule.tokens.values()) {
2928
+ switch (token.type) {
2929
+ case `atom`:
2930
+ case `mutable_atom`:
2931
+ addAtomToTimeline(token, tl, store);
2932
+ break;
2933
+ }
2934
+ }
2935
+ tl.subscriptions.set(
2936
+ molecule.key,
2937
+ molecule.subject.subscribe(
2938
+ `timeline:${tl.key}`,
2939
+ (stateCreationOrDisposal) => {
2940
+ handleStateLifecycleEvent(stateCreationOrDisposal, tl, store);
2941
+ }
2942
+ )
2943
+ );
2944
+ }
2945
+ break;
2946
+ case `molecule_disposal`:
2947
+ {
2948
+ const txUpdateInProgress = newest(store).on.transactionApplying.state?.update;
2949
+ if (txUpdateInProgress) {
2950
+ joinTransaction(tl, txUpdateInProgress, store);
2951
+ } else if (tl.timeTraveling === null) {
2952
+ const event = Object.assign(creationOrDisposal, {
2953
+ timestamp: Date.now()
2954
+ });
2955
+ tl.history.push(event);
2956
+ tl.at = tl.history.length;
2957
+ tl.subject.next(event);
2958
+ }
2959
+ const moleculeKey = creationOrDisposal.token.key;
2960
+ tl.subscriptions.get(moleculeKey)?.();
2961
+ tl.subscriptions.delete(moleculeKey);
2962
+ for (const [familyKey] of creationOrDisposal.values) {
2963
+ const stateKey = `${familyKey}(${stringifyJson(moleculeKey)})`;
2964
+ tl.subscriptions.get(stateKey)?.();
2965
+ tl.subscriptions.delete(stateKey);
2966
+ store.timelineTopics.delete(stateKey);
2967
+ }
2968
+ }
2969
+ break;
2970
+ }
2971
+ })
2972
+ );
2973
+ }
2974
+ }
2975
+ function joinTransaction(tl, txUpdateInProgress, store) {
2976
+ const currentTxKey = txUpdateInProgress.key;
2977
+ const currentTxInstanceId = txUpdateInProgress.id;
2978
+ const currentTxToken = {
2979
+ key: currentTxKey,
2980
+ type: `transaction`
2981
+ };
2982
+ const currentTransaction = withdraw(currentTxToken, store);
2983
+ if (currentTxKey && tl.transactionKey === null) {
2984
+ tl.transactionKey = currentTxKey;
2985
+ const unsubscribe = currentTransaction.subject.subscribe(
2986
+ `timeline:${tl.key}`,
2987
+ (transactionUpdate) => {
2988
+ unsubscribe();
2989
+ tl.transactionKey = null;
2990
+ if (tl.timeTraveling === null && currentTxInstanceId) {
2991
+ if (tl.at !== tl.history.length) {
2992
+ tl.history.splice(tl.at);
2993
+ }
2994
+ const timelineTopics = store.timelineTopics.getRelatedKeys(tl.key);
2995
+ const updates = filterTransactionUpdates(
2996
+ transactionUpdate.updates,
2997
+ timelineTopics
2998
+ );
2999
+ const timelineTransactionUpdate = {
3000
+ timestamp: Date.now(),
3001
+ ...transactionUpdate,
3002
+ updates
3003
+ };
3004
+ const willCapture = tl.shouldCapture?.(timelineTransactionUpdate, tl) ?? true;
3005
+ if (willCapture) {
3006
+ tl.history.push(timelineTransactionUpdate);
3007
+ tl.at = tl.history.length;
3008
+ tl.subject.next(timelineTransactionUpdate);
3009
+ }
3010
+ }
3011
+ }
3012
+ );
3013
+ }
3014
+ }
3015
+ function filterTransactionUpdates(updates, timelineTopics) {
3016
+ return updates.filter((updateFromTx) => {
3017
+ if (updateFromTx.type === `transaction_update`) {
3018
+ return true;
3019
+ }
3020
+ let key;
3021
+ switch (updateFromTx.type) {
3022
+ case `state_creation`:
3023
+ case `state_disposal`:
3024
+ case `molecule_creation`:
3025
+ case `molecule_disposal`:
3026
+ key = updateFromTx.token.key;
3027
+ break;
3028
+ default:
3029
+ key = updateFromTx.key;
3030
+ break;
3031
+ }
3032
+ return timelineTopics.has(key);
3033
+ }).map((updateFromTx) => {
3034
+ if (`updates` in updateFromTx) {
3035
+ return {
3036
+ ...updateFromTx,
3037
+ updates: filterTransactionUpdates(
3038
+ updateFromTx.updates,
3039
+ timelineTopics
3040
+ )
3041
+ };
3042
+ }
3043
+ return updateFromTx;
3044
+ });
3045
+ }
3046
+ function handleStateLifecycleEvent(event, tl, store) {
3047
+ const timestamp = Date.now();
3048
+ const timelineEvent = Object.assign(event, {
3049
+ timestamp
3050
+ });
3051
+ if (!tl.timeTraveling) {
3052
+ const txUpdateInProgress = newest(store).on.transactionApplying.state?.update;
3053
+ if (txUpdateInProgress) {
3054
+ joinTransaction(tl, txUpdateInProgress, store);
3055
+ } else {
3056
+ tl.history.push(timelineEvent);
3057
+ tl.at = tl.history.length;
3058
+ tl.subject.next(timelineEvent);
3059
+ }
3060
+ }
3061
+ switch (event.type) {
3062
+ case `state_creation`:
3063
+ addAtomToTimeline(event.token, tl, store);
3064
+ break;
3065
+ case `state_disposal`:
3066
+ tl.subscriptions.get(event.token.key)?.();
3067
+ tl.subscriptions.delete(event.token.key);
3068
+ break;
3069
+ }
3070
+ }
3071
+
3072
+ // internal/src/timeline/time-travel.ts
3073
+ var timeTravel = (action, token, store) => {
3074
+ store.logger.info(
3075
+ action === `redo` ? `\u23E9` : `\u23EA`,
3076
+ `timeline`,
3077
+ token.key,
3078
+ action
3079
+ );
3080
+ const timelineData = store.timelines.get(token.key);
3081
+ if (!timelineData) {
3082
+ store.logger.error(
3083
+ `\u{1F41E}`,
3084
+ `timeline`,
3085
+ token.key,
3086
+ `Failed to ${action}. This timeline has not been initialized.`
3087
+ );
3088
+ return;
3089
+ }
3090
+ if (action === `redo` && timelineData.at === timelineData.history.length || action === `undo` && timelineData.at === 0) {
3091
+ store.logger.warn(
3092
+ `\u{1F481}`,
3093
+ `timeline`,
3094
+ token.key,
3095
+ `Failed to ${action} at the ${action === `redo` ? `end` : `beginning`} of timeline "${token.key}". There is nothing to ${action}.`
3096
+ );
3097
+ return;
3098
+ }
3099
+ timelineData.timeTraveling = action === `redo` ? `into_future` : `into_past`;
3100
+ if (action === `undo`) {
3101
+ --timelineData.at;
3102
+ }
3103
+ const update = timelineData.history[timelineData.at];
3104
+ const applying = action === `redo` ? `newValue` : `oldValue`;
3105
+ switch (update.type) {
3106
+ case `atom_update`: {
3107
+ ingestAtomUpdate(applying, update, store);
3108
+ break;
3109
+ }
3110
+ case `selector_update`: {
3111
+ ingestSelectorUpdate(applying, update, store);
3112
+ break;
3113
+ }
3114
+ case `transaction_update`: {
3115
+ ingestTransactionUpdate(applying, update, store);
3116
+ break;
3117
+ }
3118
+ case `state_creation`: {
3119
+ ingestCreationEvent(update, applying, store);
3120
+ break;
3121
+ }
3122
+ case `state_disposal`: {
3123
+ ingestDisposalEvent(update, applying, store);
3124
+ break;
3125
+ }
3126
+ case `molecule_creation`: {
3127
+ ingestMoleculeCreationEvent(update, applying, store);
3128
+ break;
3129
+ }
3130
+ case `molecule_disposal`: {
3131
+ ingestMoleculeDisposalEvent(update, applying, store);
3132
+ break;
3133
+ }
3134
+ }
3135
+ if (action === `redo`) {
3136
+ ++timelineData.at;
3137
+ }
3138
+ timelineData.subject.next(action);
3139
+ timelineData.timeTraveling = null;
3140
+ store.logger.info(
3141
+ `\u23F9\uFE0F`,
3142
+ `timeline`,
3143
+ token.key,
3144
+ `"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`
3145
+ );
3146
+ };
3147
+
3148
+ export { FamilyTracker, Future, IMPLICIT, LazyMap, Molecule, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, createWritableSelectorFamily, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };