atom.io 0.40.8 → 0.40.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/{chunk-Cl8Af3a2.js → chunk-CTAAG5j7.js} +3 -1
  2. package/dist/eslint-plugin/index.js +2 -3
  3. package/dist/eslint-plugin/index.js.map +1 -1
  4. package/dist/internal/index.d.ts +4 -3
  5. package/dist/internal/index.d.ts.map +1 -1
  6. package/dist/internal/index.js +1129 -3
  7. package/dist/internal/index.js.map +1 -1
  8. package/dist/react-devtools/index.js.map +1 -1
  9. package/dist/realtime/index.d.ts +29 -5
  10. package/dist/realtime/index.d.ts.map +1 -1
  11. package/dist/realtime/index.js +46 -3
  12. package/dist/realtime/index.js.map +1 -1
  13. package/dist/realtime-client/index.d.ts +1 -2
  14. package/dist/realtime-client/index.d.ts.map +1 -1
  15. package/dist/realtime-client/index.js +1 -2
  16. package/dist/realtime-client/index.js.map +1 -1
  17. package/dist/realtime-react/index.d.ts +4 -4
  18. package/dist/realtime-react/index.d.ts.map +1 -1
  19. package/dist/realtime-react/index.js +1 -2
  20. package/dist/realtime-react/index.js.map +1 -1
  21. package/dist/realtime-server/index.d.ts +5 -16
  22. package/dist/realtime-server/index.d.ts.map +1 -1
  23. package/dist/realtime-server/index.js +6 -10
  24. package/dist/realtime-server/index.js.map +1 -1
  25. package/dist/realtime-testing/index.d.ts +2 -2
  26. package/dist/realtime-testing/index.d.ts.map +1 -1
  27. package/dist/realtime-testing/index.js +2 -2
  28. package/dist/realtime-testing/index.js.map +1 -1
  29. package/dist/transceivers/o-list/index.d.ts +77 -0
  30. package/dist/transceivers/o-list/index.d.ts.map +1 -0
  31. package/dist/transceivers/o-list/index.js +308 -0
  32. package/dist/transceivers/o-list/index.js.map +1 -0
  33. package/dist/transceivers/set-rtx/index.d.ts +1 -1
  34. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  35. package/dist/transceivers/set-rtx/index.js +2 -2
  36. package/dist/transceivers/set-rtx/index.js.map +1 -1
  37. package/dist/transceivers/u-list/index.d.ts +29 -0
  38. package/dist/transceivers/u-list/index.d.ts.map +1 -0
  39. package/dist/transceivers/u-list/index.js +87 -0
  40. package/dist/transceivers/u-list/index.js.map +1 -0
  41. package/package.json +14 -6
  42. package/src/internal/mutable/tracker.ts +21 -21
  43. package/src/internal/mutable/transceiver.ts +4 -4
  44. package/src/internal/set-state/index.ts +1 -0
  45. package/src/{realtime-server → realtime}/employ-socket.ts +2 -2
  46. package/src/realtime/index.ts +2 -0
  47. package/src/realtime/shared-room-store.ts +12 -11
  48. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +1 -1
  49. package/src/realtime-client/push-state.ts +1 -2
  50. package/src/realtime-react/use-single-effect.ts +1 -1
  51. package/src/realtime-server/continuity/continuity-store.ts +1 -1
  52. package/src/realtime-server/continuity/provide-outcomes.ts +2 -2
  53. package/src/realtime-server/continuity/provide-perspectives.ts +1 -2
  54. package/src/realtime-server/continuity/provide-startup-payloads.ts +3 -3
  55. package/src/realtime-server/continuity/receive-action-requests.ts +2 -4
  56. package/src/realtime-server/continuity/track-acknowledgements.ts +2 -3
  57. package/src/realtime-server/index.ts +0 -1
  58. package/src/realtime-server/ipc-sockets/custom-socket.ts +1 -2
  59. package/src/realtime-server/ipc-sockets/parent-socket.ts +2 -4
  60. package/src/realtime-server/realtime-family-provider.ts +1 -1
  61. package/src/realtime-server/realtime-mutable-family-provider.ts +1 -1
  62. package/src/realtime-server/realtime-mutable-provider.ts +1 -1
  63. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +2 -2
  64. package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -9
  65. package/src/realtime-server/realtime-state-provider.ts +1 -1
  66. package/src/realtime-server/realtime-state-receiver.ts +3 -6
  67. package/src/realtime-server/server-config.ts +1 -2
  68. package/src/realtime-testing/setup-realtime-test.tsx +3 -4
  69. package/src/transceivers/o-list/index.ts +1 -0
  70. package/src/transceivers/o-list/o-list.ts +412 -0
  71. package/src/transceivers/set-rtx/set-rtx.ts +3 -3
  72. package/src/transceivers/u-list/index.ts +1 -0
  73. package/src/transceivers/u-list/u-list.ts +123 -0
  74. package/dist/employ-socket-D6wgByWh.js +0 -12
  75. package/dist/employ-socket-D6wgByWh.js.map +0 -1
  76. package/dist/has-role-CMlaUlaf.js +0 -1133
  77. package/dist/has-role-CMlaUlaf.js.map +0 -1
  78. package/dist/is-fn-DY1wZ-md.js +0 -10
  79. package/dist/is-fn-DY1wZ-md.js.map +0 -1
  80. package/dist/mutex-store-CSvxY9i3.js +0 -11
  81. package/dist/mutex-store-CSvxY9i3.js.map +0 -1
  82. package/dist/shared-room-store-BfW3nWif.js +0 -31
  83. package/dist/shared-room-store-BfW3nWif.js.map +0 -1
  84. package/dist/shared-room-store-D2o4ZLjC.d.ts +0 -15
  85. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +0 -1
  86. /package/src/{realtime-server → realtime}/socket-interface.ts +0 -0
@@ -1,5 +1,3 @@
1
- import { DO_NOT_CREATE, Future, INTERNAL_ROLES, JOIN_OP, NotFoundError, RESET_STATE, StatefulSubject, Subject, Tracker, become, closeOperation, createRegularAtom, deposit, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, getFallback, getFamilyOfToken, getFromStore, getSelectorDependencyKeys, hasRole, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markDone, mintInStore, newest, openOperation, operateOnStore, readFromCache, readOrComputeValue, recallState, reduceReference, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setIntoStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, traceRootSelectorAtoms, withdraw, writeToCache } from "../has-role-CMlaUlaf.js";
2
- import { isFn } from "../is-fn-DY1wZ-md.js";
3
1
  import { Anarchy, AtomIOLogger, PRETTY_TOKEN_TYPES } from "atom.io";
4
2
  import { parseJson, stringifyJson } from "atom.io/json";
5
3
  import { SetRTX } from "atom.io/transceivers/set-rtx";
@@ -9,6 +7,120 @@ function arbitrary(random = Math.random) {
9
7
  return random().toString(36).slice(2);
10
8
  }
11
9
 
