atom.io 0.12.1 → 0.14.0

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 (120) hide show
  1. package/dist/index.cjs +9 -74
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +9 -6
  4. package/dist/index.d.ts +9 -6
  5. package/dist/index.js +11 -74
  6. package/dist/index.js.map +1 -1
  7. package/dist/metafile-cjs.json +1 -1
  8. package/dist/metafile-esm.json +1 -1
  9. package/internal/dist/index.cjs +1700 -1579
  10. package/internal/dist/index.cjs.map +1 -1
  11. package/internal/dist/index.d.cts +32 -15
  12. package/internal/dist/index.d.ts +32 -15
  13. package/internal/dist/index.js +1695 -1579
  14. package/internal/dist/index.js.map +1 -1
  15. package/internal/dist/metafile-cjs.json +1 -1
  16. package/internal/dist/metafile-esm.json +1 -1
  17. package/internal/src/atom/create-atom.ts +7 -6
  18. package/internal/src/atom/delete-atom.ts +11 -11
  19. package/internal/src/atom/is-default.ts +5 -5
  20. package/internal/src/caching.ts +12 -10
  21. package/internal/src/families/create-atom-family.ts +3 -3
  22. package/internal/src/families/create-readonly-selector-family.ts +3 -3
  23. package/internal/src/families/create-selector-family.ts +4 -4
  24. package/internal/src/index.ts +1 -0
  25. package/internal/src/keys.ts +4 -4
  26. package/internal/src/lazy-map.ts +6 -2
  27. package/internal/src/lineage.ts +18 -0
  28. package/internal/src/mutable/create-mutable-atom.ts +8 -6
  29. package/internal/src/mutable/get-json-family.ts +3 -3
  30. package/internal/src/mutable/tracker.ts +18 -13
  31. package/internal/src/operation.ts +19 -19
  32. package/internal/src/selector/create-read-write-selector.ts +5 -4
  33. package/internal/src/selector/create-readonly-selector.ts +4 -3
  34. package/internal/src/selector/create-selector.ts +6 -6
  35. package/internal/src/selector/delete-selector.ts +10 -10
  36. package/internal/src/selector/get-selector-dependency-keys.ts +2 -2
  37. package/internal/src/selector/register-selector.ts +4 -4
  38. package/internal/src/selector/update-selector-atoms.ts +4 -4
  39. package/internal/src/set-state/copy-mutable-if-needed.ts +4 -3
  40. package/internal/src/set-state/copy-mutable-in-transaction.ts +10 -16
  41. package/internal/src/set-state/copy-mutable-into-new-store.ts +1 -1
  42. package/internal/src/set-state/evict-downstream.ts +5 -5
  43. package/internal/src/set-state/set-atom.ts +6 -1
  44. package/internal/src/set-state/stow-update.ts +7 -2
  45. package/internal/src/store/store.ts +31 -24
  46. package/internal/src/store/withdraw-new-family-member.ts +3 -4
  47. package/internal/src/store/withdraw.ts +58 -59
  48. package/internal/src/subject.ts +14 -0
  49. package/internal/src/subscribe/index.ts +3 -0
  50. package/internal/src/subscribe/recall-state.ts +5 -11
  51. package/internal/src/subscribe/subscribe-to-state.ts +47 -0
  52. package/internal/src/subscribe/subscribe-to-timeline.ts +28 -0
  53. package/internal/src/subscribe/subscribe-to-transaction.ts +33 -0
  54. package/internal/src/timeline/add-atom-to-timeline.ts +37 -27
  55. package/internal/src/timeline/create-timeline.ts +6 -8
  56. package/internal/src/timeline/time-travel.ts +22 -4
  57. package/internal/src/transaction/abort-transaction.ts +5 -3
  58. package/internal/src/transaction/apply-transaction.ts +80 -58
  59. package/internal/src/transaction/build-transaction.ts +33 -23
  60. package/internal/src/transaction/create-transaction.ts +6 -9
  61. package/internal/src/transaction/index.ts +2 -10
  62. package/internal/src/transaction/redo-transaction.ts +15 -10
  63. package/internal/src/transaction/undo-transaction.ts +15 -16
  64. package/introspection/dist/index.cjs +2 -2
  65. package/introspection/dist/index.cjs.map +1 -1
  66. package/introspection/dist/index.js +3 -3
  67. package/introspection/dist/index.js.map +1 -1
  68. package/introspection/src/attach-atom-index.ts +2 -2
  69. package/introspection/src/attach-selector-index.ts +2 -2
  70. package/package.json +8 -8
  71. package/react/dist/index.cjs +39 -1
  72. package/react/dist/index.cjs.map +1 -1
  73. package/react/dist/index.d.cts +9 -2
  74. package/react/dist/index.d.ts +9 -2
  75. package/react/dist/index.js +41 -4
  76. package/react/dist/index.js.map +1 -1
  77. package/react/dist/metafile-cjs.json +1 -1
  78. package/react/dist/metafile-esm.json +1 -1
  79. package/react/src/store-hooks.ts +52 -3
  80. package/react-devtools/dist/index.cjs +22 -8
  81. package/react-devtools/dist/index.cjs.map +1 -1
  82. package/react-devtools/dist/index.d.cts +17 -9
  83. package/react-devtools/dist/index.d.ts +17 -9
  84. package/react-devtools/dist/index.js +22 -8
  85. package/react-devtools/dist/index.js.map +1 -1
  86. package/react-devtools/dist/metafile-cjs.json +1 -1
  87. package/react-devtools/dist/metafile-esm.json +1 -1
  88. package/react-devtools/src/Updates.tsx +22 -10
  89. package/realtime-client/dist/index.cjs +8 -7
  90. package/realtime-client/dist/index.cjs.map +1 -1
  91. package/realtime-client/dist/index.d.cts +3 -2
  92. package/realtime-client/dist/index.d.ts +3 -2
  93. package/realtime-client/dist/index.js +3 -2
  94. package/realtime-client/dist/index.js.map +1 -1
  95. package/realtime-client/dist/metafile-cjs.json +1 -1
  96. package/realtime-client/dist/metafile-esm.json +1 -1
  97. package/realtime-client/src/use-push.ts +4 -4
  98. package/realtime-client/src/use-server-action.ts +4 -4
  99. package/realtime-server/dist/index.cjs +46 -25
  100. package/realtime-server/dist/index.cjs.map +1 -1
  101. package/realtime-server/dist/index.d.cts +5 -5
  102. package/realtime-server/dist/index.d.ts +5 -5
  103. package/realtime-server/dist/index.js +38 -17
  104. package/realtime-server/dist/index.js.map +1 -1
  105. package/realtime-server/dist/metafile-cjs.json +1 -1
  106. package/realtime-server/dist/metafile-esm.json +1 -1
  107. package/realtime-server/src/hook-composition/expose-family.ts +7 -3
  108. package/realtime-server/src/hook-composition/expose-mutable-family.ts +13 -5
  109. package/realtime-server/src/hook-composition/expose-mutable.ts +11 -3
  110. package/realtime-server/src/hook-composition/expose-single.ts +6 -2
  111. package/realtime-server/src/hook-composition/receive-transaction.ts +14 -5
  112. package/src/subscribe.ts +37 -91
  113. package/src/transaction.ts +7 -2
  114. package/transceivers/set-rtx/dist/index.cjs.map +1 -1
  115. package/transceivers/set-rtx/dist/index.d.cts +2 -2
  116. package/transceivers/set-rtx/dist/index.d.ts +2 -2
  117. package/transceivers/set-rtx/dist/index.js.map +1 -1
  118. package/transceivers/set-rtx/dist/metafile-cjs.json +1 -1
  119. package/transceivers/set-rtx/dist/metafile-esm.json +1 -1
  120. package/transceivers/set-rtx/src/set-rtx.ts +3 -3
@@ -1,5 +1,6 @@
1
- import { AtomIOLogger, setState, getState, subscribe, subscribeToTimeline } from 'atom.io';
1
+ import { AtomIOLogger, getState, setState, runTransaction } from 'atom.io';
2
2
  import { selectJson, stringifyJson, parseJson, selectJsonFamily } from 'atom.io/json';
3
+ import { withdraw as withdraw$1, subscribeToRootAtoms as subscribeToRootAtoms$1 } from 'atom.io/internal';
3
4
 
4
5
  var __defProp = Object.defineProperty;
5
6
  var __defProps = Object.defineProperties;
@@ -40,129 +41,458 @@ var Future = class extends Promise {
40
41
  }
41
42
  };
42
43
 
