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