10
+ //#endregion
11
+ //#region src/internal/lineage.ts
12
+ function newest(scion) {
13
+ while (scion.child !== null) scion = scion.child;
14
+ return scion;
15
+ }
16
+ function eldest(scion) {
17
+ while (scion.parent !== null) scion = scion.parent;
18
+ return scion;
19
+ }
20
+
21
+ //#endregion
22
+ //#region src/internal/is-fn.ts
23
+ const NON_CTOR_FN_REGEX = /^\[object (?:Async|Generator|AsyncGenerator)?Function\]$/;
24
+ function isFn(input) {
25
+ const protoString = Object.prototype.toString.call(input);
26
+ return NON_CTOR_FN_REGEX.test(protoString);
27
+ }
28
+
29
+ //#endregion
30
+ //#region src/internal/set-state/become.ts
31
+ function become(nextVersionOfThing, originalThing) {
32
+ if (isFn(nextVersionOfThing)) return nextVersionOfThing(originalThing);
33
+ return nextVersionOfThing;
34
+ }
35
+
36
+ //#endregion
37
+ //#region src/internal/future.ts
38
+ /**
39
+ * A Promise whose incoming value can be hot swapped.
40
+ * @internal
41
+ * @private
42
+ * @typeParam T The type of the value that the promise will resolve to.
43
+ *
44
+ * @remarks
45
+ * Can be constructed like a Promise, or from an existing Promise.
46
+ */
47
+ var Future = class extends Promise {
48
+ fate;
49
+ resolve;
50
+ reject;
51
+ done = false;
52
+ constructor(executor) {
53
+ let superResolve;
54
+ let superReject;
55
+ super((resolve, reject) => {
56
+ superResolve = resolve;
57
+ superReject = reject;
58
+ });
59
+ this.resolve = superResolve;
60
+ this.reject = superReject;
61
+ this.use(executor instanceof Promise ? executor : new Promise(executor));
62
+ }
63
+ pass(promise, value) {
64
+ if (promise === this.fate) {
65
+ this.resolve(value);
66
+ this.done = true;
67
+ }
68
+ }
69
+ fail(promise, reason) {
70
+ if (promise === this.fate) {
71
+ this.reject(reason);
72
+ this.done = true;
73
+ }
74
+ }
75
+ use(value) {
76
+ if (this === value) return;
77
+ if (value instanceof Promise) {
78
+ const promise = value;
79
+ this.fate = promise;
80
+ promise.then((resolved) => {
81
+ this.pass(promise, resolved);
82
+ }, (reason) => {
83
+ this.fail(promise, reason);
84
+ });
85
+ } else {
86
+ this.resolve(value);
87
+ this.fate = void 0;
88
+ }
89
+ }
90
+ };
91
+
92
+ //#endregion
93
+ //#region src/internal/subject.ts
94
+ var Subject = class {
95
+ Subscriber;
96
+ subscribers = /* @__PURE__ */ new Map();
97
+ subscribe(key, subscriber) {
98
+ this.subscribers.set(key, subscriber);
99
+ const unsubscribe = () => {
100
+ this.unsubscribe(key);
101
+ };
102
+ return unsubscribe;
103
+ }
104
+ unsubscribe(key) {
105
+ this.subscribers.delete(key);
106
+ }
107
+ next(value) {
108
+ const subscribers = this.subscribers.values();
109
+ for (const subscriber of subscribers) subscriber(value);
110
+ }
111
+ };
112
+ var StatefulSubject = class extends Subject {
113
+ state;
114
+ constructor(initialState) {
115
+ super();
116
+ this.state = initialState;
117
+ }
118
+ next(value) {
119
+ this.state = value;
120
+ super.next(value);
121
+ }
122
+ };
123
+
12
124
  //#endregion
13
125
  //#region src/internal/store/circular-buffer.ts
14
126
  var CircularBuffer = class CircularBuffer {
@@ -37,6 +149,17 @@ var CircularBuffer = class CircularBuffer {
37
149
  }
38
150
  };
39
151
 
152
+ //#endregion
153
+ //#region src/internal/store/deposit.ts
154
+ function deposit(state) {
155
+ const token = {
156
+ key: state.key,
157
+ type: state.type
158
+ };
159
+ if (`family` in state) token.family = state.family;
160
+ return token;
161
+ }
162
+
40
163
  //#endregion
41
164
  //#region src/internal/overlays/map-overlay.ts
42
165
  var MapOverlay = class extends Map {
@@ -760,6 +883,15 @@ function ingestTransactionOutcomeEvent(store, event, applying) {
760
883
  }
761
884
  }
762
885
 
886
+ //#endregion
887
+ //#region src/internal/transaction/is-root-store.ts
888
+ function isRootStore(store) {
889
+ return `epoch` in store.transactionMeta;
890
+ }
891
+ function isChildStore(store) {
892
+ return `phase` in store.transactionMeta;
893
+ }
894
+
763
895
  //#endregion
764
896
  //#region src/internal/transaction/get-epoch-number.ts
