atom.io 0.12.1 → 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 +1561 -1512
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.cts +24 -14
- package/internal/dist/index.d.ts +24 -14
- package/internal/dist/index.js +1560 -1513
- 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 +1 -0
- package/internal/src/keys.ts +4 -4
- package/internal/src/lazy-map.ts +6 -2
- 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 +33 -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,1686 +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
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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}"`
|
|
719
750
|
);
|
|
720
|
-
return;
|
|
721
751
|
}
|
|
722
|
-
|
|
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) {
|
|
723
758
|
store.logger.warn(
|
|
724
|
-
`\u{
|
|
725
|
-
`
|
|
726
|
-
|
|
727
|
-
`
|
|
759
|
+
`\u{1F41E}`,
|
|
760
|
+
`unknown`,
|
|
761
|
+
key,
|
|
762
|
+
`isDone called outside of an operation. This is probably a bug.`
|
|
728
763
|
);
|
|
729
|
-
return;
|
|
764
|
+
return true;
|
|
730
765
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
766
|
+
return target.operation.done.has(key);
|
|
767
|
+
};
|
|
768
|
+
var markDone = (key, store) => {
|
|
769
|
+
const target = newest(store);
|
|
770
|
+
if (!target.operation.open) {
|
|
771
|
+
store.logger.warn(
|
|
772
|
+
`\u{1F41E}`,
|
|
773
|
+
`unknown`,
|
|
774
|
+
key,
|
|
775
|
+
`markDone called outside of an operation. This is probably a bug.`
|
|
776
|
+
);
|
|
777
|
+
return;
|
|
734
778
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
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);
|
|
792
|
+
}
|
|
793
|
+
if (state.type !== `atom`) {
|
|
794
|
+
store.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
|
|
795
|
+
return state.get();
|
|
796
|
+
}
|
|
797
|
+
const fallback = state.default instanceof Function ? state.default() : state.default;
|
|
798
|
+
store.logger.info(
|
|
799
|
+
`\u{1F481}`,
|
|
800
|
+
`atom`,
|
|
801
|
+
state.key,
|
|
802
|
+
`could not find cached value; using default`,
|
|
803
|
+
fallback
|
|
804
|
+
);
|
|
805
|
+
return state.default instanceof Function ? state.default() : state.default;
|
|
806
|
+
};
|
|
807
|
+
|
|
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;
|
|
819
|
+
}
|
|
820
|
+
return targetValue;
|
|
821
|
+
}
|
|
822
|
+
|
|
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;
|
|
745
831
|
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
|
840
|
+
);
|
|
841
|
+
if (result) {
|
|
842
|
+
return result;
|
|
843
|
+
}
|
|
751
844
|
}
|
|
752
|
-
break;
|
|
753
845
|
}
|
|
754
846
|
}
|
|
755
|
-
|
|
756
|
-
|
|
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;
|
|
757
853
|
}
|
|
758
|
-
|
|
759
|
-
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/set-state/emit-update.ts
|
|
858
|
+
var emitUpdate = (state, update, store) => {
|
|
760
859
|
store.logger.info(
|
|
761
|
-
`\
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
`
|
|
860
|
+
`\u{1F4E2}`,
|
|
861
|
+
state.type,
|
|
862
|
+
state.key,
|
|
863
|
+
`went (`,
|
|
864
|
+
update.oldValue,
|
|
865
|
+
`->`,
|
|
866
|
+
update.newValue,
|
|
867
|
+
`) subscribers:`,
|
|
868
|
+
state.subject.subscribers
|
|
765
869
|
);
|
|
870
|
+
state.subject.next(update);
|
|
766
871
|
};
|
|
767
872
|
|
|
768
|
-
// src/
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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);
|
|
877
|
+
store.logger.info(
|
|
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`
|
|
883
|
+
);
|
|
884
|
+
if (downstreamKeys) {
|
|
885
|
+
if (target.operation.open) {
|
|
780
886
|
store.logger.info(
|
|
781
|
-
`\u{
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
`
|
|
887
|
+
`\u{1F9F9}`,
|
|
888
|
+
atom.type,
|
|
889
|
+
atom.key,
|
|
890
|
+
`[ ${[...target.operation.done].join(`, `)} ] already done`
|
|
785
891
|
);
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
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;
|
|
892
|
+
}
|
|
893
|
+
for (const key of downstreamKeys) {
|
|
894
|
+
if (isDone(key, store)) {
|
|
895
|
+
continue;
|
|
814
896
|
}
|
|
815
|
-
|
|
897
|
+
evictCachedValue(key, store);
|
|
898
|
+
markDone(key, store);
|
|
816
899
|
}
|
|
817
900
|
}
|
|
818
|
-
|
|
819
|
-
}
|
|
901
|
+
};
|
|
820
902
|
|
|
821
|
-
// src/
|
|
822
|
-
function
|
|
823
|
-
if (
|
|
824
|
-
|
|
825
|
-
`\u{1F46A}`,
|
|
826
|
-
token.type,
|
|
827
|
-
token.key,
|
|
828
|
-
`creating new family member in store "${store.config.name}"`
|
|
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;
|
|
837
|
-
}
|
|
903
|
+
// src/set-state/stow-update.ts
|
|
904
|
+
function shouldUpdateBeStowed(key, update) {
|
|
905
|
+
if (isTransceiver(update.newValue)) {
|
|
906
|
+
return false;
|
|
838
907
|
}
|
|
839
|
-
|
|
908
|
+
if (key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
|
|
909
|
+
return false;
|
|
910
|
+
}
|
|
911
|
+
return true;
|
|
840
912
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
if (
|
|
845
|
-
store.logger.
|
|
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(
|
|
846
918
|
`\u{1F41E}`,
|
|
847
|
-
`
|
|
848
|
-
|
|
849
|
-
`
|
|
919
|
+
`atom`,
|
|
920
|
+
key,
|
|
921
|
+
`stowUpdate called outside of a transaction. This is probably a bug.`
|
|
850
922
|
);
|
|
851
923
|
return;
|
|
852
924
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
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}"`
|
|
885
|
-
);
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
atom_io.setState(token, newValue, store);
|
|
925
|
+
const shouldStow = shouldUpdateBeStowed(key, update);
|
|
926
|
+
if (!shouldStow) {
|
|
927
|
+
return;
|
|
889
928
|
}
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
);
|
|
894
|
-
if (myTransaction === void 0) {
|
|
895
|
-
throw new Error(
|
|
896
|
-
`Transaction "${store.transactionStatus.key}" not found. Absurd. How is this running?`
|
|
897
|
-
);
|
|
929
|
+
const atomUpdate = __spreadValues({ key }, update);
|
|
930
|
+
if (state.family) {
|
|
931
|
+
atomUpdate.family = state.family;
|
|
898
932
|
}
|
|
899
|
-
|
|
900
|
-
key: store.transactionStatus.key,
|
|
901
|
-
atomUpdates,
|
|
902
|
-
output,
|
|
903
|
-
params: store.transactionStatus.params
|
|
904
|
-
});
|
|
933
|
+
target.transactionMeta.update.updates.push(atomUpdate);
|
|
905
934
|
store.logger.info(
|
|
906
|
-
`\u{
|
|
907
|
-
`
|
|
908
|
-
|
|
909
|
-
`
|
|
935
|
+
`\u{1F4C1}`,
|
|
936
|
+
`atom`,
|
|
937
|
+
key,
|
|
938
|
+
`stowed (`,
|
|
939
|
+
update.oldValue,
|
|
940
|
+
`->`,
|
|
941
|
+
update.newValue,
|
|
942
|
+
`)`
|
|
910
943
|
);
|
|
911
|
-
store.transactionStatus = { phase: `idle` };
|
|
912
944
|
};
|
|
913
945
|
|
|
914
|
-
// src/
|
|
915
|
-
var
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
return super.get(key);
|
|
925
|
-
}
|
|
926
|
-
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
927
|
-
const value = this.source.get(key);
|
|
928
|
-
super.set(key, value);
|
|
929
|
-
return value;
|
|
930
|
-
}
|
|
931
|
-
return void 0;
|
|
932
|
-
}
|
|
933
|
-
_has(key) {
|
|
934
|
-
return super.has(key);
|
|
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);
|
|
935
956
|
}
|
|
936
|
-
|
|
937
|
-
|
|
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);
|
|
938
964
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
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);
|
|
942
973
|
}
|
|
943
974
|
};
|
|
944
975
|
|
|
945
|
-
// src/
|
|
946
|
-
var
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
operation: { open: false },
|
|
956
|
-
readonlySelectors: new LazyMap(store.readonlySelectors),
|
|
957
|
-
timelines: new LazyMap(store.timelines),
|
|
958
|
-
timelineAtoms: new Junction(store.timelineAtoms.toJSON()),
|
|
959
|
-
trackers: /* @__PURE__ */ new Map(),
|
|
960
|
-
transactions: new LazyMap(store.transactions),
|
|
961
|
-
selectorAtoms: new Junction(store.selectorAtoms.toJSON()),
|
|
962
|
-
selectorGraph: new Junction(store.selectorGraph.toJSON(), {
|
|
963
|
-
makeContentKey: (...keys) => keys.sort().join(`:`)
|
|
964
|
-
}),
|
|
965
|
-
selectors: new LazyMap(store.selectors),
|
|
966
|
-
valueMap: new LazyMap(store.valueMap)
|
|
967
|
-
},
|
|
968
|
-
atomUpdates: [],
|
|
969
|
-
params,
|
|
970
|
-
output: void 0
|
|
971
|
-
};
|
|
972
|
-
store.logger.info(
|
|
973
|
-
`\u{1F6EB}`,
|
|
974
|
-
`transaction`,
|
|
975
|
-
key,
|
|
976
|
-
`Building transaction with params:`,
|
|
977
|
-
params
|
|
978
|
-
);
|
|
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;
|
|
979
986
|
};
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
);
|
|
994
|
-
applyTransaction(output, store);
|
|
995
|
-
return output;
|
|
996
|
-
} catch (thrown) {
|
|
997
|
-
abortTransaction(store);
|
|
998
|
-
store.logger.warn(`\u{1F4A5}`, `transaction`, options.key, `caught:`, thrown);
|
|
999
|
-
throw thrown;
|
|
1000
|
-
}
|
|
1001
|
-
},
|
|
1002
|
-
install: (store2) => createTransaction(options, store2),
|
|
1003
|
-
subject: new Subject()
|
|
1004
|
-
};
|
|
1005
|
-
const core = target(store);
|
|
1006
|
-
core.transactions.set(newTransaction.key, newTransaction);
|
|
1007
|
-
const token = deposit(newTransaction);
|
|
1008
|
-
store.subject.transactionCreation.next(token);
|
|
1009
|
-
return token;
|
|
1010
|
-
}
|
|
1011
|
-
var target = (store) => store.transactionStatus.phase === `building` ? store.transactionStatus.core : store;
|
|
1012
|
-
var redoTransactionUpdate = (update, store) => {
|
|
1013
|
-
store.logger.info(`\u23ED\uFE0F`, `transaction`, update.key, `Redo`);
|
|
1014
|
-
for (const { key, newValue } of update.atomUpdates) {
|
|
1015
|
-
const token = { key, type: `atom` };
|
|
1016
|
-
const state = withdraw(token, store);
|
|
1017
|
-
if (state === void 0) {
|
|
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) {
|
|
1018
1000
|
throw new Error(
|
|
1019
|
-
`
|
|
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)
|
|
1020
1007
|
);
|
|
1008
|
+
} else if (!rootKeys.includes(indirectDependencyKey)) {
|
|
1009
|
+
rootKeys.push(indirectDependencyKey);
|
|
1021
1010
|
}
|
|
1022
|
-
atom_io.setState(state, newValue, store);
|
|
1023
1011
|
}
|
|
1012
|
+
return rootKeys;
|
|
1024
1013
|
};
|
|
1025
|
-
var
|
|
1026
|
-
store
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
update.key,
|
|
1030
|
-
`Undoing transaction update`,
|
|
1031
|
-
update
|
|
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)
|
|
1032
1018
|
);
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1019
|
+
};
|
|
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
|
+
});
|
|
1029
|
+
store.logger.info(
|
|
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(`, `)} ]`
|
|
1042
|
+
);
|
|
1043
|
+
for (const atomKey of rootKeys) {
|
|
1044
|
+
core.selectorAtoms = core.selectorAtoms.set({
|
|
1045
|
+
selectorKey,
|
|
1046
|
+
atomKey
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
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
|
+
`)`
|
|
1071
|
+
);
|
|
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);
|
|
1036
1088
|
if (state === void 0) {
|
|
1037
1089
|
throw new Error(
|
|
1038
|
-
`State "${
|
|
1090
|
+
`State "${stateToken.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
|
|
1039
1091
|
);
|
|
1040
1092
|
}
|
|
1041
|
-
|
|
1093
|
+
setAtomOrSelector(state, newValue, store);
|
|
1094
|
+
}
|
|
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
|
+
`)`
|
|
1119
|
+
);
|
|
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;
|
|
1042
1143
|
}
|
|
1144
|
+
store.subject.selectorCreation.next(token);
|
|
1145
|
+
return token;
|
|
1043
1146
|
};
|
|
1044
1147
|
|
|
1045
|
-
// src/
|
|
1046
|
-
var
|
|
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();
|
|
1166
|
+
store.logger.info(
|
|
1167
|
+
`\u2728`,
|
|
1168
|
+
readonlySelector.type,
|
|
1169
|
+
readonlySelector.key,
|
|
1170
|
+
`=`,
|
|
1171
|
+
initialValue
|
|
1172
|
+
);
|
|
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;
|
|
1182
|
+
};
|
|
1047
1183
|
|
|
1048
|
-
// src/
|
|
1049
|
-
function
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
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
|
+
);
|
|
1053
1196
|
}
|
|
1054
|
-
if (
|
|
1055
|
-
|
|
1056
|
-
target(store).valueMap.set(key, future);
|
|
1057
|
-
future.then((resolved) => {
|
|
1058
|
-
if (future.isCanceled) {
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
cacheValue(key, resolved, subject, store);
|
|
1062
|
-
subject.next({ newValue: resolved, oldValue: future });
|
|
1063
|
-
}).catch((thrown) => {
|
|
1064
|
-
if (thrown !== `canceled`) {
|
|
1065
|
-
store.logger.error(`\u{1F4A5}`, `state`, key, `rejected:`, thrown);
|
|
1066
|
-
}
|
|
1067
|
-
});
|
|
1068
|
-
return future;
|
|
1197
|
+
if (`set` in options) {
|
|
1198
|
+
return createReadWriteSelector(options, family, store);
|
|
1069
1199
|
}
|
|
1070
|
-
|
|
1071
|
-
return value;
|
|
1200
|
+
return createReadonlySelector(options, family, store);
|
|
1072
1201
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
store.logger.info(`\u{1F5D1}`, `state`, key, `evicted`);
|
|
1086
|
-
};
|
|
1087
|
-
var Tracker = class {
|
|
1088
|
-
constructor(mutableState, store) {
|
|
1089
|
-
this.unsubscribeFromInnerValue = null;
|
|
1090
|
-
this.mutableState = mutableState;
|
|
1091
|
-
this.latestUpdateState = this.initializeState(mutableState, store);
|
|
1092
|
-
this.observeCore(mutableState, this.latestUpdateState, store);
|
|
1093
|
-
this.updateCore(mutableState, this.latestUpdateState, store);
|
|
1094
|
-
const core = target(store);
|
|
1095
|
-
core.trackers.set(mutableState.key, this);
|
|
1096
|
-
}
|
|
1097
|
-
initializeState(mutableState, store) {
|
|
1098
|
-
const latestUpdateStateKey = `*${mutableState.key}`;
|
|
1099
|
-
deleteAtom({ type: `atom`, key: latestUpdateStateKey }, store);
|
|
1100
|
-
const familyMetaData = mutableState.family ? {
|
|
1101
|
-
key: `*${mutableState.family.key}`,
|
|
1102
|
-
subKey: mutableState.family.subKey
|
|
1103
|
-
} : void 0;
|
|
1104
|
-
const latestUpdateState = createAtom(
|
|
1105
|
-
{
|
|
1106
|
-
key: latestUpdateStateKey,
|
|
1107
|
-
default: null
|
|
1108
|
-
},
|
|
1109
|
-
familyMetaData,
|
|
1110
|
-
store
|
|
1111
|
-
);
|
|
1112
|
-
return latestUpdateState;
|
|
1113
|
-
}
|
|
1114
|
-
observeCore(mutableState, latestUpdateState, store) {
|
|
1115
|
-
const originalInnerValue = atom_io.getState(mutableState, store);
|
|
1116
|
-
this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
|
|
1117
|
-
`tracker:${store.config.name}:${store.transactionStatus.phase === `idle` ? `main` : store.transactionStatus.key}`,
|
|
1118
|
-
(update) => {
|
|
1119
|
-
const unsubscribe = store.subject.operationStatus.subscribe(
|
|
1120
|
-
mutableState.key,
|
|
1121
|
-
() => {
|
|
1122
|
-
unsubscribe();
|
|
1123
|
-
atom_io.setState(latestUpdateState, update, store);
|
|
1124
|
-
}
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1127
|
-
);
|
|
1128
|
-
atom_io.subscribe(
|
|
1129
|
-
mutableState,
|
|
1130
|
-
(update) => {
|
|
1131
|
-
var _a;
|
|
1132
|
-
if (update.newValue !== update.oldValue) {
|
|
1133
|
-
(_a = this.unsubscribeFromInnerValue) == null ? void 0 : _a.call(this);
|
|
1134
|
-
this.unsubscribeFromInnerValue = update.newValue.subscribe(
|
|
1135
|
-
`tracker:${store.config.name}:${store.transactionStatus.phase === `idle` ? `main` : store.transactionStatus.key}`,
|
|
1136
|
-
(update2) => {
|
|
1137
|
-
const unsubscribe = store.subject.operationStatus.subscribe(
|
|
1138
|
-
mutableState.key,
|
|
1139
|
-
() => {
|
|
1140
|
-
unsubscribe();
|
|
1141
|
-
atom_io.setState(latestUpdateState, update2, store);
|
|
1142
|
-
}
|
|
1143
|
-
);
|
|
1144
|
-
}
|
|
1145
|
-
);
|
|
1146
|
-
}
|
|
1147
|
-
},
|
|
1148
|
-
`${store.config.name}: tracker observing inner value`,
|
|
1149
|
-
store
|
|
1150
|
-
);
|
|
1202
|
+
|
|
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;
|
|
1151
1214
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
(update) => {
|
|
1165
|
-
unsubscribe2();
|
|
1166
|
-
atom_io.setState(
|
|
1167
|
-
mutableState,
|
|
1168
|
-
(transceiver) => {
|
|
1169
|
-
if (update === `redo` && newValue) {
|
|
1170
|
-
transceiver.do(newValue);
|
|
1171
|
-
} else if (update === `undo` && oldValue) {
|
|
1172
|
-
transceiver.undo(oldValue);
|
|
1173
|
-
}
|
|
1174
|
-
return transceiver;
|
|
1175
|
-
},
|
|
1176
|
-
store
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
);
|
|
1180
|
-
return;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
const unsubscribe = store.subject.operationStatus.subscribe(
|
|
1184
|
-
latestUpdateState.key,
|
|
1185
|
-
() => {
|
|
1186
|
-
unsubscribe();
|
|
1187
|
-
const mutable = atom_io.getState(mutableState, store);
|
|
1188
|
-
const updateNumber = mutable.getUpdateNumber(newValue);
|
|
1189
|
-
const eventOffset = updateNumber - mutable.cacheUpdateNumber;
|
|
1190
|
-
if (newValue && eventOffset === 1) {
|
|
1191
|
-
atom_io.setState(
|
|
1192
|
-
mutableState,
|
|
1193
|
-
(transceiver) => (transceiver.do(newValue), transceiver),
|
|
1194
|
-
store
|
|
1195
|
-
);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
);
|
|
1199
|
-
},
|
|
1200
|
-
`${store.config.name}: tracker observing latest update`,
|
|
1201
|
-
store
|
|
1202
|
-
);
|
|
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);
|
|
1221
|
+
}
|
|
1222
|
+
);
|
|
1223
|
+
for (const downstreamToken of downstreamTokens) {
|
|
1224
|
+
if (downstreamToken) {
|
|
1225
|
+
deleteSelector(downstreamToken, store);
|
|
1226
|
+
}
|
|
1203
1227
|
}
|
|
1204
|
-
|
|
1228
|
+
target.selectorGraph.delete(key);
|
|
1229
|
+
store.logger.info(`\u{1F525}`, selectorToken.type, `${key}`, `deleted`);
|
|
1230
|
+
}
|
|
1205
1231
|
|
|
1206
|
-
// src/
|
|
1207
|
-
function
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
jsonState,
|
|
1219
|
-
() => {
|
|
1220
|
-
const trackerHasBeenInitialized = target(store).trackers.has(coreState.key);
|
|
1221
|
-
if (!trackerHasBeenInitialized) {
|
|
1222
|
-
new Tracker(coreState, store);
|
|
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);
|
|
1223
1244
|
}
|
|
1245
|
+
return createSelector(
|
|
1246
|
+
{
|
|
1247
|
+
key: fullKey,
|
|
1248
|
+
get: options.get(key)
|
|
1249
|
+
},
|
|
1250
|
+
family,
|
|
1251
|
+
store
|
|
1252
|
+
);
|
|
1224
1253
|
},
|
|
1225
|
-
|
|
1254
|
+
{
|
|
1255
|
+
key: options.key,
|
|
1256
|
+
type: `readonly_selector_family`,
|
|
1257
|
+
subject
|
|
1258
|
+
}
|
|
1226
1259
|
);
|
|
1227
|
-
return coreState;
|
|
1228
1260
|
}
|
|
1229
|
-
function
|
|
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);
|
|
1230
1267
|
const subject = new Subject();
|
|
1231
|
-
const
|
|
1268
|
+
const selectorFamily = Object.assign(
|
|
1232
1269
|
(key) => {
|
|
1233
1270
|
const subKey = json.stringifyJson(key);
|
|
1234
1271
|
const family = { key: options.key, subKey };
|
|
1235
1272
|
const fullKey = `${options.key}(${subKey})`;
|
|
1236
|
-
const existing =
|
|
1237
|
-
let token;
|
|
1273
|
+
const existing = target.selectors.get(fullKey);
|
|
1238
1274
|
if (existing) {
|
|
1239
|
-
|
|
1240
|
-
} else {
|
|
1241
|
-
const individualOptions = {
|
|
1242
|
-
key: fullKey,
|
|
1243
|
-
default: options.default instanceof Function ? options.default(key) : options.default
|
|
1244
|
-
};
|
|
1245
|
-
if (options.effects) {
|
|
1246
|
-
individualOptions.effects = options.effects(key);
|
|
1247
|
-
}
|
|
1248
|
-
token = createAtom(individualOptions, family, store);
|
|
1249
|
-
subject.next(token);
|
|
1275
|
+
return deposit(existing);
|
|
1250
1276
|
}
|
|
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);
|
|
1251
1287
|
return token;
|
|
1252
1288
|
},
|
|
1253
1289
|
{
|
|
1254
1290
|
key: options.key,
|
|
1255
|
-
type: `
|
|
1256
|
-
subject
|
|
1291
|
+
type: `selector_family`
|
|
1257
1292
|
}
|
|
1258
1293
|
);
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return atomFamily;
|
|
1294
|
+
target.families.set(options.key, selectorFamily);
|
|
1295
|
+
return selectorFamily;
|
|
1262
1296
|
}
|
|
1263
1297
|
|
|
1264
|
-
// src/
|
|
1265
|
-
var
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
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
|
|
1273
1307
|
);
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
`\u2B55`,
|
|
1285
|
-
token.type,
|
|
1286
|
-
token.key,
|
|
1287
|
-
`operation start in store "${store.config.name}"${store.transactionStatus.phase === `idle` ? `` : ` ${store.transactionStatus.phase} "${store.transactionStatus.key}"`}`
|
|
1288
|
-
);
|
|
1289
|
-
};
|
|
1290
|
-
var closeOperation = (store) => {
|
|
1291
|
-
const core = target(store);
|
|
1292
|
-
if (core.operation.open) {
|
|
1293
|
-
store.logger.info(
|
|
1294
|
-
`\u{1F534}`,
|
|
1295
|
-
core.operation.token.type,
|
|
1296
|
-
core.operation.token.key,
|
|
1297
|
-
`operation done in store "${store.config.name}"`
|
|
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
|
+
}
|
|
1298
1318
|
);
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
`unknown`,
|
|
1309
|
-
key,
|
|
1310
|
-
`isDone called outside of an operation. This is probably a bug.`
|
|
1311
|
-
);
|
|
1312
|
-
return true;
|
|
1313
|
-
}
|
|
1314
|
-
return core.operation.done.has(key);
|
|
1315
|
-
};
|
|
1316
|
-
var markDone = (key, store) => {
|
|
1317
|
-
const core = target(store);
|
|
1318
|
-
if (!core.operation.open) {
|
|
1319
|
-
store.logger.warn(
|
|
1320
|
-
`\u{1F41E}`,
|
|
1321
|
-
`unknown`,
|
|
1322
|
-
key,
|
|
1323
|
-
`markDone called outside of an operation. This is probably a bug.`
|
|
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
|
+
}
|
|
1324
1328
|
);
|
|
1325
|
-
return;
|
|
1326
1329
|
}
|
|
1327
|
-
core.operation.done.add(key);
|
|
1328
1330
|
};
|
|
1329
1331
|
|
|
1330
|
-
// src/
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
)
|
|
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;
|
|
1341
|
+
}
|
|
1334
1342
|
|
|
1335
|
-
// src/
|
|
1336
|
-
var
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
if (state.type !== `atom`) {
|
|
1342
|
-
store.logger.info(`\u{1F9EE}`, state.type, state.key, `computing value`);
|
|
1343
|
-
return state.get();
|
|
1344
|
-
}
|
|
1345
|
-
const fallback = state.default instanceof Function ? state.default() : state.default;
|
|
1346
|
-
store.logger.info(
|
|
1347
|
-
`\u{1F481}`,
|
|
1348
|
-
`atom`,
|
|
1349
|
-
state.key,
|
|
1350
|
-
`could not find cached value; using default`,
|
|
1351
|
-
fallback
|
|
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
|
|
1352
1349
|
);
|
|
1353
|
-
return
|
|
1350
|
+
return jsonFamily;
|
|
1354
1351
|
};
|
|
1355
1352
|
|
|
1356
|
-
// src/
|
|
1357
|
-
|
|
1358
|
-
const
|
|
1359
|
-
const
|
|
1360
|
-
if (
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
return copiedValue;
|
|
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
|
+
};
|
|
1366
1362
|
}
|
|
1367
|
-
return
|
|
1368
|
-
}
|
|
1363
|
+
return jsonToken;
|
|
1364
|
+
};
|
|
1369
1365
|
|
|
1370
|
-
// src/
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
);
|
|
1380
|
-
return copiedValue;
|
|
1381
|
-
}
|
|
1382
|
-
if (`family` in atom) {
|
|
1383
|
-
const family = store.transactionStatus.core.families.get(atom.family.key);
|
|
1384
|
-
if (family && family.type === `atom_family`) {
|
|
1385
|
-
const result = copyMutableFamilyMemberWithinTransaction(
|
|
1386
|
-
atom,
|
|
1387
|
-
family,
|
|
1388
|
-
store,
|
|
1389
|
-
store.transactionStatus.core
|
|
1390
|
-
);
|
|
1391
|
-
if (result) {
|
|
1392
|
-
return result;
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
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
|
+
};
|
|
1396
1375
|
}
|
|
1397
|
-
return
|
|
1376
|
+
return updateToken;
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
// src/mutable/is-atom-token-mutable.ts
|
|
1380
|
+
function isAtomTokenMutable(token) {
|
|
1381
|
+
return token.key.endsWith(`::mutable`);
|
|
1398
1382
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1404
|
-
return null;
|
|
1383
|
+
|
|
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;
|
|
1405
1387
|
}
|
|
1406
1388
|
|
|
1407
|
-
// src/
|
|
1408
|
-
var
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
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);
|
|
1396
|
+
};
|
|
1397
|
+
var markAtomAsDefault = (key, store) => {
|
|
1398
|
+
const core = newest(store);
|
|
1399
|
+
core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
|
|
1400
|
+
};
|
|
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));
|
|
1421
1409
|
};
|
|
1422
1410
|
|
|
1423
|
-
// src/
|
|
1424
|
-
|
|
1425
|
-
const core = target(store);
|
|
1426
|
-
const downstreamKeys = core.selectorAtoms.getRelatedKeys(atom.key);
|
|
1411
|
+
// src/atom/create-atom.ts
|
|
1412
|
+
function createAtom(options, family, store) {
|
|
1427
1413
|
store.logger.info(
|
|
1428
|
-
`\u{
|
|
1429
|
-
atom
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
downstreamKeys != null ? downstreamKeys : `to evict`
|
|
1414
|
+
`\u{1F528}`,
|
|
1415
|
+
`atom`,
|
|
1416
|
+
options.key,
|
|
1417
|
+
`creating in store "${store.config.name}"`
|
|
1433
1418
|
);
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1419
|
+
const target = newest(store);
|
|
1420
|
+
const existing = target.atoms.get(options.key);
|
|
1421
|
+
if (existing) {
|
|
1422
|
+
store.logger.error(
|
|
1423
|
+
`\u274C`,
|
|
1424
|
+
`atom`,
|
|
1425
|
+
options.key,
|
|
1426
|
+
`Tried to create atom, but it already exists in the store.`,
|
|
1427
|
+
`(Ignore if you are in development using hot module replacement.)`
|
|
1428
|
+
);
|
|
1429
|
+
return deposit(existing);
|
|
1430
|
+
}
|
|
1431
|
+
const subject = new Subject();
|
|
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}"`
|
|
1441
1440
|
);
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1441
|
+
return `mutable` in options ? createMutableAtom(options, store2) : createAtom(options, void 0, store2);
|
|
1442
|
+
},
|
|
1443
|
+
subject
|
|
1444
|
+
}), family && { family });
|
|
1445
|
+
let initialValue = options.default;
|
|
1446
|
+
if (options.default instanceof Function) {
|
|
1447
|
+
initialValue = options.default();
|
|
1448
|
+
}
|
|
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);
|
|
1446
1463
|
}
|
|
1447
|
-
|
|
1448
|
-
markDone(key, store);
|
|
1464
|
+
++effectIndex;
|
|
1449
1465
|
}
|
|
1466
|
+
newAtom.cleanup = () => {
|
|
1467
|
+
for (const cleanup of cleanupFunctions) {
|
|
1468
|
+
cleanup();
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1450
1471
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
// src/set-state/stow-update.ts
|
|
1454
|
-
function shouldUpdateBeStowed(key, update) {
|
|
1455
|
-
if (isTransceiver(update.newValue)) {
|
|
1456
|
-
return false;
|
|
1457
|
-
}
|
|
1458
|
-
if (key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
|
|
1459
|
-
return false;
|
|
1460
|
-
}
|
|
1461
|
-
return true;
|
|
1472
|
+
store.subject.atomCreation.next(token);
|
|
1473
|
+
return token;
|
|
1462
1474
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1475
|
+
|
|
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) {
|
|
1466
1483
|
store.logger.error(
|
|
1467
|
-
`\
|
|
1484
|
+
`\u274C`,
|
|
1468
1485
|
`atom`,
|
|
1469
|
-
key
|
|
1470
|
-
`
|
|
1486
|
+
`${key}`,
|
|
1487
|
+
`Tried to delete atom, but it does not exist in the store.`
|
|
1471
1488
|
);
|
|
1472
|
-
return;
|
|
1473
1489
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
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
|
+
}
|
|
1481
1501
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
`stowed (`,
|
|
1488
|
-
update.oldValue,
|
|
1489
|
-
`->`,
|
|
1490
|
-
update.newValue,
|
|
1491
|
-
`)`
|
|
1492
|
-
);
|
|
1493
|
-
};
|
|
1502
|
+
target.selectorAtoms.delete(key);
|
|
1503
|
+
target.atomsThatAreDefault.delete(key);
|
|
1504
|
+
target.timelineAtoms.delete(key);
|
|
1505
|
+
store.logger.info(`\u{1F525}`, `atom`, `${key}`, `deleted`);
|
|
1506
|
+
}
|
|
1494
1507
|
|
|
1495
|
-
// src/
|
|
1496
|
-
var
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
newValue = cacheValue(atom.key, newValue, atom.subject, store);
|
|
1502
|
-
if (isAtomDefault(atom.key, store)) {
|
|
1503
|
-
markAtomAsNotDefault(atom.key, store);
|
|
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();
|
|
1504
1514
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1515
|
+
get(key) {
|
|
1516
|
+
const has = super.has(key);
|
|
1517
|
+
if (has) {
|
|
1518
|
+
return super.get(key);
|
|
1519
|
+
}
|
|
1520
|
+
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
1521
|
+
const value = this.source.get(key);
|
|
1522
|
+
return value;
|
|
1523
|
+
}
|
|
1524
|
+
return void 0;
|
|
1512
1525
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
}
|
|
1520
|
-
|
|
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);
|
|
1521
1539
|
}
|
|
1522
1540
|
};
|
|
1523
1541
|
|
|
1524
|
-
// src/
|
|
1525
|
-
var
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
var traceSelectorAtoms = (selectorKey, directDependencyKey, store) => {
|
|
1538
|
-
const rootKeys = [];
|
|
1539
|
-
const indirectDependencyKeys = getSelectorDependencyKeys(
|
|
1540
|
-
directDependencyKey,
|
|
1541
|
-
store
|
|
1542
|
-
);
|
|
1543
|
-
let depth = 0;
|
|
1544
|
-
while (indirectDependencyKeys.length > 0) {
|
|
1545
|
-
const indirectDependencyKey = indirectDependencyKeys.shift();
|
|
1546
|
-
++depth;
|
|
1547
|
-
if (depth > 99999) {
|
|
1548
|
-
throw new Error(
|
|
1549
|
-
`Maximum selector dependency depth exceeded (> 99999) in selector "${selectorKey}". This is likely due to a circular dependency.`
|
|
1550
|
-
);
|
|
1551
|
-
}
|
|
1552
|
-
if (!isAtomKey(indirectDependencyKey, store)) {
|
|
1553
|
-
indirectDependencyKeys.push(
|
|
1554
|
-
...getSelectorDependencyKeys(indirectDependencyKey, store)
|
|
1555
|
-
);
|
|
1556
|
-
} else if (!rootKeys.includes(indirectDependencyKey)) {
|
|
1557
|
-
rootKeys.push(indirectDependencyKey);
|
|
1558
|
-
}
|
|
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);
|
|
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
|
+
);
|
|
1559
1555
|
}
|
|
1560
|
-
return rootKeys;
|
|
1561
|
-
};
|
|
1562
|
-
var traceAllSelectorAtoms = (selectorKey, store) => {
|
|
1563
|
-
const directDependencyKeys = getSelectorDependencyKeys(selectorKey, store);
|
|
1564
|
-
return directDependencyKeys.flatMap(
|
|
1565
|
-
(depKey) => isAtomKey(depKey, store) ? depKey : traceSelectorAtoms(selectorKey, depKey, store)
|
|
1566
|
-
);
|
|
1567
1556
|
};
|
|
1568
1557
|
|
|
1569
|
-
// src/
|
|
1570
|
-
var
|
|
1571
|
-
const
|
|
1572
|
-
if (
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
`\u{1F50D}`,
|
|
1579
|
-
`selector`,
|
|
1580
|
-
selectorKey,
|
|
1581
|
-
`discovers root atom "${dependency.key}"`
|
|
1582
|
-
);
|
|
1583
|
-
} else {
|
|
1584
|
-
const rootKeys = traceSelectorAtoms(selectorKey, dependency.key, store);
|
|
1585
|
-
store.logger.info(
|
|
1586
|
-
`\u{1F50D}`,
|
|
1587
|
-
`selector`,
|
|
1588
|
-
selectorKey,
|
|
1589
|
-
`discovers root atoms: [ ${rootKeys.map((key) => `"${key}"`).join(`, `)} ]`
|
|
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.`
|
|
1590
1567
|
);
|
|
1591
|
-
|
|
1592
|
-
core.selectorAtoms = core.selectorAtoms.set({
|
|
1593
|
-
selectorKey,
|
|
1594
|
-
atomKey
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1568
|
+
return target.valueMap.get(state.key);
|
|
1597
1569
|
}
|
|
1570
|
+
return target.operation.prev.get(state.key);
|
|
1598
1571
|
};
|
|
1599
1572
|
|
|
1600
|
-
// src/
|
|
1601
|
-
var
|
|
1602
|
-
|
|
1603
|
-
const
|
|
1604
|
-
|
|
1605
|
-
const dependencyState = withdraw(dependency, store);
|
|
1606
|
-
if (dependencyState === void 0) {
|
|
1607
|
-
throw new Error(
|
|
1608
|
-
`State "${dependency.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`
|
|
1609
|
-
);
|
|
1610
|
-
}
|
|
1611
|
-
const dependencyValue = readOrComputeValue(dependencyState, store);
|
|
1612
|
-
store.logger.info(
|
|
1613
|
-
`\u{1F50C}`,
|
|
1614
|
-
`selector`,
|
|
1615
|
-
selectorKey,
|
|
1616
|
-
`registers dependency ( "${dependency.key}" =`,
|
|
1617
|
-
dependencyValue,
|
|
1618
|
-
`)`
|
|
1619
|
-
);
|
|
1620
|
-
if (!alreadyRegistered) {
|
|
1621
|
-
core.selectorGraph = core.selectorGraph.set(
|
|
1622
|
-
{
|
|
1623
|
-
upstreamSelectorKey: dependency.key,
|
|
1624
|
-
downstreamSelectorKey: selectorKey
|
|
1625
|
-
},
|
|
1626
|
-
{
|
|
1627
|
-
source: dependency.key
|
|
1628
|
-
}
|
|
1629
|
-
);
|
|
1630
|
-
}
|
|
1631
|
-
updateSelectorAtoms(selectorKey, dependency, store);
|
|
1632
|
-
return dependencyValue;
|
|
1633
|
-
},
|
|
1634
|
-
set: (stateToken, newValue) => {
|
|
1635
|
-
const state = withdraw(stateToken, store);
|
|
1636
|
-
if (state === void 0) {
|
|
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) {
|
|
1637
1578
|
throw new Error(
|
|
1638
|
-
`
|
|
1579
|
+
`Atom "${atomKey}", a dependency of selector "${state.key}", not found in store "${store.config.name}".`
|
|
1639
1580
|
);
|
|
1640
1581
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
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
|
+
}
|
|
1666
1609
|
);
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
if (store.transactionStatus.phase === `idle`) {
|
|
1670
|
-
subject.next({ newValue, oldValue });
|
|
1671
|
-
}
|
|
1672
|
-
options.set({ get, set }, newValue);
|
|
1673
|
-
};
|
|
1674
|
-
const mySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
|
|
1675
|
-
subject,
|
|
1676
|
-
install: (s) => createSelector(options, family, s),
|
|
1677
|
-
get: getSelf,
|
|
1678
|
-
set: setSelf,
|
|
1679
|
-
type: `selector`
|
|
1680
|
-
}), family && { family });
|
|
1681
|
-
core.selectors.set(options.key, mySelector);
|
|
1682
|
-
const initialValue = getSelf();
|
|
1683
|
-
store.logger.info(`\u2728`, mySelector.type, mySelector.key, `=`, initialValue);
|
|
1684
|
-
const token = {
|
|
1685
|
-
key: options.key,
|
|
1686
|
-
type: `selector`
|
|
1687
|
-
};
|
|
1688
|
-
if (family) {
|
|
1689
|
-
token.family = family;
|
|
1690
|
-
}
|
|
1691
|
-
store.subject.selectorCreation.next(token);
|
|
1692
|
-
return token;
|
|
1693
|
-
};
|
|
1694
|
-
|
|
1695
|
-
// src/selector/create-readonly-selector.ts
|
|
1696
|
-
var createReadonlySelector = (options, family, store, core) => {
|
|
1697
|
-
const subject = new Subject();
|
|
1698
|
-
const { get } = registerSelector(options.key, store);
|
|
1699
|
-
const getSelf = () => {
|
|
1700
|
-
const value = options.get({ get });
|
|
1701
|
-
cacheValue(options.key, value, subject, store);
|
|
1702
|
-
return value;
|
|
1703
|
-
};
|
|
1704
|
-
const readonlySelector = __spreadValues(__spreadProps(__spreadValues({}, options), {
|
|
1705
|
-
subject,
|
|
1706
|
-
install: (s) => createSelector(options, family, s),
|
|
1707
|
-
get: getSelf,
|
|
1708
|
-
type: `readonly_selector`
|
|
1709
|
-
}), family && { family });
|
|
1710
|
-
core.readonlySelectors.set(options.key, readonlySelector);
|
|
1711
|
-
const initialValue = getSelf();
|
|
1712
|
-
store.logger.info(
|
|
1713
|
-
`\u2728`,
|
|
1714
|
-
readonlySelector.type,
|
|
1715
|
-
readonlySelector.key,
|
|
1716
|
-
`=`,
|
|
1717
|
-
initialValue
|
|
1718
|
-
);
|
|
1719
|
-
const token = {
|
|
1720
|
-
key: options.key,
|
|
1721
|
-
type: `readonly_selector`
|
|
1722
|
-
};
|
|
1723
|
-
if (family) {
|
|
1724
|
-
token.family = family;
|
|
1725
|
-
}
|
|
1726
|
-
store.subject.selectorCreation.next(token);
|
|
1727
|
-
return token;
|
|
1610
|
+
});
|
|
1611
|
+
return dependencySubscriptions;
|
|
1728
1612
|
};
|
|
1729
1613
|
|
|
1730
|
-
// src/
|
|
1731
|
-
|
|
1732
|
-
const
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
store.logger.error(
|
|
1737
|
-
`\u274C`,
|
|
1738
|
-
existingReadonly ? `readonly_selector` : `selector`,
|
|
1739
|
-
options.key,
|
|
1740
|
-
`Tried to create selector, but it already exists in the store. (Ignore if you are in development using hot module replacement.)`
|
|
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}"`
|
|
1741
1620
|
);
|
|
1742
1621
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
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
|
+
}
|
|
1790
1801
|
}
|
|
1791
|
-
return createSelector(
|
|
1792
|
-
{
|
|
1793
|
-
key: fullKey,
|
|
1794
|
-
get: options.get(key)
|
|
1795
|
-
},
|
|
1796
|
-
family,
|
|
1797
|
-
store
|
|
1798
|
-
);
|
|
1799
|
-
},
|
|
1800
|
-
{
|
|
1801
|
-
key: options.key,
|
|
1802
|
-
type: `readonly_selector_family`,
|
|
1803
|
-
subject
|
|
1804
1802
|
}
|
|
1805
|
-
);
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
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;
|
|
1811
1823
|
}
|
|
1812
|
-
const
|
|
1813
|
-
const
|
|
1814
|
-
|
|
1815
|
-
(
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
return deposit(existing);
|
|
1822
|
-
}
|
|
1823
|
-
const token = createSelector(
|
|
1824
|
-
{
|
|
1825
|
-
key: fullKey,
|
|
1826
|
-
get: options.get(key),
|
|
1827
|
-
set: options.set(key)
|
|
1828
|
-
},
|
|
1829
|
-
family,
|
|
1830
|
-
store
|
|
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}"`
|
|
1831
1833
|
);
|
|
1832
|
-
|
|
1833
|
-
return token;
|
|
1834
|
-
},
|
|
1835
|
-
{
|
|
1836
|
-
key: options.key,
|
|
1837
|
-
type: `selector_family`
|
|
1834
|
+
continue;
|
|
1838
1835
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
this.findLatestUpdateState = createAtomFamily(
|
|
1848
|
-
{
|
|
1849
|
-
key: `*${findMutableState.key}`,
|
|
1850
|
-
default: null
|
|
1851
|
-
},
|
|
1852
|
-
store
|
|
1853
|
-
);
|
|
1854
|
-
this.findMutableState = findMutableState;
|
|
1855
|
-
this.findMutableState.subject.subscribe(
|
|
1856
|
-
`store=${store.config.name}::tracker-atom-family`,
|
|
1857
|
-
(atomToken) => {
|
|
1858
|
-
if (atomToken.family) {
|
|
1859
|
-
const key = json.parseJson(atomToken.family.subKey);
|
|
1860
|
-
this.findLatestUpdateState(key);
|
|
1861
|
-
new Tracker(atomToken, store);
|
|
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);
|
|
1862
1844
|
}
|
|
1863
1845
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
`
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
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;
|
|
1872
1860
|
}
|
|
1873
1861
|
}
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
const coreFamily = Object.assign(
|
|
1881
|
-
createAtomFamily(options, store),
|
|
1882
|
-
options
|
|
1883
|
-
);
|
|
1884
|
-
json.selectJsonFamily(coreFamily, options);
|
|
1885
|
-
new FamilyTracker(coreFamily, store);
|
|
1886
|
-
return coreFamily;
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
// src/mutable/get-json-family.ts
|
|
1890
|
-
var getJsonFamily = (mutableAtomFamily, store) => {
|
|
1891
|
-
const core = target(store);
|
|
1892
|
-
const key = `${mutableAtomFamily.key}:JSON`;
|
|
1893
|
-
const jsonFamily = core.families.get(
|
|
1894
|
-
key
|
|
1895
|
-
);
|
|
1896
|
-
return jsonFamily;
|
|
1897
|
-
};
|
|
1898
|
-
|
|
1899
|
-
// src/mutable/get-json-token.ts
|
|
1900
|
-
var getJsonToken = (mutableAtomToken) => {
|
|
1901
|
-
const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
|
|
1902
|
-
const jsonToken = { type: `selector`, key };
|
|
1903
|
-
if (mutableAtomToken.family) {
|
|
1904
|
-
jsonToken.family = {
|
|
1905
|
-
key: `${mutableAtomToken.family.key}:JSON`,
|
|
1906
|
-
subKey: mutableAtomToken.family.subKey
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
return jsonToken;
|
|
1910
|
-
};
|
|
1911
|
-
|
|
1912
|
-
// src/mutable/get-update-token.ts
|
|
1913
|
-
var getUpdateToken = (mutableAtomToken) => {
|
|
1914
|
-
const key = `*${mutableAtomToken.key}`;
|
|
1915
|
-
const updateToken = { type: `atom`, key };
|
|
1916
|
-
if (mutableAtomToken.family) {
|
|
1917
|
-
updateToken.family = {
|
|
1918
|
-
key: `*${mutableAtomToken.family.key}`,
|
|
1919
|
-
subKey: mutableAtomToken.family.subKey
|
|
1920
|
-
};
|
|
1862
|
+
addAtomToTimeline(token2, tl, store);
|
|
1863
|
+
}
|
|
1864
|
+
target.timelineAtoms = target.timelineAtoms.set({
|
|
1865
|
+
atomKey: tokenOrFamily.key,
|
|
1866
|
+
timelineKey: options.key
|
|
1867
|
+
});
|
|
1921
1868
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
// src/mutable/transceiver.ts
|
|
1931
|
-
function isTransceiver(value) {
|
|
1932
|
-
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value;
|
|
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;
|
|
1933
1876
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
var isAtomMutable = (atom) => `isMutable` in atom;
|
|
1937
|
-
|
|
1938
|
-
// src/atom/is-default.ts
|
|
1939
|
-
var isAtomDefault = (key, store) => {
|
|
1940
|
-
const core = target(store);
|
|
1941
|
-
return core.atomsThatAreDefault.has(key);
|
|
1942
|
-
};
|
|
1943
|
-
var markAtomAsDefault = (key, store) => {
|
|
1944
|
-
const core = target(store);
|
|
1945
|
-
core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key);
|
|
1946
|
-
};
|
|
1947
|
-
var markAtomAsNotDefault = (key, store) => {
|
|
1948
|
-
const core = target(store);
|
|
1949
|
-
core.atomsThatAreDefault = new Set(target(store).atomsThatAreDefault);
|
|
1950
|
-
core.atomsThatAreDefault.delete(key);
|
|
1951
|
-
};
|
|
1952
|
-
var isSelectorDefault = (key, store) => {
|
|
1953
|
-
const rootKeys = traceAllSelectorAtoms(key, store);
|
|
1954
|
-
return rootKeys.every((rootKey) => isAtomDefault(rootKey, store));
|
|
1955
|
-
};
|
|
1956
|
-
|
|
1957
|
-
// src/atom/create-atom.ts
|
|
1958
|
-
function createAtom(options, family, store) {
|
|
1877
|
+
var timeTravel = (direction, token, store) => {
|
|
1878
|
+
const action = direction === `forward` ? `redo` : `undo`;
|
|
1959
1879
|
store.logger.info(
|
|
1960
|
-
`\
|
|
1961
|
-
`
|
|
1962
|
-
|
|
1963
|
-
|
|
1880
|
+
direction === `forward` ? `\u23E9` : `\u23EA`,
|
|
1881
|
+
`timeline`,
|
|
1882
|
+
token.key,
|
|
1883
|
+
action
|
|
1964
1884
|
);
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
`Tried to create atom, but it already exists in the store.`,
|
|
1973
|
-
`(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.`
|
|
1974
1892
|
);
|
|
1975
|
-
return
|
|
1893
|
+
return;
|
|
1976
1894
|
}
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
`installing in store "${store2.config.name}"`
|
|
1986
|
-
);
|
|
1987
|
-
return `mutable` in options ? createMutableAtom(options, store2) : createAtom(options, void 0, store2);
|
|
1988
|
-
},
|
|
1989
|
-
subject
|
|
1990
|
-
}), family && { family });
|
|
1991
|
-
let initialValue = options.default;
|
|
1992
|
-
if (options.default instanceof Function) {
|
|
1993
|
-
initialValue = options.default();
|
|
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;
|
|
1994
1903
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
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);
|
|
2009
1921
|
}
|
|
2010
|
-
++effectIndex;
|
|
2011
1922
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
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);
|
|
2015
1933
|
}
|
|
2016
|
-
|
|
1934
|
+
break;
|
|
1935
|
+
}
|
|
1936
|
+
case `transaction_update`: {
|
|
1937
|
+
updateValuesFromTransactionUpdate(update);
|
|
1938
|
+
break;
|
|
1939
|
+
}
|
|
2017
1940
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
}
|
|
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
|
+
};
|
|
2021
1953
|
|
|
2022
|
-
// src/
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
`atom`,
|
|
2032
|
-
`${key}`,
|
|
2033
|
-
`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.`
|
|
2034
1963
|
);
|
|
1964
|
+
return;
|
|
2035
1965
|
}
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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
|
+
);
|
|
2045
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
|
+
);
|
|
2046
1999
|
}
|
|
2047
2000
|
}
|
|
2048
|
-
|
|
2049
|
-
core.atomsThatAreDefault.delete(key);
|
|
2050
|
-
core.timelineAtoms.delete(key);
|
|
2051
|
-
store.logger.info(`\u{1F525}`, `atom`, `${key}`, `deleted`);
|
|
2001
|
+
atom_io.setState(token, newValue, parent);
|
|
2052
2002
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
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
|
+
}
|
|
2059
2010
|
}
|
|
2060
|
-
return capitalize(token.type);
|
|
2061
2011
|
}
|
|
2062
|
-
var
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
}
|
|
2068
|
-
};
|
|
2069
|
-
|
|
2070
|
-
// src/subscribe/recall-state.ts
|
|
2071
|
-
var recallState = (state, store) => {
|
|
2072
|
-
const core = target(store);
|
|
2073
|
-
if (!core.operation.open) {
|
|
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`) {
|
|
2074
2017
|
store.logger.warn(
|
|
2075
2018
|
`\u{1F41E}`,
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
`
|
|
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.`
|
|
2079
2049
|
);
|
|
2080
|
-
|
|
2050
|
+
} else {
|
|
2051
|
+
ingestTransactionUpdate(child.transactionMeta.update, parent, child);
|
|
2052
|
+
parent.transactionMeta.update.updates.push(child.transactionMeta.update);
|
|
2081
2053
|
}
|
|
2082
|
-
|
|
2054
|
+
parent.subject.transactionApplying.next(null);
|
|
2083
2055
|
};
|
|
2084
2056
|
|
|
2085
|
-
// src/
|
|
2086
|
-
var
|
|
2087
|
-
const
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
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
|
|
2107
2115
|
);
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
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.`
|
|
2118
2143
|
);
|
|
2119
|
-
state.subject.next({ newValue, oldValue });
|
|
2120
2144
|
}
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
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
|
+
}
|
|
2124
2168
|
};
|
|
2125
2169
|
|
|
2170
|
+
// src/transaction/index.ts
|
|
2171
|
+
var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
|
|
2172
|
+
|
|
2126
2173
|
exports.FamilyTracker = FamilyTracker;
|
|
2127
2174
|
exports.Future = Future;
|
|
2128
2175
|
exports.IMPLICIT = IMPLICIT;
|
|
2129
2176
|
exports.LazyMap = LazyMap;
|
|
2130
2177
|
exports.NotFoundError = NotFoundError;
|
|
2178
|
+
exports.StatefulSubject = StatefulSubject;
|
|
2131
2179
|
exports.Store = Store;
|
|
2132
2180
|
exports.Subject = Subject;
|
|
2133
2181
|
exports.TRANSACTION_PHASES = TRANSACTION_PHASES;
|
|
@@ -2152,6 +2200,7 @@ exports.createTransaction = createTransaction;
|
|
|
2152
2200
|
exports.deleteAtom = deleteAtom;
|
|
2153
2201
|
exports.deleteSelector = deleteSelector;
|
|
2154
2202
|
exports.deposit = deposit;
|
|
2203
|
+
exports.eldest = eldest;
|
|
2155
2204
|
exports.evictCachedValue = evictCachedValue;
|
|
2156
2205
|
exports.getJsonFamily = getJsonFamily;
|
|
2157
2206
|
exports.getJsonToken = getJsonToken;
|
|
@@ -2171,6 +2220,7 @@ exports.isValueCached = isValueCached;
|
|
|
2171
2220
|
exports.markAtomAsDefault = markAtomAsDefault;
|
|
2172
2221
|
exports.markAtomAsNotDefault = markAtomAsNotDefault;
|
|
2173
2222
|
exports.markDone = markDone;
|
|
2223
|
+
exports.newest = newest;
|
|
2174
2224
|
exports.openOperation = openOperation;
|
|
2175
2225
|
exports.readCachedValue = readCachedValue;
|
|
2176
2226
|
exports.readOrComputeValue = readOrComputeValue;
|
|
@@ -2178,7 +2228,6 @@ exports.redoTransactionUpdate = redoTransactionUpdate;
|
|
|
2178
2228
|
exports.registerSelector = registerSelector;
|
|
2179
2229
|
exports.setAtomOrSelector = setAtomOrSelector;
|
|
2180
2230
|
exports.subscribeToRootAtoms = subscribeToRootAtoms;
|
|
2181
|
-
exports.target = target;
|
|
2182
2231
|
exports.timeTravel = timeTravel;
|
|
2183
2232
|
exports.traceAllSelectorAtoms = traceAllSelectorAtoms;
|
|
2184
2233
|
exports.traceSelectorAtoms = traceSelectorAtoms;
|