atom.io 0.30.7 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/data/dist/index.d.ts +20 -18
  2. package/data/dist/index.js +104 -172
  3. package/data/src/join.ts +138 -210
  4. package/dist/{chunk-UDHCFTYT.js → chunk-42UH5F5Q.js} +356 -744
  5. package/dist/chunk-ICGFFQ3H.js +272 -0
  6. package/dist/index.d.ts +52 -103
  7. package/dist/index.js +3 -11
  8. package/eslint-plugin/dist/index.d.ts +22 -3
  9. package/eslint-plugin/dist/index.js +7 -7
  10. package/immortal/dist/index.d.ts +1 -2
  11. package/immortal/dist/index.js +0 -3
  12. package/immortal/src/seek-state.ts +2 -14
  13. package/internal/dist/index.d.ts +48 -84
  14. package/internal/dist/index.js +2 -2
  15. package/internal/src/atom/dispose-atom.ts +31 -15
  16. package/internal/src/families/dispose-from-store.ts +15 -44
  17. package/internal/src/families/find-in-store.ts +15 -8
  18. package/internal/src/families/init-family-member.ts +1 -1
  19. package/internal/src/families/seek-in-store.ts +2 -14
  20. package/internal/src/get-state/get-from-store.ts +13 -79
  21. package/internal/src/get-trace.ts +7 -0
  22. package/internal/src/index.ts +2 -1
  23. package/internal/src/ingest-updates/ingest-creation-disposal.ts +63 -70
  24. package/internal/src/ingest-updates/ingest-transaction-update.ts +4 -0
  25. package/internal/src/junction.ts +52 -12
  26. package/internal/src/lineage.ts +0 -7
  27. package/internal/src/molecule.ts +7 -0
  28. package/internal/src/mutable/transceiver.ts +5 -5
  29. package/internal/src/pretty-print.ts +0 -4
  30. package/internal/src/selector/dispose-selector.ts +3 -5
  31. package/internal/src/selector/register-selector.ts +2 -26
  32. package/internal/src/set-state/set-into-store.ts +3 -2
  33. package/internal/src/store/counterfeit.ts +11 -25
  34. package/internal/src/store/deposit.ts +5 -39
  35. package/internal/src/store/store.ts +51 -12
  36. package/internal/src/store/withdraw.ts +3 -26
  37. package/internal/src/timeline/create-timeline.ts +133 -237
  38. package/internal/src/timeline/time-travel.ts +1 -8
  39. package/internal/src/transaction/build-transaction.ts +10 -5
  40. package/internal/src/transaction/index.ts +1 -1
  41. package/internal/src/utility-types.ts +2 -0
  42. package/introspection/dist/index.d.ts +2 -3
  43. package/introspection/dist/index.js +9 -9
  44. package/introspection/src/refinery.ts +1 -3
  45. package/json/dist/index.js +9 -40
  46. package/json/src/index.ts +2 -0
  47. package/json/src/select-json-family.ts +7 -44
  48. package/package.json +33 -28
  49. package/react/dist/index.js +2 -10
  50. package/react/src/parse-state-overloads.ts +3 -11
  51. package/react-devtools/dist/index.js +13 -13
  52. package/react-devtools/src/Updates.tsx +2 -0
  53. package/realtime-client/dist/index.d.ts +20 -12
  54. package/realtime-client/dist/index.js +241 -244
  55. package/realtime-client/src/continuity/index.ts +3 -0
  56. package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +231 -0
  57. package/realtime-client/src/continuity/use-conceal-state.ts +11 -0
  58. package/realtime-client/src/continuity/use-reveal-state.ts +19 -0
  59. package/realtime-client/src/index.ts +1 -0
  60. package/realtime-client/src/sync-continuity.ts +18 -262
  61. package/realtime-react/dist/index.js +2 -2
  62. package/realtime-server/dist/index.d.ts +1 -1
  63. package/realtime-server/dist/index.js +2 -2
  64. package/realtime-server/src/index.ts +1 -1
  65. package/realtime-testing/dist/index.js +2 -3
  66. package/realtime-testing/src/setup-realtime-test.tsx +1 -2
  67. package/src/allocate.ts +311 -145
  68. package/src/dispose-state.ts +5 -21
  69. package/src/get-state.ts +3 -21
  70. package/src/molecule.ts +11 -133
  71. package/src/silo.ts +1 -12
  72. package/src/timeline.ts +2 -3
  73. package/src/transaction.ts +25 -38
  74. package/dist/chunk-ADMEAXYU.js +0 -167
  75. package/internal/src/molecule/create-molecule-family.ts +0 -30
  76. package/internal/src/molecule/dispose-molecule.ts +0 -79
  77. package/internal/src/molecule/grow-molecule-in-store.ts +0 -95
  78. package/internal/src/molecule/index.ts +0 -5
  79. package/internal/src/molecule/make-molecule-in-store.ts +0 -191
  80. package/internal/src/molecule/molecule-internal.ts +0 -52
@@ -1,7 +1,6 @@
1
- import { deallocateFromStore, allocateIntoStore } from './chunk-ADMEAXYU.js';
1
+ import { deallocateFromStore, allocateIntoStore, claimWithinStore } from './chunk-ICGFFQ3H.js';
2
2
  import { stringifyJson, parseJson, selectJson, selectJsonFamily } from 'atom.io/json';
3
3
  import { AtomIOLogger } from 'atom.io';
4
- import { getJoin, findRelations } from 'atom.io/data';
5
4
  import { subscribeToTimeline, subscribeToTransaction, subscribeToState, arbitrary as arbitrary$1 } from 'atom.io/internal';
6
5
 
7
6
  // internal/src/arbitrary.ts
@@ -52,7 +51,7 @@ var Future = class extends Promise {
52
51
  );
53
52
  } else {
54
53
  this.resolve(value);
55
- this.fate = void 0;
54
+ this.fate = undefined;
56
55
  }
57
56
  }
58
57
  };
@@ -64,12 +63,6 @@ function newest(scion) {
64
63
  }
65
64
  return scion;
66
65
  }
67
- function eldest(scion) {
68
- while (scion.parent !== null) {
69
- scion = scion.parent;
70
- }
71
- return scion;
72
- }
73
66
 
74
67
  // internal/src/store/circular-buffer.ts
75
68
  var CircularBuffer = class _CircularBuffer {
@@ -115,19 +108,12 @@ function counterfeit(token, key) {
115
108
  key: fullKey,
116
109
  type
117
110
  };
118
- if (type === `molecule`) {
119
- Object.assign(stateToken, {
120
- key,
121
- family: token
122
- });
123
- } else {
124
- Object.assign(stateToken, {
125
- family: {
126
- key: token.key,
127
- subKey
128
- }
129
- });
130
- }
111
+ Object.assign(stateToken, {
112
+ family: {
113
+ key: token.key,
114
+ subKey
115
+ }
116
+ });
131
117
  Object.assign(stateToken, { counterfeit: true });
132
118
  return stateToken;
133
119
  }
@@ -200,8 +186,8 @@ var Junction = class {
200
186
  }