43
- // src/transaction/abort-transaction.ts
44
- var abortTransaction = (store) => {
45
- if (store.transactionStatus.phase === `idle`) {
46
- store.logger.warn(
47
- `\u{1F41E}`,
48
- `transaction`,
49
- `???`,
50
- `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
51
- );
52
- return;
44
+ // src/lineage.ts
45
+ function newest(scion) {
46
+ while (scion.child !== null) {
47
+ scion = scion.child;
48
+ }
49
+ return scion;
50
+ }
51
+ function eldest(scion) {
52
+ while (scion.parent !== null) {
53
+ scion = scion.parent;
54
+ }
55
+ return scion;
56
+ }
57
+
58
+ // src/caching.ts
59
+ function cacheValue(key, value, subject, store) {
60
+ const target = newest(store);
61
+ const currentValue = target.valueMap.get(key);
62
+ if (currentValue instanceof Future) {
63
+ currentValue.cancel();
64
+ }
65
+ if (value instanceof Promise) {
66
+ const future = new Future(value);
67
+ newest(store).valueMap.set(key, future);
68
+ future.then((resolved) => {
69
+ if (future.isCanceled) {
70
+ return;
71
+ }
72
+ cacheValue(key, resolved, subject, store);
73
+ subject.next({ newValue: resolved, oldValue: future });
74
+ }).catch((thrown) => {
75
+ if (thrown !== `canceled`) {
76
+ store.logger.error(`\u{1F4A5}`, `state`, key, `rejected:`, thrown);
77
+ }
78
+ });
79
+ return future;
80
+ }
81
+ target.valueMap.set(key, value);
82
+ return value;
83
+ }
84
+ var readCachedValue = (key, store) => {
85
+ return newest(store).valueMap.get(key);
86
+ };
87
+ var isValueCached = (key, store) => {
88
+ return newest(store).valueMap.has(key);
89
+ };
90
+ var evictCachedValue = (key, store) => {
91
+ const core = newest(store);
92
+ const currentValue = core.valueMap.get(key);
93
+ if (currentValue instanceof Future) {
94
+ currentValue.cancel();
95
+ }
96
+ if (core.operation.open) {
97
+ core.operation.prev.set(key, currentValue);
98
+ }
99
+ core.valueMap.delete(key);
100
+ store.logger.info(`\u{1F5D1}`, `state`, key, `evicted`);
101
+ };
102
+
103
+ // src/read-or-compute-value.ts
104
+ var readOrComputeValue = (state, store) => {
105
+ if (isValueCached(state.key, store)) {
106
+ store.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
107
+ return readCachedValue(state.key, store);
108
+ }
109
+ if (state.type !== `atom`) {
110
+ store.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
111
+ return state.get();
53
112
  }
113
+ const fallback = state.default instanceof Function ? state.default() : state.default;
54
114
  store.logger.info(
55
- `\u{1FA82}`,
56
- `transaction`,
57
- store.transactionStatus.key,
58
- `Aborting transaction`
115
+ `\u{1F481}`,
116
+ `atom`,
117
+ state.key,
118
+ `could not find cached value; using default`,
119
+ fallback
59
120
  );
60
- store.transactionStatus = { phase: `idle` };
121
+ return state.default instanceof Function ? state.default() : state.default;
61
122
  };
62
123
 
63
- // src/store/deposit.ts
64
- function deposit(state) {
65
- const token = {
66
- key: state.key,
67
- type: state.type
124
+ // src/operation.ts
125
+ var openOperation = (token, store) => {
126
+ const target = newest(store);
127
+ if (target.operation.open) {
128
+ store.logger.error(
129
+ `\u274C`,
130
+ token.type,
131
+ token.key,
132
+ `failed to setState during a setState for "${target.operation.token.key}"`
133
+ );
134
+ return `rejection`;
135
+ }
136
+ target.operation = {
137
+ open: true,
138
+ done: /* @__PURE__ */ new Set(),
139
+ prev: /* @__PURE__ */ new Map(),
140
+ time: Date.now(),
141
+ token
68
142
  };
69
- if (`family` in state) {
70
- token.family = state.family;
143
+ store.logger.info(
144
+ `\u2B55`,
145
+ token.type,
146
+ token.key,
147
+ `operation start in store "${store.config.name}"${target.transactionMeta === null ? `` : ` ${target.transactionMeta.phase} "${target.transactionMeta.update.key}"`}`
148
+ );
149
+ };
150
+ var closeOperation = (store) => {
151
+ const target = newest(store);
152
+ if (target.operation.open) {
153
+ store.logger.info(
154
+ `\u{1F534}`,
155
+ target.operation.token.type,
156
+ target.operation.token.key,
157
+ `operation done in store "${store.config.name}"`
158
+ );
71
159
  }
72
- return token;
73
- }
160
+ target.operation = { open: false };
161
+ store.subject.operationStatus.next(target.operation);
162
+ };
163
+ var isDone = (key, store) => {
164
+ const target = newest(store);
165
+ if (!target.operation.open) {
166
+ store.logger.warn(
167
+ `\u{1F41E}`,
168
+ `unknown`,
169
+ key,
170
+ `isDone called outside of an operation. This is probably a bug.`
171
+ );
172
+ return true;
173
+ }
174
+ return target.operation.done.has(key);
175
+ };
176
+ var markDone = (key, store) => {
177
+ const target = newest(store);
178
+ if (!target.operation.open) {
179
+ store.logger.warn(
180
+ `\u{1F41E}`,
181
+ `unknown`,
182
+ key,
183
+ `markDone called outside of an operation. This is probably a bug.`
184
+ );
185
+ return;
186
+ }
187
+ target.operation.done.add(key);
188
+ };
74
189
 
75
- // ../../rel8/junction/src/junction.ts
76
- var Junction = class {
77
- constructor(data, config) {
78
- this.relations = /* @__PURE__ */ new Map();
79
- this.contents = /* @__PURE__ */ new Map();
80
- this.makeContentKey = (a, b) => `${a}:${b}`;
81
- var _a, _b, _c, _d;
82
- this.a = data.between[0];
83
- this.b = data.between[1];
84
- this.cardinality = data.cardinality;
85
- if (!(config == null ? void 0 : config.externalStore)) {
86
- this.relations = new Map((_a = data.relations) == null ? void 0 : _a.map(([a, b]) => [a, new Set(b)]));
87
- this.contents = new Map(data.contents);
88
- }
89
- this.isContent = (_b = config == null ? void 0 : config.isContent) != null ? _b : null;
90
- if (config == null ? void 0 : config.makeContentKey) {
91
- this.makeContentKey = config.makeContentKey;
92
- }
93
- if (config == null ? void 0 : config.externalStore) {
94
- const externalStore = config.externalStore;
95
- this.has = (a, b) => externalStore.has(a, b);
96
- this.addRelation = (a, b) => {
97
- externalStore.addRelation(a, b);
98
- };
99
- this.deleteRelation = (a, b) => {
100
- externalStore.deleteRelation(a, b);
101
- };
102
- this.replaceRelationsSafely = (a, bs) => {
103
- externalStore.replaceRelationsSafely(a, bs);
104
- };
105
- this.replaceRelationsUnsafely = (a, bs) => {
106
- externalStore.replaceRelationsUnsafely(a, bs);
107
- };
108
- this.getRelatedKeys = (key) => externalStore.getRelatedKeys(key);
109
- if (externalStore.getContent) {
110
- this.getContentInternal = (contentKey) => {
111
- return externalStore.getContent(contentKey);
112
- };
113
- this.setContent = (contentKey, content) => {
114
- externalStore.setContent(contentKey, content);
115
- };
116
- this.deleteContent = (contentKey) => {
117
- externalStore.deleteContent(contentKey);
118
- };
119
- }
120
- for (const [x, ys] of (_c = data.relations) != null ? _c : []) {
121
- for (const y of ys)
122
- this.addRelation(x, y);
123
- }
124
- for (const [contentKey, content] of (_d = data.contents) != null ? _d : []) {
125
- this.setContent(contentKey, content);
126
- }
127
- }
190
+ // src/set-state/become.ts
191
+ var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
192
+ originalThing instanceof Function ? originalThing() : originalThing
193
+ ) : nextVersionOfThing;
194
+
195
+ // src/subject.ts
196
+ var Subject = class {
197
+ constructor() {
198
+ this.subscribers = /* @__PURE__ */ new Map();
128
199
  }
129
- getRelatedKeys(key) {
130
- return this.relations.get(key);
200
+ subscribe(key, subscriber) {
201
+ this.subscribers.set(key, subscriber);
202
+ const unsubscribe = () => this.unsubscribe(key);
203
+ return unsubscribe;
131
204
  }
132
- addRelation(a, b) {
133
- let aRelations = this.relations.get(a);
134
- let bRelations = this.relations.get(b);
135
- if (aRelations) {
136
- aRelations.add(b);
137
- } else {
138
- aRelations = /* @__PURE__ */ new Set([b]);
139
- this.relations.set(a, aRelations);
140
- }
141
- if (bRelations) {
142
- bRelations.add(a);
143
- } else {
144
- bRelations = /* @__PURE__ */ new Set([a]);
145
- this.relations.set(b, bRelations);
205
+ unsubscribe(key) {
206
+ this.subscribers.delete(key);
207
+ }
208
+ next(value) {
209
+ for (const subscriber of this.subscribers.values()) {
210
+ subscriber(value);
146
211
  }
147
212
  }
148
- deleteRelation(a, b) {
149
- const aRelations = this.relations.get(a);
150
- if (aRelations) {
151
- aRelations.delete(b);
152
- if (aRelations.size === 0) {
153
- this.relations.delete(a);
154
- }
155
- const bRelations = this.relations.get(b);
156
- if (bRelations) {
157
- bRelations.delete(a);
158
- if (bRelations.size === 0) {
159
- this.relations.delete(b);
213
+ };
214
+ var StatefulSubject = class extends Subject {
215
+ constructor(initialState) {
216
+ super();
217
+ this.state = initialState;
218
+ }
219
+ next(value) {
220
+ this.state = value;
221
+ super.next(value);
222
+ }
223
+ };
224
+
225
+ // src/set-state/copy-mutable-if-needed.ts
226
+ function copyMutableIfNeeded(atom, transform, origin, target) {
227
+ const originValue = origin.valueMap.get(atom.key);
228
+ const targetValue = target.valueMap.get(atom.key);
229
+ if (originValue === targetValue) {
230
+ origin.logger.info(`\u{1F4C3}`, `atom`, `${atom.key}`, `copying`);
231
+ const jsonValue = transform.toJson(originValue);
232
+ const copiedValue = transform.fromJson(jsonValue);
233
+ target.valueMap.set(atom.key, copiedValue);
234
+ new Tracker(atom, origin);
235
+ return copiedValue;
236
+ }
237
+ return targetValue;
238
+ }
239
+
240
+ // src/set-state/copy-mutable-in-transaction.ts
241
+ function copyMutableIfWithinTransaction(oldValue, atom, store) {
242
+ const target = newest(store);
243
+ const parent = target.parent;
244
+ if (parent !== null) {
245
+ if (`toJson` in atom && `fromJson` in atom) {
246
+ const copiedValue = copyMutableIfNeeded(atom, atom, parent, target);
247
+ return copiedValue;
248
+ }
249
+ if (`family` in atom) {
250
+ const family = parent.families.get(atom.family.key);
251
+ if (family && family.type === `atom_family`) {
252
+ const result = copyMutableFamilyMemberWithinTransaction(
253
+ atom,
254
+ family,
255
+ parent,
256
+ target
257
+ );
258
+ if (result) {
259
+ return result;
160
260
  }
161
261
  }
162
262
  }
163
263
  }
164
- replaceRelationsUnsafely(a, bs) {
165
- this.relations.set(a, new Set(bs));
264
+ return oldValue;
265
+ }
266
+ function copyMutableFamilyMemberWithinTransaction(atom, family, origin, target) {
267
+ if (`toJson` in family && `fromJson` in family) {
268
+ const copyCreated = copyMutableIfNeeded(atom, family, origin, target);
269
+ return copyCreated;
270
+ }
271
+ return null;
272
+ }
273
+
274
+ // src/set-state/emit-update.ts
275
+ var emitUpdate = (state, update, store) => {
276
+ store.logger.info(
277
+ `\u{1F4E2}`,
278
+ state.type,
279
+ state.key,
280
+ `went (`,
281
+ update.oldValue,
282
+ `->`,
283
+ update.newValue,
284
+ `) subscribers:`,
285
+ state.subject.subscribers
286
+ );
287
+ state.subject.next(update);
288
+ };
289
+
290
+ // src/set-state/evict-downstream.ts
291
+ var evictDownStream = (atom, store) => {
292
+ const target = newest(store);
293
+ const downstreamKeys = target.selectorAtoms.getRelatedKeys(atom.key);
294
+ store.logger.info(
295
+ `\u{1F9F9}`,
296
+ atom.type,
297
+ atom.key,
298
+ downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
299
+ downstreamKeys != null ? downstreamKeys : `to evict`
300
+ );
301
+ if (downstreamKeys) {
302
+ if (target.operation.open) {
303
+ store.logger.info(
304
+ `\u{1F9F9}`,
305
+ atom.type,
306
+ atom.key,
307
+ `[ ${[...target.operation.done].join(`, `)} ] already done`
308
+ );
309
+ }
310
+ for (const key of downstreamKeys) {
311
+ if (isDone(key, store)) {
312
+ continue;
313
+ }
314
+ evictCachedValue(key, store);
315
+ markDone(key, store);
316
+ }
317
+ }
318
+ };
319
+
320
+ // src/set-state/stow-update.ts
321
+ function shouldUpdateBeStowed(key, update) {
322
+ if (isTransceiver(update.newValue)) {
323
+ return false;
324
+ }
325
+ if (key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
326
+ return false;
327
+ }
328
+ return true;
329
+ }
330
+ var stowUpdate = (state, update, store) => {
331
+ const { key } = state;
332
+ const target = newest(store);
333
+ if (target.transactionMeta === null || target.transactionMeta.phase !== `building`) {
334
+ store.logger.error(
335
+ `\u{1F41E}`,
336
+ `atom`,
337
+ key,
338
+ `stowUpdate called outside of a transaction. This is probably a bug.`
339
+ );
340
+ return;
341
+ }
342
+ const shouldStow = shouldUpdateBeStowed(key, update);
343
+ if (!shouldStow) {
344
+ return;
345
+ }
346
+ const atomUpdate = __spreadValues({ key }, update);
347
+ if (state.family) {
348
+ atomUpdate.family = state.family;
349
+ }
350
+ target.transactionMeta.update.updates.push(atomUpdate);
351
+ store.logger.info(
352
+ `\u{1F4C1}`,
353
+ `atom`,
354
+ key,
355
+ `stowed (`,
356
+ update.oldValue,
357
+ `->`,
358
+ update.newValue,
359
+ `)`
360
+ );
361
+ };
362
+
363
+ // src/set-state/set-atom.ts
364
+ var setAtom = (atom, next, store) => {
365
+ const target = newest(store);
366
+ const oldValue = readOrComputeValue(atom, store);
367
+ let newValue = copyMutableIfWithinTransaction(oldValue, atom, store);
368
+ newValue = become(next)(newValue);
369
+ store.logger.info(`\u{1F4DD}`, `atom`, atom.key, `set to`, newValue);
370
+ newValue = cacheValue(atom.key, newValue, atom.subject, store);
371
+ if (isAtomDefault(atom.key, store)) {
372
+ markAtomAsNotDefault(atom.key, store);
373
+ }
374
+ markDone(atom.key, store);
375
+ evictDownStream(atom, store);
376
+ const update = { oldValue, newValue };
377
+ if (target.transactionMeta === null || target.transactionMeta.phase === `applying`) {
378
+ emitUpdate(atom, update, store);
379
+ } else {
380
+ stowUpdate(atom, update, store);
381
+ }
382
+ };
383
+
384
+ // src/set-state/set-atom-or-selector.ts
385
+ var setAtomOrSelector = (state, value, store) => {
386
+ if (state.type === `selector`) {
387
+ state.set(value);
388
+ } else {
389
+ setAtom(state, value, store);
390
+ }
391
+ };
392
+
393
+ // src/store/deposit.ts
394
+ function deposit(state) {
395
+ const token = {
396
+ key: state.key,
397
+ type: state.type
398
+ };
399
+ if (`family` in state) {
400
+ token.family = state.family;
401
+ }
402
+ return token;
403
+ }
404
+
405
+ // ../../rel8/junction/src/junction.ts
406
+ var Junction = class {
407
+ constructor(data, config) {
408
+ this.relations = /* @__PURE__ */ new Map();
409
+ this.contents = /* @__PURE__ */ new Map();
410
+ this.makeContentKey = (a, b) => `${a}:${b}`;
411
+ var _a, _b, _c, _d;
412
+ this.a = data.between[0];
413
+ this.b = data.between[1];
414
+ this.cardinality = data.cardinality;
415
+ if (!(config == null ? void 0 : config.externalStore)) {
416
+ this.relations = new Map((_a = data.relations) == null ? void 0 : _a.map(([a, b]) => [a, new Set(b)]));
417
+ this.contents = new Map(data.contents);
418
+ }
419
+ this.isContent = (_b = config == null ? void 0 : config.isContent) != null ? _b : null;
420
+ if (config == null ? void 0 : config.makeContentKey) {
421
+ this.makeContentKey = config.makeContentKey;
422
+ }
423
+ if (config == null ? void 0 : config.externalStore) {
424
+ const externalStore = config.externalStore;
425
+ this.has = (a, b) => externalStore.has(a, b);
426
+ this.addRelation = (a, b) => {
427
+ externalStore.addRelation(a, b);
428
+ };
429
+ this.deleteRelation = (a, b) => {
430
+ externalStore.deleteRelation(a, b);
431
+ };
432
+ this.replaceRelationsSafely = (a, bs) => {
433
+ externalStore.replaceRelationsSafely(a, bs);
434
+ };
435
+ this.replaceRelationsUnsafely = (a, bs) => {
436
+ externalStore.replaceRelationsUnsafely(a, bs);
437
+ };
438
+ this.getRelatedKeys = (key) => externalStore.getRelatedKeys(key);
439
+ if (externalStore.getContent) {
440
+ this.getContentInternal = (contentKey) => {
441
+ return externalStore.getContent(contentKey);
442
+ };
443
+ this.setContent = (contentKey, content) => {
444
+ externalStore.setContent(contentKey, content);
445
+ };
446
+ this.deleteContent = (contentKey) => {
447
+ externalStore.deleteContent(contentKey);
448
+ };
449
+ }
450
+ for (const [x, ys] of (_c = data.relations) != null ? _c : []) {
451
+ for (const y of ys)
452
+ this.addRelation(x, y);
453
+ }
454
+ for (const [contentKey, content] of (_d = data.contents) != null ? _d : []) {
455
+ this.setContent(contentKey, content);
456
+ }
457
+ }
458
+ }
459
+ getRelatedKeys(key) {
460
+ return this.relations.get(key);
461
+ }
462
+ addRelation(a, b) {
463
+ let aRelations = this.relations.get(a);
464
+ let bRelations = this.relations.get(b);
465
+ if (aRelations) {
466
+ aRelations.add(b);
467
+ } else {
468
+ aRelations = /* @__PURE__ */ new Set([b]);
469
+ this.relations.set(a, aRelations);
470
+ }
471
+ if (bRelations) {
472
+ bRelations.add(a);
473
+ } else {
474
+ bRelations = /* @__PURE__ */ new Set([a]);
475
+ this.relations.set(b, bRelations);
476
+ }
477
+ }
478
+ deleteRelation(a, b) {
479
+ const aRelations = this.relations.get(a);
480
+ if (aRelations) {
481
+ aRelations.delete(b);
482
+ if (aRelations.size === 0) {
483
+ this.relations.delete(a);
484
+ }
485
+ const bRelations = this.relations.get(b);
486
+ if (bRelations) {
487
+ bRelations.delete(a);
488
+ if (bRelations.size === 0) {
489
+ this.relations.delete(b);
490
+ }
491
+ }
492
+ }
493
+ }
494
+ replaceRelationsUnsafely(a, bs) {
495
+ this.relations.set(a, new Set(bs));
166
496
  for (const b of bs) {
167
497
  const bRelations = /* @__PURE__ */ new Set([a]);
168
498
  this.relations.set(b, bRelations);
@@ -330,29 +660,11 @@ var Junction = class {
330
660
  }
331
661
  };
332
662
 
333
- // src/subject.ts
334
- var Subject = class {
335
- constructor() {
336
- this.subscribers = /* @__PURE__ */ new Map();
337
- }
338
- subscribe(key, subscriber) {
339
- this.subscribers.set(key, subscriber);
340
- const unsubscribe = () => this.unsubscribe(key);
341
- return unsubscribe;
342
- }
343
- unsubscribe(key) {
344
- this.subscribers.delete(key);
345
- }
346
- next(value) {
347
- for (const subscriber of this.subscribers.values()) {
348
- subscriber(value);
349
- }
350
- }
351
- };
352
-
353
663
  // src/store/store.ts
354
664
  var Store = class {
355
665
  constructor(name, store = null) {
666
+ this.parent = null;
667
+ this.child = null;
356
668
  this.valueMap = /* @__PURE__ */ new Map();
357
669
  this.atoms = /* @__PURE__ */ new Map();
358
670
  this.selectors = /* @__PURE__ */ new Map();
@@ -384,10 +696,11 @@ var Store = class {
384
696
  selectorCreation: new Subject(),
385
697
  transactionCreation: new Subject(),
386
698
  timelineCreation: new Subject(),
699
+ transactionApplying: new StatefulSubject(null),
387
700
  operationStatus: new Subject()
388
701
  };
389
702
  this.operation = { open: false };
390
- this.transactionStatus = { phase: `idle` };
703
+ this.transactionMeta = null;
391
704
  this.config = {
392
705
  name: `IMPLICIT_STORE`
393
706
  };
@@ -411,7 +724,7 @@ var Store = class {
411
724
  if (store !== null) {
412
725
  this.valueMap = new Map(store == null ? void 0 : store.valueMap);
413
726
  this.operation = __spreadValues({}, store == null ? void 0 : store.operation);
414
- this.transactionStatus = __spreadValues({}, store == null ? void 0 : store.transactionStatus);
727
+ this.transactionMeta = (store == null ? void 0 : store.transactionMeta) ? __spreadValues({}, store == null ? void 0 : store.transactionMeta) : null;
415
728
  this.config = __spreadProps(__spreadValues({}, store == null ? void 0 : store.config), {
416
729
  name
417
730
  });
@@ -446,651 +759,427 @@ var clearStore = (store) => {
446
759
  store.config = config;
447
760
  };
448
761
 
449
- // src/timeline/add-atom-to-timeline.ts
450
- var addAtomToTimeline = (atomToken, tl, store) => {
451
- const atom = withdraw(atomToken, store);
452
- if (atom === void 0) {
453
- throw new Error(
454
- `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
455
- );
762
+ // src/store/withdraw.ts
763
+ function withdraw(token, store) {
764
+ var _a, _b, _c, _d;
765
+ const target = newest(store);
766
+ const state = (_d = (_c = (_b = (_a = target.atoms.get(token.key)) != null ? _a : target.selectors.get(token.key)) != null ? _b : target.readonlySelectors.get(token.key)) != null ? _c : target.transactions.get(token.key)) != null ? _d : target.timelines.get(token.key);
767
+ if (state) {
768
+ return state;
456
769
  }
457
- atom.subject.subscribe(`timeline`, (update) => {
458
- var _a, _b, _c, _d;
459
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
460
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
461
- const currentTransactionKey = store.transactionStatus.phase === `applying` ? store.transactionStatus.key : null;
462
- const currentTransactionTime = store.transactionStatus.phase === `applying` ? store.transactionStatus.time : null;
770
+ return void 0;
771
+ }
772
+
773
+ // src/store/withdraw-new-family-member.ts
774
+ function withdrawNewFamilyMember(token, store) {
775
+ if (token.family) {
463
776
  store.logger.info(
464
- `\u23F3`,
465
- `timeline`,
466
- tl.key,
467
- `atom`,
468
- atomToken.key,
469
- `went`,
470
- update.oldValue,
471
- `->`,
472
- update.newValue,
473
- currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
777
+ `\u{1F46A}`,
778
+ token.type,
779
+ token.key,
780
+ `creating new family member in store "${store.config.name}"`
474
781
  );
475
- if (tl.timeTraveling === null) {
476
- if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
477
- const mostRecentUpdate = tl.history.at(-1);
478
- if (mostRecentUpdate === void 0) {
479
- throw new Error(
480
- `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
481
- );
482
- }
483
- }
484
- if (currentTransactionKey && store.transactionStatus.phase === `applying`) {
485
- const currentTransaction = withdraw(
486
- { key: currentTransactionKey, type: `transaction` },
487
- store
488
- );
489
- if (currentTransaction === void 0) {
490
- throw new Error(
491
- `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
492
- );
493
- }
494
- if (tl.transactionKey !== currentTransactionKey) {
495
- if (tl.transactionKey) {
496
- store.logger.error(
497
- `\u{1F41E}`,
498
- `timeline`,
499
- tl.key,
500
- `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
501
- );
502
- }
503
- tl.transactionKey = currentTransactionKey;
504
- const unsubscribe = currentTransaction.subject.subscribe(
505
- `timeline:${tl.key}`,
506
- (update2) => {
507
- var _a2, _b2;
508
- unsubscribe();
509
- if (tl.timeTraveling === null && currentTransactionTime) {
510
- if (tl.at !== tl.history.length) {
511
- tl.history.splice(tl.at);
512
- }
513
- const atomUpdates = update2.atomUpdates.filter((atomUpdate) => {
514
- const core = target(store);
515
- const atomOrFamilyKeys = core.timelineAtoms.getRelatedKeys(
516
- tl.key
517
- );
518
- return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
519
- (key) => {
520
- var _a3;
521
- return key === atomUpdate.key || key === ((_a3 = atomUpdate.family) == null ? void 0 : _a3.key);
522
- }
523
- ) : false;
524
- });
525
- const timelineTransactionUpdate = __spreadProps(__spreadValues({
526
- type: `transaction_update`,
527
- timestamp: currentTransactionTime
528
- }, update2), {
529
- atomUpdates
530
- });
531
- const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
532
- if (willCapture) {
533
- tl.history.push(timelineTransactionUpdate);
534
- tl.at = tl.history.length;
535
- tl.subject.next(timelineTransactionUpdate);
536
- }
537
- }
538
- tl.transactionKey = null;
539
- store.logger.info(
540
- `\u231B`,
541
- `timeline`,
542
- tl.key,
543
- `got a transaction_update "${update2.key}"`
544
- );
545
- }
546
- );
547
- }
548
- } else if (currentSelectorKey && currentSelectorTime) {
549
- let latestUpdate = tl.history.at(-1);
550
- if (currentSelectorTime !== tl.selectorTime) {
551
- latestUpdate = {
552
- type: `selector_update`,
553
- timestamp: currentSelectorTime,
554
- key: currentSelectorKey,
555
- atomUpdates: []
556
- };
557
- latestUpdate.atomUpdates.push(__spreadValues({
558
- key: atom.key,
559
- type: `atom_update`
560
- }, update));
561
- if (tl.at !== tl.history.length) {
562
- tl.history.splice(tl.at);
563
- }
564
- tl.history.push(latestUpdate);
565
- store.logger.info(
566
- `\u231B`,
567
- `timeline`,
568
- tl.key,
569
- `got a selector_update "${currentSelectorKey}" with`,
570
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
571
- );
572
- tl.at = tl.history.length;
573
- tl.selectorTime = currentSelectorTime;
574
- } else {
575
- if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
576
- latestUpdate.atomUpdates.push(__spreadValues({
577
- key: atom.key,
578
- type: `atom_update`
579
- }, update));
580
- store.logger.info(
581
- `\u231B`,
582
- `timeline`,
583
- tl.key,
584
- `set selector_update "${currentSelectorKey}" to`,
585
- latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
586
- );
587
- }
588
- }
589
- if (latestUpdate) {
590
- const willCaptureSelectorUpdate = (_b = (_a = tl.shouldCapture) == null ? void 0 : _a.call(tl, latestUpdate, tl)) != null ? _b : true;
591
- if (willCaptureSelectorUpdate) {
592
- tl.subject.next(latestUpdate);
593
- } else {
594
- tl.history.pop();
595
- tl.at = tl.history.length;
596
- }
597
- }
598
- } else {
599
- const timestamp = Date.now();
600
- tl.selectorTime = null;
601
- if (tl.at !== tl.history.length) {
602
- tl.history.splice(tl.at);
603
- }
604
- const atomUpdate = {
605
- type: `atom_update`,
606
- timestamp,
607
- key: atom.key,
608
- oldValue: update.oldValue,
609
- newValue: update.newValue
610
- };
611
- if (atom.family) {
612
- atomUpdate.family = atom.family;
613
- }
614
- const willCapture = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, atomUpdate, tl)) != null ? _d : true;
615
- store.logger.info(
616
- `\u231B`,
617
- `timeline`,
618
- tl.key,
619
- `got an atom_update to "${atom.key}"`
620
- );
621
- if (willCapture) {
622
- tl.history.push(atomUpdate);
623
- tl.at = tl.history.length;
624
- tl.subject.next(atomUpdate);
625
- }
626
- }
782
+ const target = newest(store);
783
+ const family = target.families.get(token.family.key);
784
+ if (family) {
785
+ const jsonSubKey = JSON.parse(token.family.subKey);
786
+ family(jsonSubKey);
787
+ const state = withdraw(token, store);
788
+ return state;
627
789
  }
628
- });
790
+ }
791
+ return void 0;
792
+ }
793
+
794
+ // src/keys.ts
795
+ var isAtomKey = (key, store) => newest(store).atoms.has(key);
796
+ var isSelectorKey = (key, store) => newest(store).selectors.has(key);
797
+ var isReadonlySelectorKey = (key, store) => newest(store).readonlySelectors.has(key);
798
+ var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
799
+
800
+ // src/selector/get-selector-dependency-keys.ts
801
+ var getSelectorDependencyKeys = (key, store) => {
802
+ const sources = newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
803
+ return sources;
629
804
  };
630
805
 
631
- // src/timeline/create-timeline.ts
632
- function createTimeline(options, store, data) {
633
- var _a, _b;
634
- const tl = __spreadProps(__spreadValues({
635
- type: `timeline`,
636
- key: options.key,
637
- at: 0,
638
- timeTraveling: null,
639
- selectorTime: null,
640
- transactionKey: null
641
- }, data), {
642
- history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
643
- install: (store2) => createTimeline(options, store2, tl),
644
- subject: new Subject()
645
- });
646
- if (options.shouldCapture) {
647
- tl.shouldCapture = options.shouldCapture;
648
- }
649
- const core = target(store);
650
- for (const tokenOrFamily of options.atoms) {
651
- const timelineKey = core.timelineAtoms.getRelatedKey(tokenOrFamily.key);
652
- if (timelineKey) {
653
- store.logger.error(
654
- `\u274C`,
655
- `timeline`,
656
- options.key,
657
- `Failed to add atom "${tokenOrFamily.key}" because it already belongs to timeline "${timelineKey}"`
806
+ // src/selector/trace-selector-atoms.ts
807
+ var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
808
+ const rootKeys = [];
809
+ const indirectDependencyKeys = getSelectorDependencyKeys(
810
+ directDependencyKey,
811
+ store
812
+ );
813
+ let depth = 0;
814
+ while (indirectDependencyKeys.length > 0) {
815
+ const indirectDependencyKey = indirectDependencyKeys.shift();
816
+ ++depth;
817
+ if (depth > 99999) {
818
+ throw new Error(
819
+ `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
658
820
  );
659
- continue;
660
821
  }
661
- if (tokenOrFamily.type === `atom_family`) {
662
- const family = tokenOrFamily;
663
- family.subject.subscribe(`timeline:${options.key}`, (token2) => {
664
- addAtomToTimeline(token2, tl, store);
665
- });
666
- for (const atom of core.atoms.values()) {
667
- if (((_b = atom.family) == null ? void 0 : _b.key) === family.key) {
668
- addAtomToTimeline(atom, tl, store);
669
- }
670
- }
671
- } else {
672
- const token2 = tokenOrFamily;
673
- if (`family` in token2 && token2.family) {
674
- const familyTimelineKey = core.timelineAtoms.getRelatedKey(
675
- token2.family.key
676
- );
677
- if (familyTimelineKey) {
678
- store.logger.error(
679
- `\u274C`,
680
- `timeline`,
681
- options.key,
682
- `Failed to add atom "${token2.key}" because its family "${token2.family.key}" already belongs to timeline "${familyTimelineKey}"`
683
- );
684
- continue;
685
- }
686
- }
687
- addAtomToTimeline(token2, tl, store);
822
+ if (!isAtomKey(indirectDependencyKey, store)) {
823
+ indirectDependencyKeys.push(
824
+ ...getSelectorDependencyKeys(indirectDependencyKey, store)
825
+ );
826
+ } else if (!rootKeys.includes(indirectDependencyKey)) {
827
+ rootKeys.push(indirectDependencyKey);
688
828
  }
689
- core.timelineAtoms = core.timelineAtoms.set({
690
- atomKey: tokenOrFamily.key,
691
- timelineKey: options.key
692
- });
693
829
  }
694
- store.timelines.set(options.key, tl);
695
- const token = {
696
- key: options.key,
697
- type: `timeline`
698
- };
699
- store.subject.timelineCreation.next(token);
700
- return token;
701
- }
702
- var timeTravel = (direction, token, store) => {
703
- const action = direction === `forward` ? `redo` : `undo`;
704
- store.logger.info(
705
- direction === `forward` ? `\u23E9` : `\u23EA`,
706
- `timeline`,
707
- token.key,
708
- action
830
+ return rootKeys;
831
+ };
832
+ var traceAllSelectorAtoms = (selectorKey, store) => {
833
+ const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
834
+ return directDependencyKeys.flatMap(
835
+ (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
709
836
  );
710
- const timelineData = store.timelines.get(token.key);
711
- if (!timelineData) {
712
- store.logger.error(
713
- `\u{1F41E}`,
714
- `timeline`,
715
- token.key,
716
- `Failed to ${action}. This timeline has not been initialized.`
837
+ };
838
+
839
+ // src/selector/update-selector-atoms.ts
840
+ var updateSelectorAtoms = (selectorKey, dependency, store) => {
841
+ const target = newest(store);
842
+ if (dependency.type === `atom`) {
843
+ target.selectorAtoms.set({
844
+ selectorKey,
845
+ atomKey: dependency.key
846
+ });
847
+ store.logger.info(
848
+ `\u{1F50D}`,
849
+ `selector`,
850
+ selectorKey,
851
+ `discovers root atom "${dependency.key}"`
717
852
  );
718
- return;
719
- }
720
- if (direction === `forward` && timelineData.at === timelineData.history.length || direction === `backward` && timelineData.at === 0) {
721
- store.logger.warn(
722
- `\u{1F481}`,
723
- `timeline`,
724
- token.key,
725
- `Failed to ${action} at the ${direction === `forward` ? `end` : `beginning`} of timeline "${token.key}". There is nothing to ${action}.`
853
+ } else {
854
+ const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
855
+ store.logger.info(
856
+ `\u{1F50D}`,
857
+ `selector`,
858
+ selectorKey,
859
+ `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
726
860
  );
727
- return;
728
- }
729
- timelineData.timeTraveling = direction === `forward` ? `into_future` : `into_past`;
730
- if (direction === `backward`) {
731
- --timelineData.at;
732
- }
733
- const update = timelineData.history[timelineData.at];
734
- const updateValues = (atomUpdate) => {
735
- const { key, newValue, oldValue } = atomUpdate;
736
- const value = direction === `forward` ? newValue : oldValue;
737
- setState({ key, type: `atom` }, value, store);
738
- };
739
- switch (update.type) {
740
- case `atom_update`: {
741
- updateValues(update);
742
- break;
743
- }
744
- case `selector_update`:
745
- case `transaction_update`: {
746
- const updates = direction === `forward` ? update.atomUpdates : [...update.atomUpdates].reverse();
747
- for (const atomUpdate of updates) {
748
- updateValues(atomUpdate);
749
- }
750
- break;
861
+ for (const atomKey of rootKeys) {
862
+ target.selectorAtoms = target.selectorAtoms.set({
863
+ selectorKey,
864
+ atomKey
865
+ });
751
866
  }
752
867
  }
753
- if (direction === `forward`) {
754
- ++timelineData.at;
755
- }
756
- timelineData.subject.next(action);
757
- timelineData.timeTraveling = null;
758
- store.logger.info(
759
- `\u23F9\uFE0F`,
760
- `timeline`,
761
- token.key,
762
- `"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`
763
- );
764
868
  };
765
869
 
766
- // src/store/withdraw.ts
767
- function withdraw(token, store) {
768
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
769
- let core = target(store);
770
- let state = (_d = (_c = (_b = (_a = core.atoms.get(token.key)) != null ? _a : core.selectors.get(token.key)) != null ? _b : core.readonlySelectors.get(token.key)) != null ? _c : core.transactions.get(token.key)) != null ? _d : core.timelines.get(token.key);
771
- if (state) {
772
- return state;
773
- }
774
- if (store.transactionStatus.phase === `applying`) {
775
- core = store.transactionStatus.core;
776
- state = (_h = (_g = (_f = (_e = core.atoms.get(token.key)) != null ? _e : core.selectors.get(token.key)) != null ? _f : core.readonlySelectors.get(token.key)) != null ? _g : core.transactions.get(token.key)) != null ? _h : core.timelines.get(token.key);
777
- if (state) {
778
- store.logger.info(
779
- `\u{1F6E0}\uFE0F`,
780
- token.type,
781
- token.key,
782
- `add ${token.type} "${token.key}"`
870
+ // src/selector/register-selector.ts
871
+ var registerSelector = (selectorKey, store) => ({
872
+ get: (dependency) => {
873
+ const target = newest(store);
874
+ const alreadyRegistered = target.selectorGraph.getRelationEntries({ downstreamSelectorKey: selectorKey }).some(([_, { source }]) => source === dependency.key);
875
+ const dependencyState = withdraw(dependency, store);
876
+ if (dependencyState === void 0) {
877
+ throw new Error(
878
+ `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
783
879
  );
784
- switch (state.type) {
785
- case `atom`: {
786
- store.atoms.set(token.key, state);
787
- store.valueMap.set(token.key, state.default);
788
- const stateKey = state.key;
789
- const familyKey = (_i = state.family) == null ? void 0 : _i.key;
790
- let timelineKey = core.timelineAtoms.getRelatedKey(stateKey);
791
- if (timelineKey === void 0 && typeof familyKey === `string`) {
792
- timelineKey = core.timelineAtoms.getRelatedKey(familyKey);
793
- }
794
- const timeline = typeof timelineKey === `string` ? store.timelines.get(timelineKey) : void 0;
795
- if (timeline) {
796
- addAtomToTimeline(state, timeline, store);
797
- }
798
- break;
880
+ }
881
+ const dependencyValue = readOrComputeValue(dependencyState, store);
882
+ store.logger.info(
883
+ `\u{1F50C}`,
884
+ `selector`,
885
+ selectorKey,
886
+ `registers dependency ( "${dependency.key}" =`,
887
+ dependencyValue,
888
+ `)`
889
+ );
890
+ if (!alreadyRegistered) {
891
+ target.selectorGraph.set(
892
+ {
893
+ upstreamSelectorKey: dependency.key,
894
+ downstreamSelectorKey: selectorKey
895
+ },
896
+ {
897
+ source: dependency.key
799
898
  }
800
- case `selector`:
801
- core.selectors.set(token.key, state);
802
- break;
803
- case `readonly_selector`:
804
- core.readonlySelectors.set(token.key, state);
805
- break;
806
- case `transaction`:
807
- core.transactions.set(token.key, state);
808
- break;
809
- case `timeline`:
810
- core.timelines.set(token.key, state);
811
- break;
812
- }
813
- return state;
899
+ );
900
+ }
901
+ updateSelectorAtoms(selectorKey, dependency, store);
902
+ return dependencyValue;
903
+ },
904
+ set: (stateToken, newValue) => {
905
+ const state = withdraw(stateToken, store);
906
+ if (state === void 0) {
907
+ throw new Error(
908
+ `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
909
+ );
814
910
  }
911
+ setAtomOrSelector(state, newValue, store);
815
912
  }
816
- return void 0;
817
- }
913
+ });
818
914
 
819
- // src/store/withdraw-new-family-member.ts
820
- function withdrawNewFamilyMember(token, store) {
821
- if (token.family) {
915
+ // src/selector/create-read-write-selector.ts
916
+ var createReadWriteSelector = (options, family, store) => {
917
+ const target = newest(store);
918
+ const subject = new Subject();
919
+ const { get, set } = registerSelector(options.key, store);
920
+ const getSelf = () => {
921
+ const value = options.get({ get });
922
+ cacheValue(options.key, value, subject, store);
923
+ return value;
924
+ };
925
+ const setSelf = (next) => {
926
+ const oldValue = getSelf();
927
+ const newValue = become(next)(oldValue);
822
928
  store.logger.info(
823
- `\u{1F46A}`,
824
- token.type,
825
- token.key,
826
- `creating new family member in store "${store.config.name}"`
929
+ `\u{1F4DD}`,
930
+ `selector`,
931
+ options.key,
932
+ `set (`,
933
+ oldValue,
934
+ `->`,
935
+ newValue,
936
+ `)`
827
937
  );
828
- const core = target(store);
829
- const family = core.families.get(token.family.key);
830
- if (family) {
831
- const jsonSubKey = JSON.parse(token.family.subKey);
832
- family(jsonSubKey);
833
- const state = withdraw(token, store);
834
- return state;
938
+ cacheValue(options.key, newValue, subject, store);
939
+ markDone(options.key, store);
940
+ if (target.transactionMeta === null) {
941
+ subject.next({ newValue, oldValue });
835
942
  }
943
+ options.set({ get, set }, newValue);
944
+ };
945
+ const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
946
+ subject,
947
+ install: (s) => createSelector(options, family, s),
948
+ get: getSelf,
949
+ set: setSelf,
950
+ type: `selector`
951
+ }), family && { family });
952
+ target.selectors.set(options.key, mySelector);
953
+ const initialValue = getSelf();
954
+ store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
955
+ const token = {
956
+ key: options.key,
957
+ type: `selector`
958
+ };
959
+ if (family) {
960
+ token.family = family;
836
961
  }
837
- return void 0;
838
- }
962
+ store.subject.selectorCreation.next(token);
963
+ return token;
964
+ };
839
965
 
840
- // src/transaction/apply-transaction.ts
841
- var applyTransaction = (output, store) => {
842
- if (store.transactionStatus.phase !== `building`) {
843
- store.logger.warn(
844
- `\u{1F41E}`,
845
- `transaction`,
846
- `???`,
847
- `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
848
- );
849
- return;
850
- }
851
- store.transactionStatus.phase = `applying`;
852
- store.transactionStatus.output = output;
853
- const { atomUpdates } = store.transactionStatus;
966
+ // src/selector/create-readonly-selector.ts
967
+ var createReadonlySelector = (options, family, store) => {
968
+ const target = newest(store);
969
+ const subject = new Subject();
970
+ const { get } = registerSelector(options.key, store);
971
+ const getSelf = () => {
972
+ const value = options.get({ get });
973
+ cacheValue(options.key, value, subject, store);
974
+ return value;
975
+ };
976
+ const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
977
+ subject,
978
+ install: (s) => createSelector(options, family, s),
979
+ get: getSelf,
980
+ type: `readonly_selector`
981
+ }), family && { family });
982
+ target.readonlySelectors.set(options.key, readonlySelector);
983
+ const initialValue = getSelf();
854
984
  store.logger.info(
855
- `\u{1F6C4}`,
856
- `transaction`,
857
- store.transactionStatus.key,
858
- `Applying transaction with ${atomUpdates.length} updates:`,
859
- atomUpdates
985
+ `\u2728`,
986
+ readonlySelector.type,
987
+ readonlySelector.key,
988
+ `=`,
989
+ initialValue
860
990
  );
861
- for (const { key, newValue } of atomUpdates) {
862
- const token = { key, type: `atom` };
863
- if (!store.valueMap.has(token.key)) {
864
- if (token.family) {
865
- const family = store.families.get(token.family.key);
866
- if (family) {
867
- family(token.family.subKey);
868
- }
869
- } else {
870
- const newAtom = store.transactionStatus.core.atoms.get(token.key);
871
- if (!newAtom) {
872
- throw new Error(
873
- `Absurd Error: Atom "${token.key}" not found while copying updates from transaction "${store.transactionStatus.key}" to store "${store.config.name}"`
874
- );
875
- }
876
- store.atoms.set(newAtom.key, newAtom);
877
- store.valueMap.set(newAtom.key, newAtom.default);
878
- store.logger.info(
879
- `\u{1F528}`,
880
- `transaction`,
881
- store.transactionStatus.key,
882
- `Adding atom "${newAtom.key}"`
883
- );
884
- }
885
- }
886
- setState(token, newValue, store);
991
+ const token = {
992
+ key: options.key,
993
+ type: `readonly_selector`
994
+ };
995
+ if (family) {
996
+ token.family = family;
887
997
  }
888
- const myTransaction = withdraw(
889
- { key: store.transactionStatus.key, type: `transaction` },
890
- store
891
- );
892
- if (myTransaction === void 0) {
893
- throw new Error(
894
- `Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
998
+ store.subject.selectorCreation.next(token);
999
+ return token;
1000
+ };
1001
+
1002
+ // src/selector/create-selector.ts
1003
+ function createSelector(options, family, store) {
1004
+ const target = newest(store);
1005
+ const existingWritable = target.selectors.get(options.key);
1006
+ const existingReadonly = target.readonlySelectors.get(options.key);
1007
+ if (existingWritable || existingReadonly) {
1008
+ store.logger.error(
1009
+ `\u274C`,
1010
+ existingReadonly ? `readonly_selector` : `selector`,
1011
+ options.key,
1012
+ `Tried to create selector, but it already exists in the store. (Ignore if you are in development using hot module replacement.)`
895
1013
  );
896
1014
  }
897
- myTransaction.subject.next({
898
- key: store.transactionStatus.key,
899
- atomUpdates,
900
- output,
901
- params: store.transactionStatus.params
902
- });
903
- store.logger.info(
904
- `\u{1F6EC}`,
905
- `transaction`,
906
- store.transactionStatus.key,
907
- `Finished applying transaction.`
908
- );
909
- store.transactionStatus = { phase: `idle` };
910
- };
1015
+ if (`set` in options) {
1016
+ return createReadWriteSelector(options, family, store);
1017
+ }
1018
+ return createReadonlySelector(options, family, store);
1019
+ }
911
1020
 
912
- // src/lazy-map.ts
913
- var LazyMap = class extends Map {
914
- constructor(source) {
915
- super();
916
- this.source = source;
917
- this.deleted = /* @__PURE__ */ new Set();
1021
+ // src/selector/delete-selector.ts
1022
+ function deleteSelector(selectorToken, store) {
1023
+ const target = newest(store);
1024
+ const { key } = selectorToken;
1025
+ switch (selectorToken.type) {
1026
+ case `selector`:
1027
+ target.selectors.delete(key);
1028
+ break;
1029
+ case `readonly_selector`:
1030
+ target.readonlySelectors.delete(key);
1031
+ break;
918
1032
  }
919
- get(key) {
920
- const has = super.has(key);
921
- if (has) {
922
- return super.get(key);
1033
+ target.valueMap.delete(key);
1034
+ target.selectorAtoms.delete(key);
1035
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1036
+ ([downstreamSelectorKey]) => {
1037
+ var _a;
1038
+ return (_a = target.selectors.get(downstreamSelectorKey)) != null ? _a : target.readonlySelectors.get(downstreamSelectorKey);
923
1039
  }
924
- if (!this.deleted.has(key) && this.source.has(key)) {
925
- const value = this.source.get(key);
926
- super.set(key, value);
927
- return value;
1040
+ );
1041
+ for (const downstreamToken of downstreamTokens) {
1042
+ if (downstreamToken) {
1043
+ deleteSelector(downstreamToken, store);
928
1044
  }
929
- return void 0;
930
- }
931
- _has(key) {
932
- return super.has(key);
933
- }
934
- has(key) {
935
- return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
936
1045
  }
937
- delete(key) {
938
- this.deleted.add(key);
939
- return super.delete(key);
1046
+ target.selectorGraph.delete(key);
1047
+ store.logger.info(`\u{1F525}`, selectorToken.type, `${key}`, `deleted`);
1048
+ }
1049
+
1050
+ // src/subscribe/recall-state.ts
1051
+ var recallState = (state, store) => {
1052
+ const target = newest(store);
1053
+ if (!target.operation.open) {
1054
+ return target.valueMap.get(state.key);
940
1055
  }
1056
+ return target.operation.prev.get(state.key);
941
1057
  };
942
1058
 
943
- // src/transaction/build-transaction.ts
944
- var buildTransaction = (key, params, store) => {
945
- store.transactionStatus = {
946
- key,
947
- phase: `building`,
948
- time: Date.now(),
949
- core: {
950
- atoms: new LazyMap(store.atoms),
951
- atomsThatAreDefault: new Set(store.atomsThatAreDefault),
952
- families: new LazyMap(store.families),
953
- operation: { open: false },
954
- readonlySelectors: new LazyMap(store.readonlySelectors),
955
- timelines: new LazyMap(store.timelines),
956
- timelineAtoms: new Junction(store.timelineAtoms.toJSON()),
957
- trackers: /* @__PURE__ */ new Map(),
958
- transactions: new LazyMap(store.transactions),
959
- selectorAtoms: new Junction(store.selectorAtoms.toJSON()),
960
- selectorGraph: new Junction(store.selectorGraph.toJSON(), {
961
- makeContentKey: (...keys) => keys.sort().join(`:`)
962
- }),
963
- selectors: new LazyMap(store.selectors),
964
- valueMap: new LazyMap(store.valueMap)
965
- },
966
- atomUpdates: [],
967
- params,
968
- output: void 0
969
- };
970
- store.logger.info(
971
- `\u{1F6EB}`,
972
- `transaction`,
973
- key,
974
- `Building transaction with params:`,
975
- params
976
- );
977
- };
978
- function createTransaction(options, store) {
979
- const newTransaction = {
980
- key: options.key,
981
- type: `transaction`,
982
- run: (...params) => {
983
- buildTransaction(options.key, params, store);
984
- try {
985
- const output = options.do(
986
- {
987
- get: (token2) => getState(token2, store),
988
- set: (token2, value) => setState(token2, value, store)
989
- },
990
- ...params
1059
+ // src/subscribe/subscribe-to-root-atoms.ts
1060
+ var subscribeToRootAtoms = (state, store) => {
1061
+ const dependencySubscriptions = `default` in state ? null : traceAllSelectorAtoms(state.key, store).map((atomKey) => {
1062
+ const atom = store.atoms.get(atomKey);
1063
+ if (atom === void 0) {
1064
+ throw new Error(
1065
+ `Atom "${atomKey}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`
1066
+ );
1067
+ }
1068
+ return atom.subject.subscribe(
1069
+ `${state.type}:${state.key}`,
1070
+ (atomChange) => {
1071
+ store.logger.info(
1072
+ `\u{1F4E2}`,
1073
+ state.type,
1074
+ state.key,
1075
+ `root`,
1076
+ atomKey,
1077
+ `went`,
1078
+ atomChange.oldValue,
1079
+ `->`,
1080
+ atomChange.newValue
991
1081
  );
992
- applyTransaction(output, store);
993
- return output;
994
- } catch (thrown) {
995
- abortTransaction(store);
996
- store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
997
- throw thrown;
1082
+ const oldValue = recallState(state, store);
1083
+ const newValue = readOrComputeValue(state, store);
1084
+ store.logger.info(
1085
+ `\u2728`,
1086
+ state.type,
1087
+ state.key,
1088
+ `went`,
1089
+ oldValue,
1090
+ `->`,
1091
+ newValue
1092
+ );
1093
+ state.subject.next({ newValue, oldValue });
998
1094
  }
999
- },
1000
- install: (store2) => createTransaction(options, store2),
1001
- subject: new Subject()
1095
+ );
1096
+ });
1097
+ return dependencySubscriptions;
1098
+ };
1099
+ function subscribeToState(token, handleUpdate, key, store) {
1100
+ const state = withdraw$1(token, store);
1101
+ if (state === void 0) {
1102
+ throw new Error(
1103
+ `State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1104
+ );
1105
+ }
1106
+ const unsubFunction = state.subject.subscribe(key, handleUpdate);
1107
+ store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
1108
+ const dependencyUnsubFunctions = state.type !== `atom` ? subscribeToRootAtoms$1(state, store) : null;
1109
+ const unsubscribe = dependencyUnsubFunctions === null ? () => {
1110
+ store.logger.info(
1111
+ `\u{1F648}`,
1112
+ state.type,
1113
+ state.key,
1114
+ `Removing subscription "${key}"`
1115
+ );
1116
+ unsubFunction();
1117
+ } : () => {
1118
+ store.logger.info(
1119
+ `\u{1F648}`,
1120
+ state.type,
1121
+ state.key,
1122
+ `Removing subscription "${key}"`
1123
+ );
1124
+ unsubFunction();
1125
+ for (const unsubFromDependency of dependencyUnsubFunctions) {
1126
+ unsubFromDependency();
1127
+ }
1002
1128
  };
1003
- const core = target(store);
1004
- core.transactions.set(newTransaction.key, newTransaction);
1005
- const token = deposit(newTransaction);
1006
- store.subject.transactionCreation.next(token);
1007
- return token;
1129
+ return unsubscribe;
1008
1130
  }
1009
- var target = (store) => store.transactionStatus.phase === `building` ? store.transactionStatus.core : store;
1010
- var redoTransactionUpdate = (update, store) => {
1011
- store.logger.info(`\u23ED\uFE0F`, `transaction`, update.key, `Redo`);
1012
- for (const { key, newValue } of update.atomUpdates) {
1013
- const token = { key, type: `atom` };
1014
- const state = withdraw(token, store);
1015
- if (state === void 0) {
1016
- throw new Error(
1017
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1018
- );
1019
- }
1020
- setState(state, newValue, store);
1131
+ var subscribeToTimeline = (token, handleUpdate, key, store) => {
1132
+ const tl = withdraw$1(token, store);
1133
+ if (tl === void 0) {
1134
+ throw new Error(
1135
+ `Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`
1136
+ );
1021
1137
  }
1138
+ store.logger.info(`\u{1F440}`, `timeline`, token.key, `Adding subscription "${key}"`);
1139
+ const unsubscribe = tl.subject.subscribe(key, handleUpdate);
1140
+ return () => {
1141
+ store.logger.info(
1142
+ `\u{1F648}`,
1143
+ `timeline`,
1144
+ token.key,
1145
+ `Removing subscription "${key}" from timeline`
1146
+ );
1147
+ unsubscribe();
1148
+ };
1022
1149
  };
1023
- var undoTransactionUpdate = (update, store) => {
1150
+ var subscribeToTransaction = (token, handleUpdate, key, store) => {
1151
+ const tx = withdraw$1(token, store);
1152
+ if (tx === void 0) {
1153
+ throw new Error(
1154
+ `Cannot subscribe to transaction "${token.key}": transaction not found in store "${store.config.name}".`
1155
+ );
1156
+ }
1024
1157
  store.logger.info(
1025
- `\u23EE\uFE0F`,
1158
+ `\u{1F440}`,
1026
1159
  `transaction`,
1027
- update.key,
1028
- `Undoing transaction update`,
1029
- update
1160
+ token.key,
1161
+ `Adding subscription "${key}"`
1030
1162
  );
1031
- for (const { key, oldValue } of update.atomUpdates) {
1032
- const token = { key, type: `atom` };
1033
- const state = withdraw(token, store);
1034
- if (state === void 0) {
1035
- throw new Error(
1036
- `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
1037
- );
1038
- }
1039
- setState(state, oldValue, store);
1040
- }
1041
- };
1042
-
1043
- // src/transaction/index.ts
1044
- var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1045
-
1046
- // src/caching.ts
1047
- function cacheValue(key, value, subject, store) {
1048
- const currentValue = target(store).valueMap.get(key);
1049
- if (currentValue instanceof Future) {
1050
- currentValue.cancel();
1051
- }
1052
- if (value instanceof Promise) {
1053
- const future = new Future(value);
1054
- target(store).valueMap.set(key, future);
1055
- future.then((resolved) => {
1056
- if (future.isCanceled) {
1057
- return;
1058
- }
1059
- cacheValue(key, resolved, subject, store);
1060
- subject.next({ newValue: resolved, oldValue: future });
1061
- }).catch((thrown) => {
1062
- if (thrown !== `canceled`) {
1063
- store.logger.error(`\u{1F4A5}`, `state`, key, `rejected:`, thrown);
1064
- }
1065
- });
1066
- return future;
1067
- }
1068
- target(store).valueMap.set(key, value);
1069
- return value;
1070
- }
1071
- var readCachedValue = (key, store) => target(store).valueMap.get(key);
1072
- var isValueCached = (key, store) => target(store).valueMap.has(key);
1073
- var evictCachedValue = (key, store) => {
1074
- const core = target(store);
1075
- const currentValue = core.valueMap.get(key);
1076
- if (currentValue instanceof Future) {
1077
- currentValue.cancel();
1078
- }
1079
- if (core.operation.open) {
1080
- core.operation.prev.set(key, currentValue);
1081
- }
1082
- core.valueMap.delete(key);
1083
- store.logger.info(`\u{1F5D1}`, `state`, key, `evicted`);
1163
+ const unsubscribe = tx.subject.subscribe(key, handleUpdate);
1164
+ return () => {
1165
+ store.logger.info(
1166
+ `\u{1F648}`,
1167
+ `transaction`,
1168
+ token.key,
1169
+ `Removing subscription "${key}"`
1170
+ );
1171
+ unsubscribe();
1172
+ };
1084
1173
  };
1085
1174
  var Tracker = class {
1086
1175
  constructor(mutableState, store) {
1087
1176
  this.unsubscribeFromInnerValue = null;
1088
1177
  this.mutableState = mutableState;
1089
- this.latestUpdateState = this.initializeState(mutableState, store);
1090
- this.observeCore(mutableState, this.latestUpdateState, store);
1091
- this.updateCore(mutableState, this.latestUpdateState, store);
1092
- const core = target(store);
1093
- core.trackers.set(mutableState.key, this);
1178
+ const target = newest(store);
1179
+ this.latestUpdateState = this.initializeState(mutableState, target);
1180
+ this.observeCore(mutableState, this.latestUpdateState, target);
1181
+ this.updateCore(mutableState, this.latestUpdateState, target);
1182
+ target.trackers.set(mutableState.key, this);
1094
1183
  }
1095
1184
  initializeState(mutableState, store) {
1096
1185
  const latestUpdateStateKey = `*${mutableState.key}`;
@@ -1111,8 +1200,9 @@ var Tracker = class {
1111
1200
  }
1112
1201
  observeCore(mutableState, latestUpdateState, store) {
1113
1202
  const originalInnerValue = getState(mutableState, store);
1203
+ const target = newest(store);
1114
1204
  this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
1115
- `tracker:${store.config.name}:${store.transactionStatus.phase === `idle` ? `main` : store.transactionStatus.key}`,
1205
+ `tracker:${store.config.name}:${target.transactionMeta === null ? `main` : target.transactionMeta.update.key}`,
1116
1206
  (update) => {
1117
1207
  const unsubscribe = store.subject.operationStatus.subscribe(
1118
1208
  mutableState.key,
@@ -1123,14 +1213,15 @@ var Tracker = class {
1123
1213
  );
1124
1214
  }
1125
1215
  );
1126
- subscribe(
1216
+ subscribeToState(
1127
1217
  mutableState,
1128
1218
  (update) => {
1129
1219
  var _a;
1130
1220
  if (update.newValue !== update.oldValue) {
1131
1221
  (_a = this.unsubscribeFromInnerValue) == null ? void 0 : _a.call(this);
1222
+ const target2 = newest(store);
1132
1223
  this.unsubscribeFromInnerValue = update.newValue.subscribe(
1133
- `tracker:${store.config.name}:${store.transactionStatus.phase === `idle` ? `main` : store.transactionStatus.key}`,
1224
+ `tracker:${store.config.name}:${target2.transactionMeta === null ? `main` : target2.transactionMeta.update.key}`,
1134
1225
  (update2) => {
1135
1226
  const unsubscribe = store.subject.operationStatus.subscribe(
1136
1227
  mutableState.key,
@@ -1148,7 +1239,7 @@ var Tracker = class {
1148
1239
  );
1149
1240
  }
1150
1241
  updateCore(mutableState, latestUpdateState, store) {
1151
- subscribe(
1242
+ subscribeToState(
1152
1243
  latestUpdateState,
1153
1244
  ({ newValue, oldValue }) => {
1154
1245
  const timelineId = store.timelineAtoms.getRelatedKey(
@@ -1173,7 +1264,9 @@ var Tracker = class {
1173
1264
  },
1174
1265
  store
1175
1266
  );
1176
- }
1267
+ },
1268
+ `${mutableState.key}: tracker observing timeline`,
1269
+ store
1177
1270
  );
1178
1271
  return;
1179
1272
  }
@@ -1182,945 +1275,968 @@ var Tracker = class {
1182
1275
  latestUpdateState.key,
1183
1276
  () => {
1184
1277
  unsubscribe();
1185
- const mutable = getState(mutableState, store);
1186
- const updateNumber = mutable.getUpdateNumber(newValue);
1187
- const eventOffset = updateNumber - mutable.cacheUpdateNumber;
1188
- if (newValue && eventOffset === 1) {
1189
- setState(
1190
- mutableState,
1191
- (transceiver) => (transceiver.do(newValue), transceiver),
1192
- store
1193
- );
1194
- }
1195
- }
1196
- );
1197
- },
1198
- `${store.config.name}: tracker observing latest update`,
1199
- store
1200
- );
1201
- }
1202
- };
1203
-
1204
- // src/mutable/create-mutable-atom.ts
1205
- function createMutableAtom(options, store) {
1206
- store.logger.info(
1207
- `\u{1F527}`,
1208
- `atom`,
1209
- options.key,
1210
- `creating in store "${store.config.name}"`
1211
- );
1212
- const coreState = createAtom(options, void 0, store);
1213
- new Tracker(coreState, store);
1214
- const jsonState = selectJson(coreState, options, store);
1215
- subscribe(
1216
- jsonState,
1217
- () => {
1218
- const trackerHasBeenInitialized = target(store).trackers.has(coreState.key);
1219
- if (!trackerHasBeenInitialized) {
1220
- new Tracker(coreState, store);
1221
- }
1222
- },
1223
- `tracker-initializer:${store == null ? void 0 : store.config.name}:${store.transactionStatus.phase === `idle` ? `main` : store.transactionStatus.key}`
1224
- );
1225
- return coreState;
1226
- }
1227
- function createAtomFamily(options, store) {
1228
- const subject = new Subject();
1229
- const atomFamily = Object.assign(
1230
- (key) => {
1231
- const subKey = stringifyJson(key);
1232
- const family = { key: options.key, subKey };
1233
- const fullKey = `${options.key}(${subKey})`;
1234
- const existing = withdraw({ key: fullKey, type: `atom` }, store);
1235
- let token;
1236
- if (existing) {
1237
- token = deposit(existing);
1238
- } else {
1239
- const individualOptions = {
1240
- key: fullKey,
1241
- default: options.default instanceof Function ? options.default(key) : options.default
1242
- };
1243
- if (options.effects) {
1244
- individualOptions.effects = options.effects(key);
1245
- }
1246
- token = createAtom(individualOptions, family, store);
1247
- subject.next(token);
1248
- }
1249
- return token;
1250
- },
1251
- {
1252
- key: options.key,
1253
- type: `atom_family`,
1254
- subject
1255
- }
1256
- );
1257
- const core = target(store);
1258
- core.families.set(options.key, atomFamily);
1259
- return atomFamily;
1260
- }
1261
-
1262
- // src/operation.ts
1263
- var openOperation = (token, store) => {
1264
- const core = target(store);
1265
- if (core.operation.open) {
1266
- store.logger.error(
1267
- `\u274C`,
1268
- token.type,
1269
- token.key,
1270
- `failed to setState during a setState for "${core.operation.token.key}"`
1271
- );
1272
- return `rejection`;
1273
- }
1274
- core.operation = {
1275
- open: true,
1276
- done: /* @__PURE__ */ new Set(),
1277
- prev: /* @__PURE__ */ new Map(),
1278
- time: Date.now(),
1279
- token
1280
- };
1281
- store.logger.info(
1282
- `\u2B55`,
1283
- token.type,
1284
- token.key,
1285
- `operation start in store "${store.config.name}"${store.transactionStatus.phase === `idle` ? `` : ` ${store.transactionStatus.phase} "${store.transactionStatus.key}"`}`
1286
- );
1287
- };
1288
- var closeOperation = (store) => {
1289
- const core = target(store);
1290
- if (core.operation.open) {
1291
- store.logger.info(
1292
- `\u{1F534}`,
1293
- core.operation.token.type,
1294
- core.operation.token.key,
1295
- `operation done in store "${store.config.name}"`
1296
- );
1297
- }
1298
- core.operation = { open: false };
1299
- store.subject.operationStatus.next(core.operation);
1300
- };
1301
- var isDone = (key, store) => {
1302
- const core = target(store);
1303
- if (!core.operation.open) {
1304
- store.logger.warn(
1305
- `\u{1F41E}`,
1306
- `unknown`,
1307
- key,
1308
- `isDone called outside of an operation. This is probably a bug.`
1309
- );
1310
- return true;
1311
- }
1312
- return core.operation.done.has(key);
1313
- };
1314
- var markDone = (key, store) => {
1315
- const core = target(store);
1316
- if (!core.operation.open) {
1317
- store.logger.warn(
1318
- `\u{1F41E}`,
1319
- `unknown`,
1320
- key,
1321
- `markDone called outside of an operation. This is probably a bug.`
1322
- );
1323
- return;
1324
- }
1325
- core.operation.done.add(key);
1326
- };
1327
-
1328
- // src/set-state/become.ts
1329
- var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
1330
- originalThing instanceof Function ? originalThing() : originalThing
1331
- ) : nextVersionOfThing;
1332
-
1333
- // src/read-or-compute-value.ts
1334
- var readOrComputeValue = (state, store) => {
1335
- if (isValueCached(state.key, store)) {
1336
- store.logger.info(`\u{1F4D6}`, state.type, state.key, `reading cached value`);
1337
- return readCachedValue(state.key, store);
1338
- }
1339
- if (state.type !== `atom`) {
1340
- store.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
1341
- return state.get();
1342
- }
1343
- const fallback = state.default instanceof Function ? state.default() : state.default;
1344
- store.logger.info(
1345
- `\u{1F481}`,
1346
- `atom`,
1347
- state.key,
1348
- `could not find cached value; using default`,
1349
- fallback
1350
- );
1351
- return state.default instanceof Function ? state.default() : state.default;
1352
- };
1353
-
1354
- // src/set-state/copy-mutable-if-needed.ts
1355
- function copyMutableIfNeeded(atom, transform, origin, target2) {
1356
- const originValue = origin.valueMap.get(atom.key);
1357
- const targetValue = target2.valueMap.get(atom.key);
1358
- if (originValue === targetValue) {
1359
- origin.logger.info(`\u{1F4C3}`, `atom`, `${atom.key}`, `copying`);
1360
- const copiedValue = transform.fromJson(transform.toJson(originValue));
1361
- target2.valueMap.set(atom.key, copiedValue);
1362
- new Tracker(atom, origin);
1363
- return copiedValue;
1364
- }
1365
- return targetValue;
1366
- }
1367
-
1368
- // src/set-state/copy-mutable-in-transaction.ts
1369
- function copyMutableIfWithinTransaction(oldValue, atom, store) {
1370
- if (store.transactionStatus.phase === `building` || store.transactionStatus.phase === `applying`) {
1371
- if (`toJson` in atom && `fromJson` in atom) {
1372
- const copiedValue = copyMutableIfNeeded(
1373
- atom,
1374
- atom,
1375
- store,
1376
- store.transactionStatus.core
1377
- );
1378
- return copiedValue;
1379
- }
1380
- if (`family` in atom) {
1381
- const family = store.transactionStatus.core.families.get(atom.family.key);
1382
- if (family && family.type === `atom_family`) {
1383
- const result = copyMutableFamilyMemberWithinTransaction(
1384
- atom,
1385
- family,
1386
- store,
1387
- store.transactionStatus.core
1278
+ const mutable = getState(mutableState, store);
1279
+ const updateNumber = mutable.getUpdateNumber(newValue);
1280
+ const eventOffset = updateNumber - mutable.cacheUpdateNumber;
1281
+ if (newValue && eventOffset === 1) {
1282
+ setState(
1283
+ mutableState,
1284
+ (transceiver) => (transceiver.do(newValue), transceiver),
1285
+ store
1286
+ );
1287
+ }
1288
+ }
1388
1289
  );
1389
- if (result) {
1390
- return result;
1391
- }
1392
- }
1393
- }
1394
- }
1395
- return oldValue;
1396
- }
1397
- function copyMutableFamilyMemberWithinTransaction(atom, family, origin, target2) {
1398
- if (`toJson` in family && `fromJson` in family) {
1399
- const copyCreated = copyMutableIfNeeded(atom, family, origin, target2);
1400
- return copyCreated;
1290
+ },
1291
+ `${store.config.name}: tracker observing latest update`,
1292
+ store
1293
+ );
1401
1294
  }
1402
- return null;
1403
- }
1404
-
1405
- // src/set-state/emit-update.ts
1406
- var emitUpdate = (state, update, store) => {
1407
- store.logger.info(
1408
- `\u{1F4E2}`,
1409
- state.type,
1410
- state.key,
1411
- `went (`,
1412
- update.oldValue,
1413
- `->`,
1414
- update.newValue,
1415
- `) subscribers:`,
1416
- state.subject.subscribers
1417
- );
1418
- state.subject.next(update);
1419
1295
  };
1420
1296
 
1421
- // src/set-state/evict-downstream.ts
1422
- var evictDownStream = (atom, store) => {
1423
- const core = target(store);
1424
- const downstreamKeys = core.selectorAtoms.getRelatedKeys(atom.key);
1297
+ // src/mutable/create-mutable-atom.ts
1298
+ function createMutableAtom(options, store) {
1425
1299
  store.logger.info(
1426
- `\u{1F9F9}`,
1427
- atom.type,
1428
- atom.key,
1429
- downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`,
1430
- downstreamKeys != null ? downstreamKeys : `to evict`
1300
+ `\u{1F527}`,
1301
+ `atom`,
1302
+ options.key,
1303
+ `creating in store "${store.config.name}"`
1431
1304
  );
1432
- if (downstreamKeys) {
1433
- if (core.operation.open) {
1434
- store.logger.info(
1435
- `\u{1F9F9}`,
1436
- atom.type,
1437
- atom.key,
1438
- `[ ${[...core.operation.done].join(`, `)} ] already done`
1439
- );
1305
+ const coreState = createAtom(options, void 0, store);
1306
+ new Tracker(coreState, store);
1307
+ const jsonState = selectJson(coreState, options, store);
1308
+ const target = newest(store);
1309
+ subscribeToState(
1310
+ jsonState,
1311
+ () => {
1312
+ const trackerHasBeenInitialized = newest(store).trackers.has(coreState.key);
1313
+ if (!trackerHasBeenInitialized) {
1314
+ new Tracker(coreState, store);
1315
+ }
1316
+ },
1317
+ `tracker-initializer:${store == null ? void 0 : store.config.name}:${target.transactionMeta === null ? `main` : `${target.transactionMeta.update.key}`}`,
1318
+ store
1319
+ );
1320
+ return coreState;
1321
+ }
1322
+ function createAtomFamily(options, store) {
1323
+ const subject = new Subject();
1324
+ const atomFamily = Object.assign(
1325
+ (key) => {
1326
+ const subKey = stringifyJson(key);
1327
+ const family = { key: options.key, subKey };
1328
+ const fullKey = `${options.key}(${subKey})`;
1329
+ const existing = withdraw({ key: fullKey, type: `atom` }, store);
1330
+ let token;
1331
+ if (existing) {
1332
+ token = deposit(existing);
1333
+ } else {
1334
+ const individualOptions = {
1335
+ key: fullKey,
1336
+ default: options.default instanceof Function ? options.default(key) : options.default
1337
+ };
1338
+ if (options.effects) {
1339
+ individualOptions.effects = options.effects(key);
1340
+ }
1341
+ token = createAtom(individualOptions, family, store);
1342
+ subject.next(token);
1343
+ }
1344
+ return token;
1345
+ },
1346
+ {
1347
+ key: options.key,
1348
+ type: `atom_family`,
1349
+ subject
1440
1350
  }
1441
- for (const key of downstreamKeys) {
1442
- if (isDone(key, store)) {
1443
- continue;
1351
+ );
1352
+ const target = newest(store);
1353
+ target.families.set(options.key, atomFamily);
1354
+ return atomFamily;
1355
+ }
1356
+ function createReadonlySelectorFamily(options, store) {
1357
+ const subject = new Subject();
1358
+ return Object.assign(
1359
+ (key) => {
1360
+ const target = newest(store);
1361
+ const subKey = stringifyJson(key);
1362
+ const family = { key: options.key, subKey };
1363
+ const fullKey = `${options.key}(${subKey})`;
1364
+ const existing = target.readonlySelectors.get(fullKey);
1365
+ if (existing) {
1366
+ return deposit(existing);
1444
1367
  }
1445
- evictCachedValue(key, store);
1446
- markDone(key, store);
1368
+ return createSelector(
1369
+ {
1370
+ key: fullKey,
1371
+ get: options.get(key)
1372
+ },
1373
+ family,
1374
+ store
1375
+ );
1376
+ },
1377
+ {
1378
+ key: options.key,
1379
+ type: `readonly_selector_family`,
1380
+ subject
1447
1381
  }
1448
- }
1449
- };
1450
-
1451
- // src/set-state/stow-update.ts
1452
- function shouldUpdateBeStowed(key, update) {
1453
- if (isTransceiver(update.newValue)) {
1454
- return false;
1455
- }
1456
- if (key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
1457
- return false;
1458
- }
1459
- return true;
1382
+ );
1460
1383
  }
1461
- var stowUpdate = (state, update, store) => {
1462
- const { key } = state;
1463
- if (store.transactionStatus.phase !== `building`) {
1464
- store.logger.error(
1465
- `\u{1F41E}`,
1466
- `atom`,
1467
- key,
1468
- `stowUpdate called outside of a transaction. This is probably a bug.`
1469
- );
1470
- return;
1471
- }
1472
- const shouldStow = shouldUpdateBeStowed(key, update);
1473
- if (!shouldStow) {
1474
- return;
1475
- }
1476
- const atomUpdate = __spreadValues({ key }, update);
1477
- if (state.family) {
1478
- atomUpdate.family = state.family;
1384
+ function createSelectorFamily(options, store) {
1385
+ const isReadonly = !(`set` in options);
1386
+ if (isReadonly) {
1387
+ return createReadonlySelectorFamily(options, store);
1479
1388
  }
1480
- store.transactionStatus.atomUpdates.push(atomUpdate);
1481
- store.logger.info(
1482
- `\u{1F4C1}`,
1483
- `atom`,
1484
- key,
1485
- `stowed (`,
1486
- update.oldValue,
1487
- `->`,
1488
- update.newValue,
1489
- `)`
1389
+ const target = newest(store);
1390
+ const subject = new Subject();
1391
+ const selectorFamily = Object.assign(
1392
+ (key) => {
1393
+ const subKey = stringifyJson(key);
1394
+ const family = { key: options.key, subKey };
1395
+ const fullKey = `${options.key}(${subKey})`;
1396
+ const existing = target.selectors.get(fullKey);
1397
+ if (existing) {
1398
+ return deposit(existing);
1399
+ }
1400
+ const token = createSelector(
1401
+ {
1402
+ key: fullKey,
1403
+ get: options.get(key),
1404
+ set: options.set(key)
1405
+ },
1406
+ family,
1407
+ store
1408
+ );
1409
+ subject.next(token);
1410
+ return token;
1411
+ },
1412
+ {
1413
+ key: options.key,
1414
+ type: `selector_family`
1415
+ }
1490
1416
  );
1491
- };
1492
-
1493
- // src/set-state/set-atom.ts
1494
- var setAtom = (atom, next, store) => {
1495
- const oldValue = readOrComputeValue(atom, store);
1496
- let newValue = copyMutableIfWithinTransaction(oldValue, atom, store);
1497
- newValue = become(next)(newValue);
1498
- store.logger.info(`\u{1F4DD}`, `atom`, atom.key, `set to`, newValue);
1499
- newValue = cacheValue(atom.key, newValue, atom.subject, store);
1500
- if (isAtomDefault(atom.key, store)) {
1501
- markAtomAsNotDefault(atom.key, store);
1502
- }
1503
- markDone(atom.key, store);
1504
- evictDownStream(atom, store);
1505
- const update = { oldValue, newValue };
1506
- if (store.transactionStatus.phase !== `building`) {
1507
- emitUpdate(atom, update, store);
1508
- } else {
1509
- stowUpdate(atom, update, store);
1510
- }
1511
- };
1417
+ target.families.set(options.key, selectorFamily);
1418
+ return selectorFamily;
1419
+ }
1512
1420
 
1513
- // src/set-state/set-atom-or-selector.ts
1514
- var setAtomOrSelector = (state, value, store) => {
1515
- if (state.type === `selector`) {
1516
- state.set(value);
1517
- } else {
1518
- setAtom(state, value, store);
1421
+ // src/mutable/tracker-family.ts
1422
+ var FamilyTracker = class {
1423
+ constructor(findMutableState, store) {
1424
+ this.findLatestUpdateState = createAtomFamily(
1425
+ {
1426
+ key: `*${findMutableState.key}`,
1427
+ default: null
1428
+ },
1429
+ store
1430
+ );
1431
+ this.findMutableState = findMutableState;
1432
+ this.findMutableState.subject.subscribe(
1433
+ `store=${store.config.name}::tracker-atom-family`,
1434
+ (atomToken) => {
1435
+ if (atomToken.family) {
1436
+ const key = parseJson(atomToken.family.subKey);
1437
+ this.findLatestUpdateState(key);
1438
+ new Tracker(atomToken, store);
1439
+ }
1440
+ }
1441
+ );
1442
+ this.findLatestUpdateState.subject.subscribe(
1443
+ `store=${store.config.name}::tracker-atom-family`,
1444
+ (atomToken) => {
1445
+ if (atomToken.family) {
1446
+ const key = parseJson(atomToken.family.subKey);
1447
+ const mutableAtomToken = this.findMutableState(key);
1448
+ new Tracker(mutableAtomToken, store);
1449
+ }
1450
+ }
1451
+ );
1519
1452
  }
1520
1453
  };
1521
1454
 
1522
- // src/keys.ts
1523
- var isAtomKey = (key, store) => target(store).atoms.has(key);
1524
- var isSelectorKey = (key, store) => target(store).selectors.has(key);
1525
- var isReadonlySelectorKey = (key, store) => target(store).readonlySelectors.has(key);
1526
- var isStateKey = (key, store) => isAtomKey(key, store) || isSelectorKey(key, store) || isReadonlySelectorKey(key, store);
1455
+ // src/mutable/create-mutable-atom-family.ts
1456
+ function createMutableAtomFamily(options, store) {
1457
+ const coreFamily = Object.assign(
1458
+ createAtomFamily(options, store),
1459
+ options
1460
+ );
1461
+ selectJsonFamily(coreFamily, options);
1462
+ new FamilyTracker(coreFamily, store);
1463
+ return coreFamily;
1464
+ }
1527
1465
 
1528
- // src/selector/get-selector-dependency-keys.ts
1529
- var getSelectorDependencyKeys = (key, store) => {
1530
- const sources = target(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(source, store));
1531
- return sources;
1466
+ // src/mutable/get-json-family.ts
1467
+ var getJsonFamily = (mutableAtomFamily, store) => {
1468
+ const target = newest(store);
1469
+ const key = `${mutableAtomFamily.key}:JSON`;
1470
+ const jsonFamily = target.families.get(
1471
+ key
1472
+ );
1473
+ return jsonFamily;
1532
1474
  };
1533
1475
 
1534
- // src/selector/trace-selector-atoms.ts
1535
- var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
1536
- const rootKeys = [];
1537
- const indirectDependencyKeys = getSelectorDependencyKeys(
1538
- directDependencyKey,
1539
- store
1540
- );
1541
- let depth = 0;
1542
- while (indirectDependencyKeys.length > 0) {
1543
- const indirectDependencyKey = indirectDependencyKeys.shift();
1544
- ++depth;
1545
- if (depth > 99999) {
1546
- throw new Error(
1547
- `Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
1548
- );
1549
- }
1550
- if (!isAtomKey(indirectDependencyKey, store)) {
1551
- indirectDependencyKeys.push(
1552
- ...getSelectorDependencyKeys(indirectDependencyKey, store)
1553
- );
1554
- } else if (!rootKeys.includes(indirectDependencyKey)) {
1555
- rootKeys.push(indirectDependencyKey);
1556
- }
1476
+ // src/mutable/get-json-token.ts
1477
+ var getJsonToken = (mutableAtomToken) => {
1478
+ const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1479
+ const jsonToken = { type: `selector`, key };
1480
+ if (mutableAtomToken.family) {
1481
+ jsonToken.family = {
1482
+ key: `${mutableAtomToken.family.key}:JSON`,
1483
+ subKey: mutableAtomToken.family.subKey
1484
+ };
1557
1485
  }
1558
- return rootKeys;
1559
- };
1560
- var traceAllSelectorAtoms = (selectorKey, store) => {
1561
- const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
1562
- return directDependencyKeys.flatMap(
1563
- (depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
1564
- );
1486
+ return jsonToken;
1565
1487
  };
1566
1488
 
1567
- // src/selector/update-selector-atoms.ts
1568
- var updateSelectorAtoms = (selectorKey, dependency, store) => {
1569
- const core = target(store);
1570
- if (dependency.type === `atom`) {
1571
- core.selectorAtoms = core.selectorAtoms.set({
1572
- selectorKey,
1573
- atomKey: dependency.key
1574
- });
1575
- store.logger.info(
1576
- `\u{1F50D}`,
1577
- `selector`,
1578
- selectorKey,
1579
- `discovers root atom "${dependency.key}"`
1580
- );
1581
- } else {
1582
- const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
1583
- store.logger.info(
1584
- `\u{1F50D}`,
1585
- `selector`,
1586
- selectorKey,
1587
- `discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
1588
- );
1589
- for (const atomKey of rootKeys) {
1590
- core.selectorAtoms = core.selectorAtoms.set({
1591
- selectorKey,
1592
- atomKey
1593
- });
1594
- }
1489
+ // src/mutable/get-update-token.ts
1490
+ var getUpdateToken = (mutableAtomToken) => {
1491
+ const key = `*${mutableAtomToken.key}`;
1492
+ const updateToken = { type: `atom`, key };
1493
+ if (mutableAtomToken.family) {
1494
+ updateToken.family = {
1495
+ key: `*${mutableAtomToken.family.key}`,
1496
+ subKey: mutableAtomToken.family.subKey
1497
+ };
1595
1498
  }
1499
+ return updateToken;
1596
1500
  };
1597
1501
 
1598
- // src/selector/register-selector.ts
1599
- var registerSelector = (selectorKey, store) => ({
1600
- get: (dependency) => {
1601
- const core = target(store);
1602
- const alreadyRegistered = core.selectorGraph.getRelationEntries({ downstreamSelectorKey: selectorKey }).some(([_, { source }]) => source === dependency.key);
1603
- const dependencyState = withdraw(dependency, store);
1604
- if (dependencyState === void 0) {
1605
- throw new Error(
1606
- `State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1607
- );
1608
- }
1609
- const dependencyValue = readOrComputeValue(dependencyState, store);
1610
- store.logger.info(
1611
- `\u{1F50C}`,
1612
- `selector`,
1613
- selectorKey,
1614
- `registers dependency ( "${dependency.key}" =`,
1615
- dependencyValue,
1616
- `)`
1617
- );
1618
- if (!alreadyRegistered) {
1619
- core.selectorGraph = core.selectorGraph.set(
1620
- {
1621
- upstreamSelectorKey: dependency.key,
1622
- downstreamSelectorKey: selectorKey
1623
- },
1624
- {
1625
- source: dependency.key
1626
- }
1627
- );
1628
- }
1629
- updateSelectorAtoms(selectorKey, dependency, store);
1630
- return dependencyValue;
1631
- },
1632
- set: (stateToken, newValue) => {
1633
- const state = withdraw(stateToken, store);
1634
- if (state === void 0) {
1635
- throw new Error(
1636
- `State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
1637
- );
1638
- }
1639
- setAtomOrSelector(state, newValue, store);
1640
- }
1641
- });
1502
+ // src/mutable/is-atom-token-mutable.ts
1503
+ function isAtomTokenMutable(token) {
1504
+ return token.key.endsWith(`::mutable`);
1505
+ }
1642
1506
 
1643
- // src/selector/create-read-write-selector.ts
1644
- var createReadWriteSelector = (options, family, store, core) => {
1645
- const subject = new Subject();
1646
- const { get, set } = registerSelector(options.key, store);
1647
- const getSelf = () => {
1648
- const value = options.get({ get });
1649
- cacheValue(options.key, value, subject, store);
1650
- return value;
1651
- };
1652
- const setSelf = (next) => {
1653
- const oldValue = getSelf();
1654
- const newValue = become(next)(oldValue);
1655
- store.logger.info(
1656
- `\u{1F4DD}`,
1657
- `selector`,
1658
- options.key,
1659
- `set (`,
1660
- oldValue,
1661
- `->`,
1662
- newValue,
1663
- `)`
1664
- );
1665
- cacheValue(options.key, newValue, subject, store);
1666
- markDone(options.key, store);
1667
- if (store.transactionStatus.phase === `idle`) {
1668
- subject.next({ newValue, oldValue });
1669
- }
1670
- options.set({ get, set }, newValue);
1671
- };
1672
- const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1673
- subject,
1674
- install: (s) => createSelector(options, family, s),
1675
- get: getSelf,
1676
- set: setSelf,
1677
- type: `selector`
1678
- }), family && { family });
1679
- core.selectors.set(options.key, mySelector);
1680
- const initialValue = getSelf();
1681
- store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
1682
- const token = {
1683
- key: options.key,
1684
- type: `selector`
1685
- };
1686
- if (family) {
1687
- token.family = family;
1688
- }
1689
- store.subject.selectorCreation.next(token);
1690
- return token;
1507
+ // src/mutable/transceiver.ts
1508
+ function isTransceiver(value) {
1509
+ return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
1510
+ }
1511
+
1512
+ // src/mutable/index.ts
1513
+ var isAtomMutable = (atom) => `isMutable` in atom;
1514
+
1515
+ // src/atom/is-default.ts
1516
+ var isAtomDefault = (key, store) => {
1517
+ const core = newest(store);
1518
+ return core.atomsThatAreDefault.has(key);
1519
+ };
1520
+ var markAtomAsDefault = (key, store) => {
1521
+ const core = newest(store);
1522
+ core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
1523
+ };
1524
+ var markAtomAsNotDefault = (key, store) => {
1525
+ const core = newest(store);
1526
+ core.atomsThatAreDefault = new Set(newest(store).atomsThatAreDefault);
1527
+ core.atomsThatAreDefault.delete(key);
1528
+ };
1529
+ var isSelectorDefault = (key, store) => {
1530
+ const rootKeys = traceAllSelectorAtoms(key, store);
1531
+ return rootKeys.every((rootKey) => isAtomDefault(rootKey, store));
1691
1532
  };
1692
1533
 
1693
- // src/selector/create-readonly-selector.ts
1694
- var createReadonlySelector = (options, family, store, core) => {
1695
- const subject = new Subject();
1696
- const { get } = registerSelector(options.key, store);
1697
- const getSelf = () => {
1698
- const value = options.get({ get });
1699
- cacheValue(options.key, value, subject, store);
1700
- return value;
1701
- };
1702
- const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
1703
- subject,
1704
- install: (s) => createSelector(options, family, s),
1705
- get: getSelf,
1706
- type: `readonly_selector`
1707
- }), family && { family });
1708
- core.readonlySelectors.set(options.key, readonlySelector);
1709
- const initialValue = getSelf();
1534
+ // src/atom/create-atom.ts
1535
+ function createAtom(options, family, store) {
1710
1536
  store.logger.info(
1711
- `\u2728`,
1712
- readonlySelector.type,
1713
- readonlySelector.key,
1714
- `=`,
1715
- initialValue
1537
+ `\u{1F528}`,
1538
+ `atom`,
1539
+ options.key,
1540
+ `creating in store "${store.config.name}"`
1716
1541
  );
1717
- const token = {
1718
- key: options.key,
1719
- type: `readonly_selector`
1720
- };
1721
- if (family) {
1722
- token.family = family;
1542
+ const target = newest(store);
1543
+ const existing = target.atoms.get(options.key);
1544
+ if (existing) {
1545
+ store.logger.error(
1546
+ `\u274C`,
1547
+ `atom`,
1548
+ options.key,
1549
+ `Tried to create atom, but it already exists in the store.`,
1550
+ `(Ignore if you are in development using hot module replacement.)`
1551
+ );
1552
+ return deposit(existing);
1553
+ }
1554
+ const subject = new Subject();
1555
+ const newAtom = __spreadValues(__spreadProps(__spreadValues({}, options), {
1556
+ type: `atom`,
1557
+ install: (store2) => {
1558
+ store2.logger.info(
1559
+ `\u{1F6E0}\uFE0F`,
1560
+ `atom`,
1561
+ options.key,
1562
+ `installing in store "${store2.config.name}"`
1563
+ );
1564
+ return `mutable` in options ? createMutableAtom(options, store2) : createAtom(options, void 0, store2);
1565
+ },
1566
+ subject
1567
+ }), family && { family });
1568
+ let initialValue = options.default;
1569
+ if (options.default instanceof Function) {
1570
+ initialValue = options.default();
1723
1571
  }
1724
- store.subject.selectorCreation.next(token);
1572
+ target.atoms.set(newAtom.key, newAtom);
1573
+ markAtomAsDefault(options.key, store);
1574
+ cacheValue(options.key, initialValue, subject, store);
1575
+ const token = deposit(newAtom);
1576
+ if (options.effects) {
1577
+ let effectIndex = 0;
1578
+ const cleanupFunctions = [];
1579
+ for (const effect of options.effects) {
1580
+ const cleanup = effect({
1581
+ setSelf: (next) => setState(token, next, store),
1582
+ onSet: (handle) => subscribeToState(token, handle, `effect[${effectIndex}]`, store)
1583
+ });
1584
+ if (cleanup) {
1585
+ cleanupFunctions.push(cleanup);
1586
+ }
1587
+ ++effectIndex;
1588
+ }
1589
+ newAtom.cleanup = () => {
1590
+ for (const cleanup of cleanupFunctions) {
1591
+ cleanup();
1592
+ }
1593
+ };
1594
+ }
1595
+ store.subject.atomCreation.next(token);
1725
1596
  return token;
1726
- };
1597
+ }
1727
1598
 
1728
- // src/selector/create-selector.ts
1729
- function createSelector(options, family, store) {
1730
- const core = target(store);
1731
- const existingWritable = core.selectors.get(options.key);
1732
- const existingReadonly = core.readonlySelectors.get(options.key);
1733
- if (existingWritable || existingReadonly) {
1599
+ // src/atom/delete-atom.ts
1600
+ function deleteAtom(atomToken, store) {
1601
+ var _a, _b;
1602
+ const target = newest(store);
1603
+ const { key } = atomToken;
1604
+ const atom = target.atoms.get(key);
1605
+ if (!atom) {
1734
1606
  store.logger.error(
1735
1607
  `\u274C`,
1736
- existingReadonly ? `readonly_selector` : `selector`,
1737
- options.key,
1738
- `Tried to create selector, but it already exists in the store. (Ignore if you are in development using hot module replacement.)`
1608
+ `atom`,
1609
+ `${key}`,
1610
+ `Tried to delete atom, but it does not exist in the store.`
1739
1611
  );
1740
1612
  }
1741
- if (`set` in options) {
1742
- return createReadWriteSelector(options, family, store, core);
1613
+ (_a = atom == null ? void 0 : atom.cleanup) == null ? void 0 : _a.call(atom);
1614
+ target.atoms.delete(key);
1615
+ target.valueMap.delete(key);
1616
+ const selectorKeys = target.selectorAtoms.getRelatedKeys(key);
1617
+ if (selectorKeys) {
1618
+ for (const selectorKey of selectorKeys) {
1619
+ const token = (_b = target.selectors.get(selectorKey)) != null ? _b : target.readonlySelectors.get(selectorKey);
1620
+ if (token) {
1621
+ deleteSelector(token, store);
1622
+ }
1623
+ }
1743
1624
  }
1744
- return createReadonlySelector(options, family, store, core);
1625
+ target.selectorAtoms.delete(key);
1626
+ target.atomsThatAreDefault.delete(key);
1627
+ target.timelineAtoms.delete(key);
1628
+ store.logger.info(`\u{1F525}`, `atom`, `${key}`, `deleted`);
1745
1629
  }
1746
1630
 
1747
- // src/selector/delete-selector.ts
1748
- function deleteSelector(selectorToken, store) {
1749
- const core = target(store);
1750
- const { key } = selectorToken;
1751
- switch (selectorToken.type) {
1752
- case `selector`:
1753
- core.selectors.delete(key);
1754
- break;
1755
- case `readonly_selector`:
1756
- core.readonlySelectors.delete(key);
1757
- break;
1631
+ // src/lazy-map.ts
1632
+ var LazyMap = class extends Map {
1633
+ constructor(source) {
1634
+ super();
1635
+ this.source = source;
1636
+ this.deleted = /* @__PURE__ */ new Set();
1758
1637
  }
1759
- core.valueMap.delete(key);
1760
- core.selectorAtoms.delete(key);
1761
- const downstreamTokens = core.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
1762
- ([downstreamSelectorKey]) => {
1763
- var _a;
1764
- return (_a = core.selectors.get(downstreamSelectorKey)) != null ? _a : core.readonlySelectors.get(downstreamSelectorKey);
1638
+ get(key) {
1639
+ const has = super.has(key);
1640
+ if (has) {
1641
+ return super.get(key);
1765
1642
  }
1766
- );
1767
- for (const downstreamToken of downstreamTokens) {
1768
- if (downstreamToken) {
1769
- deleteSelector(downstreamToken, store);
1643
+ if (!this.deleted.has(key) && this.source.has(key)) {
1644
+ const value = this.source.get(key);
1645
+ return value;
1770
1646
  }
1647
+ return void 0;
1771
1648
  }
1772
- core.selectorGraph.delete(key);
1773
- store.logger.info(`\u{1F525}`, selectorToken.type, `${key}`, `deleted`);
1649
+ set(key, value) {
1650
+ this.deleted.delete(key);
1651
+ return super.set(key, value);
1652
+ }
1653
+ hasOwn(key) {
1654
+ return super.has(key);
1655
+ }
1656
+ has(key) {
1657
+ return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
1658
+ }
1659
+ delete(key) {
1660
+ this.deleted.add(key);
1661
+ return super.delete(key);
1662
+ }
1663
+ };
1664
+
1665
+ // src/not-found-error.ts
1666
+ var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
1667
+ function prettyPrintTokenType(token) {
1668
+ if (token.type === `readonly_selector`) {
1669
+ return `Readonly Selector`;
1670
+ }
1671
+ return capitalize(token.type);
1774
1672
  }
1673
+ var NotFoundError = class extends Error {
1674
+ constructor(token, store) {
1675
+ super(
1676
+ `${prettyPrintTokenType(token)} "${token.key}" not found in store "${store.config.name}".`
1677
+ );
1678
+ }
1679
+ };
1775
1680
 
1776
- // src/families/create-readonly-selector-family.ts
1777
- function createReadonlySelectorFamily(options, store) {
1778
- const core = target(store);
1779
- const subject = new Subject();
1780
- return Object.assign(
1781
- (key) => {
1782
- const subKey = stringifyJson(key);
1783
- const family = { key: options.key, subKey };
1784
- const fullKey = `${options.key}(${subKey})`;
1785
- const existing = core.readonlySelectors.get(fullKey);
1786
- if (existing) {
1787
- return deposit(existing);
1681
+ // src/timeline/add-atom-to-timeline.ts
1682
+ var addAtomToTimeline = (atomToken, tl, store) => {
1683
+ const atom = withdraw(atomToken, store);
1684
+ if (atom === void 0) {
1685
+ throw new Error(
1686
+ `Cannot subscribe to atom "${atomToken.key}" because it has not been initialized in store "${store.config.name}"`
1687
+ );
1688
+ }
1689
+ atom.subject.subscribe(`timeline`, (update) => {
1690
+ var _a, _b, _c, _d, _e, _f;
1691
+ const target = newest(store);
1692
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
1693
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
1694
+ const currentTransactionKey = (_a = target.subject.transactionApplying.state) == null ? void 0 : _a.update.key;
1695
+ const currentTransactionTime = (_b = target.subject.transactionApplying.state) == null ? void 0 : _b.time;
1696
+ store.logger.info(
1697
+ `\u23F3`,
1698
+ `timeline`,
1699
+ tl.key,
1700
+ `atom`,
1701
+ atomToken.key,
1702
+ `went`,
1703
+ update.oldValue,
1704
+ `->`,
1705
+ update.newValue,
1706
+ currentTransactionKey ? `in transaction "${currentTransactionKey}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
1707
+ );
1708
+ if (tl.timeTraveling === null) {
1709
+ if (tl.selectorTime && tl.selectorTime !== currentSelectorTime) {
1710
+ const mostRecentUpdate = tl.history.at(-1);
1711
+ if (mostRecentUpdate === void 0) {
1712
+ throw new Error(
1713
+ `Timeline "${tl.key}" has a selectorTime, but no history. This is most likely a bug in AtomIO.`
1714
+ );
1715
+ }
1716
+ }
1717
+ if (currentTransactionKey) {
1718
+ const currentTransaction = withdraw(
1719
+ { key: currentTransactionKey, type: `transaction` },
1720
+ store
1721
+ );
1722
+ if (currentTransaction === void 0) {
1723
+ throw new Error(
1724
+ `Transaction "${currentTransactionKey}" not found in store "${store.config.name}". This is surprising, because we are in the application phase of "${currentTransactionKey}".`
1725
+ );
1726
+ }
1727
+ if (tl.transactionKey !== currentTransactionKey) {
1728
+ if (tl.transactionKey) {
1729
+ store.logger.error(
1730
+ `\u{1F41E}`,
1731
+ `timeline`,
1732
+ tl.key,
1733
+ `unable to resolve transaction "${tl.transactionKey}. This is probably a bug in AtomIO.`
1734
+ );
1735
+ }
1736
+ tl.transactionKey = currentTransactionKey;
1737
+ const unsubscribe = currentTransaction.subject.subscribe(
1738
+ `timeline:${tl.key}`,
1739
+ (update2) => {
1740
+ var _a2, _b2;
1741
+ unsubscribe();
1742
+ if (tl.timeTraveling === null && currentTransactionTime) {
1743
+ if (tl.at !== tl.history.length) {
1744
+ tl.history.splice(tl.at);
1745
+ }
1746
+ const filterUpdates = (updates2) => updates2.filter((updateFromTx) => {
1747
+ const target2 = newest(store);
1748
+ if (`updates` in updateFromTx) {
1749
+ return true;
1750
+ }
1751
+ const atomOrFamilyKeys = target2.timelineAtoms.getRelatedKeys(tl.key);
1752
+ return atomOrFamilyKeys ? [...atomOrFamilyKeys].some(
1753
+ (key) => {
1754
+ var _a3;
1755
+ return key === updateFromTx.key || key === ((_a3 = updateFromTx.family) == null ? void 0 : _a3.key);
1756
+ }
1757
+ ) : false;
1758
+ }).map((updateFromTx) => {
1759
+ if (`updates` in updateFromTx) {
1760
+ return __spreadProps(__spreadValues({}, updateFromTx), {
1761
+ updates: filterUpdates(updateFromTx.updates)
1762
+ });
1763
+ }
1764
+ return updateFromTx;
1765
+ });
1766
+ const updates = filterUpdates(update2.updates);
1767
+ const timelineTransactionUpdate = __spreadProps(__spreadValues({
1768
+ type: `transaction_update`,
1769
+ timestamp: currentTransactionTime
1770
+ }, update2), {
1771
+ updates
1772
+ });
1773
+ const willCapture = (_b2 = (_a2 = tl.shouldCapture) == null ? void 0 : _a2.call(tl, timelineTransactionUpdate, tl)) != null ? _b2 : true;
1774
+ if (willCapture) {
1775
+ tl.history.push(timelineTransactionUpdate);
1776
+ tl.at = tl.history.length;
1777
+ tl.subject.next(timelineTransactionUpdate);
1778
+ }
1779
+ }
1780
+ tl.transactionKey = null;
1781
+ store.logger.info(
1782
+ `\u231B`,
1783
+ `timeline`,
1784
+ tl.key,
1785
+ `got a transaction_update "${update2.key}"`
1786
+ );
1787
+ }
1788
+ );
1789
+ }
1790
+ } else if (currentSelectorKey && currentSelectorTime) {
1791
+ let latestUpdate = tl.history.at(-1);
1792
+ if (currentSelectorTime !== tl.selectorTime) {
1793
+ latestUpdate = {
1794
+ type: `selector_update`,
1795
+ timestamp: currentSelectorTime,
1796
+ key: currentSelectorKey,
1797
+ atomUpdates: []
1798
+ };
1799
+ latestUpdate.atomUpdates.push(__spreadValues({
1800
+ key: atom.key,
1801
+ type: `atom_update`
1802
+ }, update));
1803
+ if (tl.at !== tl.history.length) {
1804
+ tl.history.splice(tl.at);
1805
+ }
1806
+ tl.history.push(latestUpdate);
1807
+ store.logger.info(
1808
+ `\u231B`,
1809
+ `timeline`,
1810
+ tl.key,
1811
+ `got a selector_update "${currentSelectorKey}" with`,
1812
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1813
+ );
1814
+ tl.at = tl.history.length;
1815
+ tl.selectorTime = currentSelectorTime;
1816
+ } else {
1817
+ if ((latestUpdate == null ? void 0 : latestUpdate.type) === `selector_update`) {
1818
+ latestUpdate.atomUpdates.push(__spreadValues({
1819
+ key: atom.key,
1820
+ type: `atom_update`
1821
+ }, update));
1822
+ store.logger.info(
1823
+ `\u231B`,
1824
+ `timeline`,
1825
+ tl.key,
1826
+ `set selector_update "${currentSelectorKey}" to`,
1827
+ latestUpdate == null ? void 0 : latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
1828
+ );
1829
+ }
1830
+ }
1831
+ if (latestUpdate) {
1832
+ const willCaptureSelectorUpdate = (_d = (_c = tl.shouldCapture) == null ? void 0 : _c.call(tl, latestUpdate, tl)) != null ? _d : true;
1833
+ if (willCaptureSelectorUpdate) {
1834
+ tl.subject.next(latestUpdate);
1835
+ } else {
1836
+ tl.history.pop();
1837
+ tl.at = tl.history.length;
1838
+ }
1839
+ }
1840
+ } else {
1841
+ const timestamp = Date.now();
1842
+ tl.selectorTime = null;
1843
+ if (tl.at !== tl.history.length) {
1844
+ tl.history.splice(tl.at);
1845
+ }
1846
+ const atomUpdate = {
1847
+ type: `atom_update`,
1848
+ timestamp,
1849
+ key: atom.key,
1850
+ oldValue: update.oldValue,
1851
+ newValue: update.newValue
1852
+ };
1853
+ if (atom.family) {
1854
+ atomUpdate.family = atom.family;
1855
+ }
1856
+ const willCapture = (_f = (_e = tl.shouldCapture) == null ? void 0 : _e.call(tl, atomUpdate, tl)) != null ? _f : true;
1857
+ store.logger.info(
1858
+ `\u231B`,
1859
+ `timeline`,
1860
+ tl.key,
1861
+ `got an atom_update to "${atom.key}"`
1862
+ );
1863
+ if (willCapture) {
1864
+ tl.history.push(atomUpdate);
1865
+ tl.at = tl.history.length;
1866
+ tl.subject.next(atomUpdate);
1867
+ }
1788
1868
  }
1789
- return createSelector(
1790
- {
1791
- key: fullKey,
1792
- get: options.get(key)
1793
- },
1794
- family,
1795
- store
1796
- );
1797
- },
1798
- {
1799
- key: options.key,
1800
- type: `readonly_selector_family`,
1801
- subject
1802
1869
  }
1803
- );
1804
- }
1805
- function createSelectorFamily(options, store) {
1806
- const isReadonly = !(`set` in options);
1807
- if (isReadonly) {
1808
- return createReadonlySelectorFamily(options, store);
1870
+ });
1871
+ };
1872
+
1873
+ // src/timeline/create-timeline.ts
1874
+ function createTimeline(options, store, data) {
1875
+ var _a, _b;
1876
+ const tl = __spreadProps(__spreadValues({
1877
+ type: `timeline`,
1878
+ key: options.key,
1879
+ at: 0,
1880
+ timeTraveling: null,
1881
+ selectorTime: null,
1882
+ transactionKey: null
1883
+ }, data), {
1884
+ history: (_a = data == null ? void 0 : data.history.map((update) => __spreadValues({}, update))) != null ? _a : [],
1885
+ install: (store2) => createTimeline(options, store2, tl),
1886
+ subject: new Subject()
1887
+ });
1888
+ if (options.shouldCapture) {
1889
+ tl.shouldCapture = options.shouldCapture;
1809
1890
  }
1810
- const core = target(store);
1811
- const subject = new Subject();
1812
- const selectorFamily = Object.assign(
1813
- (key) => {
1814
- const subKey = stringifyJson(key);
1815
- const family = { key: options.key, subKey };
1816
- const fullKey = `${options.key}(${subKey})`;
1817
- const existing = core.selectors.get(fullKey);
1818
- if (existing) {
1819
- return deposit(existing);
1820
- }
1821
- const token = createSelector(
1822
- {
1823
- key: fullKey,
1824
- get: options.get(key),
1825
- set: options.set(key)
1826
- },
1827
- family,
1828
- store
1891
+ const target = newest(store);
1892
+ for (const tokenOrFamily of options.atoms) {
1893
+ const timelineKey = target.timelineAtoms.getRelatedKey(tokenOrFamily.key);
1894
+ if (timelineKey) {
1895
+ store.logger.error(
1896
+ `\u274C`,
1897
+ `timeline`,
1898
+ options.key,
1899
+ `Failed to add atom "${tokenOrFamily.key}" because it already belongs to timeline "${timelineKey}"`
1829
1900
  );
1830
- subject.next(token);
1831
- return token;
1832
- },
1833
- {
1834
- key: options.key,
1835
- type: `selector_family`
1901
+ continue;
1836
1902
  }
1837
- );
1838
- core.families.set(options.key, selectorFamily);
1839
- return selectorFamily;
1840
- }
1841
-
1842
- // src/mutable/tracker-family.ts
1843
- var FamilyTracker = class {
1844
- constructor(findMutableState, store) {
1845
- this.findLatestUpdateState = createAtomFamily(
1846
- {
1847
- key: `*${findMutableState.key}`,
1848
- default: null
1849
- },
1850
- store
1851
- );
1852
- this.findMutableState = findMutableState;
1853
- this.findMutableState.subject.subscribe(
1854
- `store=${store.config.name}::tracker-atom-family`,
1855
- (atomToken) => {
1856
- if (atomToken.family) {
1857
- const key = parseJson(atomToken.family.subKey);
1858
- this.findLatestUpdateState(key);
1859
- new Tracker(atomToken, store);
1903
+ if (tokenOrFamily.type === `atom_family`) {
1904
+ const family = tokenOrFamily;
1905
+ family.subject.subscribe(`timeline:${options.key}`, (token2) => {
1906
+ addAtomToTimeline(token2, tl, store);
1907
+ });
1908
+ for (const atom of target.atoms.values()) {
1909
+ if (((_b = atom.family) == null ? void 0 : _b.key) === family.key) {
1910
+ addAtomToTimeline(atom, tl, store);
1860
1911
  }
1861
1912
  }
1862
- );
1863
- this.findLatestUpdateState.subject.subscribe(
1864
- `store=${store.config.name}::tracker-atom-family`,
1865
- (atomToken) => {
1866
- if (atomToken.family) {
1867
- const key = parseJson(atomToken.family.subKey);
1868
- const mutableAtomToken = this.findMutableState(key);
1869
- new Tracker(mutableAtomToken, store);
1913
+ } else {
1914
+ const token2 = tokenOrFamily;
1915
+ if (`family` in token2 && token2.family) {
1916
+ const familyTimelineKey = target.timelineAtoms.getRelatedKey(
1917
+ token2.family.key
1918
+ );
1919
+ if (familyTimelineKey) {
1920
+ store.logger.error(
1921
+ `\u274C`,
1922
+ `timeline`,
1923
+ options.key,
1924
+ `Failed to add atom "${token2.key}" because its family "${token2.family.key}" already belongs to timeline "${familyTimelineKey}"`
1925
+ );
1926
+ continue;
1870
1927
  }
1871
1928
  }
1872
- );
1873
- }
1874
- };
1875
-
1876
- // src/mutable/create-mutable-atom-family.ts
1877
- function createMutableAtomFamily(options, store) {
1878
- const coreFamily = Object.assign(
1879
- createAtomFamily(options, store),
1880
- options
1881
- );
1882
- selectJsonFamily(coreFamily, options);
1883
- new FamilyTracker(coreFamily, store);
1884
- return coreFamily;
1885
- }
1886
-
1887
- // src/mutable/get-json-family.ts
1888
- var getJsonFamily = (mutableAtomFamily, store) => {
1889
- const core = target(store);
1890
- const key = `${mutableAtomFamily.key}:JSON`;
1891
- const jsonFamily = core.families.get(
1892
- key
1893
- );
1894
- return jsonFamily;
1895
- };
1896
-
1897
- // src/mutable/get-json-token.ts
1898
- var getJsonToken = (mutableAtomToken) => {
1899
- const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1900
- const jsonToken = { type: `selector`, key };
1901
- if (mutableAtomToken.family) {
1902
- jsonToken.family = {
1903
- key: `${mutableAtomToken.family.key}:JSON`,
1904
- subKey: mutableAtomToken.family.subKey
1905
- };
1906
- }
1907
- return jsonToken;
1908
- };
1909
-
1910
- // src/mutable/get-update-token.ts
1911
- var getUpdateToken = (mutableAtomToken) => {
1912
- const key = `*${mutableAtomToken.key}`;
1913
- const updateToken = { type: `atom`, key };
1914
- if (mutableAtomToken.family) {
1915
- updateToken.family = {
1916
- key: `*${mutableAtomToken.family.key}`,
1917
- subKey: mutableAtomToken.family.subKey
1918
- };
1929
+ addAtomToTimeline(token2, tl, store);
1930
+ }
1931
+ target.timelineAtoms = target.timelineAtoms.set({
1932
+ atomKey: tokenOrFamily.key,
1933
+ timelineKey: options.key
1934
+ });
1919
1935
  }
1920
- return updateToken;
1921
- };
1922
-
1923
- // src/mutable/is-atom-token-mutable.ts
1924
- function isAtomTokenMutable(token) {
1925
- return token.key.endsWith(`::mutable`);
1926
- }
1927
-
1928
- // src/mutable/transceiver.ts
1929
- function isTransceiver(value) {
1930
- return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
1936
+ store.timelines.set(options.key, tl);
1937
+ const token = {
1938
+ key: options.key,
1939
+ type: `timeline`
1940
+ };
1941
+ store.subject.timelineCreation.next(token);
1942
+ return token;
1931
1943
  }
1932
-
1933
- // src/mutable/index.ts
1934
- var isAtomMutable = (atom) => `isMutable` in atom;
1935
-
1936
- // src/atom/is-default.ts
1937
- var isAtomDefault = (key, store) => {
1938
- const core = target(store);
1939
- return core.atomsThatAreDefault.has(key);
1940
- };
1941
- var markAtomAsDefault = (key, store) => {
1942
- const core = target(store);
1943
- core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
1944
- };
1945
- var markAtomAsNotDefault = (key, store) => {
1946
- const core = target(store);
1947
- core.atomsThatAreDefault = new Set(target(store).atomsThatAreDefault);
1948
- core.atomsThatAreDefault.delete(key);
1949
- };
1950
- var isSelectorDefault = (key, store) => {
1951
- const rootKeys = traceAllSelectorAtoms(key, store);
1952
- return rootKeys.every((rootKey) => isAtomDefault(rootKey, store));
1953
- };
1954
-
1955
- // src/atom/create-atom.ts
1956
- function createAtom(options, family, store) {
1944
+ var timeTravel = (direction, token, store) => {
1945
+ const action = direction === `forward` ? `redo` : `undo`;
1957
1946
  store.logger.info(
1958
- `\u{1F528}`,
1959
- `atom`,
1960
- options.key,
1961
- `creating in store "${store.config.name}"`
1947
+ direction === `forward` ? `\u23E9` : `\u23EA`,
1948
+ `timeline`,
1949
+ token.key,
1950
+ action
1962
1951
  );
1963
- const core = target(store);
1964
- const existing = core.atoms.get(options.key);
1965
- if (existing) {
1952
+ const timelineData = store.timelines.get(token.key);
1953
+ if (!timelineData) {
1966
1954
  store.logger.error(
1967
- `\u274C`,
1968
- `atom`,
1969
- options.key,
1970
- `Tried to create atom, but it already exists in the store.`,
1971
- `(Ignore if you are in development using hot module replacement.)`
1955
+ `\u{1F41E}`,
1956
+ `timeline`,
1957
+ token.key,
1958
+ `Failed to ${action}. This timeline has not been initialized.`
1972
1959
  );
1973
- return deposit(existing);
1960
+ return;
1974
1961
  }
1975
- const subject = new Subject();
1976
- const newAtom = __spreadValues(__spreadProps(__spreadValues({}, options), {
1977
- type: `atom`,
1978
- install: (store2) => {
1979
- store2.logger.info(
1980
- `\u{1F6E0}\uFE0F`,
1981
- `atom`,
1982
- options.key,
1983
- `installing in store "${store2.config.name}"`
1984
- );
1985
- return `mutable` in options ? createMutableAtom(options, store2) : createAtom(options, void 0, store2);
1986
- },
1987
- subject
1988
- }), family && { family });
1989
- let initialValue = options.default;
1990
- if (options.default instanceof Function) {
1991
- initialValue = options.default();
1962
+ if (direction === `forward` && timelineData.at === timelineData.history.length || direction === `backward` && timelineData.at === 0) {
1963
+ store.logger.warn(
1964
+ `\u{1F481}`,
1965
+ `timeline`,
1966
+ token.key,
1967
+ `Failed to ${action} at the ${direction === `forward` ? `end` : `beginning`} of timeline "${token.key}". There is nothing to ${action}.`
1968
+ );
1969
+ return;
1992
1970
  }
1993
- core.atoms.set(newAtom.key, newAtom);
1994
- markAtomAsDefault(options.key, store);
1995
- cacheValue(options.key, initialValue, subject, store);
1996
- const token = deposit(newAtom);
1997
- if (options.effects) {
1998
- let effectIndex = 0;
1999
- const cleanupFunctions = [];
2000
- for (const effect of options.effects) {
2001
- const cleanup = effect({
2002
- setSelf: (next) => setState(token, next, store),
2003
- onSet: (handle) => subscribe(token, handle, `effect[${effectIndex}]`, store)
2004
- });
2005
- if (cleanup) {
2006
- cleanupFunctions.push(cleanup);
1971
+ timelineData.timeTraveling = direction === `forward` ? `into_future` : `into_past`;
1972
+ if (direction === `backward`) {
1973
+ --timelineData.at;
1974
+ }
1975
+ const update = timelineData.history[timelineData.at];
1976
+ const updateValues = (atomUpdate) => {
1977
+ const { key, newValue, oldValue } = atomUpdate;
1978
+ const value = direction === `forward` ? newValue : oldValue;
1979
+ setState({ key, type: `atom` }, value, store);
1980
+ };
1981
+ const updateValuesFromTransactionUpdate = (transactionUpdate) => {
1982
+ const updates = direction === `forward` ? transactionUpdate.updates : [...transactionUpdate.updates].reverse();
1983
+ for (const updateFromTransaction of updates) {
1984
+ if (`newValue` in updateFromTransaction) {
1985
+ updateValues(updateFromTransaction);
1986
+ } else {
1987
+ updateValuesFromTransactionUpdate(updateFromTransaction);
2007
1988
  }
2008
- ++effectIndex;
2009
1989
  }
2010
- newAtom.cleanup = () => {
2011
- for (const cleanup of cleanupFunctions) {
2012
- cleanup();
1990
+ };
1991
+ switch (update.type) {
1992
+ case `atom_update`: {
1993
+ updateValues(update);
1994
+ break;
1995
+ }
1996
+ case `selector_update`: {
1997
+ const updates = direction === `forward` ? update.atomUpdates : [...update.atomUpdates].reverse();
1998
+ for (const atomUpdate of updates) {
1999
+ updateValues(atomUpdate);
2013
2000
  }
2014
- };
2001
+ break;
2002
+ }
2003
+ case `transaction_update`: {
2004
+ updateValuesFromTransactionUpdate(update);
2005
+ break;
2006
+ }
2015
2007
  }
2016
- store.subject.atomCreation.next(token);
2017
- return token;
2018
- }
2008
+ if (direction === `forward`) {
2009
+ ++timelineData.at;
2010
+ }
2011
+ timelineData.subject.next(action);
2012
+ timelineData.timeTraveling = null;
2013
+ store.logger.info(
2014
+ `\u23F9\uFE0F`,
2015
+ `timeline`,
2016
+ token.key,
2017
+ `"${token.key}" is now at ${timelineData.at} / ${timelineData.history.length}`
2018
+ );
2019
+ };
2019
2020
 
2020
- // src/atom/delete-atom.ts
2021
- function deleteAtom(atomToken, store) {
2022
- var _a, _b;
2023
- const core = target(store);
2024
- const { key } = atomToken;
2025
- const atom = core.atoms.get(key);
2026
- if (!atom) {
2027
- store.logger.error(
2028
- `\u274C`,
2029
- `atom`,
2030
- `${key}`,
2031
- `Tried to delete atom, but it does not exist in the store.`
2021
+ // src/transaction/abort-transaction.ts
2022
+ var abortTransaction = (store) => {
2023
+ const target = newest(store);
2024
+ if (target.transactionMeta === null || target.parent === null) {
2025
+ store.logger.warn(
2026
+ `\u{1F41E}`,
2027
+ `transaction`,
2028
+ `???`,
2029
+ `abortTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2032
2030
  );
2031
+ return;
2033
2032
  }
2034
- (_a = atom == null ? void 0 : atom.cleanup) == null ? void 0 : _a.call(atom);
2035
- core.atoms.delete(key);
2036
- core.valueMap.delete(key);
2037
- const selectorKeys = core.selectorAtoms.getRelatedKeys(key);
2038
- if (selectorKeys) {
2039
- for (const selectorKey of selectorKeys) {
2040
- const token = (_b = core.selectors.get(selectorKey)) != null ? _b : core.readonlySelectors.get(selectorKey);
2041
- if (token) {
2042
- deleteSelector(token, store);
2033
+ store.logger.info(
2034
+ `\u{1FA82}`,
2035
+ `transaction`,
2036
+ target.transactionMeta.update.key,
2037
+ `Aborting transaction`
2038
+ );
2039
+ target.parent.child = null;
2040
+ };
2041
+ function ingestAtomUpdate(update, parent, child) {
2042
+ var _a, _b, _c;
2043
+ const { key, newValue } = update;
2044
+ const token = { key, type: `atom` };
2045
+ if (!parent.valueMap.has(token.key)) {
2046
+ if (token.family) {
2047
+ const family = parent.families.get(token.family.key);
2048
+ if (family) {
2049
+ family(token.family.subKey);
2050
+ }
2051
+ } else {
2052
+ const newAtom = child.atoms.get(token.key);
2053
+ if (!newAtom) {
2054
+ throw new Error(
2055
+ `Absurd Error: Atom "${token.key}" not found while copying updates from transaction "${(_a = child.transactionMeta) == null ? void 0 : _a.update.key}" to store "${parent.config.name}"`
2056
+ );
2043
2057
  }
2058
+ parent.atoms.set(newAtom.key, newAtom);
2059
+ parent.valueMap.set(newAtom.key, newAtom.default);
2060
+ parent.logger.info(
2061
+ `\u{1F528}`,
2062
+ `transaction`,
2063
+ (_c = (_b = child.transactionMeta) == null ? void 0 : _b.update.key) != null ? _c : `???`,
2064
+ `Adding atom "${newAtom.key}"`
2065
+ );
2044
2066
  }
2045
2067
  }
2046
- core.selectorAtoms.delete(key);
2047
- core.atomsThatAreDefault.delete(key);
2048
- core.timelineAtoms.delete(key);
2049
- store.logger.info(`\u{1F525}`, `atom`, `${key}`, `deleted`);
2068
+ setState(token, newValue, parent);
2050
2069
  }
2051
-
2052
- // src/not-found-error.ts
2053
- var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
2054
- function prettyPrintTokenType(token) {
2055
- if (token.type === `readonly_selector`) {
2056
- return `Readonly Selector`;
2070
+ function ingestTransactionUpdate(transactionUpdate, parent, child) {
2071
+ for (const update of transactionUpdate.updates) {
2072
+ if (`newValue` in update) {
2073
+ ingestAtomUpdate(update, parent, child);
2074
+ } else {
2075
+ ingestTransactionUpdate(update, parent, child);
2076
+ }
2057
2077
  }
2058
- return capitalize(token.type);
2059
2078
  }
2060
- var NotFoundError = class extends Error {
2061
- constructor(token, store) {
2062
- super(
2063
- `${prettyPrintTokenType(token)} "${token.key}" not found in store "${store.config.name}".`
2064
- );
2065
- }
2066
- };
2067
-
2068
- // src/subscribe/recall-state.ts
2069
- var recallState = (state, store) => {
2070
- const core = target(store);
2071
- if (!core.operation.open) {
2079
+ var applyTransaction = (output, store) => {
2080
+ var _a;
2081
+ const child = newest(store);
2082
+ const { parent } = child;
2083
+ if (parent === null || child.transactionMeta === null || ((_a = child.transactionMeta) == null ? void 0 : _a.phase) !== `building`) {
2072
2084
  store.logger.warn(
2073
2085
  `\u{1F41E}`,
2074
- state.type,
2075
- state.key,
2076
- `recall called outside of an operation. This is probably a bug.`
2086
+ `transaction`,
2087
+ `???`,
2088
+ `applyTransaction called outside of a transaction. This is probably a bug in AtomIO.`
2089
+ );
2090
+ return;
2091
+ }
2092
+ child.transactionMeta.phase = `applying`;
2093
+ child.transactionMeta.update.output = output;
2094
+ parent.child = null;
2095
+ parent.subject.transactionApplying.next(child.transactionMeta);
2096
+ const { updates } = child.transactionMeta.update;
2097
+ store.logger.info(
2098
+ `\u{1F6C4}`,
2099
+ `transaction`,
2100
+ child.transactionMeta.update.key,
2101
+ `Applying transaction with ${updates.length} updates:`,
2102
+ updates
2103
+ );
2104
+ if (parent.transactionMeta === null) {
2105
+ ingestTransactionUpdate(child.transactionMeta.update, parent, child);
2106
+ const myTransaction = withdraw(
2107
+ { key: child.transactionMeta.update.key, type: `transaction` },
2108
+ store
2109
+ );
2110
+ myTransaction == null ? void 0 : myTransaction.subject.next(child.transactionMeta.update);
2111
+ store.logger.info(
2112
+ `\u{1F6EC}`,
2113
+ `transaction`,
2114
+ child.transactionMeta.update.key,
2115
+ `Finished applying transaction.`
2077
2116
  );
2078
- return core.valueMap.get(state.key);
2117
+ } else {
2118
+ ingestTransactionUpdate(child.transactionMeta.update, parent, child);
2119
+ parent.transactionMeta.update.updates.push(child.transactionMeta.update);
2079
2120
  }
2080
- return core.operation.prev.get(state.key);
2121
+ parent.subject.transactionApplying.next(null);
2081
2122
  };
2082
2123
 
2083
- // src/subscribe/subscribe-to-root-atoms.ts
2084
- var subscribeToRootAtoms = (state, store) => {
2085
- const dependencySubscriptions = `default` in state ? null : traceAllSelectorAtoms(state.key, store).map((atomKey) => {
2086
- const atom = store.atoms.get(atomKey);
2087
- if (atom === void 0) {
2088
- throw new Error(
2089
- `Atom "${atomKey}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`
2090
- );
2091
- }
2092
- return atom.subject.subscribe(
2093
- `${state.type}:${state.key}`,
2094
- (atomChange) => {
2095
- store.logger.info(
2096
- `\u{1F4E2}`,
2097
- state.type,
2098
- state.key,
2099
- `root`,
2100
- atomKey,
2101
- `went`,
2102
- atomChange.oldValue,
2103
- `->`,
2104
- atomChange.newValue
2124
+ // src/transaction/build-transaction.ts
2125
+ var buildTransaction = (key, params, store) => {
2126
+ const parent = newest(store);
2127
+ parent.child = {
2128
+ parent,
2129
+ child: null,
2130
+ subject: parent.subject,
2131
+ loggers: parent.loggers,
2132
+ logger: parent.logger,
2133
+ config: parent.config,
2134
+ transactionMeta: {
2135
+ phase: `building`,
2136
+ time: Date.now(),
2137
+ update: {
2138
+ key,
2139
+ updates: [],
2140
+ params,
2141
+ output: void 0
2142
+ }
2143
+ },
2144
+ atoms: new LazyMap(parent.atoms),
2145
+ atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2146
+ families: new LazyMap(parent.families),
2147
+ operation: { open: false },
2148
+ readonlySelectors: new LazyMap(parent.readonlySelectors),
2149
+ timelines: new LazyMap(parent.timelines),
2150
+ timelineAtoms: new Junction(parent.timelineAtoms.toJSON()),
2151
+ trackers: /* @__PURE__ */ new Map(),
2152
+ transactions: new LazyMap(parent.transactions),
2153
+ selectorAtoms: new Junction(parent.selectorAtoms.toJSON()),
2154
+ selectorGraph: new Junction(parent.selectorGraph.toJSON(), {
2155
+ makeContentKey: (...keys) => keys.sort().join(`:`)
2156
+ }),
2157
+ selectors: new LazyMap(parent.selectors),
2158
+ valueMap: new LazyMap(parent.valueMap)
2159
+ };
2160
+ store.logger.info(
2161
+ `\u{1F6EB}`,
2162
+ `transaction`,
2163
+ key,
2164
+ `Building transaction with params:`,
2165
+ params
2166
+ );
2167
+ };
2168
+ function createTransaction(options, store) {
2169
+ const newTransaction = {
2170
+ key: options.key,
2171
+ type: `transaction`,
2172
+ run: (...params) => {
2173
+ buildTransaction(options.key, params, store);
2174
+ try {
2175
+ const output = options.do(
2176
+ {
2177
+ get: (token2) => getState(token2, store),
2178
+ set: (token2, value) => setState(token2, value, store),
2179
+ run: (token2) => runTransaction(token2, store)
2180
+ },
2181
+ ...params
2105
2182
  );
2106
- const oldValue = recallState(state, store);
2107
- const newValue = readOrComputeValue(state, store);
2108
- store.logger.info(
2109
- `\u2728`,
2110
- state.type,
2111
- state.key,
2112
- `went`,
2113
- oldValue,
2114
- `->`,
2115
- newValue
2183
+ applyTransaction(output, store);
2184
+ return output;
2185
+ } catch (thrown) {
2186
+ abortTransaction(store);
2187
+ store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
2188
+ throw thrown;
2189
+ }
2190
+ },
2191
+ install: (store2) => createTransaction(options, store2),
2192
+ subject: new Subject()
2193
+ };
2194
+ const target = newest(store);
2195
+ target.transactions.set(newTransaction.key, newTransaction);
2196
+ const token = deposit(newTransaction);
2197
+ store.subject.transactionCreation.next(token);
2198
+ return token;
2199
+ }
2200
+ var redoTransactionUpdate = (transactionUpdate, store) => {
2201
+ store.logger.info(`\u23ED\uFE0F`, `transaction`, transactionUpdate.key, `Redo`);
2202
+ for (const update of transactionUpdate.updates) {
2203
+ if (`newValue` in update) {
2204
+ const { key, newValue } = update;
2205
+ const token = { key, type: `atom` };
2206
+ const state = withdraw(token, store);
2207
+ if (state === void 0) {
2208
+ throw new Error(
2209
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
2116
2210
  );
2117
- state.subject.next({ newValue, oldValue });
2118
2211
  }
2119
- );
2120
- });
2121
- return dependencySubscriptions;
2212
+ setState(state, newValue, store);
2213
+ } else {
2214
+ redoTransactionUpdate(update, store);
2215
+ }
2216
+ }
2217
+ };
2218
+ var undoTransactionUpdate = (transactionUpdate, store) => {
2219
+ store.logger.info(`\u23EE\uFE0F`, `transaction`, transactionUpdate.key, `Undo`);
2220
+ for (const update of transactionUpdate.updates.reverse()) {
2221
+ if (`newValue` in update) {
2222
+ const { key, newValue } = update;
2223
+ const token = { key, type: `atom` };
2224
+ const state = withdraw(token, store);
2225
+ if (state === void 0) {
2226
+ throw new Error(
2227
+ `State "${token.key}" not found in this store. This is surprising, because we are navigating the history of the store.`
2228
+ );
2229
+ }
2230
+ setState(state, newValue, store);
2231
+ } else {
2232
+ undoTransactionUpdate(update, store);
2233
+ }
2234
+ }
2122
2235
  };
2123
2236
 
2124
- export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, addAtomToTimeline, applyTransaction, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtom, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelectorFamily, createSelector, createSelectorFamily, createTimeline, createTransaction, deleteAtom, deleteSelector, deposit, evictCachedValue, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, isAtomDefault, isAtomKey, isAtomMutable, isAtomTokenMutable, isDone, isReadonlySelectorKey, isSelectorDefault, isSelectorKey, isStateKey, isTransceiver, isValueCached, markAtomAsDefault, markAtomAsNotDefault, markDone, openOperation, readCachedValue, readOrComputeValue, redoTransactionUpdate, registerSelector, setAtomOrSelector, subscribeToRootAtoms, target, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, undoTransactionUpdate, updateSelectorAtoms, withdraw, withdrawNewFamilyMember };
2237
+ // src/transaction/index.ts
2238
+ var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2239
+
2240
+ export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, addAtomToTimeline, applyTransaction, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtom, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelectorFamily, createSelector, createSelectorFamily, createTimeline, createTransaction, deleteAtom, deleteSelector, deposit, eldest, evictCachedValue, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, isAtomDefault, isAtomKey, isAtomMutable, isAtomTokenMutable, isDone, isReadonlySelectorKey, isSelectorDefault, isSelectorKey, isStateKey, isTransceiver, isValueCached, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, readCachedValue, readOrComputeValue, redoTransactionUpdate, registerSelector, setAtomOrSelector, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, undoTransactionUpdate, updateSelectorAtoms, withdraw, withdrawNewFamilyMember };
2125
2241
  //# sourceMappingURL=out.js.map
2126
2242
  //# sourceMappingURL=index.js.map