atom.io 0.27.5 → 0.28.1

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 (73) hide show
  1. package/data/dist/index.d.ts +31 -29
  2. package/data/dist/index.js +16 -17
  3. package/data/src/join.ts +17 -19
  4. package/dist/{chunk-6ABWLAGY.js → chunk-6WL4RQMQ.js} +314 -249
  5. package/dist/chunk-D52JNVER.js +721 -0
  6. package/dist/chunk-YQ46F5O2.js +95 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +3 -1
  9. package/internal/dist/index.d.ts +72 -36
  10. package/internal/dist/index.js +1 -1
  11. package/internal/src/atom/dispose-atom.ts +2 -9
  12. package/internal/src/families/dispose-from-store.ts +29 -18
  13. package/internal/src/families/find-in-store.ts +17 -7
  14. package/internal/src/get-state/get-from-store.ts +41 -32
  15. package/internal/src/ingest-updates/ingest-creation-disposal.ts +10 -1
  16. package/internal/src/molecule/dispose-molecule.ts +6 -17
  17. package/internal/src/pretty-print.ts +1 -16
  18. package/internal/src/selector/dispose-selector.ts +2 -9
  19. package/internal/src/set-state/set-into-store.ts +17 -19
  20. package/internal/src/store/circular-buffer.ts +34 -0
  21. package/internal/src/store/counterfeit.ts +109 -0
  22. package/internal/src/store/deposit.ts +14 -0
  23. package/internal/src/store/index.ts +1 -0
  24. package/internal/src/store/store.ts +3 -0
  25. package/internal/src/store/withdraw.ts +15 -10
  26. package/internal/src/transaction/build-transaction.ts +1 -0
  27. package/introspection/dist/index.d.ts +84 -4
  28. package/introspection/dist/index.js +1 -392
  29. package/introspection/src/attach-introspection-states.ts +7 -4
  30. package/introspection/src/attach-type-selectors.ts +26 -0
  31. package/introspection/src/differ.ts +167 -0
  32. package/introspection/src/index.ts +2 -0
  33. package/introspection/src/refinery.ts +100 -0
  34. package/json/dist/index.d.ts +31 -30
  35. package/json/dist/index.js +2 -77
  36. package/json/src/entries.ts +6 -0
  37. package/json/src/index.ts +53 -6
  38. package/package.json +18 -9
  39. package/react-devtools/dist/index.d.ts +1 -91
  40. package/react-devtools/dist/index.js +285 -414
  41. package/react-devtools/src/AtomIODevtools.tsx +2 -2
  42. package/react-devtools/src/StateEditor.tsx +20 -12
  43. package/react-devtools/src/StateIndex.tsx +10 -27
  44. package/react-devtools/src/TimelineIndex.tsx +3 -3
  45. package/react-devtools/src/TransactionIndex.tsx +6 -6
  46. package/react-devtools/src/Updates.tsx +2 -3
  47. package/react-devtools/src/index.ts +0 -71
  48. package/react-devtools/src/store.ts +51 -0
  49. package/realtime/dist/index.d.ts +7 -7
  50. package/realtime/dist/index.js +18 -22
  51. package/realtime/src/realtime-continuity.ts +30 -37
  52. package/realtime-client/dist/index.js +24 -10
  53. package/realtime-client/src/pull-atom-family-member.ts +2 -0
  54. package/realtime-client/src/pull-mutable-atom-family-member.ts +2 -0
  55. package/realtime-client/src/pull-selector-family-member.ts +2 -0
  56. package/realtime-client/src/realtime-client-stores/client-main-store.ts +6 -6
  57. package/realtime-client/src/sync-continuity.ts +28 -6
  58. package/realtime-server/dist/index.js +41 -5
  59. package/realtime-server/src/ipc-sockets/child-socket.ts +2 -0
  60. package/realtime-server/src/realtime-continuity-synchronizer.ts +42 -78
  61. package/realtime-testing/dist/index.d.ts +2 -0
  62. package/realtime-testing/dist/index.js +50 -8
  63. package/realtime-testing/src/setup-realtime-test.tsx +61 -9
  64. package/src/logger.ts +1 -0
  65. package/src/silo.ts +7 -3
  66. package/transceivers/set-rtx/src/set-rtx.ts +1 -0
  67. package/web/dist/index.d.ts +9 -0
  68. package/{dist/chunk-H6EDLPKH.js → web/dist/index.js} +5 -4
  69. package/web/package.json +13 -0
  70. package/web/src/index.ts +1 -0
  71. package/web/src/persist-sync.ts +25 -0
  72. package/dist/chunk-AK23DRMD.js +0 -21
  73. package/dist/chunk-IW6WYRS7.js +0 -140