201
187
  replaceRelationsSafely(x, ys) {
202
188
  const xRelationsPrev = this.relations.get(x);
203
- let a = this.isAType?.(x) ? x : void 0;
204
- let b = a === void 0 ? x : void 0;
189
+ let a = this.isAType?.(x) ? x : undefined;
190
+ let b = a === undefined ? x : undefined;
205
191
  if (xRelationsPrev) {
206
192
  for (const y of xRelationsPrev) {
207
193
  a ??= y;
@@ -283,8 +269,8 @@ var Junction = class {
283
269
  };
284
270
  }
285
271
  for (const [x, ys] of data.relations ?? []) {
286
- let a = this.isAType?.(x) ? x : void 0;
287
- let b = a === void 0 ? x : void 0;
272
+ let a = this.isAType?.(x) ? x : undefined;
273
+ let b = a === undefined ? x : undefined;
288
274
  for (const y of ys) {
289
275
  a ??= y;
290
276
  b ??= y;
@@ -309,10 +295,36 @@ var Junction = class {
309
295
  contents: [...this.contents.entries()]
310
296
  };
311
297
  }
312
- set(a, ...rest) {
313
- const b = typeof rest[0] === `string` ? rest[0] : a[this.b];
314
- const content = rest[1] ?? typeof rest[0] === `string` ? void 0 : rest[0];
315
- a = typeof a === `string` ? a : a[this.a];
298
+ set(...params) {
299
+ let a;
300
+ let b;
301
+ let content;
302
+ switch (params.length) {
303
+ case 1: {
304
+ const relation = params[0];
305
+ a = relation[this.a];
306
+ b = relation[this.b];
307
+ content = undefined;
308
+ break;
309
+ }
310
+ case 2: {
311
+ const zeroth = params[0];
312
+ if (typeof zeroth === `string`) {
313
+ [a, b] = params;
314
+ } else {
315
+ a = zeroth[this.a];
316
+ b = zeroth[this.b];
317
+ content = params[1];
318
+ }
319
+ break;
320
+ }
321
+ default: {
322
+ a = params[0];
323
+ b = params[1];
324
+ content = params[2];
325
+ break;
326
+ }
327
+ }
316
328
  switch (this.cardinality) {
317
329
  // biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
318
330
  case `1:1`: {
@@ -337,7 +349,7 @@ var Junction = class {
337
349
  // @ts-expect-error we deduce that this.a may index x
338
350
  typeof x === `string` ? x : x[this.a]
339
351
  );
340
- if (a === void 0 && typeof b === `string`) {
352
+ if (a === undefined && typeof b === `string`) {
341
353
  const bRelations = this.getRelatedKeys(b);
342
354
  if (bRelations) {
343
355
  for (const bRelation of bRelations) {
@@ -345,7 +357,7 @@ var Junction = class {
345
357
  }
346
358
  }
347
359
  }
348
- if (typeof a === `string` && b === void 0) {
360
+ if (typeof a === `string` && b === undefined) {
349
361
  const aRelations = this.getRelatedKeys(a);
350
362
  if (aRelations) {
351
363
  for (const aRelation of aRelations) {
@@ -402,7 +414,7 @@ var Junction = class {
402
414
  getRelationEntries(input) {
403
415
  const a = input[this.a];
404
416
  const b = input[this.b];
405
- if (a !== void 0 && b === void 0) {
417
+ if (a !== undefined && b === undefined) {
406
418
  const aRelations = this.getRelatedKeys(a);
407
419
  if (aRelations) {
408
420
  return [...aRelations].map((aRelation) => {
@@ -410,7 +422,7 @@ var Junction = class {
410
422
  });
411
423
  }
412
424
  }
413
- if (a === void 0 && b !== void 0) {
425
+ if (a === undefined && b !== undefined) {
414
426
  const bRelations = this.getRelatedKeys(b);
415
427
  if (bRelations) {
416
428
  return [...bRelations].map((bRelation) => {
@@ -823,86 +835,6 @@ function createAtomFamily(store, options) {
823
835
  return createRegularAtomFamily(store, options);
824
836
  }
825
837
 
826
- // internal/src/families/get-family-of-token.ts
827
- function getFamilyOfToken(store, token) {
828
- if (token.family) {
829
- const family = store.families.get(token.family.key);
830
- if (family) {
831
- return family;
832
- }
833
- }
834
- }
835
-
836
- // internal/src/get-state/get-from-store.ts
837
- function getFromStore(store, ...params) {
838
- let token;
839
- let family;
840
- let key;
841
- if (params.length === 1) {
842
- token = params[0];
843
- if (token.type !== `molecule`) {
844
- family = getFamilyOfToken(store, token) ?? null;
845
- if (family) {
846
- key = token.family ? parseJson(token.family.subKey) : null;
847
- token = findInStore(store, family, key);
848
- }
849
- }
850
- } else {
851
- family = params[0];
852
- key = params[1];
853
- let maybeToken;
854
- if (family.type === `molecule_family`) {
855
- maybeToken = seekInStore(store, family, key) ?? counterfeit(family, key);
856
- } else {
857
- maybeToken = findInStore(store, family, key);
858
- }
859
- token = maybeToken;
860
- }
861
- if (`counterfeit` in token && `family` in token) {
862
- family = token.type === `molecule` ? withdraw(token.family, store) : (
863
- // biome-ignore lint/style/noNonNullAssertion: family must be present
864
- store.families.get(token.family.key)
865
- );
866
- const subKey = token.type === `molecule` ? token.key : token.family.subKey;
867
- const disposal = store.disposalTraces.buffer.find(
868
- (item) => item?.key === token.key
869
- );
870
- store.logger.error(
871
- `\u274C`,
872
- token.type,
873
- token.key,
874
- `could not be retrieved because it was not found in the store "${store.config.name}".`,
875
- disposal ? `This state was previously disposed:
876
- ${disposal.trace}` : `No previous disposal trace was found.`
877
- );
878
- switch (family.type) {
879
- case `atom_family`:
880
- case `mutable_atom_family`:
881
- return store.defaults.get(family.key);
882
- case `selector_family`:
883
- case `readonly_selector_family`: {
884
- if (store.defaults.has(family.key)) {
885
- return store.defaults.get(token.family.key);
886
- }
887
- const defaultValue = withdraw(family, store).default(subKey);
888
- store.defaults.set(family.key, defaultValue);
889
- return defaultValue;
890
- }
891
- case `molecule_family`:
892
- throw new NotFoundError(family, subKey, store);
893
- }
894
- }
895
- switch (token.type) {
896
- case `atom`:
897
- case `mutable_atom`:
898
- case `selector`:
899
- case `readonly_selector`:
900
- return readOrComputeValue(withdraw(token, store), store);
901
- case `molecule`:
902
- return withdraw(token, store).instance;
903
- }
904
- }
905
-
906
838
  // internal/src/keys.ts
907
839
  var isAtomKey = (key, store) => newest(store).atoms.has(key);
908
840
  var isSelectorKey = (key, store) => newest(store).selectors.has(key);
@@ -986,27 +918,10 @@ var registerSelector = (selectorKey, covered, store) => ({
986
918
  let dependency;
987
919
  if (params.length === 2) {
988
920
  const [family, key] = params;
989
- switch (family.type) {
990
- case `molecule_family`:
991
- return getFromStore(store, family, key);
992
- default:
993
- if (store.config.lifespan === `ephemeral`) {
994
- dependency = findInStore(store, family, key);
995
- } else {
996
- const maybeDependency = seekInStore(store, family, key);
997
- if (maybeDependency) {
998
- dependency = maybeDependency;
999
- } else {
1000
- throw new NotFoundError(family, key, store);
1001
- }
1002
- }
1003
- }
921
+ dependency = findInStore(store, family, key);
1004
922
  } else {
1005
923
  [dependency] = params;
1006
924
  }
1007
- if (dependency.type === `molecule`) {
1008
- return getFromStore(store, dependency);
1009
- }
1010
925
  const dependencyState = withdraw(dependency, store);
1011
926
  const dependencyValue = readOrComputeValue(dependencyState, store);
1012
927
  store.logger.info(
@@ -1158,11 +1073,11 @@ var createWritableSelector = (store, options, family) => {
1158
1073
  function createStandaloneSelector(store, options) {
1159
1074
  const isWritable = `set` in options;
1160
1075
  if (isWritable) {
1161
- const state2 = createWritableSelector(store, options, void 0);
1076
+ const state2 = createWritableSelector(store, options, undefined);
1162
1077
  store.on.selectorCreation.next(state2);
1163
1078
  return state2;
1164
1079
  }
1165
- const state = createReadonlySelector(store, options, void 0);
1080
+ const state = createReadonlySelector(store, options, undefined);
1166
1081
  store.on.selectorCreation.next(state);
1167
1082
  return state;
1168
1083
  }
@@ -1182,20 +1097,16 @@ function disposeSelector(selectorToken, store) {
1182
1097
  } else {
1183
1098
  const molecule = target.molecules.get(selector.family.subKey);
1184
1099
  if (molecule) {
1185
- molecule.tokens.delete(key);
1100
+ target.moleculeData.delete(selector.family.subKey, selector.family.key);
1186
1101
  }
1187
1102
  switch (selectorToken.type) {
1188
1103
  case `selector`:
1189
1104
  {
1190
1105
  target.selectors.delete(key);
1191
- const family = withdraw(
1106
+ withdraw(
1192
1107
  { key: selector.family.key, type: `selector_family` },
1193
1108
  store
1194
1109
  );
1195
- family.subject.next({
1196
- type: `state_disposal`,
1197
- token: selectorToken
1198
- });
1199
1110
  }
1200
1111
  break;
1201
1112
  case `readonly_selector`:
@@ -1207,6 +1118,7 @@ function disposeSelector(selectorToken, store) {
1207
1118
  );
1208
1119
  family.subject.next({
1209
1120
  type: `state_disposal`,
1121
+ subType: `selector`,
1210
1122
  token: selectorToken
1211
1123
  });
1212
1124
  }
@@ -1219,6 +1131,7 @@ function disposeSelector(selectorToken, store) {
1219
1131
  if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1220
1132
  target.transactionMeta.update.updates.push({
1221
1133
  type: `state_disposal`,
1134
+ subType: `selector`,
1222
1135
  token: selectorToken
1223
1136
  });
1224
1137
  } else {
@@ -1339,267 +1252,15 @@ function createSelectorFamily(store, options) {
1339
1252
  return createReadonlySelectorFamily(store, options);
1340
1253
  }
1341
1254
 
1342
- // internal/src/molecule/dispose-molecule.ts
1343
- function disposeMolecule(token, store) {
1344
- let molecule;
1345
- molecule = withdraw(token, store);
1346
- const { family } = token;
1347
- for (const join of molecule.joins.values()) {
1348
- join.relations.delete(molecule.key);
1349
- join.molecules.delete(molecule.stringKey);
1350
- }
1351
- const context = [];
1352
- for (const above of molecule.above.values()) {
1353
- context.push(deposit(above));
1354
- }
1355
- const values = [];
1356
- for (const stateToken of molecule.tokens.values()) {
1357
- const tokenFamily = stateToken.family;
1358
- values.push([tokenFamily.key, store.valueMap.get(stateToken.key)]);
1359
- }
1360
- if (family) {
1361
- const Formula = withdraw(family, store);
1362
- const disposalEvent = {
1363
- type: `molecule_disposal`,
1364
- subType: `classic`,
1365
- token,
1366
- family,
1367
- context,
1368
- values
1369
- };
1370
- if (token.family) {
1371
- disposalEvent.family = token.family;
1372
- }
1373
- for (const state of molecule.tokens.values()) {
1374
- disposeFromStore(store, state);
1375
- }
1376
- for (const child of molecule.below.values()) {
1377
- if (child.dependsOn === `all`) {
1378
- disposeMolecule(child, store);
1379
- } else {
1380
- child.above.delete(molecule.stringKey);
1381
- if (child.above.size === 0) {
1382
- disposeMolecule(child, store);
1383
- }
1384
- }
1385
- }
1386
- molecule.below.clear();
1387
- const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1388
- if (isTransaction) {
1389
- store.transactionMeta.update.updates.push(disposalEvent);
1390
- } else {
1391
- Formula.subject.next(disposalEvent);
1392
- }
1393
- store.molecules.delete(molecule.stringKey);
1394
- }
1395
- for (const parent of molecule.above.values()) {
1396
- parent.below.delete(molecule.stringKey);
1397
- }
1398
- }
1399
-
1400
- // internal/src/molecule/create-molecule-family.ts
1401
- function createMoleculeFamily(store, options) {
1402
- const subject = new Subject();
1403
- const token = {
1404
- type: `molecule_family`,
1405
- key: options.key,
1406
- dependsOn: options.dependsOn ?? `all`
1407
- };
1408
- const family = {
1409
- ...token,
1410
- subject,
1411
- new: options.new
1412
- };
1413
- store.moleculeFamilies.set(options.key, family);
1414
- return token;
1415
- }
1416
-
1417
- // internal/src/molecule/grow-molecule-in-store.ts
1418
- function growMoleculeInStore(molecule, family, store) {
1419
- const stateToken = initFamilyMemberInStore(store, family, molecule.key);
1420
- molecule.tokens.set(stateToken.key, stateToken);
1421
- const isTransaction = isChildStore(store) && store.transactionMeta.phase === `building`;
1422
- const moleculeInProgress = store.moleculeInProgress === molecule.key;
1423
- if (!isTransaction && !moleculeInProgress) {
1424
- molecule.subject.next({ type: `state_creation`, token: stateToken });
1425
- }
1426
- return stateToken;
1427
- }
1428
-
1429
- // internal/src/get-environment-data.ts
1430
- function getEnvironmentData(store) {
1431
- return {
1432
- store
1433
- };
1434
- }
1435
- var Molecule = class {
1436
- constructor(ctx, key, family) {
1437
- this.key = key;
1438
- this.stringKey = stringifyJson(key);
1439
- if (family) {
1440
- this.family = family;
1441
- this._dependsOn = family.dependsOn;
1442
- }
1443
- if (ctx) {
1444
- for (const molecule of ctx) {
1445
- this.above.set(molecule.stringKey, molecule);
1446
- }
1447
- }
1448
- }
1449
- type = `molecule`;
1450
- stringKey;
1451
- family;
1452
- _dependsOn;
1453
- get dependsOn() {
1454
- if (this.family) {
1455
- return this.family.dependsOn;
1456
- }
1457
- return this._dependsOn;
1458
- }
1459
- subject = new Subject();
1460
- tokens = /* @__PURE__ */ new Map();
1461
- above = /* @__PURE__ */ new Map();
1462
- below = /* @__PURE__ */ new Map();
1463
- joins = /* @__PURE__ */ new Map();
1464
- instance;
1465
- };
1466
-
1467
- // internal/src/molecule/make-molecule-in-store.ts
1468
- function capitalize2(string) {
1469
- return string[0].toUpperCase() + string.slice(1);
1470
- }
1471
- function makeMoleculeInStore(store, context, familyToken, key, ...params) {
1472
- const rootStore = eldest(store);
1473
- const target = newest(store);
1474
- const stringKey = stringifyJson(key);
1475
- target.moleculeInProgress = stringKey;
1476
- const contextArray = Array.isArray(context) ? context : [context];
1477
- const owners = contextArray.map((ctx) => {
1478
- if (ctx instanceof Molecule) {
1479
- return ctx;
1480
- }
1481
- const ctxStringKey = stringifyJson(ctx.key);
1482
- const molecule2 = store.molecules.get(ctxStringKey);
1483
- if (!molecule2) {
1484
- throw new Error(
1485
- `Molecule ${ctxStringKey} not found in store "${store.config.name}"`
1486
- );
1487
- }
1488
- return molecule2;
1489
- });
1490
- const molecule = new Molecule(owners, key, familyToken);
1491
- target.molecules.set(stringKey, molecule);
1492
- for (const owner of owners) {
1493
- owner.below.set(molecule.stringKey, molecule);
1494
- }
1495
- const toolkit = {
1496
- get: (...ps) => getFromStore(newest(rootStore), ...ps),
1497
- set: (...ps) => {
1498
- setIntoStore(newest(rootStore), ...ps);
1499
- },
1500
- seek: (t, k) => seekInStore(newest(rootStore), t, k),
1501
- json: (t) => getJsonToken(newest(rootStore), t),
1502
- run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
1503
- make: (ctx, f, k, ...args) => makeMoleculeInStore(newest(rootStore), ctx, f, k, ...args),
1504
- dispose: (t) => {
1505
- disposeFromStore(newest(rootStore), t);
1506
- },
1507
- env: () => getEnvironmentData(newest(rootStore)),
1508
- bond: (token2, maybeRole) => {
1509
- if (token2.type === `join`) {
1510
- const { as: role } = maybeRole;
1511
- const join = getJoin(token2, rootStore);
1512
- join.molecules.set(stringKey, molecule);
1513
- molecule.joins.set(token2.key, join);
1514
- const unsubFromFamily = family.subject.subscribe(
1515
- `join:${token2.key}-${stringKey}`,
1516
- (event) => {
1517
- if (event.type === `molecule_disposal`) {
1518
- if (stringifyJson(event.token.key) === stringKey) {
1519
- unsubFromFamily();
1520
- join.molecules.delete(stringKey);
1521
- }
1522
- }
1523
- }
1524
- );
1525
- if (role === null) {
1526
- return;
1527
- }
1528
- const otherRole = token2.a === role ? token2.b : token2.a;
1529
- const relations = findRelations(token2, key);
1530
- const relatedKeys = relations[`${otherRole}KeysOf${capitalize2(role)}`];
1531
- const relatedEntries = relations[`${otherRole}EntriesOf${capitalize2(role)}`];
1532
- let tokens = { relatedKeys };
1533
- if (relatedEntries) {
1534
- tokens = Object.assign(tokens, { relatedEntries });
1535
- }
1536
- return tokens;
1537
- }
1538
- return growMoleculeInStore(
1539
- molecule,
1540
- withdraw(token2, rootStore),
1541
- newest(rootStore)
1542
- );
1543
- },
1544
- claim: (below, options) => {
1545
- const { exclusive } = options;
1546
- const belowMolecule = newest(store).molecules.get(stringifyJson(below.key));
1547
- if (belowMolecule) {
1548
- if (exclusive) {
1549
- for (const value of belowMolecule.above.values()) {
1550
- value.below.delete(belowMolecule.stringKey);
1551
- }
1552
- belowMolecule.above.clear();
1553
- belowMolecule.above.set(molecule.stringKey, molecule);
1554
- molecule.below.set(belowMolecule.stringKey, belowMolecule);
1555
- } else {
1556
- belowMolecule.above.set(molecule.stringKey, molecule);
1557
- molecule.below.set(belowMolecule.stringKey, belowMolecule);
1558
- }
1559
- }
1560
- },
1561
- spawn: (f, k, ...p) => makeMoleculeInStore(
1562
- newest(store),
1563
- [molecule],
1564
- withdraw(f, store),
1565
- k,
1566
- ...p
1567
- )
1568
- };
1569
- const family = withdraw(familyToken, store);
1570
- const Constructor = family.new;
1571
- molecule.instance = new Constructor(toolkit, key, ...params);
1572
- const token = {
1573
- type: `molecule`,
1574
- key,
1575
- family: familyToken
1576
- };
1577
- const update = {
1578
- type: `molecule_creation`,
1579
- subType: `classic`,
1580
- token,
1581
- family: familyToken,
1582
- context: contextArray,
1583
- params
1584
- };
1585
- if (isRootStore(target)) {
1586
- family.subject.next(update);
1587
- } else if (isChildStore(target) && target.on.transactionApplying.state === null) {
1588
- target.transactionMeta.update.updates.push(update);
1589
- }
1590
- target.moleculeInProgress = null;
1591
- return token;
1592
- }
1593
-
1594
1255
  // internal/src/families/init-family-member.ts
1595
1256
  function initFamilyMemberInStore(store, token, key) {
1596
1257
  const family = store.families.get(token.key);
1597
- if (family === void 0) {
1258
+ if (family === undefined) {
1598
1259
  throw new NotFoundError(token, store);
1599
1260
  }
1600
1261
  const state = family(key);
1601
1262
  const target = newest(store);
1602
- if (state.family && target.moleculeInProgress === null) {
1263
+ if (state.family) {
1603
1264
  if (isRootStore(target)) {
1604
1265
  switch (state.type) {
1605
1266
  case `atom`:
@@ -1636,8 +1297,6 @@ function seekInStore(store, token, key) {
1636
1297
  case `readonly_selector_family`:
1637
1298
  state = target.readonlySelectors.get(fullKey);
1638
1299
  break;
1639
- case `molecule_family`:
1640
- state = target.molecules.get(stringifyJson(key));
1641
1300
  }
1642
1301
  if (state) {
1643
1302
  return deposit(state);
@@ -1651,11 +1310,9 @@ function findInStore(store, token, key) {
1651
1310
  if (state) {
1652
1311
  return state;
1653
1312
  }
1654
- const molecule = store.molecules.get(stringifyJson(key));
1655
- if (molecule) {
1656
- return growMoleculeInStore(molecule, token, store);
1657
- }
1658
- if (store.config.lifespan === `immortal`) {
1313
+ const stringKey = stringifyJson(key);
1314
+ const molecule = store.molecules.get(stringKey);
1315
+ if (!molecule && store.config.lifespan === `immortal`) {
1659
1316
  const fakeToken = counterfeit(token, key);
1660
1317
  store.logger.error(
1661
1318
  `\u274C`,
@@ -1666,6 +1323,10 @@ function findInStore(store, token, key) {
1666
1323
  return fakeToken;
1667
1324
  }
1668
1325
  state = initFamilyMemberInStore(store, token, key);
1326
+ if (molecule) {
1327
+ const target = newest(store);
1328
+ target.moleculeData.set(stringKey, token.key);
1329
+ }
1669
1330
  return state;
1670
1331
  }
1671
1332
 
@@ -1674,27 +1335,23 @@ function disposeFromStore(store, ...params) {
1674
1335
  let token;
1675
1336
  if (params.length === 1) {
1676
1337
  token = params[0];
1677
- token.key;
1678
1338
  } else {
1679
1339
  const family = params[0];
1680
1340
  const key = params[1];
1681
- const maybeToken = family.type === `molecule_family` ? seekInStore(store, family, key) ?? counterfeit(family, key) : findInStore(store, family, key);
1341
+ const maybeToken = findInStore(store, family, key);
1682
1342
  token = maybeToken;
1683
1343
  }
1684
1344
  try {
1685
1345
  withdraw(token, store);
1686
1346
  } catch (thrown) {
1687
- const disposal = store.disposalTraces.buffer.find(
1688
- (item) => item?.key === token.key
1689
- );
1690
1347
  store.logger.error(
1691
1348
  `\u274C`,
1692
1349
  token.type,
1693
1350
  token.key,
1694
- `could not be disposed because it was not found in the store "${store.config.name}".`,
1695
- disposal ? `
1696
- This state was most recently disposed
1697
- ${disposal.trace}` : `No previous disposal trace was found.`
1351
+ `could not be disposed because it was not found in the store "${store.config.name}".`
1352
+ // disposal
1353
+ // ? `\n This state was most recently disposed\n${disposal.trace}`
1354
+ // : `No previous disposal trace was found.`,
1698
1355
  );
1699
1356
  return;
1700
1357
  }
@@ -1707,16 +1364,16 @@ ${disposal.trace}` : `No previous disposal trace was found.`
1707
1364
  case `readonly_selector`:
1708
1365
  disposeSelector(token, store);
1709
1366
  break;
1710
- case `molecule`:
1711
- disposeMolecule(token, store);
1712
- break;
1713
1367
  }
1714
- const { stack } = new Error();
1715
- if (stack) {
1716
- const trace = stack?.split(`
1717
- `)?.slice(3)?.join(`
1718
- `);
1719
- store.disposalTraces.add({ key: token.key, trace });
1368
+ }
1369
+
1370
+ // internal/src/families/get-family-of-token.ts
1371
+ function getFamilyOfToken(store, token) {
1372
+ if (token.family) {
1373
+ const family = store.families.get(token.family.key);
1374
+ if (family) {
1375
+ return family;
1376
+ }
1720
1377
  }
1721
1378
  }
1722
1379
 
@@ -1740,9 +1397,10 @@ function setIntoStore(store, ...params) {
1740
1397
  value = params[2];
1741
1398
  token = findInStore(store, family, key);
1742
1399
  }
1743
- if (`counterfeit` in token) {
1400
+ if (`counterfeit` in token && `family` in token) {
1401
+ const subKey = token.family.subKey;
1744
1402
  const disposal = store.disposalTraces.buffer.find(
1745
- (item) => item?.key === token.key
1403
+ (item) => item?.key === subKey
1746
1404
  );
1747
1405
  store.logger.error(
1748
1406
  `\u274C`,
@@ -1806,7 +1464,9 @@ function ingestDisposalEvent(update, applying, store) {
1806
1464
  }
1807
1465
  case `oldValue`: {
1808
1466
  createInStore(update, store);
1809
- store.valueMap.set(update.token.key, update.value);
1467
+ if (update.subType === `atom`) {
1468
+ store.valueMap.set(update.token.key, update.value);
1469
+ }
1810
1470
  break;
1811
1471
  }
1812
1472
  }
@@ -1823,88 +1483,60 @@ function createInStore(update, store) {
1823
1483
  function ingestMoleculeCreationEvent(update, applying, store) {
1824
1484
  switch (applying) {
1825
1485
  case `newValue`:
1826
- switch (update.subType) {
1827
- case `classic`:
1828
- makeMoleculeInStore(
1829
- store,
1830
- update.context,
1831
- update.family,
1832
- update.token.key,
1833
- ...update.params
1834
- );
1835
- break;
1836
- case `modern`:
1837
- allocateIntoStore(store, update.provenance, update.key);
1838
- break;
1839
- }
1486
+ allocateIntoStore(store, update.provenance, update.key);
1840
1487
  break;
1841
1488
  case `oldValue`:
1842
- switch (update.subType) {
1843
- case `classic`:
1844
- disposeFromStore(store, update.token);
1845
- break;
1846
- case `modern`:
1847
- deallocateFromStore(store, update.key);
1848
- break;
1849
- }
1489
+ deallocateFromStore(store, update.key);
1850
1490
  break;
1851
1491
  }
1852
1492
  }
1853
1493
  function ingestMoleculeDisposalEvent(update, applying, store) {
1854
1494
  switch (applying) {
1855
1495
  case `newValue`:
1856
- switch (update.subType) {
1857
- case `classic`:
1858
- disposeFromStore(store, update.token);
1859
- break;
1860
- case `modern`:
1861
- deallocateFromStore(store, update.key);
1862
- break;
1863
- }
1496
+ deallocateFromStore(store, update.key);
1864
1497
  break;
1865
1498
  case `oldValue`:
1866
1499
  {
1867
- switch (update.subType) {
1868
- case `classic`:
1869
- {
1870
- const moleculeToken = makeMoleculeInStore(
1871
- store,
1872
- update.context,
1873
- update.family,
1874
- update.token.key
1875
- );
1876
- for (const [familyKey, value] of update.values) {
1877
- const memberKey = `${familyKey}(${stringifyJson(moleculeToken.key)})`;
1878
- const molecule = withdraw(moleculeToken, store);
1879
- const alreadyCreated = molecule.tokens.has(memberKey);
1880
- const family = store.families.get(familyKey);
1881
- if (family && !alreadyCreated) {
1882
- growMoleculeInStore(molecule, family, store);
1883
- }
1884
- store.valueMap.set(memberKey, value);
1885
- }
1886
- }
1887
- break;
1888
- case `modern`: {
1889
- allocateIntoStore(
1890
- store,
1891
- update.provenance,
1892
- update.key
1893
- );
1894
- for (const [familyKey, value] of update.values) {
1895
- const family = store.families.get(familyKey);
1896
- if (family) {
1897
- findInStore(store, family, update.key);
1898
- const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
1899
- store.valueMap.set(memberKey, value);
1900
- }
1901
- }
1500
+ const provenanceJson = update.provenance.map(parseJson);
1501
+ allocateIntoStore(store, provenanceJson, update.key);
1502
+ for (const [familyKey, value] of update.values) {
1503
+ const family = store.families.get(familyKey);
1504
+ if (family) {
1505
+ findInStore(store, family, update.key);
1506
+ const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
1507
+ store.valueMap.set(memberKey, value);
1902
1508
  }
1903
1509
  }
1904
1510
  }
1905
1511
  break;
1906
1512
  }
1907
1513
  }
1514
+ function ingestMoleculeTransferEvent(update, applying, store) {
1515
+ switch (applying) {
1516
+ case `newValue`:
1517
+ {
1518
+ const provenance = update.to.length === 1 ? update.to[0] : update.to;
1519
+ claimWithinStore(
1520
+ store,
1521
+ provenance,
1522
+ update.key,
1523
+ `exclusive`
1524
+ );
1525
+ }
1526
+ break;
1527
+ case `oldValue`:
1528
+ {
1529
+ const provenance = update.from.length === 1 ? update.from[0] : update.from;
1530
+ claimWithinStore(
1531
+ store,
1532
+ provenance,
1533
+ update.key,
1534
+ `exclusive`
1535
+ );
1536
+ }
1537
+ break;
1538
+ }
1539
+ }
1908
1540
 
1909
1541
  // internal/src/ingest-updates/ingest-selector-update.ts
1910
1542
  function ingestSelectorUpdate(applying, selectorUpdate, store) {
@@ -1935,6 +1567,9 @@ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1935
1567
  case `molecule_disposal`:
1936
1568
  ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1937
1569
  break;
1570
+ case `molecule_transfer`:
1571
+ ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
1572
+ break;
1938
1573
  case `transaction_update`:
1939
1574
  ingestTransactionUpdate(applying, updateFromTransaction, store);
1940
1575
  break;
@@ -1955,7 +1590,7 @@ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1955
1590
  return;
1956
1591
  }
1957
1592
  const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1958
- if (continuityKey !== void 0) {
1593
+ if (continuityKey !== undefined) {
1959
1594
  store.transactionMeta.epoch.set(continuityKey, newEpoch);
1960
1595
  }
1961
1596
  }
@@ -2022,6 +1657,57 @@ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2022
1657
  }
2023
1658
  }
2024
1659
 
1660
+ // internal/src/get-environment-data.ts
1661
+ function getEnvironmentData(store) {
1662
+ return {
1663
+ store
1664
+ };
1665
+ }
1666
+
1667
+ // internal/src/get-state/get-from-store.ts
1668
+ function getFromStore(store, ...params) {
1669
+ let token;
1670
+ let family;
1671
+ let key;
1672
+ if (params.length === 1) {
1673
+ token = params[0];
1674
+ } else {
1675
+ family = params[0];
1676
+ key = params[1];
1677
+ token = findInStore(store, family, key);
1678
+ }
1679
+ if (`counterfeit` in token && `family` in token) {
1680
+ family = store.families.get(token.family.key);
1681
+ const subKey = token.family.subKey;
1682
+ const disposal = store.disposalTraces.buffer.find(
1683
+ (item) => item?.key === subKey
1684
+ );
1685
+ store.logger.error(
1686
+ `\u274C`,
1687
+ token.type,
1688
+ token.key,
1689
+ `could not be retrieved because it was not found in the store "${store.config.name}".`,
1690
+ disposal ? `This state was previously disposed:
1691
+ ${disposal.trace}` : `No previous disposal trace was found.`
1692
+ );
1693
+ switch (family.type) {
1694
+ case `atom_family`:
1695
+ case `mutable_atom_family`:
1696
+ return store.defaults.get(family.key);
1697
+ case `selector_family`:
1698
+ case `readonly_selector_family`: {
1699
+ if (store.defaults.has(family.key)) {
1700
+ return store.defaults.get(token.family.key);
1701
+ }
1702
+ const defaultValue = withdraw(family, store).default(subKey);
1703
+ store.defaults.set(family.key, defaultValue);
1704
+ return defaultValue;
1705
+ }
1706
+ }
1707
+ }
1708
+ return readOrComputeValue(withdraw(token, store), store);
1709
+ }
1710
+
2025
1711
  // internal/src/lazy-map.ts
2026
1712
  var LazyMap = class extends Map {
2027
1713
  constructor(source) {
@@ -2038,7 +1724,7 @@ var LazyMap = class extends Map {
2038
1724
  const value = this.source.get(key);
2039
1725
  return value;
2040
1726
  }
2041
- return void 0;
1727
+ return undefined;
2042
1728
  }
2043
1729
  set(key, value) {
2044
1730
  this.deleted.delete(key);
@@ -2069,6 +1755,7 @@ var buildTransaction = (key, params, store, id) => {
2069
1755
  atoms: new LazyMap(parent.atoms),
2070
1756
  atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2071
1757
  families: new LazyMap(parent.families),
1758
+ joins: new LazyMap(parent.joins),
2072
1759
  operation: { open: false },
2073
1760
  readonlySelectors: new LazyMap(parent.readonlySelectors),
2074
1761
  timelines: new LazyMap(parent.timelines),
@@ -2084,8 +1771,15 @@ var buildTransaction = (key, params, store, id) => {
2084
1771
  defaults: parent.defaults,
2085
1772
  disposalTraces: store.disposalTraces.copy(),
2086
1773
  molecules: new LazyMap(parent.molecules),
2087
- moleculeFamilies: new LazyMap(parent.moleculeFamilies),
2088
- moleculeInProgress: parent.moleculeInProgress,
1774
+ moleculeGraph: new Junction(parent.moleculeGraph.toJSON(), {
1775
+ makeContentKey: parent.moleculeGraph.makeContentKey
1776
+ }),
1777
+ moleculeData: new Junction(parent.moleculeData.toJSON(), {
1778
+ makeContentKey: parent.moleculeData.makeContentKey
1779
+ }),
1780
+ moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), {
1781
+ makeContentKey: parent.moleculeJoins.makeContentKey
1782
+ }),
2089
1783
  miscResources: new LazyMap(parent.miscResources)
2090
1784
  };
2091
1785
  const epoch = getEpochNumberOfAction(key, store);
@@ -2095,10 +1789,10 @@ var buildTransaction = (key, params, store, id) => {
2095
1789
  type: `transaction_update`,
2096
1790
  key,
2097
1791
  id,
2098
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
1792
+ epoch: epoch === undefined ? Number.NaN : epoch + 1,
2099
1793
  updates: [],
2100
1794
  params,
2101
- output: void 0
1795
+ output: undefined
2102
1796
  },
2103
1797
  toolkit: {
2104
1798
  get: (...ps) => getFromStore(child, ...ps),
@@ -2109,7 +1803,6 @@ var buildTransaction = (key, params, store, id) => {
2109
1803
  find: (token, k) => findInStore(child, token, k),
2110
1804
  seek: (token, k) => seekInStore(child, token, k),
2111
1805
  json: (token) => getJsonToken(child, token),
2112
- make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
2113
1806
  dispose: (...ps) => {
2114
1807
  disposeFromStore(child, ...ps);
2115
1808
  },
@@ -2162,18 +1855,18 @@ function createTransaction(options, store) {
2162
1855
  // internal/src/transaction/get-epoch-number.ts
2163
1856
  function getContinuityKey(transactionKey, store) {
2164
1857
  const isRoot = isRootStore(store);
2165
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
1858
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : undefined;
2166
1859
  return continuity;
2167
1860
  }
2168
1861
  function getEpochNumberOfContinuity(continuityKey, store) {
2169
1862
  const isRoot = isRootStore(store);
2170
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
1863
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : undefined;
2171
1864
  return epoch;
2172
1865
  }
2173
1866
  function getEpochNumberOfAction(transactionKey, store) {
2174
1867
  const isRoot = isRootStore(store);
2175
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2176
- const epoch = isRoot && continuity !== void 0 ? store.transactionMeta.epoch.get(continuity) : void 0;
1868
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : undefined;
1869
+ const epoch = isRoot && continuity !== undefined ? store.transactionMeta.epoch.get(continuity) : undefined;
2177
1870
  return epoch;
2178
1871
  }
2179
1872
 
@@ -2205,6 +1898,7 @@ var Store = class {
2205
1898
  );
2206
1899
  trackers = /* @__PURE__ */ new Map();
2207
1900
  families = /* @__PURE__ */ new Map();
1901
+ joins = /* @__PURE__ */ new Map();
2208
1902
  transactions = /* @__PURE__ */ new Map();
2209
1903
  transactionMeta = {
2210
1904
  epoch: /* @__PURE__ */ new Map(),
@@ -2220,8 +1914,33 @@ var Store = class {
2220
1914
  });
2221
1915
  disposalTraces = new CircularBuffer(100);
2222
1916
  molecules = /* @__PURE__ */ new Map();
2223
- moleculeFamilies = /* @__PURE__ */ new Map();
2224
- moleculeInProgress = null;
1917
+ moleculeJoins = new Junction(
1918
+ {
1919
+ between: [`moleculeKey`, `joinKey`],
1920
+ cardinality: `n:n`
1921
+ },
1922
+ {
1923
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1924
+ }
1925
+ );
1926
+ moleculeGraph = new Junction(
1927
+ {
1928
+ between: [`upstreamMoleculeKey`, `downstreamMoleculeKey`],
1929
+ cardinality: `n:n`
1930
+ },
1931
+ {
1932
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1933
+ }
1934
+ );
1935
+ moleculeData = new Junction(
1936
+ {
1937
+ between: [`moleculeKey`, `stateFamilyKey`],
1938
+ cardinality: `n:n`
1939
+ },
1940
+ {
1941
+ makeContentKey: (...keys) => keys.sort().join(`:`)
1942
+ }
1943
+ );
2225
1944
  miscResources = /* @__PURE__ */ new Map();
2226
1945
  on = {
2227
1946
  atomCreation: new Subject(),
@@ -2234,8 +1953,7 @@ var Store = class {
2234
1953
  null
2235
1954
  ),
2236
1955
  operationClose: new Subject(),
2237
- moleculeCreationStart: new Subject(),
2238
- moleculeCreationDone: new Subject(),
1956
+ moleculeCreation: new Subject(),
2239
1957
  moleculeDisposal: new Subject()
2240
1958
  };
2241
1959
  operation = { open: false };
@@ -2329,6 +2047,8 @@ var clearStore = (store) => {
2329
2047
  Object.assign(store, new Store(config));
2330
2048
  store.config = config;
2331
2049
  };
2050
+
2051
+ // internal/src/store/withdraw.ts
2332
2052
  function withdraw(token, store) {
2333
2053
  let withdrawn;
2334
2054
  let target = store;
@@ -2356,12 +2076,6 @@ function withdraw(token, store) {
2356
2076
  case `transaction`:
2357
2077
  withdrawn = target.transactions.get(token.key);
2358
2078
  break;
2359
- case `molecule`:
2360
- withdrawn = target.molecules.get(stringifyJson(token.key));
2361
- break;
2362
- case `molecule_family`:
2363
- withdrawn = target.moleculeFamilies.get(token.key);
2364
- break;
2365
2079
  }
2366
2080
  if (withdrawn) {
2367
2081
  return withdrawn;
@@ -2399,7 +2113,7 @@ var subscribeToRootAtoms = (selector, store) => {
2399
2113
  const dependencySubscriptions = traceAllSelectorAtoms(selector, store).map(
2400
2114
  (atomKey) => {
2401
2115
  const atom = target.atoms.get(atomKey);
2402
- if (atom === void 0) {
2116
+ if (atom === undefined) {
2403
2117
  throw new Error(
2404
2118
  `Atom "${atomKey}", a dependency of selector "${selector.key}", not found in store "${store.config.name}".`
2405
2119
  );
@@ -2532,7 +2246,7 @@ var Tracker = class {
2532
2246
  const familyMetaData = mutableState.family ? {
2533
2247
  key: `*${mutableState.family.key}`,
2534
2248
  subKey: mutableState.family.subKey
2535
- } : void 0;
2249
+ } : undefined;
2536
2250
  const latestUpdateState = createRegularAtom(
2537
2251
  store,
2538
2252
  {
@@ -2872,7 +2586,7 @@ function copyMutableIfNeeded(atom, origin, target) {
2872
2586
  const originValue = origin.valueMap.get(atom.key);
2873
2587
  const targetValue = target.valueMap.get(atom.key);
2874
2588
  if (originValue === targetValue) {
2875
- if (originValue === void 0) {
2589
+ if (originValue === undefined) {
2876
2590
  return typeof atom.default === `function` ? atom.default() : atom.default;
2877
2591
  }
2878
2592
  origin.logger.info(`\u{1F4C3}`, `atom`, atom.key, `copying`);
@@ -3020,11 +2734,11 @@ function createRegularAtom(store, options, family) {
3020
2734
  function createStandaloneAtom(store, options) {
3021
2735
  const isMutable = `mutable` in options;
3022
2736
  if (isMutable) {
3023
- const state2 = createMutableAtom(store, options, void 0);
2737
+ const state2 = createMutableAtom(store, options, undefined);
3024
2738
  store.on.atomCreation.next(state2);
3025
2739
  return state2;
3026
2740
  }
3027
- const state = createRegularAtom(store, options, void 0);
2741
+ const state = createRegularAtom(store, options, undefined);
3028
2742
  store.on.atomCreation.next(state);
3029
2743
  return state;
3030
2744
  }
@@ -3032,23 +2746,22 @@ function createStandaloneAtom(store, options) {
3032
2746
  // internal/src/atom/dispose-atom.ts
3033
2747
  function disposeAtom(atomToken, store) {
3034
2748
  const target = newest(store);
3035
- const { key } = atomToken;
2749
+ const { key, family } = atomToken;
3036
2750
  const atom = withdraw(atomToken, target);
3037
- if (!atom.family) {
2751
+ if (!family) {
3038
2752
  store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
3039
2753
  } else {
3040
2754
  atom.cleanup?.();
3041
2755
  const lastValue = store.valueMap.get(atom.key);
3042
- const family = withdraw({ key: atom.family.key, type: `atom_family` }, store);
3043
- family.subject.next({
2756
+ const atomFamily = withdraw({ key: family.key, type: `atom_family` }, store);
2757
+ const disposal = {
3044
2758
  type: `state_disposal`,
2759
+ subType: `atom`,
3045
2760
  token: atomToken,
3046
2761
  value: lastValue
3047
- });
3048
- const molecule = target.molecules.get(atom.family.subKey);
3049
- if (molecule) {
3050
- molecule.tokens.delete(key);
3051
- }
2762
+ };
2763
+ atomFamily.subject.next(disposal);
2764
+ const isChild = isChildStore(target);
3052
2765
  target.atoms.delete(key);
3053
2766
  target.valueMap.delete(key);
3054
2767
  target.selectorAtoms.delete(key);
@@ -3060,16 +2773,32 @@ function disposeAtom(atomToken, store) {
3060
2773
  store.trackers.delete(key);
3061
2774
  }
3062
2775
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
3063
- if (isChildStore(target) && target.transactionMeta.phase === `building`) {
3064
- target.transactionMeta.update.updates.push({
3065
- type: `state_disposal`,
3066
- token: atomToken
3067
- });
2776
+ if (isChild && target.transactionMeta.phase === `building`) {
2777
+ const mostRecentUpdate = target.transactionMeta.update.updates.at(-1);
2778
+ const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
2779
+ const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
2780
+ if (!updateAlreadyCaptured) {
2781
+ target.transactionMeta.update.updates.push(disposal);
2782
+ }
3068
2783
  } else {
3069
2784
  store.on.atomDisposal.next(atomToken);
3070
2785
  }
3071
2786
  }
3072
2787
  }
2788
+
2789
+ // internal/src/get-trace.ts
2790
+ function getTrace(error) {
2791
+ const { stack } = error;
2792
+ if (stack) {
2793
+ return `
2794
+ ` + stack.split(`
2795
+ `)?.slice(1)?.join(`
2796
+ `);
2797
+ }
2798
+ return ``;
2799
+ }
2800
+
2801
+ // internal/src/timeline/create-timeline.ts
3073
2802
  function createTimeline(options, store, data) {
3074
2803
  const tl = {
3075
2804
  type: `timeline`,
@@ -3140,23 +2869,6 @@ function createTimeline(options, store, data) {
3140
2869
  addAtomFamilyToTimeline(familyToken, tl, store);
3141
2870
  }
3142
2871
  break;
3143
- case `molecule_family`:
3144
- {
3145
- const familyToken = initialTopic;
3146
- const familyKey = familyToken.key;
3147
- const existingTimelineKey = target.timelineTopics.getRelatedKey(familyKey);
3148
- if (existingTimelineKey) {
3149
- store.logger.error(
3150
- `\u274C`,
3151
- `timeline`,
3152
- options.key,
3153
- `Failed to add molecule family "${familyKey}" because it already belongs to timeline "${existingTimelineKey}"`
3154
- );
3155
- continue;
3156
- }
3157
- addMoleculeFamilyToTimeline(familyToken, tl, store);
3158
- }
3159
- break;
3160
2872
  }
3161
2873
  }
3162
2874
  store.timelines.set(options.key, tl);
@@ -3180,109 +2892,112 @@ function addAtomToTimeline(atomToken, tl, store) {
3180
2892
  );
3181
2893
  tl.subscriptions.set(
3182
2894
  atom.key,
3183
- atom.subject.subscribe(`timeline`, (update) => {
3184
- const target = newest(store);
3185
- const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
3186
- const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
3187
- const txUpdateInProgress = target.on.transactionApplying.state?.update;
3188
- store.logger.info(
3189
- `\u23F3`,
3190
- `timeline`,
3191
- tl.key,
3192
- `atom`,
3193
- atomToken.key,
3194
- `went`,
3195
- update.oldValue,
3196
- `->`,
3197
- update.newValue,
3198
- txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
3199
- );
3200
- if (tl.timeTraveling === null) {
3201
- if (txUpdateInProgress) {
3202
- joinTransaction(tl, txUpdateInProgress, store);
3203
- } else if (currentSelectorKey && currentSelectorTime) {
3204
- let latestUpdate = tl.history.at(-1);
3205
- if (currentSelectorTime !== tl.selectorTime) {
3206
- latestUpdate = {
3207
- type: `selector_update`,
3208
- timestamp: currentSelectorTime,
3209
- key: currentSelectorKey,
3210
- atomUpdates: []
3211
- };
3212
- latestUpdate.atomUpdates.push({
3213
- key: atom.key,
3214
- type: `atom_update`,
3215
- ...update
3216
- });
3217
- if (tl.at !== tl.history.length) {
3218
- tl.history.splice(tl.at);
3219
- }
3220
- tl.history.push(latestUpdate);
3221
- store.logger.info(
3222
- `\u231B`,
3223
- `timeline`,
3224
- tl.key,
3225
- `got a selector_update "${currentSelectorKey}" with`,
3226
- latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
3227
- );
3228
- tl.at = tl.history.length;
3229
- tl.selectorTime = currentSelectorTime;
3230
- } else {
3231
- if (latestUpdate?.type === `selector_update`) {
2895
+ atom.subject.subscribe(
2896
+ `timeline`,
2897
+ function timelineCapturesAtomUpdate(update) {
2898
+ const target = newest(store);
2899
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
2900
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
2901
+ const txUpdateInProgress = target.on.transactionApplying.state?.update;
2902
+ store.logger.info(
2903
+ `\u23F3`,
2904
+ `timeline`,
2905
+ tl.key,
2906
+ `atom`,
2907
+ atomToken.key,
2908
+ `went`,
2909
+ update.oldValue,
2910
+ `->`,
2911
+ update.newValue,
2912
+ txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
2913
+ );
2914
+ if (tl.timeTraveling === null) {
2915
+ if (txUpdateInProgress) {
2916
+ joinTransaction(tl, txUpdateInProgress, store);
2917
+ } else if (currentSelectorKey && currentSelectorTime) {
2918
+ let latestUpdate = tl.history.at(-1);
2919
+ if (currentSelectorTime !== tl.selectorTime) {
2920
+ latestUpdate = {
2921
+ type: `selector_update`,
2922
+ timestamp: currentSelectorTime,
2923
+ key: currentSelectorKey,
2924
+ atomUpdates: []
2925
+ };
3232
2926
  latestUpdate.atomUpdates.push({
3233
2927
  key: atom.key,
3234
2928
  type: `atom_update`,
3235
2929
  ...update
3236
2930
  });
2931
+ if (tl.at !== tl.history.length) {
2932
+ tl.history.splice(tl.at);
2933
+ }
2934
+ tl.history.push(latestUpdate);
3237
2935
  store.logger.info(
3238
2936
  `\u231B`,
3239
2937
  `timeline`,
3240
2938
  tl.key,
3241
- `set selector_update "${currentSelectorKey}" to`,
3242
- latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
2939
+ `got a selector_update "${currentSelectorKey}" with`,
2940
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
3243
2941
  );
3244
- }
3245
- }
3246
- if (latestUpdate) {
3247
- const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
3248
- if (willCaptureSelectorUpdate) {
3249
- tl.subject.next(latestUpdate);
2942
+ tl.at = tl.history.length;
2943
+ tl.selectorTime = currentSelectorTime;
3250
2944
  } else {
3251
- tl.history.pop();
2945
+ if (latestUpdate?.type === `selector_update`) {
2946
+ latestUpdate.atomUpdates.push({
2947
+ key: atom.key,
2948
+ type: `atom_update`,
2949
+ ...update
2950
+ });
2951
+ store.logger.info(
2952
+ `\u231B`,
2953
+ `timeline`,
2954
+ tl.key,
2955
+ `set selector_update "${currentSelectorKey}" to`,
2956
+ latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
2957
+ );
2958
+ }
2959
+ }
2960
+ if (latestUpdate) {
2961
+ const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
2962
+ if (willCaptureSelectorUpdate) {
2963
+ tl.subject.next(latestUpdate);
2964
+ } else {
2965
+ tl.history.pop();
2966
+ tl.at = tl.history.length;
2967
+ }
2968
+ }
2969
+ } else {
2970
+ const timestamp = Date.now();
2971
+ tl.selectorTime = null;
2972
+ if (tl.at !== tl.history.length) {
2973
+ tl.history.splice(tl.at);
2974
+ }
2975
+ const atomUpdate = {
2976
+ type: `atom_update`,
2977
+ timestamp,
2978
+ key: atom.key,
2979
+ oldValue: update.oldValue,
2980
+ newValue: update.newValue
2981
+ };
2982
+ if (atom.family) {
2983
+ atomUpdate.family = atom.family;
2984
+ }
2985
+ const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
2986
+ store.logger.info(
2987
+ `\u231B`,
2988
+ `timeline`,
2989
+ tl.key,
2990
+ `got an atom_update to "${atom.key}"`
2991
+ );
2992
+ if (willCapture) {
2993
+ tl.history.push(atomUpdate);
3252
2994
  tl.at = tl.history.length;
2995
+ tl.subject.next(atomUpdate);
3253
2996
  }
3254
2997
  }
3255
- } else {
3256
- const timestamp = Date.now();
3257
- tl.selectorTime = null;
3258
- if (tl.at !== tl.history.length) {
3259
- tl.history.splice(tl.at);
3260
- }
3261
- const atomUpdate = {
3262
- type: `atom_update`,
3263
- timestamp,
3264
- key: atom.key,
3265
- oldValue: update.oldValue,
3266
- newValue: update.newValue
3267
- };
3268
- if (atom.family) {
3269
- atomUpdate.family = atom.family;
3270
- }
3271
- const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
3272
- store.logger.info(
3273
- `\u231B`,
3274
- `timeline`,
3275
- tl.key,
3276
- `got an atom_update to "${atom.key}"`
3277
- );
3278
- if (willCapture) {
3279
- tl.history.push(atomUpdate);
3280
- tl.at = tl.history.length;
3281
- tl.subject.next(atomUpdate);
3282
- }
3283
2998
  }
3284
2999
  }
3285
- })
3000
+ )
3286
3001
  );
3287
3002
  }
3288
3003
  function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
@@ -3293,9 +3008,12 @@ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
3293
3008
  );
3294
3009
  tl.subscriptions.set(
3295
3010
  family.key,
3296
- family.subject.subscribe(`timeline`, (creationOrDisposal) => {
3297
- handleStateLifecycleEvent(creationOrDisposal, tl, store);
3298
- })
3011
+ family.subject.subscribe(
3012
+ `timeline`,
3013
+ function timelineCapturesStateLifecycleEvent(creationOrDisposal) {
3014
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
3015
+ }
3016
+ )
3299
3017
  );
3300
3018
  for (const atom of store.atoms.values()) {
3301
3019
  if (atom.family?.key === family.key) {
@@ -3303,99 +3021,6 @@ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
3303
3021
  }
3304
3022
  }
3305
3023
  }
3306
- function addMoleculeFamilyToTimeline(familyToken, tl, store) {
3307
- store.timelineTopics.set(
3308
- { topicKey: familyToken.key, timelineKey: tl.key },
3309
- { topicType: `molecule_family` }
3310
- );
3311
- const family = store.moleculeFamilies.get(familyToken.key);
3312
- if (family) {
3313
- tl.subscriptions.set(
3314
- familyToken.key,
3315
- family.subject.subscribe(`timeline:${tl.key}`, (creationOrDisposal) => {
3316
- store.logger.info(
3317
- `\u{1F41E}`,
3318
- `timeline`,
3319
- tl.key,
3320
- `got a molecule creation or disposal`,
3321
- creationOrDisposal
3322
- );
3323
- if (creationOrDisposal.subType === `classic`) {
3324
- switch (creationOrDisposal.type) {
3325
- case `molecule_creation`:
3326
- {
3327
- store.timelineTopics.set(
3328
- {
3329
- topicKey: creationOrDisposal.token.key,
3330
- timelineKey: tl.key
3331
- },
3332
- { topicType: `molecule` }
3333
- );
3334
- const txUpdateInProgress = newest(store).on.transactionApplying.state?.update;
3335
- if (txUpdateInProgress) {
3336
- joinTransaction(tl, txUpdateInProgress, store);
3337
- } else if (tl.timeTraveling === null) {
3338
- const event = Object.assign(creationOrDisposal, {
3339
- timestamp: Date.now()
3340
- });
3341
- tl.history.push(event);
3342
- tl.at = tl.history.length;
3343
- tl.subject.next(event);
3344
- }
3345
- const molecule = withdraw(creationOrDisposal.token, store);
3346
- for (const token of molecule.tokens.values()) {
3347
- switch (token.type) {
3348
- case `atom`:
3349
- case `mutable_atom`:
3350
- addAtomToTimeline(token, tl, store);
3351
- break;
3352
- }
3353
- }
3354
- tl.subscriptions.set(
3355
- molecule.key,
3356
- molecule.subject.subscribe(
3357
- `timeline:${tl.key}`,
3358
- (stateCreationOrDisposal) => {
3359
- handleStateLifecycleEvent(
3360
- stateCreationOrDisposal,
3361
- tl,
3362
- store
3363
- );
3364
- }
3365
- )
3366
- );
3367
- }
3368
- break;
3369
- case `molecule_disposal`:
3370
- {
3371
- const txUpdateInProgress = newest(store).on.transactionApplying.state?.update;
3372
- if (txUpdateInProgress) {
3373
- joinTransaction(tl, txUpdateInProgress, store);
3374
- } else if (tl.timeTraveling === null) {
3375
- const event = Object.assign(creationOrDisposal, {
3376
- timestamp: Date.now()
3377
- });
3378
- tl.history.push(event);
3379
- tl.at = tl.history.length;
3380
- tl.subject.next(event);
3381
- }
3382
- const moleculeKey = stringifyJson(creationOrDisposal.token.key);
3383
- tl.subscriptions.get(moleculeKey)?.();
3384
- tl.subscriptions.delete(moleculeKey);
3385
- for (const [familyKey] of creationOrDisposal.values) {
3386
- const stateKey = `${familyKey}(${stringifyJson(moleculeKey)})`;
3387
- tl.subscriptions.get(stateKey)?.();
3388
- tl.subscriptions.delete(stateKey);
3389
- store.timelineTopics.delete(stateKey);
3390
- }
3391
- }
3392
- break;
3393
- }
3394
- }
3395
- })
3396
- );
3397
- }
3398
- }
3399
3024
  function joinTransaction(tl, txUpdateInProgress, store) {
3400
3025
  const currentTxKey = txUpdateInProgress.key;
3401
3026
  const currentTxInstanceId = txUpdateInProgress.id;
@@ -3451,14 +3076,9 @@ function filterTransactionUpdates(updates, timelineTopics) {
3451
3076
  break;
3452
3077
  case `molecule_creation`:
3453
3078
  case `molecule_disposal`:
3454
- switch (updateFromTx.subType) {
3455
- case `classic`:
3456
- key = updateFromTx.token.key;
3457
- break;
3458
- case `modern`:
3459
- return true;
3460
- }
3461
- break;
3079
+ case `molecule_transfer`:
3080
+ return true;
3081
+ // always include
3462
3082
  default:
3463
3083
  key = updateFromTx.key;
3464
3084
  familyKey = updateFromTx.family?.key;
@@ -3565,14 +3185,6 @@ var timeTravel = (store, action, token) => {
3565
3185
  ingestDisposalEvent(update, applying, store);
3566
3186
  break;
3567
3187
  }
3568
- case `molecule_creation`: {
3569
- ingestMoleculeCreationEvent(update, applying, store);
3570
- break;
3571
- }
3572
- case `molecule_disposal`: {
3573
- ingestMoleculeDisposalEvent(update, applying, store);
3574
- break;
3575
- }
3576
3188
  }
3577
3189
  if (action === `redo`) {
3578
3190
  ++timelineData.at;
@@ -3587,4 +3199,4 @@ var timeTravel = (store, action, token) => {
3587
3199
  );
3588
3200
  };
3589
3201
 
3590
- export { CircularBuffer, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Junction, 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 };
3202
+ export { CircularBuffer, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Junction, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, createWritableSelectorFamily, deposit, disposeAtom, disposeFromStore, disposeSelector, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, 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 };