765
897
  function getContinuityKey(store, transactionKey) {
@@ -1058,6 +1190,342 @@ const clearStore = (store) => {
1058
1190
  store.config = config;
1059
1191
  };
1060
1192
 
1193
+ //#endregion
1194
+ //#region src/internal/not-found-error.ts
1195
+ var NotFoundError = class extends Error {
1196
+ constructor(token, store) {
1197
+ super(`${PRETTY_TOKEN_TYPES[token.type]} ${stringifyJson(token.key)} not found in store "${store.config.name}".`);
1198
+ }
1199
+ };
1200
+
1201
+ //#endregion
1202
+ //#region src/internal/store/withdraw.ts
1203
+ function withdraw(store, token) {
1204
+ let withdrawn;
1205
+ let target = store;
1206
+ while (target !== null) {
1207
+ switch (token.type) {
1208
+ case `atom`:
1209
+ case `mutable_atom`:
1210
+ withdrawn = target.atoms.get(token.key);
1211
+ break;
1212
+ case `writable_pure_selector`:
1213
+ case `writable_held_selector`:
1214
+ withdrawn = target.writableSelectors.get(token.key);
1215
+ break;
1216
+ case `readonly_pure_selector`:
1217
+ case `readonly_held_selector`:
1218
+ withdrawn = target.readonlySelectors.get(token.key);
1219
+ break;
1220
+ case `atom_family`:
1221
+ case `mutable_atom_family`:
1222
+ case `writable_pure_selector_family`:
1223
+ case `readonly_pure_selector_family`:
1224
+ case `writable_held_selector_family`:
1225
+ case `readonly_held_selector_family`:
1226
+ withdrawn = target.families.get(token.key);
1227
+ break;
1228
+ case `timeline`:
1229
+ withdrawn = target.timelines.get(token.key);
1230
+ break;
1231
+ case `transaction`:
1232
+ withdrawn = target.transactions.get(token.key);
1233
+ break;
1234
+ }
1235
+ if (withdrawn) return withdrawn;
1236
+ target = target.child;
1237
+ }
1238
+ throw new NotFoundError(token, store);
1239
+ }
1240
+
1241
+ //#endregion
1242
+ //#region src/internal/get-state/get-fallback.ts
1243
+ function getFallback(store, token, family, subKey) {
1244
+ const disposal = store.disposalTraces.buffer.find((item) => item?.key === stringifyJson(subKey));
1245
+ store.logger.error(`❌`, token.type, token.key, `gets a fallback value because key`, subKey, `is not allocated`, disposal ? `This key was previously disposed:\n${disposal.trace}` : `(no previous disposal trace found)`);
1246
+ switch (family.type) {
1247
+ case `mutable_atom_family`: {
1248
+ if (store.defaults.has(family.key)) return store.defaults.get(family.key);
1249
+ const defaultValue = new family.class();
1250
+ store.defaults.set(family.key, defaultValue);
1251
+ return defaultValue.READONLY_VIEW;
1252
+ }
1253
+ case `atom_family`: {
1254
+ if (store.defaults.has(family.key)) return store.defaults.get(family.key);
1255
+ const def = family.default;
1256
+ const defaultValue = def(subKey);
1257
+ store.defaults.set(family.key, defaultValue);
1258
+ return defaultValue;
1259
+ }
1260
+ case `readonly_pure_selector_family`:
1261
+ case `writable_pure_selector_family`:
1262
+ case `readonly_held_selector_family`:
1263
+ case `writable_held_selector_family`: {
1264
+ if (store.defaults.has(family.key)) return store.defaults.get(family.key);
1265
+ const defaultValue = family.default(subKey);
1266
+ store.defaults.set(family.key, defaultValue);
1267
+ return defaultValue;
1268
+ }
1269
+ }
1270
+ }
1271
+
1272
+ //#endregion
1273
+ //#region src/internal/safe-compute.ts
1274
+ function safeCompute(target, state) {
1275
+ const { type, key, catch: canCatch } = state;
1276
+ switch (type) {
1277
+ case `readonly_pure_selector`:
1278
+ case `writable_pure_selector`: {
1279
+ let val;
1280
+ target.logger.info(`🧮`, type, key, `computing value`);
1281
+ try {
1282
+ val = state.getFrom(target);
1283
+ if (val instanceof Promise) return val.catch((thrown) => {
1284
+ target.logger.error(`💥`, type, key, `rejected:`, thrown);
1285
+ if (canCatch) {
1286
+ for (const Class of canCatch) if (thrown instanceof Class) return thrown;
1287
+ }
1288
+ throw thrown;
1289
+ });
1290
+ } catch (e) {
1291
+ target.logger.error(`💥`, type, key, `rejected:`, e);
1292
+ if (canCatch) {
1293
+ for (const Class of canCatch) if (e instanceof Class) return writeToCache(target, state, e);
1294
+ }
1295
+ throw e;
1296
+ }
1297
+ return writeToCache(target, state, val);
1298
+ }
1299
+ case `atom`: {
1300
+ let def;
1301
+ if (isFn(state.default)) try {
1302
+ def = state.default();
1303
+ if (def instanceof Promise) def = def.catch((thrown) => {
1304
+ target.logger.error(`💥`, type, key, `rejected:`, thrown);
1305
+ if (canCatch) {
1306
+ for (const Class of canCatch) if (thrown instanceof Class) return thrown;
1307
+ }
1308
+ throw thrown;
1309
+ });
1310
+ } catch (e) {
1311
+ target.logger.error(`💥`, type, key, `rejected:`, e);
1312
+ if (canCatch) {
1313
+ for (const Class of canCatch) if (e instanceof Class) {
1314
+ def = writeToCache(target, state, e);
1315
+ target.logger.info(`✨`, state.type, key, `computed default`, def);
1316
+ return def;
1317
+ }
1318
+ }
1319
+ throw e;
1320
+ }
1321
+ else {
1322
+ def = state.default;
1323
+ target.logger.info(`✨`, state.type, key, `using static default`, def);
1324
+ }
1325
+ return writeToCache(target, state, def);
1326
+ }
1327
+ }
1328
+ }
1329
+
1330
+ //#endregion
1331
+ //#region src/internal/get-state/read-or-compute-value.ts
1332
+ function readOrComputeValue(target, state, mut) {
1333
+ if (target.valueMap.has(state.key)) return readFromCache(target, state, mut);
1334
+ target.logger.info(`❔`, state.type, state.key, `value not found in cache`);
1335
+ const { key } = state;
1336
+ switch (state.type) {
1337
+ case `readonly_held_selector`:
1338
+ case `writable_held_selector`:
1339
+ target.logger.info(`🧮`, state.type, key, `computing value`);
1340
+ return state.getFrom(target);
1341
+ case `writable_pure_selector`:
1342
+ case `readonly_pure_selector`:
1343
+ case `atom`: return safeCompute(target, state);
1344
+ case `mutable_atom`: {
1345
+ const instance = new state.class();
1346
+ target.logger.info(`✨`, state.type, key, `created new instance`, instance);
1347
+ return writeToCache(target, state, instance);
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ //#endregion
1353
+ //#region src/internal/families/get-family-of-token.ts
1354
+ function getFamilyOfToken(store, token) {
1355
+ return withdraw(store, {
1356
+ key: token.family.key,
1357
+ type: `${token.type}_family`
1358
+ });
1359
+ }
1360
+
1361
+ //#endregion
1362
+ //#region src/internal/families/mint-in-store.ts
1363
+ const FAMILY_MEMBER_TOKEN_TYPES = {
1364
+ atom_family: `atom`,
1365
+ molecule_family: `molecule`,
1366
+ mutable_atom_family: `mutable_atom`,
1367
+ readonly_held_selector_family: `readonly_held_selector`,
1368
+ readonly_pure_selector_family: `readonly_pure_selector`,
1369
+ writable_held_selector_family: `writable_held_selector`,
1370
+ writable_pure_selector_family: `writable_pure_selector`
1371
+ };
1372
+ const MUST_CREATE = Symbol(`MUST_CREATE`);
1373
+ const DO_NOT_CREATE = Symbol(`DO_NOT_CREATE`);
1374
+ function mintInStore(mustCreate, store, family, key) {
1375
+ const stringKey = stringifyJson(key);
1376
+ const molecule = store.molecules.get(stringKey);
1377
+ if (!molecule && store.config.lifespan === `immortal`) {
1378
+ const { type: familyType, key: familyKey } = family;
1379
+ store.logger.warn(`💣`, `key`, stringKey, `was used to mint a counterfeit token for`, familyType, `"${familyKey}"`);
1380
+ const fullKey = `${familyKey}(${stringKey})`;
1381
+ const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
1382
+ return {
1383
+ counterfeit: true,
1384
+ key: fullKey,
1385
+ type,
1386
+ family: {
1387
+ key: familyKey,
1388
+ subKey: stringKey
1389
+ }
1390
+ };
1391
+ }
1392
+ let token;
1393
+ if (mustCreate === MUST_CREATE) {
1394
+ store.logger.info(`👪`, family.type, family.key, `adds member`, typeof key === `string` ? `\`${key}\`` : key);
1395
+ token = family.create(key);
1396
+ if (molecule) store.moleculeData.set(stringKey, family.key);
1397
+ } else {
1398
+ const { type: familyType, key: familyKey } = family;
1399
+ const fullKey = `${familyKey}(${stringKey})`;
1400
+ const type = FAMILY_MEMBER_TOKEN_TYPES[familyType];
1401
+ return {
1402
+ key: fullKey,
1403
+ type,
1404
+ family: {
1405
+ key: familyKey,
1406
+ subKey: stringKey
1407
+ }
1408
+ };
1409
+ }
1410
+ return token;
1411
+ }
1412
+
1413
+ //#endregion
1414
+ //#region src/internal/get-state/reduce-reference.ts
1415
+ function reduceReference(store, ...params) {
1416
+ let existingToken;
1417
+ let brandNewToken;
1418
+ let family;
1419
+ let subKey;
1420
+ let token;
1421
+ if (params.length === 1) {
1422
+ token = params[0];
1423
+ if (`family` in token) {
1424
+ const familyToken = getFamilyOfToken(store, token);
1425
+ family = withdraw(store, familyToken);
1426
+ subKey = parseJson(token.family.subKey);
1427
+ existingToken = seekInStore(store, familyToken, subKey);
1428
+ if (`counterfeit` in token) return {
1429
+ token,
1430
+ family,
1431
+ subKey,
1432
+ isNew: false
1433
+ };
1434
+ if (!existingToken) {
1435
+ brandNewToken = mintInStore(MUST_CREATE, store, familyToken, subKey);
1436
+ token = brandNewToken;
1437
+ } else token = existingToken;
1438
+ }
1439
+ } else {
1440
+ family = withdraw(store, params[0]);
1441
+ subKey = params[1];
1442
+ existingToken = seekInStore(store, family, subKey);
1443
+ if (!existingToken) {
1444
+ brandNewToken = mintInStore(MUST_CREATE, store, family, subKey);
1445
+ token = brandNewToken;
1446
+ } else token = existingToken;
1447
+ }
1448
+ const isCounterfeit = `counterfeit` in token;
1449
+ if (Boolean(brandNewToken) && isCounterfeit === false && family) {
1450
+ let subType;
1451
+ switch (token.type) {
1452
+ case `readonly_pure_selector`:
1453
+ case `readonly_held_selector`:
1454
+ subType = `readable`;
1455
+ break;
1456
+ case `atom`:
1457
+ case `mutable_atom`:
1458
+ case `writable_pure_selector`:
1459
+ case `writable_held_selector`:
1460
+ subType = `writable`;
1461
+ break;
1462
+ }
1463
+ const stateCreationEvent = {
1464
+ type: `state_creation`,
1465
+ subType,
1466
+ token,
1467
+ timestamp: Date.now()
1468
+ };
1469
+ family.subject.next(stateCreationEvent);
1470
+ const target = newest(store);
1471
+ if (token.family) {
1472
+ if (isRootStore(target)) switch (token.type) {
1473
+ case `atom`:
1474
+ case `mutable_atom`:
1475
+ store.on.atomCreation.next(token);
1476
+ break;
1477
+ case `writable_pure_selector`:
1478
+ case `readonly_pure_selector`:
1479
+ case `writable_held_selector`:
1480
+ case `readonly_held_selector`:
1481
+ store.on.selectorCreation.next(token);
1482
+ break;
1483
+ }
1484
+ else if (isChildStore(target) && target.on.transactionApplying.state === null) target.transactionMeta.update.subEvents.push(stateCreationEvent);
1485
+ }
1486
+ }
1487
+ return {
1488
+ token,
1489
+ family,
1490
+ subKey,
1491
+ isNew: Boolean(brandNewToken)
1492
+ };
1493
+ }
1494
+
1495
+ //#endregion
1496
+ //#region src/internal/get-state/get-from-store.ts
1497
+ function getFromStore(store, ...params) {
1498
+ const { token, family, subKey } = reduceReference(store, ...params);
1499
+ if (`counterfeit` in token && family && subKey) return getFallback(store, token, family, subKey);
1500
+ const state = withdraw(store, token);
1501
+ return readOrComputeValue(store, state);
1502
+ }
1503
+
1504
+ //#endregion
1505
+ //#region src/internal/families/seek-in-store.ts
1506
+ function seekInStore(store, token, key) {
1507
+ const subKey = stringifyJson(key);
1508
+ const fullKey = `${token.key}(${subKey})`;
1509
+ const target = newest(store);
1510
+ let state;
1511
+ switch (token.type) {
1512
+ case `atom_family`:
1513
+ case `mutable_atom_family`:
1514
+ state = target.atoms.get(fullKey);
1515
+ break;
1516
+ case `writable_held_selector_family`:
1517
+ case `writable_pure_selector_family`:
1518
+ state = target.writableSelectors.get(fullKey);
1519
+ break;
1520
+ case `readonly_held_selector_family`:
1521
+ case `readonly_pure_selector_family`:
1522
+ state = target.readonlySelectors.get(fullKey);
1523
+ break;
1524
+ }
1525
+ if (state) return deposit(state);
1526
+ return state;
1527
+ }
1528
+
1061
1529
  //#endregion
1062
1530
  //#region src/internal/families/find-in-store.ts
1063
1531
  function findInStore(store, familyToken, key) {
@@ -1316,6 +1784,330 @@ function disposeFromStore(store, ...params) {
1316
1784
  }
1317
1785
  }
1318
1786
 
1787
+ //#endregion
1788
+ //#region src/internal/operation.ts
1789
+ function openOperation(store, token) {
1790
+ if (store.operation.open) {
1791
+ const rejectionTime = performance.now();
1792
+ store.logger.info(`🚫`, token.type, token.key, `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`);
1793
+ return rejectionTime;
1794
+ }
1795
+ store.operation = {
1796
+ open: true,
1797
+ done: /* @__PURE__ */ new Set(),
1798
+ prev: /* @__PURE__ */ new Map(),
1799
+ timestamp: Date.now(),
1800
+ token,
1801
+ subEvents: []
1802
+ };
1803
+ store.logger.info(`⭕`, token.type, token.key, `operation start in store "${store.config.name}"${isChildStore(store) ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"` : ``}`);
1804
+ return store;
1805
+ }
1806
+ function closeOperation(store) {
1807
+ if (store.operation.open) store.logger.info(`🔴`, store.operation.token.type, store.operation.token.key, `operation done in store "${store.config.name}"`);
1808
+ store.operation = { open: false };
1809
+ store.on.operationClose.next(store.operation);
1810
+ }
1811
+ const isDone = (store, key) => {
1812
+ if (!store.operation.open) {
1813
+ store.logger.error(`🐞`, `unknown`, key, `isDone called outside of an operation. This is probably a bug in AtomIO.`);
1814
+ return true;
1815
+ }
1816
+ return store.operation.done.has(key);
1817
+ };
1818
+ const markDone = (store, key) => {
1819
+ if (!store.operation.open) {
1820
+ store.logger.error(`🐞`, `unknown`, key, `markDone called outside of an operation. This is probably a bug in AtomIO.`);
1821
+ return;
1822
+ }
1823
+ store.operation.done.add(key);
1824
+ };
1825
+
1826
+ //#endregion
1827
+ //#region src/internal/set-state/dispatch-state-update.ts
1828
+ function dispatchOrDeferStateUpdate(target, state, { oldValue, newValue }, stateIsNewlyCreated, family) {
1829
+ const token = deposit(state);
1830
+ if (stateIsNewlyCreated && family) {
1831
+ state.subject.next({ newValue });
1832
+ const stateCreationEvent = {
1833
+ checkpoint: true,
1834
+ type: `state_creation`,
1835
+ subType: `writable`,
1836
+ token,
1837
+ timestamp: Date.now(),
1838
+ value: newValue
1839
+ };
1840
+ target.operation.subEvents.push(stateCreationEvent);
1841
+ family.subject.next(stateCreationEvent);
1842
+ const innerTarget = newest(target);
1843
+ if (token.family) {
1844
+ if (isRootStore(innerTarget)) switch (token.type) {
1845
+ case `atom`:
1846
+ case `mutable_atom`:
1847
+ target.on.atomCreation.next(token);
1848
+ break;
1849
+ case `writable_pure_selector`:
1850
+ case `writable_held_selector`:
1851
+ target.on.selectorCreation.next(token);
1852
+ break;
1853
+ }
1854
+ else if (isChildStore(innerTarget) && innerTarget.on.transactionApplying.state === null) innerTarget.transactionMeta.update.subEvents.push(stateCreationEvent);
1855
+ }
1856
+ return;
1857
+ }
1858
+ const { key, subject, type } = state;
1859
+ const update = {
1860
+ oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
1861
+ newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue
1862
+ };
1863
+ if (isRootStore(target)) {
1864
+ switch (type) {
1865
+ case `mutable_atom`:
1866
+ target.logger.info(`📢`, type, key, `is now (`, newValue, `) subscribers:`, subject.subscribers.keys());
1867
+ break;
1868
+ case `atom`:
1869
+ case `writable_pure_selector`:
1870
+ case `writable_held_selector`: target.logger.info(`📢`, type, key, `went (`, oldValue, `->`, newValue, `) subscribers:`, subject.subscribers.keys());
1871
+ }
1872
+ subject.next(update);
1873
+ }
1874
+ if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
1875
+ if (target.on.transactionApplying.state === null) {
1876
+ if (isTransceiver(newValue)) return;
1877
+ const { timestamp } = target.operation;
1878
+ const atomUpdate = {
1879
+ type: `atom_update`,
1880
+ token,
1881
+ timestamp,
1882
+ update
1883
+ };
1884
+ target.transactionMeta.update.subEvents.push(atomUpdate);
1885
+ target.logger.info(`📁`, `atom`, key, `stowed (`, oldValue, `->`, newValue, `)`);
1886
+ return;
1887
+ }
1888
+ if (hasRole(state, `tracker:signal`)) {
1889
+ const keyOfMutable = key.slice(1);
1890
+ const mutable = target.atoms.get(keyOfMutable);
1891
+ if (readOrComputeValue(target, mutable, `mut`).do(update.newValue) === null === true) evictDownstreamFromAtom(target, mutable);
1892
+ }
1893
+ }
1894
+ }
1895
+
1896
+ //#endregion
1897
+ //#region src/internal/set-state/set-atom.ts
1898
+ const setAtom = (target, atom, next) => {
1899
+ const oldValue = readOrComputeValue(target, atom, `mut`);
1900
+ let newValue = become(next, oldValue);
1901
+ target.logger.info(`⭐`, `atom`, atom.key, `setting value`, newValue);
1902
+ newValue = writeToCache(target, atom, newValue);
1903
+ markDone(target, atom.key);
1904
+ evictDownstreamFromAtom(target, atom);
1905
+ return {
1906
+ oldValue,
1907
+ newValue
1908
+ };
1909
+ };
1910
+
1911
+ //#endregion
1912
+ //#region src/internal/set-state/reset-atom-or-selector.ts
1913
+ function resetAtom(target, atom) {
1914
+ switch (atom.type) {
1915
+ case `mutable_atom`: return setAtom(target, atom, new atom.class());
1916
+ case `atom`: {
1917
+ let def;
1918
+ if (isFn(atom.default)) def = safeCompute(target, atom);
1919
+ else def = atom.default;
1920
+ return setAtom(target, atom, def);
1921
+ }
1922
+ }
1923
+ }
1924
+ function resetAtomOrSelector(target, state) {
1925
+ let protoUpdate;
1926
+ switch (state.type) {
1927
+ case `atom`:
1928
+ case `mutable_atom`:
1929
+ protoUpdate = resetAtom(target, state);
1930
+ break;
1931
+ case `writable_held_selector`:
1932
+ {
1933
+ const atoms = traceRootSelectorAtoms(target, state.key);
1934
+ for (const atom of atoms.values()) {
1935
+ const rootProtoUpdate = resetAtom(target, atom);
1936
+ dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
1937
+ }
1938
+ const value = state.getFrom(target);
1939
+ protoUpdate = {
1940
+ oldValue: value,
1941
+ newValue: value
1942
+ };
1943
+ }
1944
+ break;
1945
+ case `writable_pure_selector`:
1946
+ {
1947
+ const oldValue = safeCompute(target, state);
1948
+ const atoms = traceRootSelectorAtoms(target, state.key);
1949
+ for (const atom of atoms.values()) {
1950
+ const rootProtoUpdate = resetAtom(target, atom);
1951
+ dispatchOrDeferStateUpdate(target, state, rootProtoUpdate, false);
1952
+ }
1953
+ const newValue = safeCompute(target, state);
1954
+ protoUpdate = {
1955
+ oldValue,
1956
+ newValue
1957
+ };
1958
+ }
1959
+ break;
1960
+ }
1961
+ return protoUpdate;
1962
+ }
1963
+
1964
+ //#endregion
1965
+ //#region src/internal/set-state/set-into-store.ts
1966
+ function setIntoStore(store, ...params) {
1967
+ operateOnStore(OWN_OP, store, ...params);
1968
+ }
1969
+
1970
+ //#endregion
1971
+ //#region src/internal/set-state/reset-in-store.ts
1972
+ const RESET_STATE = Symbol(`RESET`);
1973
+ function resetInStore(store, ...params) {
1974
+ const subParams = [...params, RESET_STATE];
1975
+ setIntoStore(store, ...subParams);
1976
+ }
1977
+
1978
+ //#endregion
1979
+ //#region src/internal/set-state/set-selector.ts
1980
+ function setSelector(target, selector, next) {
1981
+ let oldValue;
1982
+ let newValue;
1983
+ let constant;
1984
+ const { type, key } = selector;
1985
+ switch (selector.type) {
1986
+ case `writable_pure_selector`:
1987
+ oldValue = readOrComputeValue(target, selector, `mut`);
1988
+ newValue = become(next, oldValue);
1989
+ newValue = writeToCache(target, selector, newValue);
1990
+ break;
1991
+ case `writable_held_selector`:
1992
+ constant = selector.const;
1993
+ become(next, constant);
1994
+ oldValue = constant;
1995
+ newValue = constant;
1996
+ }
1997
+ target.logger.info(`⭐`, type, key, `setting to`, newValue);
1998
+ markDone(target, key);
1999
+ selector.setSelf(newValue);
2000
+ return {
2001
+ oldValue,
2002
+ newValue
2003
+ };
2004
+ }
2005
+
2006
+ //#endregion
2007
+ //#region src/internal/set-state/set-atom-or-selector.ts
2008
+ const setAtomOrSelector = (target, state, value) => {
2009
+ let protoUpdate;
2010
+ switch (state.type) {
2011
+ case `atom`:
2012
+ case `mutable_atom`:
2013
+ protoUpdate = setAtom(target, state, value);
2014
+ break;
2015
+ case `writable_pure_selector`:
2016
+ case `writable_held_selector`:
2017
+ protoUpdate = setSelector(target, state, value);
2018
+ break;
2019
+ }
2020
+ return protoUpdate;
2021
+ };
2022
+
2023
+ //#endregion
2024
+ //#region src/internal/set-state/operate-on-store.ts
2025
+ const OWN_OP = Symbol(`OWN_OP`);
2026
+ const JOIN_OP = Symbol(`JOIN_OP`);
2027
+ function operateOnStore(opMode, store, ...params) {
2028
+ let existingToken;
2029
+ let brandNewToken;
2030
+ let token;
2031
+ let family;
2032
+ let key;
2033
+ let value;
2034
+ if (params.length === 2) {
2035
+ token = params[0];
2036
+ value = params[1];
2037
+ if (`family` in token) {
2038
+ family = getFamilyOfToken(store, token);
2039
+ key = parseJson(token.family.subKey);
2040
+ existingToken = seekInStore(store, family, key);
2041
+ if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
2042
+ else token = existingToken;
2043
+ }
2044
+ } else {
2045
+ family = withdraw(store, params[0]);
2046
+ key = params[1];
2047
+ value = params[2];
2048
+ existingToken = seekInStore(store, family, key);
2049
+ if (!existingToken) token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
2050
+ else token = existingToken;
2051
+ }
2052
+ const action = value === RESET_STATE ? `reset` : `set`;
2053
+ let target;
2054
+ if (opMode === OWN_OP) {
2055
+ const result = openOperation(store, token);
2056
+ if (typeof result === `number`) {
2057
+ const rejectionTime = result;
2058
+ const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
2059
+ unsubscribe();
2060
+ store.logger.info(`🟢`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
2061
+ operateOnStore(opMode, store, token, value);
2062
+ });
2063
+ return;
2064
+ }
2065
+ target = result;
2066
+ } else target = store;
2067
+ if (`counterfeit` in token && `family` in token) {
2068
+ const subKey = token.family.subKey;
2069
+ const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
2070
+ store.logger.error(`❌`, token.type, token.key, `could not be`, action, `because key`, subKey, `is not allocated.`, disposal ? `this key was previously disposed:${disposal.trace}` : `(no previous disposal trace found)`);
2071
+ return;
2072
+ }
2073
+ const state = withdraw(target, token);
2074
+ let protoUpdate;
2075
+ if (value === RESET_STATE) protoUpdate = resetAtomOrSelector(target, state);
2076
+ else protoUpdate = setAtomOrSelector(target, state, value);
2077
+ dispatchOrDeferStateUpdate(target, state, protoUpdate, Boolean(brandNewToken), family);
2078
+ if (opMode === OWN_OP) closeOperation(target);
2079
+ }
2080
+
2081
+ //#endregion
2082
+ //#region src/internal/keys.ts
2083
+ const isAtomKey = (store, key) => newest(store).atoms.has(key);
2084
+ const isSelectorKey = (store, key) => newest(store).writableSelectors.has(key);
2085
+ const isReadonlySelectorKey = (store, key) => newest(store).readonlySelectors.has(key);
2086
+ const isStateKey = (store, key) => isAtomKey(store, key) || isSelectorKey(store, key) || isReadonlySelectorKey(store, key);
2087
+
2088
+ //#endregion
2089
+ //#region src/internal/selector/get-selector-dependency-keys.ts
2090
+ function getSelectorDependencyKeys(store, key) {
2091
+ return newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(store, source));
2092
+ }
2093
+
2094
+ //#endregion
2095
+ //#region src/internal/selector/trace-selector-atoms.ts
2096
+ function traceRootSelectorAtoms(store, selectorKey, covered = /* @__PURE__ */ new Set()) {
2097
+ const dependencies = getSelectorDependencyKeys(store, selectorKey);
2098
+ const roots = /* @__PURE__ */ new Map();
2099
+ while (dependencies.length > 0) {
2100
+ const dependencyKey = dependencies.pop();
2101
+ if (covered.has(dependencyKey)) continue;
2102
+ covered.add(dependencyKey);
2103
+ if (isAtomKey(store, dependencyKey)) {
2104
+ const atom = store.atoms.get(dependencyKey);
2105
+ roots.set(atom.key, atom);
2106
+ } else dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
2107
+ }
2108
+ return roots;
2109
+ }
2110
+
1319
2111
  //#endregion
1320
2112
  //#region src/internal/selector/update-selector-atoms.ts
1321
2113
  function updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered) {
@@ -1648,6 +2440,82 @@ function disposeSelector(store, selectorToken) {
1648
2440
  }
1649
2441
  }
1650
2442
 
2443
+ //#endregion
2444
+ //#region src/internal/subscribe/recall-state.ts
2445
+ const recallState = (store, state) => {
2446
+ const target = newest(store);
2447
+ if (target.operation.open) return target.operation.prev.get(state.key);
2448
+ return target.valueMap.get(state.key);
2449
+ };
2450
+
2451
+ //#endregion
2452
+ //#region src/internal/subscribe/subscribe-to-root-atoms.ts
2453
+ const subscribeToRootDependency = (target, selector, atom) => {
2454
+ return atom.subject.subscribe(`${selector.type}:${selector.key}`, (atomChange) => {
2455
+ target.logger.info(`📢`, selector.type, selector.key, `root`, atom.key, `went`, atomChange.oldValue, `->`, atomChange.newValue);
2456
+ const oldValue = recallState(target, selector);
2457
+ const newValue = readOrComputeValue(target, selector);
2458
+ target.logger.info(`✨`, selector.type, selector.key, `went`, oldValue, `->`, newValue);
2459
+ selector.subject.next({
2460
+ newValue,
2461
+ oldValue
2462
+ });
2463
+ });
2464
+ };
2465
+
2466
+ //#endregion
2467
+ //#region src/internal/subscribe/subscribe-to-state.ts
2468
+ function subscribeToState(store, token, key, handleUpdate) {
2469
+ function safelyHandleUpdate(update) {
2470
+ if (store.operation.open) {
2471
+ if (state?.type === `atom` && hasRole(state, `tracker:signal`) && `*` + store.operation.token.key === token.key && `inboundTracker` in handleUpdate) return;
2472
+ const unsubscribe$1 = store.on.operationClose.subscribe(`state subscription ${key}`, () => {
2473
+ unsubscribe$1();
2474
+ handleUpdate(update);
2475
+ });
2476
+ } else handleUpdate(update);
2477
+ }
2478
+ reduceReference(store, token);
2479
+ const state = withdraw(store, token);
2480
+ store.logger.info(`👀`, state.type, state.key, `Adding subscription "${key}"`);
2481
+ const isSelector = state.type === `writable_pure_selector` || state.type === `readonly_pure_selector`;
2482
+ const rootSubs = /* @__PURE__ */ new Map();
2483
+ let updateHandler = safelyHandleUpdate;
2484
+ if (isSelector) {
2485
+ readOrComputeValue(store, state);
2486
+ for (const [atomKey, atom] of traceRootSelectorAtoms(store, state.key)) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
2487
+ updateHandler = function updateRootsBeforeHandlingUpdate(update) {
2488
+ const dependencies = traceRootSelectorAtoms(store, state.key);
2489
+ for (const [previousRootKey, unsub] of rootSubs) if (dependencies.get(previousRootKey)) dependencies.delete(previousRootKey);
2490
+ else {
2491
+ unsub();
2492
+ rootSubs.delete(previousRootKey);
2493
+ }
2494
+ for (const [atomKey, atom] of dependencies) rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
2495
+ safelyHandleUpdate(update);
2496
+ };
2497
+ }
2498
+ const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
2499
+ const unsubscribe = () => {
2500
+ store.logger.info(`🙈`, state.type, state.key, `Removing subscription "${key}"`);
2501
+ mainUnsubFunction();
2502
+ for (const unsubFromDependency of rootSubs.values()) unsubFromDependency();
2503
+ };
2504
+ return unsubscribe;
2505
+ }
2506
+
2507
+ //#endregion
2508
+ //#region src/internal/subscribe/subscribe-to-timeline.ts
2509
+ const subscribeToTimeline = (store, token, key, handleUpdate) => {
2510
+ const tl = withdraw(store, token);
2511
+ store.logger.info(`👀`, `timeline`, token.key, `Adding subscription "${key}"`);
2512
+ const unsubscribe = tl.subject.subscribe(key, handleUpdate);
2513
+ return () => {
2514
+ store.logger.info(`🙈`, `timeline`, token.key, `Removing subscription "${key}" from timeline`);
2515
+ unsubscribe();
2516
+ };
2517
+ };
2518
+
1651
2519
  //#endregion
1652
2520
  //#region src/internal/subscribe/subscribe-to-transaction.ts
1653
2521
  const subscribeToTransaction = (store, token, key, handleUpdate) => {
@@ -1675,6 +2543,93 @@ function subscribeInStore(store, token, handleUpdate, key = arbitrary()) {
1675
2543
  }
1676
2544
  }
1677
2545
 
2546
+ //#endregion
2547
+ //#region src/internal/mutable/tracker.ts
2548
+ /**
2549
+ * @internal Give the tracker a transceiver state and a store, and it will
2550
+ * subscribe to the transceiver's inner value. When the inner value changes,
2551
+ * the tracker will update its own state to reflect the change.
2552
+ */
2553
+ var Tracker = class {
2554
+ initializeSignalAtom(mutableState, store) {
2555
+ const latestSignalStateKey = `*${mutableState.key}`;
2556
+ store.atoms.delete(latestSignalStateKey);
2557
+ store.valueMap.delete(latestSignalStateKey);
2558
+ const familyMetaData = mutableState.family ? {
2559
+ key: `*${mutableState.family.key}`,
2560
+ subKey: mutableState.family.subKey
2561
+ } : void 0;
2562
+ const latestSignalState = createRegularAtom(store, {
2563
+ key: latestSignalStateKey,
2564
+ default: null
2565
+ }, familyMetaData, [`tracker:signal`]);
2566
+ if (store.parent?.valueMap.has(latestSignalStateKey)) {
2567
+ const parentValue = store.parent.valueMap.get(latestSignalStateKey);
2568
+ store.valueMap.set(latestSignalStateKey, parentValue);
2569
+ }
2570
+ return latestSignalState;
2571
+ }
2572
+ unsubscribeFromInnerValue;
2573
+ unsubscribeFromState;
2574
+ captureSignalsFromCore(mutableState, latestSignalState, target) {
2575
+ const stateKey = mutableState.key;
2576
+ const storeName = target.config.name;
2577
+ const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
2578
+ const subscriptionKey = `tracker-from-core:${storeName}:${storeStatus}:${stateKey}`;
2579
+ const trackerCapturesOutboundSignal = (update) => {
2580
+ operateOnStore(JOIN_OP, target, latestSignalState, update);
2581
+ };
2582
+ this.unsubscribeFromInnerValue = getFromStore(target, mutableState).subscribe(subscriptionKey, trackerCapturesOutboundSignal);
2583
+ this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, function trackerLooksForNewReference(update) {
2584
+ if (update.newValue !== update.oldValue) {
2585
+ this.unsubscribeFromInnerValue();
2586
+ this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
2587
+ }
2588
+ }.bind(this));
2589
+ }
2590
+ supplySignalsToCore(mutableState, latestSignalState, target) {
2591
+ const stateKey = mutableState.key;
2592
+ const storeName = target.config.name;
2593
+ const storeStatus = isChildStore(target) ? target.transactionMeta.update.token.key : `main`;
2594
+ const subscriptionKey = `tracker-to-core:${storeName}:${storeStatus}:${stateKey}`;
2595
+ subscribeToState(target, latestSignalState, subscriptionKey, Object.assign(function trackerCapturesInboundSignal({ newValue, oldValue }) {
2596
+ const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
2597
+ if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
2598
+ const unsubscribe = subscribeToTimeline(target, {
2599
+ key: timelineId,
2600
+ type: `timeline`
2601
+ }, subscriptionKey, function trackerWaitsForTimeTravelToFinish(update) {
2602
+ unsubscribe();
2603
+ setIntoStore(target, mutableState, (transceiver) => {
2604
+ if (update === `redo` && newValue) transceiver.do(newValue);
2605
+ else if (update === `undo` && oldValue) transceiver.undo(oldValue);
2606
+ return transceiver;
2607
+ });
2608
+ });
2609
+ return;
2610
+ }
2611
+ setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
2612
+ }, { inboundTracker: true }));
2613
+ }
2614
+ mutableAtomToken;
2615
+ latestSignalToken;
2616
+ [Symbol.dispose];
2617
+ constructor(mutableAtomToken, store) {
2618
+ const target = newest(store);
2619
+ const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target);
2620
+ this.mutableAtomToken = mutableAtomToken;
2621
+ this.latestSignalToken = latestSignalToken;
2622
+ this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target);
2623
+ this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target);
2624
+ target.trackers.set(mutableAtomToken.key, this);
2625
+ this[Symbol.dispose] = () => {
2626
+ this.unsubscribeFromInnerValue();
2627
+ this.unsubscribeFromState();
2628
+ target.trackers.delete(mutableAtomToken.key);
2629
+ };
2630
+ }
2631
+ };
2632
+
1678
2633
  //#endregion
1679
2634
  //#region src/internal/mutable/create-mutable-atom.ts
1680
2635
  function createMutableAtom(store, options, family) {
@@ -1861,6 +2816,177 @@ const getUpdateToken = (mutableAtomToken) => {
1861
2816
  return updateToken;
1862
2817
  };
1863
2818
 
2819
+ //#endregion
2820
+ //#region src/internal/mutable/transceiver.ts
2821
+ function isTransceiver(value) {
2822
+ return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value && `READONLY_VIEW` in value && `toJSON` in value;
2823
+ }
2824
+
2825
+ //#endregion
2826
+ //#region src/internal/caching.ts
2827
+ function writeToCache(target, state, value) {
2828
+ const { key, subject, type } = state;
2829
+ const currentValue = target.valueMap.get(key);
2830
+ if (currentValue instanceof Future && !currentValue.done) {
2831
+ const future = currentValue;
2832
+ if (value instanceof Promise) {
2833
+ future.use(value);
2834
+ return future;
2835
+ }
2836
+ target.valueMap.set(key, value);
2837
+ return value;
2838
+ }
2839
+ if (value instanceof Promise) {
2840
+ const future = new Future(value);
2841
+ target.valueMap.set(key, future);
2842
+ future.then(function handleResolvedFuture(resolved) {
2843
+ if (target.valueMap.get(key) === future) {
2844
+ openOperation(target, state);
2845
+ writeToCache(target, state, resolved);
2846
+ switch (type) {
2847
+ case `atom`:
2848
+ evictDownstreamFromAtom(target, state);
2849
+ break;
2850
+ case `readonly_pure_selector`:
2851
+ case `writable_pure_selector`:
2852
+ evictDownstreamFromSelector(target, key);
2853
+ break;
2854
+ }
2855
+ closeOperation(target);
2856
+ subject.next({
2857
+ newValue: resolved,
2858
+ oldValue: future
2859
+ });
2860
+ }
2861
+ }).catch((thrown) => {
2862
+ target.logger.error(`💥`, state.type, key, `rejected:`, thrown);
2863
+ });
2864
+ return future;
2865
+ }
2866
+ target.logger.info(`📝`, state.type, state.key, `writing to cache`, value);
2867
+ target.valueMap.set(key, value);
2868
+ return value;
2869
+ }
2870
+ /**
2871
+ * @param target - the newest layer of the store
2872
+ * @param state - the state to read from cache
2873
+ * @param mut - whether the value is intended to be mutable
2874
+ * @returns the state's current value
2875
+ */
2876
+ function readFromCache(target, state, mut) {
2877
+ target.logger.info(`📖`, state.type, state.key, `reading cached value`);
2878
+ let value = target.valueMap.get(state.key);
2879
+ if (mut === `mut` && state.type === `mutable_atom` && isChildStore(target)) {
2880
+ const mutableAtom$1 = state;
2881
+ const { parent } = target;
2882
+ if (target.valueMap.hasOwn(mutableAtom$1.key)) return value;
2883
+ const parentValue = parent.valueMap.get(mutableAtom$1.key);
2884
+ target.logger.info(`📃`, `atom`, mutableAtom$1.key, `copying`);
2885
+ const jsonValue = parentValue.toJSON();
2886
+ const copiedValue = mutableAtom$1.class.fromJSON(jsonValue);
2887
+ target.valueMap.set(mutableAtom$1.key, copiedValue);
2888
+ new Tracker(mutableAtom$1, parent);
2889
+ value = copiedValue;
2890
+ }
2891
+ return value;
2892
+ }
2893
+ function evictCachedValue(target, key) {
2894
+ const currentValue = target.valueMap.get(key);
2895
+ if (currentValue instanceof Future) {
2896
+ const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
2897
+ if (selector) selector.getFrom(target);
2898
+ return;
2899
+ }
2900
+ if (target.operation.open) target.operation.prev.set(key, currentValue);
2901
+ target.valueMap.delete(key);
2902
+ target.logger.info(`🗑`, `state`, key, `evicted`);
2903
+ }
2904
+
2905
+ //#endregion
2906
+ //#region src/internal/set-state/evict-downstream.ts
2907
+ function evictDownstreamFromAtom(store, atom) {
2908
+ const target = newest(store);
2909
+ const { key, type } = atom;
2910
+ const downstreamKeys = target.selectorAtoms.getRelatedKeys(key);
2911
+ target.logger.info(`🧹`, type, key, downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`, downstreamKeys ?? `to evict`);
2912
+ if (downstreamKeys) {
2913
+ if (target.operation.open) target.logger.info(`🧹`, type, key, `[ ${[...target.operation.done].join(`, `)} ] already done`);
2914
+ for (const downstreamKey of downstreamKeys) {
2915
+ if (isDone(target, downstreamKey)) continue;
2916
+ evictCachedValue(target, downstreamKey);
2917
+ markDone(target, downstreamKey);
2918
+ }
2919
+ }
2920
+ }
2921
+ function evictDownstreamFromSelector(store, selectorKey) {
2922
+ const target = newest(store);
2923
+ const relationEntries = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: selectorKey }).filter(([_, { source }]) => source === selectorKey);
2924
+ for (const [downstreamSelectorKey] of relationEntries) {
2925
+ if (isDone(target, downstreamSelectorKey)) continue;
2926
+ evictCachedValue(target, downstreamSelectorKey);
2927
+ markDone(target, downstreamSelectorKey);
2928
+ evictDownstreamFromSelector(store, downstreamSelectorKey);
2929
+ }
2930
+ }
2931
+
2932
+ //#endregion
2933
+ //#region src/internal/atom/create-regular-atom.ts
2934
+ function createRegularAtom(store, options, family, internalRoles) {
2935
+ const type = `atom`;
2936
+ const { key } = options;
2937
+ store.logger.info(`🔨`, type, key, `is being created`);
2938
+ const target = newest(store);
2939
+ const existing = target.atoms.get(key);
2940
+ if (existing && existing.type === type) {
2941
+ store.logger.error(`❌`, `atom`, key, `Tried to create atom, but it already exists in the store.`);
2942
+ return deposit(existing);
2943
+ }
2944
+ const subject = new Subject();
2945
+ const newAtom = {
2946
+ ...options,
2947
+ type,
2948
+ install: (s) => {
2949
+ s.logger.info(`🛠️`, type, key, `installing in store "${s.config.name}"`);
2950
+ return createRegularAtom(s, options, family);
2951
+ },
2952
+ subject
2953
+ };
2954
+ if (family) newAtom.family = family;
2955
+ if (internalRoles) newAtom.internalRoles = internalRoles;
2956
+ target.atoms.set(key, newAtom);
2957
+ const token = deposit(newAtom);
2958
+ if (options.effects) {
2959
+ let effectIndex = 0;
2960
+ const cleanupFunctions = [];
2961
+ for (const effect of options.effects) {
2962
+ const cleanup = effect({
2963
+ resetSelf: () => {
2964
+ resetInStore(store, token);
2965
+ },
2966
+ setSelf: (next) => {
2967
+ setIntoStore(store, token, next);
2968
+ },
2969
+ onSet: (handle) => subscribeToState(store, token, `effect[${effectIndex}]`, handle)
2970
+ });
2971
+ if (cleanup) cleanupFunctions.push(cleanup);
2972
+ ++effectIndex;
2973
+ }
2974
+ newAtom.cleanup = () => {
2975
+ for (const cleanup of cleanupFunctions) cleanup();
2976
+ };
2977
+ }
2978
+ store.on.atomCreation.next(token);
2979
+ return token;
2980
+ }
2981
+
2982
+ //#endregion
2983
+ //#region src/internal/atom/has-role.ts
2984
+ const INTERNAL_ROLES = [`tracker:signal`];
2985
+ function hasRole(atom, role) {
2986
+ if (`internalRoles` in atom === false) return false;
2987
+ return atom.internalRoles.includes(role);
2988
+ }
2989
+
1864
2990
  //#endregion
1865
2991
  //#region src/internal/atom/dispose-atom.ts
1866
2992
  function disposeAtom(store, atomToken) {
@@ -2650,5 +3776,5 @@ const timeTravel = (store, action, token) => {
2650
3776
  };
2651
3777
 
2652
3778
  //#endregion
2653
- export { CircularBuffer, FamilyTracker, Future, IMPLICIT, INTERNAL_ROLES, Join, Junction, MapOverlay, NotFoundError, RESET_STATE, RelationsOverlay, SetOverlay, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, capitalize, claimWithinStore, clearStore, closeOperation, createClaimTX, createDeallocateTX, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFamilyOfToken, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, hasRole, ingestAtomUpdateEvent, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdateEvent, ingestTransactionOutcomeEvent, installIntoStore, isAtomKey, isChildStore, isDone, isFn, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, readFromCache, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw, writeToCache };
3779
+ export { CircularBuffer, FamilyTracker, Future, IMPLICIT, INTERNAL_ROLES, JOIN_OP, Join, Junction, MapOverlay, NotFoundError, OWN_OP, RESET_STATE, RelationsOverlay, SetOverlay, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, capitalize, claimWithinStore, clearStore, closeOperation, createClaimTX, createDeallocateTX, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, eldest, evictCachedValue, evictDownstreamFromAtom, evictDownstreamFromSelector, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFamilyOfToken, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, hasRole, ingestAtomUpdateEvent, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdateEvent, ingestTransactionOutcomeEvent, installIntoStore, isAtomKey, isChildStore, isDone, isFn, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, operateOnStore, readFromCache, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw, writeToCache };
2654
3780
  //# sourceMappingURL=index.js.map