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