@@ -67,6 +67,37 @@ function eldest(scion) {
67
67
  }
68
68
  return scion;
69
69
  }
70
+ var FAMILY_MEMBER_TOKEN_TYPES = {
71
+ atom_family: `atom`,
72
+ mutable_atom_family: `mutable_atom`,
73
+ selector_family: `selector`,
74
+ readonly_selector_family: `readonly_selector`,
75
+ molecule_family: `molecule`
76
+ };
77
+ function counterfeit(token, key) {
78
+ const subKey = stringifyJson(key);
79
+ const fullKey = `${token.key}(${subKey})`;
80
+ const type = FAMILY_MEMBER_TOKEN_TYPES[token.type];
81
+ const stateToken = {
82
+ key: fullKey,
83
+ type
84
+ };
85
+ if (type === `molecule`) {
86
+ Object.assign(stateToken, {
87
+ key,
88
+ family: token
89
+ });
90
+ } else {
91
+ Object.assign(stateToken, {
92
+ family: {
93
+ key: token.key,
94
+ subKey
95
+ }
96
+ });
97
+ }
98
+ Object.assign(stateToken, { counterfeit: true });
99
+ return stateToken;
100
+ }
70
101
 
71
102
  // internal/src/store/deposit.ts
72
103
  function deposit(state) {
@@ -145,22 +176,7 @@ var abortTransaction = (store) => {
145
176
  // internal/src/pretty-print.ts
146
177
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
147
178
  function prettyPrintTokenType(token) {
148
- switch (token.type) {
149
- case `atom_family`:
150
- return `Atom Family`;
151
- case `molecule_family`:
152
- return `Molecule Family`;
153
- case `mutable_atom_family`:
154
- return `Mutable Atom Family`;
155
- case `readonly_selector`:
156
- return `Readonly Selector`;
157
- case `readonly_selector_family`:
158
- return `Readonly Selector Family`;
159
- case `selector_family`:
160
- return `Selector Family`;
161
- default:
162
- return capitalize(token.type);
163
- }
179
+ return token.type.split(`_`).map(capitalize).join(` `);
164
180
  }
165
181
 
166
182
  // internal/src/not-found-error.ts
@@ -490,6 +506,8 @@ function createAtomFamily(store, options) {
490
506
  }
491
507
  return createRegularAtomFamily(store, options);
492
508
  }
509
+
510
+ // internal/src/get-state/get-from-store.ts
493
511
  function getFromStore(store, ...params) {
494
512
  let token;
495
513
  if (params.length === 1) {
@@ -497,35 +515,47 @@ function getFromStore(store, ...params) {
497
515
  } else {
498
516
  const family = params[0];
499
517
  const key = params[1];
500
- const maybeToken = family.type === `molecule_family` ? seekInStore(store, family, key) : store.config.lifespan === `immortal` ? seekInStore(store, family, key) : findInStore(store, family, key);
501
- if (!maybeToken) {
502
- store.logger.error(
503
- `\u2757`,
504
- family.type,
505
- family.key,
506
- `tried to get member`,
507
- stringifyJson(key),
508
- `but it was not found in store`,
509
- store.config.name
510
- );
511
- switch (family.type) {
512
- case `atom_family`:
513
- case `mutable_atom_family`:
514
- return store.defaults.get(family.key);
515
- case `selector_family`:
516
- case `readonly_selector_family`: {
517
- if (store.defaults.has(family.key)) {
518
- return store.defaults.get(family.key);
519
- }
520
- const defaultValue = withdraw(family, store).default(key);
521
- store.defaults.set(family.key, defaultValue);
522
- return defaultValue;
518
+ let maybeToken;
519
+ if (family.type === `molecule_family`) {
520
+ maybeToken = seekInStore(store, family, key) ?? counterfeit(family, key);
521
+ } else {
522
+ maybeToken = findInStore(store, family, key);
523
+ }
524
+ token = maybeToken;
525
+ }
526
+ if (`counterfeit` in token && `family` in token) {
527
+ const family = token.type === `molecule` ? withdraw(token.family, store) : (
528
+ // biome-ignore lint/style/noNonNullAssertion: family must be present
529
+ store.families.get(token.family.key)
530
+ );
531
+ const subKey = token.type === `molecule` ? token.key : token.family.subKey;
532
+ const disposal = store.disposalTraces.buffer.find(
533
+ (item) => item?.key === token.key
534
+ );
535
+ store.logger.error(
536
+ `\u274C`,
537
+ token.type,
538
+ token.key,
539
+ `could not be retrieved because it was not found in the store "${store.config.name}".`,
540
+ disposal ? `This state was previously disposed:
541
+ ${disposal.trace}` : `No previous disposal trace was found.`
542
+ );
543
+ switch (family.type) {
544
+ case `atom_family`:
545
+ case `mutable_atom_family`:
546
+ return store.defaults.get(family.key);
547
+ case `selector_family`:
548
+ case `readonly_selector_family`: {
549
+ if (store.defaults.has(family.key)) {
550
+ return store.defaults.get(token.family.key);
523
551
  }
524
- case `molecule_family`:
525
- throw new NotFoundError(family, key, store);
552
+ const defaultValue = withdraw(family, store).default(subKey);
553
+ store.defaults.set(family.key, defaultValue);
554
+ return defaultValue;
526
555
  }
556
+ case `molecule_family`:
557
+ throw new NotFoundError(family, subKey, store);
527
558
  }
528
- token = maybeToken;
529
559
  }
530
560
  switch (token.type) {
531
561
  case `atom`:
@@ -806,15 +836,8 @@ function createStandaloneSelector(store, options) {
806
836
  function disposeSelector(selectorToken, store) {
807
837
  const target = newest(store);
808
838
  const { key } = selectorToken;
809
- const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key);
810
- if (!selector) {
811
- store.logger.info(
812
- `\u274C`,
813
- `selector`,
814
- key,
815
- `Tried to dispose selector, but it does not exist in the store.`
816
- );
817
- } else if (!selector.family) {
839
+ const selector = withdraw(selectorToken, target);
840
+ if (!selector.family) {
818
841
  store.logger.error(
819
842
  `\u274C`,
820
843
  `selector`,
@@ -992,21 +1015,12 @@ function createSelectorFamily(store, options) {
992
1015
  // internal/src/molecule/dispose-molecule.ts
993
1016
  function disposeMolecule(token, store) {
994
1017
  let molecule;
995
- try {
996
- molecule = withdraw(token, store);
997
- } catch (thrown) {
998
- if (thrown instanceof Error) {
999
- store.logger.error(
1000
- `\u{1F41E}`,
1001
- `molecule`,
1002
- JSON.stringify(token.key),
1003
- `Failed to dispose molecule, because it was not found in the store.`,
1004
- thrown.message
1005
- );
1006
- }
1007
- return;
1008
- }
1018
+ molecule = withdraw(token, store);
1009
1019
  const { family } = token;
1020
+ for (const join of molecule.joins.values()) {
1021
+ join.relations.delete(molecule.key);
1022
+ join.molecules.delete(molecule.stringKey);
1023
+ }
1010
1024
  const context = [];
1011
1025
  for (const above of molecule.above.values()) {
1012
1026
  context.push(deposit(above));
@@ -1050,183 +1064,11 @@ function disposeMolecule(token, store) {
1050
1064
  }
1051
1065
  store.molecules.delete(molecule.stringKey);
1052
1066
  }
1053
- for (const join of molecule.joins.values()) {
1054
- join.molecules.delete(molecule.stringKey);
1055
- }
1056
1067
  for (const parent of molecule.above.values()) {
1057
1068
  parent.below.delete(molecule.stringKey);
1058
1069
  }
1059
1070
  }
1060
1071
 
1061
- // internal/src/families/init-family-member.ts
1062
- function initFamilyMemberInStore(store, token, key) {
1063
- const familyKey = token.key;
1064
- const family = store.families.get(familyKey);
1065
- if (family === void 0) {
1066
- throw new NotFoundError(token, store);
1067
- }
1068
- const state = family(key);
1069
- const target = newest(store);
1070
- if (state.family && target.moleculeInProgress === null) {
1071
- if (isRootStore(target)) {
1072
- switch (state.type) {
1073
- case `atom`:
1074
- case `mutable_atom`:
1075
- store.on.atomCreation.next(state);
1076
- break;
1077
- case `selector`:
1078
- case `readonly_selector`:
1079
- store.on.selectorCreation.next(state);
1080
- break;
1081
- }
1082
- } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1083
- target.transactionMeta.update.updates.push({
1084
- type: `state_creation`,
1085
- token: state
1086
- });
1087
- }
1088
- }
1089
- return state;
1090
- }
1091
- function seekInStore(store, token, key) {
1092
- const subKey = stringifyJson(key);
1093
- const fullKey = `${token.key}(${subKey})`;
1094
- const target = newest(store);
1095
- let state;
1096
- switch (token.type) {
1097
- case `atom_family`:
1098
- case `mutable_atom_family`:
1099
- state = target.atoms.get(fullKey);
1100
- break;
1101
- case `selector_family`:
1102
- state = target.selectors.get(fullKey);
1103
- break;
1104
- case `readonly_selector_family`:
1105
- state = target.readonlySelectors.get(fullKey);
1106
- break;
1107
- case `molecule_family`:
1108
- state = target.molecules.get(stringifyJson(key));
1109
- }
1110
- if (state) {
1111
- return deposit(state);
1112
- }
1113
- return state;
1114
- }
1115
-
1116
- // internal/src/families/find-in-store.ts
1117
- function findInStore(store, token, key) {
1118
- if (store.config.lifespan === `immortal`) {
1119
- throw new Error(
1120
- `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
1121
- );
1122
- }
1123
- let state = seekInStore(store, token, key);
1124
- if (state) {
1125
- return state;
1126
- }
1127
- state = initFamilyMemberInStore(store, token, key);
1128
- return state;
1129
- }
1130
-
1131
- // internal/src/families/dispose-from-store.ts
1132
- function disposeFromStore(store, ...params) {
1133
- let token;
1134
- if (params.length === 1) {
1135
- token = params[0];
1136
- } else {
1137
- const family = params[0];
1138
- const key = params[1];
1139
- const maybeToken = family.type === `molecule_family` ? seekInStore(store, family, key) : store.config.lifespan === `immortal` ? seekInStore(store, family, key) : findInStore(store, family, key);
1140
- if (!maybeToken) {
1141
- store.logger.error(
1142
- `\u2757`,
1143
- family.type,
1144
- family.key,
1145
- `tried to dispose of member`,
1146
- stringifyJson(key),
1147
- `but it was not found in store`,
1148
- store.config.name
1149
- );
1150
- return;
1151
- }
1152
- token = maybeToken;
1153
- }
1154
- switch (token.type) {
1155
- case `atom`:
1156
- case `mutable_atom`:
1157
- disposeAtom(token, store);
1158
- break;
1159
- case `selector`:
1160
- case `readonly_selector`:
1161
- disposeSelector(token, store);
1162
- break;
1163
- case `molecule`:
1164
- disposeMolecule(token, store);
1165
- break;
1166
- }
1167
- }
1168
-
1169
- // internal/src/set-state/set-into-store.ts
1170
- function setIntoStore(store, ...params) {
1171
- let token;
1172
- let value;
1173
- if (params.length === 2) {
1174
- token = params[0];
1175
- value = params[1];
1176
- } else {
1177
- const family = params[0];
1178
- const key = params[1];
1179
- value = params[2];
1180
- const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(store, family, key) : seekInStore(store, family, key);
1181
- if (!maybeToken) {
1182
- store.logger.error(
1183
- `\u2757`,
1184
- family.type,
1185
- family.key,
1186
- `tried to set member`,
1187
- stringifyJson(key),
1188
- `to`,
1189
- value,
1190
- `but it was not found in store`,
1191
- store.config.name
1192
- );
1193
- return;
1194
- }
1195
- token = maybeToken;
1196
- }
1197
- const rejectionTime = openOperation(token, store);
1198
- if (rejectionTime) {
1199
- const unsubscribe = store.on.operationClose.subscribe(
1200
- `waiting to set "${token.key}" at T-${rejectionTime}`,
1201
- () => {
1202
- unsubscribe();
1203
- store.logger.info(
1204
- `\u{1F7E2}`,
1205
- token.type,
1206
- token.key,
1207
- `resuming deferred setState from T-${rejectionTime}`
1208
- );
1209
- setIntoStore(store, token, value);
1210
- }
1211
- );
1212
- return;
1213
- }
1214
- const state = withdraw(token, store);
1215
- setAtomOrSelector(state, value, store);
1216
- closeOperation(store);
1217
- }
1218
-
1219
- // internal/src/ingest-updates/ingest-atom-update.ts
1220
- function ingestAtomUpdate(applying, atomUpdate, store) {
1221
- const { key, newValue, oldValue } = atomUpdate;
1222
- const value = applying === `newValue` ? newValue : oldValue;
1223
- const token = { key, type: `atom` };
1224
- if (atomUpdate.family) {
1225
- Object.assign(token, { family: atomUpdate.family });
1226
- }
1227
- setIntoStore(store, token, value);
1228
- }
1229
-
1230
1072
  // internal/src/molecule/create-molecule-family.ts
1231
1073
  function createMoleculeFamily(store, options) {
1232
1074
  const subject = new Subject();
@@ -1414,7 +1256,196 @@ function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1414
1256
  return token;
1415
1257
  }
1416
1258
 
1417
- // internal/src/ingest-updates/ingest-creation-disposal.ts
1259
+ // internal/src/families/init-family-member.ts
1260
+ function initFamilyMemberInStore(store, token, key) {
1261
+ const familyKey = token.key;
1262
+ const family = store.families.get(familyKey);
1263
+ if (family === void 0) {
1264
+ throw new NotFoundError(token, store);
1265
+ }
1266
+ const state = family(key);
1267
+ const target = newest(store);
1268
+ if (state.family && target.moleculeInProgress === null) {
1269
+ if (isRootStore(target)) {
1270
+ switch (state.type) {
1271
+ case `atom`:
1272
+ case `mutable_atom`:
1273
+ store.on.atomCreation.next(state);
1274
+ break;
1275
+ case `selector`:
1276
+ case `readonly_selector`:
1277
+ store.on.selectorCreation.next(state);
1278
+ break;
1279
+ }
1280
+ } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1281
+ target.transactionMeta.update.updates.push({
1282
+ type: `state_creation`,
1283
+ token: state
1284
+ });
1285
+ }
1286
+ }
1287
+ return state;
1288
+ }
1289
+ function seekInStore(store, token, key) {
1290
+ const subKey = stringifyJson(key);
1291
+ const fullKey = `${token.key}(${subKey})`;
1292
+ const target = newest(store);
1293
+ let state;
1294
+ switch (token.type) {
1295
+ case `atom_family`:
1296
+ case `mutable_atom_family`:
1297
+ state = target.atoms.get(fullKey);
1298
+ break;
1299
+ case `selector_family`:
1300
+ state = target.selectors.get(fullKey);
1301
+ break;
1302
+ case `readonly_selector_family`:
1303
+ state = target.readonlySelectors.get(fullKey);
1304
+ break;
1305
+ case `molecule_family`:
1306
+ state = target.molecules.get(stringifyJson(key));
1307
+ }
1308
+ if (state) {
1309
+ return deposit(state);
1310
+ }
1311
+ return state;
1312
+ }
1313
+
1314
+ // internal/src/families/find-in-store.ts
1315
+ function findInStore(store, token, key) {
1316
+ let state = seekInStore(store, token, key);
1317
+ if (state) {
1318
+ return state;
1319
+ }
1320
+ const molecule = store.molecules.get(stringifyJson(key));
1321
+ if (molecule) {
1322
+ return growMoleculeInStore(molecule, token, store);
1323
+ }
1324
+ if (store.config.lifespan === `immortal`) {
1325
+ const fakeToken = counterfeit(token, key);
1326
+ store.logger.error(
1327
+ `\u274C`,
1328
+ fakeToken.type,
1329
+ fakeToken.key,
1330
+ `was not found in store "${store.config.name}"; returned a counterfeit token.`
1331
+ );
1332
+ return fakeToken;
1333
+ }
1334
+ state = initFamilyMemberInStore(store, token, key);
1335
+ return state;
1336
+ }
1337
+
1338
+ // internal/src/families/dispose-from-store.ts
1339
+ function disposeFromStore(store, ...params) {
1340
+ let token;
1341
+ if (params.length === 1) {
1342
+ token = params[0];
1343
+ token.key;
1344
+ } else {
1345
+ const family = params[0];
1346
+ const key = params[1];
1347
+ const maybeToken = family.type === `molecule_family` ? seekInStore(store, family, key) ?? counterfeit(family, key) : findInStore(store, family, key);
1348
+ token = maybeToken;
1349
+ }
1350
+ try {
1351
+ withdraw(token, store);
1352
+ } catch (thrown) {
1353
+ const disposal = store.disposalTraces.buffer.find(
1354
+ (item) => item?.key === token.key
1355
+ );
1356
+ store.logger.error(
1357
+ `\u274C`,
1358
+ token.type,
1359
+ token.key,
1360
+ `could not be disposed because it was not found in the store "${store.config.name}".`,
1361
+ disposal ? `
1362
+ This state was most recently disposed
1363
+ ${disposal.trace}` : `No previous disposal trace was found.`
1364
+ );
1365
+ return;
1366
+ }
1367
+ switch (token.type) {
1368
+ case `atom`:
1369
+ case `mutable_atom`:
1370
+ disposeAtom(token, store);
1371
+ break;
1372
+ case `selector`:
1373
+ case `readonly_selector`:
1374
+ disposeSelector(token, store);
1375
+ break;
1376
+ case `molecule`:
1377
+ disposeMolecule(token, store);
1378
+ break;
1379
+ }
1380
+ const { stack } = new Error();
1381
+ if (stack) {
1382
+ const trace = stack?.split(`
1383
+ `)?.slice(3)?.join(`
1384
+ `);
1385
+ store.disposalTraces.add({ key: token.key, trace });
1386
+ }
1387
+ }
1388
+
1389
+ // internal/src/set-state/set-into-store.ts
1390
+ function setIntoStore(store, ...params) {
1391
+ let token;
1392
+ let value;
1393
+ if (params.length === 2) {
1394
+ token = params[0];
1395
+ value = params[1];
1396
+ } else {
1397
+ const family = params[0];
1398
+ const key = params[1];
1399
+ value = params[2];
1400
+ const maybeToken = findInStore(store, family, key);
1401
+ token = maybeToken;
1402
+ }
1403
+ if (`counterfeit` in token) {
1404
+ const disposal = store.disposalTraces.buffer.find(
1405
+ (item) => item?.key === token.key
1406
+ );
1407
+ store.logger.error(
1408
+ `\u274C`,
1409
+ token.type,
1410
+ token.key,
1411
+ `could not be set because it was not found in the store "${store.config.name}".`,
1412
+ disposal ? `This state was previously disposed:
1413
+ ${disposal.trace}` : `No previous disposal trace was found.`
1414
+ );
1415
+ return;
1416
+ }
1417
+ const rejectionTime = openOperation(token, store);
1418
+ if (rejectionTime) {
1419
+ const unsubscribe = store.on.operationClose.subscribe(
1420
+ `waiting to set "${token.key}" at T-${rejectionTime}`,
1421
+ () => {
1422
+ unsubscribe();
1423
+ store.logger.info(
1424
+ `\u{1F7E2}`,
1425
+ token.type,
1426
+ token.key,
1427
+ `resuming deferred setState from T-${rejectionTime}`
1428
+ );
1429
+ setIntoStore(store, token, value);
1430
+ }
1431
+ );
1432
+ return;
1433
+ }
1434
+ const state = withdraw(token, store);
1435
+ setAtomOrSelector(state, value, store);
1436
+ closeOperation(store);
1437
+ }
1438
+
1439
+ // internal/src/ingest-updates/ingest-atom-update.ts
1440
+ function ingestAtomUpdate(applying, atomUpdate, store) {
1441
+ const { key, newValue, oldValue } = atomUpdate;
1442
+ const value = applying === `newValue` ? newValue : oldValue;
1443
+ const token = { key, type: `atom` };
1444
+ if (atomUpdate.family) {
1445
+ Object.assign(token, { family: atomUpdate.family });
1446
+ }
1447
+ setIntoStore(store, token, value);
1448
+ }
1418
1449
  function ingestCreationEvent(update, applying, store) {
1419
1450
  switch (applying) {
1420
1451
  case `newValue`: {
@@ -1450,7 +1481,16 @@ function createInStore(token, store) {
1450
1481
  return;
1451
1482
  }
1452
1483
  if (store.config.lifespan === `immortal`) {
1453
- throw new Error(`No molecule found for key "${token.family.subKey}"`);
1484
+ store.logger.error(
1485
+ `\u{1F41E}`,
1486
+ `atom`,
1487
+ token.family.key,
1488
+ `tried to create member`,
1489
+ `"${token.family.subKey}"`,
1490
+ `but a molecule with that key was not found in store`,
1491
+ `"${store.config.name}"`
1492
+ );
1493
+ return;
1454
1494
  }
1455
1495
  initFamilyMemberInStore(store, family, parseJson(token.family.subKey));
1456
1496
  }
@@ -1676,6 +1716,7 @@ var buildTransaction = (key, params, store, id) => {
1676
1716
  selectors: new LazyMap(parent.selectors),
1677
1717
  valueMap: new LazyMap(parent.valueMap),
1678
1718
  defaults: parent.defaults,
1719
+ disposalTraces: store.disposalTraces.copy(),
1679
1720
  molecules: new LazyMap(parent.molecules),
1680
1721
  moleculeFamilies: new LazyMap(parent.moleculeFamilies),
1681
1722
  moleculeInProgress: parent.moleculeInProgress,
@@ -1773,6 +1814,36 @@ function getEpochNumberOfAction(transactionKey, store) {
1773
1814
  // internal/src/transaction/index.ts
1774
1815
  var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
1775
1816
 
1817
+ // internal/src/store/circular-buffer.ts
1818
+ var CircularBuffer = class _CircularBuffer {
1819
+ _buffer;
1820
+ _index = 0;
1821
+ constructor(lengthOrArray) {
1822
+ let length;
1823
+ if (typeof lengthOrArray === `number`) {
1824
+ length = lengthOrArray;
1825
+ } else {
1826
+ length = lengthOrArray.length;
1827
+ }
1828
+ this._buffer = Array.from({ length });
1829
+ }
1830
+ get buffer() {
1831
+ return this._buffer;
1832
+ }
1833
+ get index() {
1834
+ return this._index;
1835
+ }
1836
+ add(item) {
1837
+ this._buffer[this._index] = item;
1838
+ this._index = (this._index + 1) % this._buffer.length;
1839
+ }
1840
+ copy() {
1841
+ const copy = new _CircularBuffer([...this._buffer]);
1842
+ copy._index = this._index;
1843
+ return copy;
1844
+ }
1845
+ };
1846
+
1776
1847
  // internal/src/store/store.ts
1777
1848
  var Store = class {
1778
1849
  parent = null;
@@ -1811,6 +1882,7 @@ var Store = class {
1811
1882
  between: [`timelineKey`, `topicKey`],
1812
1883
  cardinality: `1:n`
1813
1884
  });
1885
+ disposalTraces = new CircularBuffer(100);
1814
1886
  molecules = /* @__PURE__ */ new Map();
1815
1887
  moleculeFamilies = /* @__PURE__ */ new Map();
1816
1888
  moleculeInProgress = null;
@@ -2625,15 +2697,8 @@ function createStandaloneAtom(store, options) {
2625
2697
  function disposeAtom(atomToken, store) {
2626
2698
  const target = newest(store);
2627
2699
  const { key } = atomToken;
2628
- const atom = target.atoms.get(key);
2629
- if (!atom) {
2630
- store.logger.error(
2631
- `\u274C`,
2632
- `atom`,
2633
- key,
2634
- `Tried to dispose atom, but it does not exist in the store.`
2635
- );
2636
- } else if (!atom.family) {
2700
+ const atom = withdraw(atomToken, target);
2701
+ if (!atom.family) {
2637
2702
  store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
2638
2703
  } else {
2639
2704
  atom.cleanup?.();
@@ -3171,4 +3236,4 @@ var timeTravel = (store, action, token) => {
3171
3236
  );
3172
3237
  };
3173
3238
 
3174
- export { FamilyTracker, Future, IMPLICIT, LazyMap, Molecule, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, createWritableSelectorFamily, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState2 as subscribeToState, subscribeToTimeline2 as subscribeToTimeline, subscribeToTransaction2 as subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };
3239
+ export { FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, LazyMap, Molecule, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, createWritableSelectorFamily, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState2 as subscribeToState, subscribeToTimeline2 as subscribeToTimeline, subscribeToTransaction2 as subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };