atom.io 0.30.7 → 0.31.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 (92) 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-Y5MBNTVU.js} +582 -762
  5. package/dist/index.d.ts +254 -173
  6. package/dist/index.js +91 -14
  7. package/ephemeral/dist/index.d.ts +35 -25
  8. package/ephemeral/src/find-state.ts +35 -25
  9. package/eslint-plugin/dist/index.d.ts +22 -3
  10. package/eslint-plugin/dist/index.js +7 -7
  11. package/immortal/dist/index.d.ts +1 -2
  12. package/immortal/dist/index.js +0 -3
  13. package/immortal/src/seek-state.ts +2 -14
  14. package/internal/dist/index.d.ts +57 -88
  15. package/internal/dist/index.js +1 -2
  16. package/internal/src/atom/dispose-atom.ts +31 -15
  17. package/internal/src/families/dispose-from-store.ts +15 -44
  18. package/internal/src/families/find-in-store.ts +9 -7
  19. package/internal/src/families/init-family-member.ts +1 -1
  20. package/internal/src/families/seek-in-store.ts +2 -14
  21. package/internal/src/get-state/get-from-store.ts +13 -79
  22. package/internal/src/get-trace.ts +7 -0
  23. package/internal/src/index.ts +17 -8
  24. package/internal/src/ingest-updates/ingest-creation-disposal.ts +65 -73
  25. package/internal/src/ingest-updates/ingest-transaction-update.ts +4 -0
  26. package/internal/src/install-into-store.ts +48 -0
  27. package/internal/src/junction.ts +52 -12
  28. package/internal/src/lineage.ts +0 -7
  29. package/internal/src/molecule.ts +306 -0
  30. package/internal/src/mutable/transceiver.ts +5 -5
  31. package/internal/src/not-found-error.ts +8 -30
  32. package/internal/src/pretty-print.ts +1 -16
  33. package/internal/src/selector/dispose-selector.ts +3 -5
  34. package/internal/src/selector/register-selector.ts +3 -34
  35. package/internal/src/set-state/set-into-store.ts +3 -2
  36. package/internal/src/store/counterfeit.ts +11 -25
  37. package/internal/src/store/deposit.ts +10 -42
  38. package/internal/src/store/store.ts +51 -12
  39. package/internal/src/store/withdraw.ts +18 -60
  40. package/internal/src/timeline/create-timeline.ts +133 -237
  41. package/internal/src/timeline/time-travel.ts +1 -8
  42. package/internal/src/transaction/build-transaction.ts +10 -5
  43. package/internal/src/transaction/index.ts +1 -1
  44. package/internal/src/utility-types.ts +2 -0
  45. package/introspection/dist/index.d.ts +2 -3
  46. package/introspection/dist/index.js +9 -9
  47. package/introspection/src/refinery.ts +1 -3
  48. package/json/dist/index.js +8 -40
  49. package/json/src/index.ts +2 -0
  50. package/json/src/select-json-family.ts +7 -44
  51. package/package.json +33 -28
  52. package/react/dist/index.js +2 -10
  53. package/react/src/parse-state-overloads.ts +3 -11
  54. package/react-devtools/dist/index.js +13 -13
  55. package/react-devtools/src/Updates.tsx +2 -0
  56. package/realtime-client/dist/index.d.ts +20 -12
  57. package/realtime-client/dist/index.js +241 -244
  58. package/realtime-client/src/continuity/index.ts +3 -0
  59. package/realtime-client/src/continuity/register-and-attempt-confirmed-update.ts +231 -0
  60. package/realtime-client/src/continuity/use-conceal-state.ts +11 -0
  61. package/realtime-client/src/continuity/use-reveal-state.ts +19 -0
  62. package/realtime-client/src/index.ts +1 -0
  63. package/realtime-client/src/sync-continuity.ts +18 -262
  64. package/realtime-react/dist/index.js +2 -2
  65. package/realtime-server/dist/index.d.ts +1 -1
  66. package/realtime-server/dist/index.js +2 -2
  67. package/realtime-server/src/index.ts +1 -1
  68. package/realtime-server/src/ipc-sockets/child-socket.ts +0 -1
  69. package/realtime-server/src/realtime-server-stores/server-room-external-actions.ts +1 -1
  70. package/realtime-testing/dist/index.js +5 -7
  71. package/realtime-testing/src/setup-realtime-test.tsx +5 -6
  72. package/src/atom.ts +53 -29
  73. package/src/dispose-state.ts +17 -23
  74. package/src/get-state.ts +19 -21
  75. package/src/index.ts +73 -3
  76. package/src/realm.ts +169 -0
  77. package/src/selector.ts +20 -0
  78. package/src/set-state.ts +16 -8
  79. package/src/silo.ts +9 -14
  80. package/src/timeline.ts +2 -3
  81. package/src/transaction.ts +25 -38
  82. package/transceivers/set-rtx/dist/index.js +4 -1
  83. package/transceivers/set-rtx/src/set-rtx.ts +4 -1
  84. package/dist/chunk-ADMEAXYU.js +0 -167
  85. package/internal/src/molecule/create-molecule-family.ts +0 -30
  86. package/internal/src/molecule/dispose-molecule.ts +0 -79
  87. package/internal/src/molecule/grow-molecule-in-store.ts +0 -95
  88. package/internal/src/molecule/index.ts +0 -5
  89. package/internal/src/molecule/make-molecule-in-store.ts +0 -191
  90. package/internal/src/molecule/molecule-internal.ts +0 -52
  91. package/src/allocate.ts +0 -277
  92. package/src/molecule.ts +0 -138
@@ -1,7 +1,5 @@
1
- import { deallocateFromStore, allocateIntoStore } from './chunk-ADMEAXYU.js';
2
1
  import { stringifyJson, parseJson, selectJson, selectJsonFamily } from 'atom.io/json';
3
2
  import { AtomIOLogger } from 'atom.io';
4
- import { getJoin, findRelations } from 'atom.io/data';
5
3
  import { subscribeToTimeline, subscribeToTransaction, subscribeToState, arbitrary as arbitrary$1 } from 'atom.io/internal';
6
4
 
7
5
  // internal/src/arbitrary.ts
@@ -52,7 +50,7 @@ var Future = class extends Promise {
52
50
  );
53
51
  } else {
54
52
  this.resolve(value);
55
- this.fate = void 0;
53
+ this.fate = undefined;
56
54
  }
57
55
  }
58
56
  };
@@ -64,12 +62,6 @@ function newest(scion) {
64
62
  }
65
63
  return scion;
66
64
  }
67
- function eldest(scion) {
68
- while (scion.parent !== null) {
69
- scion = scion.parent;
70
- }
71
- return scion;
72
- }
73
65
 
74
66
  // internal/src/store/circular-buffer.ts
75
67
  var CircularBuffer = class _CircularBuffer {
@@ -115,19 +107,12 @@ function counterfeit(token, key) {
115
107
  key: fullKey,
116
108
  type
117
109
  };
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
- }
110
+ Object.assign(stateToken, {
111
+ family: {
112
+ key: token.key,
113
+ subKey
114
+ }
115
+ });
131
116
  Object.assign(stateToken, { counterfeit: true });
132
117
  return stateToken;
133
118
  }
@@ -200,8 +185,8 @@ var Junction = class {
200
185
  }
201
186
  replaceRelationsSafely(x, ys) {
202
187
  const xRelationsPrev = this.relations.get(x);
203
- let a = this.isAType?.(x) ? x : void 0;
204
- let b = a === void 0 ? x : void 0;
188
+ let a = this.isAType?.(x) ? x : undefined;
189
+ let b = a === undefined ? x : undefined;
205
190
  if (xRelationsPrev) {
206
191
  for (const y of xRelationsPrev) {
207
192
  a ??= y;
@@ -283,8 +268,8 @@ var Junction = class {
283
268
  };
284
269
  }
285
270
  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;
271
+ let a = this.isAType?.(x) ? x : undefined;
272
+ let b = a === undefined ? x : undefined;
288
273
  for (const y of ys) {
289
274
  a ??= y;
290
275
  b ??= y;
@@ -309,10 +294,36 @@ var Junction = class {
309
294
  contents: [...this.contents.entries()]
310
295
  };
311
296
  }
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];
297
+ set(...params) {
298
+ let a;
299
+ let b;
300
+ let content;
301
+ switch (params.length) {
302
+ case 1: {
303
+ const relation = params[0];
304
+ a = relation[this.a];
305
+ b = relation[this.b];
306
+ content = undefined;
307
+ break;
308
+ }
309
+ case 2: {
310
+ const zeroth = params[0];
311
+ if (typeof zeroth === `string`) {
312
+ [a, b] = params;
313
+ } else {
314
+ a = zeroth[this.a];
315
+ b = zeroth[this.b];
316
+ content = params[1];
317
+ }
318
+ break;
319
+ }
320
+ default: {
321
+ a = params[0];
322
+ b = params[1];
323
+ content = params[2];
324
+ break;
325
+ }
326
+ }
316
327
  switch (this.cardinality) {
317
328
  // biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
318
329
  case `1:1`: {
@@ -337,7 +348,7 @@ var Junction = class {
337
348
  // @ts-expect-error we deduce that this.a may index x
338
349
  typeof x === `string` ? x : x[this.a]
339
350
  );
340
- if (a === void 0 && typeof b === `string`) {
351
+ if (a === undefined && typeof b === `string`) {
341
352
  const bRelations = this.getRelatedKeys(b);
342
353
  if (bRelations) {
343
354
  for (const bRelation of bRelations) {
@@ -345,7 +356,7 @@ var Junction = class {
345
356
  }
346
357
  }
347
358
  }
348
- if (typeof a === `string` && b === void 0) {
359
+ if (typeof a === `string` && b === undefined) {
349
360
  const aRelations = this.getRelatedKeys(a);
350
361
  if (aRelations) {
351
362
  for (const aRelation of aRelations) {
@@ -402,7 +413,7 @@ var Junction = class {
402
413
  getRelationEntries(input) {
403
414
  const a = input[this.a];
404
415
  const b = input[this.b];
405
- if (a !== void 0 && b === void 0) {
416
+ if (a !== undefined && b === undefined) {
406
417
  const aRelations = this.getRelatedKeys(a);
407
418
  if (aRelations) {
408
419
  return [...aRelations].map((aRelation) => {
@@ -410,7 +421,7 @@ var Junction = class {
410
421
  });
411
422
  }
412
423
  }
413
- if (a === void 0 && b !== void 0) {
424
+ if (a === undefined && b !== undefined) {
414
425
  const bRelations = this.getRelatedKeys(b);
415
426
  if (bRelations) {
416
427
  return [...bRelations].map((bRelation) => {
@@ -499,19 +510,10 @@ function prettyPrintTokenType(token) {
499
510
 
500
511
  // internal/src/not-found-error.ts
501
512
  var NotFoundError = class extends Error {
502
- constructor(...params) {
503
- const token = params[0];
504
- const store = params.length === 2 ? params[1] : params[2];
505
- if (params.length === 2) {
506
- super(
507
- `${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
508
- );
509
- } else {
510
- const key = params[1];
511
- super(
512
- `${prettyPrintTokenType(token)} "${token.key}" member ${stringifyJson(key)} not found in store "${store.config.name}".`
513
- );
514
- }
513
+ constructor(token, store) {
514
+ super(
515
+ `${prettyPrintTokenType(token)} ${stringifyJson(token.key)} not found in store "${store.config.name}".`
516
+ );
515
517
  }
516
518
  };
517
519
 
@@ -823,86 +825,6 @@ function createAtomFamily(store, options) {
823
825
  return createRegularAtomFamily(store, options);
824
826
  }
825
827
 
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
828
  // internal/src/keys.ts
907
829
  var isAtomKey = (key, store) => newest(store).atoms.has(key);
908
830
  var isSelectorKey = (key, store) => newest(store).selectors.has(key);
@@ -986,27 +908,10 @@ var registerSelector = (selectorKey, covered, store) => ({
986
908
  let dependency;
987
909
  if (params.length === 2) {
988
910
  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
- }
911
+ dependency = findInStore(store, family, key);
1004
912
  } else {
1005
913
  [dependency] = params;
1006
914
  }
1007
- if (dependency.type === `molecule`) {
1008
- return getFromStore(store, dependency);
1009
- }
1010
915
  const dependencyState = withdraw(dependency, store);
1011
916
  const dependencyValue = readOrComputeValue(dependencyState, store);
1012
917
  store.logger.info(
@@ -1039,11 +944,7 @@ var registerSelector = (selectorKey, covered, store) => ({
1039
944
  const family = params[0];
1040
945
  const key = params[1];
1041
946
  value = params[2];
1042
- const maybeToken = store.config.lifespan === `ephemeral` ? findInStore(store, family, key) : seekInStore(store, family, key);
1043
- if (!maybeToken) {
1044
- throw new NotFoundError(family, key, store);
1045
- }
1046
- token = maybeToken;
947
+ token = findInStore(store, family, key);
1047
948
  }
1048
949
  const target = newest(store);
1049
950
  const state = withdraw(token, target);
@@ -1158,11 +1059,11 @@ var createWritableSelector = (store, options, family) => {
1158
1059
  function createStandaloneSelector(store, options) {
1159
1060
  const isWritable = `set` in options;
1160
1061
  if (isWritable) {
1161
- const state2 = createWritableSelector(store, options, void 0);
1062
+ const state2 = createWritableSelector(store, options, undefined);
1162
1063
  store.on.selectorCreation.next(state2);
1163
1064
  return state2;
1164
1065
  }
1165
- const state = createReadonlySelector(store, options, void 0);
1066
+ const state = createReadonlySelector(store, options, undefined);
1166
1067
  store.on.selectorCreation.next(state);
1167
1068
  return state;
1168
1069
  }
@@ -1182,20 +1083,16 @@ function disposeSelector(selectorToken, store) {
1182
1083
  } else {
1183
1084
  const molecule = target.molecules.get(selector.family.subKey);
1184
1085
  if (molecule) {
1185
- molecule.tokens.delete(key);
1086
+ target.moleculeData.delete(selector.family.subKey, selector.family.key);
1186
1087
  }
1187
1088
  switch (selectorToken.type) {
1188
1089
  case `selector`:
1189
1090
  {
1190
1091
  target.selectors.delete(key);
1191
- const family = withdraw(
1092
+ withdraw(
1192
1093
  { key: selector.family.key, type: `selector_family` },
1193
1094
  store
1194
1095
  );
1195
- family.subject.next({
1196
- type: `state_disposal`,
1197
- token: selectorToken
1198
- });
1199
1096
  }
1200
1097
  break;
1201
1098
  case `readonly_selector`:
@@ -1207,6 +1104,7 @@ function disposeSelector(selectorToken, store) {
1207
1104
  );
1208
1105
  family.subject.next({
1209
1106
  type: `state_disposal`,
1107
+ subType: `selector`,
1210
1108
  token: selectorToken
1211
1109
  });
1212
1110
  }
@@ -1219,6 +1117,7 @@ function disposeSelector(selectorToken, store) {
1219
1117
  if (isChildStore(target) && target.transactionMeta.phase === `building`) {
1220
1118
  target.transactionMeta.update.updates.push({
1221
1119
  type: `state_disposal`,
1120
+ subType: `selector`,
1222
1121
  token: selectorToken
1223
1122
  });
1224
1123
  } else {
@@ -1339,267 +1238,15 @@ function createSelectorFamily(store, options) {
1339
1238
  return createReadonlySelectorFamily(store, options);
1340
1239
  }
1341
1240
 
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
1241
  // internal/src/families/init-family-member.ts
1595
1242
  function initFamilyMemberInStore(store, token, key) {
1596
1243
  const family = store.families.get(token.key);
1597
- if (family === void 0) {
1244
+ if (family === undefined) {
1598
1245
  throw new NotFoundError(token, store);
1599
1246
  }
1600
1247
  const state = family(key);
1601
1248
  const target = newest(store);
1602
- if (state.family && target.moleculeInProgress === null) {
1249
+ if (state.family) {
1603
1250
  if (isRootStore(target)) {
1604
1251
  switch (state.type) {
1605
1252
  case `atom`:
@@ -1636,8 +1283,6 @@ function seekInStore(store, token, key) {
1636
1283
  case `readonly_selector_family`:
1637
1284
  state = target.readonlySelectors.get(fullKey);
1638
1285
  break;
1639
- case `molecule_family`:
1640
- state = target.molecules.get(stringifyJson(key));
1641
1286
  }
1642
1287
  if (state) {
1643
1288
  return deposit(state);
@@ -1651,11 +1296,9 @@ function findInStore(store, token, key) {
1651
1296
  if (state) {
1652
1297
  return state;
1653
1298
  }
1654
- const molecule = store.molecules.get(stringifyJson(key));
1655
- if (molecule) {
1656
- return growMoleculeInStore(molecule, token, store);
1657
- }
1658
- if (store.config.lifespan === `immortal`) {
1299
+ const stringKey = stringifyJson(key);
1300
+ const molecule = store.molecules.get(stringKey);
1301
+ if (!molecule && store.config.lifespan === `immortal`) {
1659
1302
  const fakeToken = counterfeit(token, key);
1660
1303
  store.logger.error(
1661
1304
  `\u274C`,
@@ -1666,6 +1309,10 @@ function findInStore(store, token, key) {
1666
1309
  return fakeToken;
1667
1310
  }
1668
1311
  state = initFamilyMemberInStore(store, token, key);
1312
+ if (molecule) {
1313
+ const target = newest(store);
1314
+ target.moleculeData.set(stringKey, token.key);
1315
+ }
1669
1316
  return state;
1670
1317
  }
1671
1318
 
@@ -1674,27 +1321,23 @@ function disposeFromStore(store, ...params) {
1674
1321
  let token;
1675
1322
  if (params.length === 1) {
1676
1323
  token = params[0];
1677
- token.key;
1678
1324
  } else {
1679
1325
  const family = params[0];
1680
1326
  const key = params[1];
1681
- const maybeToken = family.type === `molecule_family` ? seekInStore(store, family, key) ?? counterfeit(family, key) : findInStore(store, family, key);
1327
+ const maybeToken = findInStore(store, family, key);
1682
1328
  token = maybeToken;
1683
1329
  }
1684
1330
  try {
1685
1331
  withdraw(token, store);
1686
1332
  } catch (thrown) {
1687
- const disposal = store.disposalTraces.buffer.find(
1688
- (item) => item?.key === token.key
1689
- );
1690
1333
  store.logger.error(
1691
1334
  `\u274C`,
1692
1335
  token.type,
1693
1336
  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.`
1337
+ `could not be disposed because it was not found in the store "${store.config.name}".`
1338
+ // disposal
1339
+ // ? `\n This state was most recently disposed\n${disposal.trace}`
1340
+ // : `No previous disposal trace was found.`,
1698
1341
  );
1699
1342
  return;
1700
1343
  }
@@ -1707,16 +1350,16 @@ ${disposal.trace}` : `No previous disposal trace was found.`
1707
1350
  case `readonly_selector`:
1708
1351
  disposeSelector(token, store);
1709
1352
  break;
1710
- case `molecule`:
1711
- disposeMolecule(token, store);
1712
- break;
1713
1353
  }
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 });
1354
+ }
1355
+
1356
+ // internal/src/families/get-family-of-token.ts
1357
+ function getFamilyOfToken(store, token) {
1358
+ if (token.family) {
1359
+ const family = store.families.get(token.family.key);
1360
+ if (family) {
1361
+ return family;
1362
+ }
1720
1363
  }
1721
1364
  }
1722
1365
 
@@ -1740,9 +1383,10 @@ function setIntoStore(store, ...params) {
1740
1383
  value = params[2];
1741
1384
  token = findInStore(store, family, key);
1742
1385
  }
1743
- if (`counterfeit` in token) {
1386
+ if (`counterfeit` in token && `family` in token) {
1387
+ const subKey = token.family.subKey;
1744
1388
  const disposal = store.disposalTraces.buffer.find(
1745
- (item) => item?.key === token.key
1389
+ (item) => item?.key === subKey
1746
1390
  );
1747
1391
  store.logger.error(
1748
1392
  `\u274C`,
@@ -1786,6 +1430,240 @@ function ingestAtomUpdate(applying, atomUpdate, store) {
1786
1430
  }
1787
1431
  setIntoStore(store, token, value);
1788
1432
  }
1433
+
1434
+ // internal/src/get-trace.ts
1435
+ function getTrace(error) {
1436
+ const { stack } = error;
1437
+ if (stack) {
1438
+ return `
1439
+ ` + stack.split(`
1440
+ `)?.slice(1)?.join(`
1441
+ `);
1442
+ }
1443
+ return ``;
1444
+ }
1445
+
1446
+ // internal/src/molecule.ts
1447
+ function makeRootMoleculeInStore(key, store = IMPLICIT.STORE) {
1448
+ const molecule = {
1449
+ key,
1450
+ stringKey: stringifyJson(key),
1451
+ dependsOn: `any`
1452
+ };
1453
+ store.molecules.set(stringifyJson(key), molecule);
1454
+ return key;
1455
+ }
1456
+ function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
1457
+ const origin = provenance;
1458
+ const stringKey = stringifyJson(key);
1459
+ const invalidKeys = [];
1460
+ const target = newest(store);
1461
+ if (Array.isArray(origin)) {
1462
+ for (const formerClaim of origin) {
1463
+ const claimString = stringifyJson(formerClaim);
1464
+ const claim = target.molecules.get(claimString);
1465
+ if (claim) {
1466
+ store.moleculeGraph.set(claimString, stringKey, { source: claimString });
1467
+ } else {
1468
+ invalidKeys.push(claimString);
1469
+ }
1470
+ }
1471
+ } else {
1472
+ const claimString = stringifyJson(origin);
1473
+ const claim = target.molecules.get(claimString);
1474
+ if (claim) {
1475
+ store.moleculeGraph.set(claimString, stringKey, { source: claimString });
1476
+ } else {
1477
+ invalidKeys.push(claimString);
1478
+ }
1479
+ }
1480
+ if (invalidKeys.length === 0) {
1481
+ target.molecules.set(stringKey, { key, stringKey, dependsOn });
1482
+ }
1483
+ const creationEvent = {
1484
+ type: `molecule_creation`,
1485
+ key,
1486
+ provenance: origin
1487
+ };
1488
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
1489
+ if (isTransaction) {
1490
+ target.transactionMeta.update.updates.push(creationEvent);
1491
+ } else {
1492
+ target.on.moleculeCreation.next(creationEvent);
1493
+ }
1494
+ for (const claim of invalidKeys) {
1495
+ const disposal = store.disposalTraces.buffer.find(
1496
+ (item) => item?.key === claim
1497
+ );
1498
+ store.logger.error(
1499
+ `\u274C`,
1500
+ `molecule`,
1501
+ key,
1502
+ `allocation failed:`,
1503
+ `Could not allocate to ${claim} in store "${store.config.name}".`,
1504
+ disposal ? `
1505
+ ${claim} was most recently disposed
1506
+ ${disposal.trace}` : `No previous disposal trace for ${claim} was found.`
1507
+ );
1508
+ }
1509
+ return key;
1510
+ }
1511
+ function fuseWithinStore(store, type, sideA, sideB) {
1512
+ const compoundKey = `T$--${type}==${sideA}++${sideB}`;
1513
+ const above = [sideA, sideB];
1514
+ allocateIntoStore(
1515
+ store,
1516
+ above,
1517
+ compoundKey,
1518
+ `all`
1519
+ );
1520
+ return compoundKey;
1521
+ }
1522
+ function deallocateFromStore(store, claim) {
1523
+ const stringKey = stringifyJson(claim);
1524
+ const molecule = store.molecules.get(stringKey);
1525
+ if (!molecule) {
1526
+ const disposal = store.disposalTraces.buffer.find(
1527
+ (item) => item?.key === stringKey
1528
+ );
1529
+ store.logger.error(
1530
+ `\u274C`,
1531
+ `molecule`,
1532
+ claim,
1533
+ `deallocation failed:`,
1534
+ `Could not find allocation for ${stringKey} in store "${store.config.name}".`,
1535
+ disposal ? `
1536
+ This state was most recently deallocated
1537
+ ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
1538
+ );
1539
+ return;
1540
+ }
1541
+ const joinKeys = store.moleculeJoins.getRelatedKeys(
1542
+ molecule.key
1543
+ );
1544
+ if (joinKeys) {
1545
+ for (const joinKey of joinKeys) {
1546
+ const join = store.joins.get(joinKey);
1547
+ if (join) {
1548
+ join.relations.delete(molecule.key);
1549
+ join.molecules.delete(molecule.stringKey);
1550
+ }
1551
+ }
1552
+ }
1553
+ store.moleculeJoins.delete(molecule.stringKey);
1554
+ const provenance = [];
1555
+ const values = [];
1556
+ const disposalEvent = {
1557
+ type: `molecule_disposal`,
1558
+ key: molecule.key,
1559
+ values,
1560
+ provenance
1561
+ };
1562
+ const target = newest(store);
1563
+ target.molecules.delete(stringKey);
1564
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
1565
+ if (isTransaction) {
1566
+ target.transactionMeta.update.updates.push(disposalEvent);
1567
+ }
1568
+ const relatedMolecules = store.moleculeGraph.getRelationEntries({
1569
+ downstreamMoleculeKey: molecule.stringKey
1570
+ });
1571
+ if (relatedMolecules) {
1572
+ for (const [relatedStringKey, { source }] of relatedMolecules) {
1573
+ if (source === molecule.stringKey) {
1574
+ const relatedKey = parseJson(relatedStringKey);
1575
+ deallocateFromStore(store, relatedKey);
1576
+ } else {
1577
+ provenance.push(source);
1578
+ }
1579
+ }
1580
+ }
1581
+ const familyKeys = target.moleculeData.getRelatedKeys(molecule.stringKey);
1582
+ if (familyKeys) {
1583
+ for (const familyKey of familyKeys) {
1584
+ const family = target.families.get(familyKey);
1585
+ const token = findInStore(store, family, molecule.key);
1586
+ values.push([family.key, token]);
1587
+ disposeFromStore(store, token);
1588
+ }
1589
+ }
1590
+ target.moleculeGraph.delete(molecule.stringKey);
1591
+ target.moleculeJoins.delete(molecule.stringKey);
1592
+ target.moleculeData.delete(molecule.stringKey);
1593
+ if (!isTransaction) {
1594
+ target.on.moleculeDisposal.next(disposalEvent);
1595
+ }
1596
+ target.molecules.delete(molecule.stringKey);
1597
+ const trace = getTrace(new Error());
1598
+ store.disposalTraces.add({ key: stringKey, trace });
1599
+ }
1600
+ function claimWithinStore(store, newProvenance, claim, exclusive) {
1601
+ const stringKey = stringifyJson(claim);
1602
+ const target = newest(store);
1603
+ const molecule = target.molecules.get(stringKey);
1604
+ if (!molecule) {
1605
+ const disposal = store.disposalTraces.buffer.find(
1606
+ (item) => item?.key === stringKey
1607
+ );
1608
+ store.logger.error(
1609
+ `\u274C`,
1610
+ `molecule`,
1611
+ claim,
1612
+ `claim failed:`,
1613
+ `Could not allocate to ${stringKey} in store "${store.config.name}".`,
1614
+ disposal ? `
1615
+ ${stringKey} was most recently disposed
1616
+ ${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`
1617
+ );
1618
+ return claim;
1619
+ }
1620
+ const newProvenanceKey = stringifyJson(newProvenance);
1621
+ const newProvenanceMolecule = target.molecules.get(newProvenanceKey);
1622
+ if (!newProvenanceMolecule) {
1623
+ const disposal = store.disposalTraces.buffer.find(
1624
+ (item) => item?.key === newProvenanceKey
1625
+ );
1626
+ store.logger.error(
1627
+ `\u274C`,
1628
+ `molecule`,
1629
+ claim,
1630
+ `claim failed:`,
1631
+ `Could not allocate to ${newProvenanceKey} in store "${store.config.name}".`,
1632
+ disposal ? `
1633
+ ${newProvenanceKey} was most recently disposed
1634
+ ${disposal.trace}` : `No previous disposal trace for ${newProvenanceKey} was found.`
1635
+ );
1636
+ return claim;
1637
+ }
1638
+ const priorProvenance = store.moleculeGraph.getRelationEntries({
1639
+ downstreamMoleculeKey: molecule.stringKey
1640
+ }).filter(([, { source }]) => source !== stringKey).map(([key]) => parseJson(key));
1641
+ if (exclusive) {
1642
+ target.moleculeGraph.delete(stringKey);
1643
+ }
1644
+ target.moleculeGraph.set(
1645
+ {
1646
+ upstreamMoleculeKey: newProvenanceMolecule.stringKey,
1647
+ downstreamMoleculeKey: molecule.stringKey
1648
+ },
1649
+ {
1650
+ source: newProvenanceMolecule.stringKey
1651
+ }
1652
+ );
1653
+ const transferEvent = {
1654
+ type: `molecule_transfer`,
1655
+ key: molecule.key,
1656
+ from: priorProvenance,
1657
+ to: [newProvenanceMolecule.key]
1658
+ };
1659
+ const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
1660
+ if (isTransaction) {
1661
+ target.transactionMeta.update.updates.push(transferEvent);
1662
+ }
1663
+ return claim;
1664
+ }
1665
+
1666
+ // internal/src/ingest-updates/ingest-creation-disposal.ts
1789
1667
  function ingestCreationEvent(update, applying, store) {
1790
1668
  switch (applying) {
1791
1669
  case `newValue`: {
@@ -1806,7 +1684,9 @@ function ingestDisposalEvent(update, applying, store) {
1806
1684
  }
1807
1685
  case `oldValue`: {
1808
1686
  createInStore(update, store);
1809
- store.valueMap.set(update.token.key, update.value);
1687
+ if (update.subType === `atom`) {
1688
+ store.valueMap.set(update.token.key, update.value);
1689
+ }
1810
1690
  break;
1811
1691
  }
1812
1692
  }
@@ -1823,88 +1703,60 @@ function createInStore(update, store) {
1823
1703
  function ingestMoleculeCreationEvent(update, applying, store) {
1824
1704
  switch (applying) {
1825
1705
  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
- }
1706
+ allocateIntoStore(store, update.provenance, update.key);
1840
1707
  break;
1841
1708
  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
- }
1709
+ deallocateFromStore(store, update.key);
1850
1710
  break;
1851
1711
  }
1852
1712
  }
1853
1713
  function ingestMoleculeDisposalEvent(update, applying, store) {
1854
1714
  switch (applying) {
1855
1715
  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
- }
1716
+ deallocateFromStore(store, update.key);
1864
1717
  break;
1865
1718
  case `oldValue`:
1866
1719
  {
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
- }
1720
+ const provenanceJson = update.provenance.map(parseJson);
1721
+ allocateIntoStore(store, provenanceJson, update.key);
1722
+ for (const [familyKey, value] of update.values) {
1723
+ const family = store.families.get(familyKey);
1724
+ if (family) {
1725
+ findInStore(store, family, update.key);
1726
+ const memberKey = `${familyKey}(${stringifyJson(update.key)})`;
1727
+ store.valueMap.set(memberKey, value);
1902
1728
  }
1903
1729
  }
1904
1730
  }
1905
1731
  break;
1906
1732
  }
1907
1733
  }
1734
+ function ingestMoleculeTransferEvent(update, applying, store) {
1735
+ switch (applying) {
1736
+ case `newValue`:
1737
+ {
1738
+ const provenance = update.to.length === 1 ? update.to[0] : update.to;
1739
+ claimWithinStore(
1740
+ store,
1741
+ provenance,
1742
+ update.key,
1743
+ `exclusive`
1744
+ );
1745
+ }
1746
+ break;
1747
+ case `oldValue`:
1748
+ {
1749
+ const provenance = update.from.length === 1 ? update.from[0] : update.from;
1750
+ claimWithinStore(
1751
+ store,
1752
+ provenance,
1753
+ update.key,
1754
+ `exclusive`
1755
+ );
1756
+ }
1757
+ break;
1758
+ }
1759
+ }
1908
1760
 
1909
1761
  // internal/src/ingest-updates/ingest-selector-update.ts
1910
1762
  function ingestSelectorUpdate(applying, selectorUpdate, store) {
@@ -1935,6 +1787,9 @@ function ingestTransactionUpdate(applying, transactionUpdate, store) {
1935
1787
  case `molecule_disposal`:
1936
1788
  ingestMoleculeDisposalEvent(updateFromTransaction, applying, store);
1937
1789
  break;
1790
+ case `molecule_transfer`:
1791
+ ingestMoleculeTransferEvent(updateFromTransaction, applying, store);
1792
+ break;
1938
1793
  case `transaction_update`:
1939
1794
  ingestTransactionUpdate(applying, updateFromTransaction, store);
1940
1795
  break;
@@ -1955,7 +1810,7 @@ function setEpochNumberOfAction(transactionKey, newEpoch, store) {
1955
1810
  return;
1956
1811
  }
1957
1812
  const continuityKey = store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
1958
- if (continuityKey !== void 0) {
1813
+ if (continuityKey !== undefined) {
1959
1814
  store.transactionMeta.epoch.set(continuityKey, newEpoch);
1960
1815
  }
1961
1816
  }
@@ -2022,6 +1877,57 @@ function assignTransactionToContinuity(continuityKey, transactionKey, store) {
2022
1877
  }
2023
1878
  }
2024
1879
 
1880
+ // internal/src/get-environment-data.ts
1881
+ function getEnvironmentData(store) {
1882
+ return {
1883
+ store
1884
+ };
1885
+ }
1886
+
1887
+ // internal/src/get-state/get-from-store.ts
1888
+ function getFromStore(store, ...params) {
1889
+ let token;
1890
+ let family;
1891
+ let key;
1892
+ if (params.length === 1) {
1893
+ token = params[0];
1894
+ } else {
1895
+ family = params[0];
1896
+ key = params[1];
1897
+ token = findInStore(store, family, key);
1898
+ }
1899
+ if (`counterfeit` in token && `family` in token) {
1900
+ family = store.families.get(token.family.key);
1901
+ const subKey = token.family.subKey;
1902
+ const disposal = store.disposalTraces.buffer.find(
1903
+ (item) => item?.key === subKey
1904
+ );
1905
+ store.logger.error(
1906
+ `\u274C`,
1907
+ token.type,
1908
+ token.key,
1909
+ `could not be retrieved because it was not found in the store "${store.config.name}".`,
1910
+ disposal ? `This state was previously disposed:
1911
+ ${disposal.trace}` : `No previous disposal trace was found.`
1912
+ );
1913
+ switch (family.type) {
1914
+ case `atom_family`:
1915
+ case `mutable_atom_family`:
1916
+ return store.defaults.get(family.key);
1917
+ case `selector_family`:
1918
+ case `readonly_selector_family`: {
1919
+ if (store.defaults.has(family.key)) {
1920
+ return store.defaults.get(token.family.key);
1921
+ }
1922
+ const defaultValue = withdraw(family, store).default(subKey);
1923
+ store.defaults.set(family.key, defaultValue);
1924
+ return defaultValue;
1925
+ }
1926
+ }
1927
+ }
1928
+ return readOrComputeValue(withdraw(token, store), store);
1929
+ }
1930
+
2025
1931
  // internal/src/lazy-map.ts
2026
1932
  var LazyMap = class extends Map {
2027
1933
  constructor(source) {
@@ -2038,7 +1944,7 @@ var LazyMap = class extends Map {
2038
1944
  const value = this.source.get(key);
2039
1945
  return value;
2040
1946
  }
2041
- return void 0;
1947
+ return undefined;
2042
1948
  }
2043
1949
  set(key, value) {
2044
1950
  this.deleted.delete(key);
@@ -2069,6 +1975,7 @@ var buildTransaction = (key, params, store, id) => {
2069
1975
  atoms: new LazyMap(parent.atoms),
2070
1976
  atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
2071
1977
  families: new LazyMap(parent.families),
1978
+ joins: new LazyMap(parent.joins),
2072
1979
  operation: { open: false },
2073
1980
  readonlySelectors: new LazyMap(parent.readonlySelectors),
2074
1981
  timelines: new LazyMap(parent.timelines),
@@ -2084,8 +1991,15 @@ var buildTransaction = (key, params, store, id) => {
2084
1991
  defaults: parent.defaults,
2085
1992
  disposalTraces: store.disposalTraces.copy(),
2086
1993
  molecules: new LazyMap(parent.molecules),
2087
- moleculeFamilies: new LazyMap(parent.moleculeFamilies),
2088
- moleculeInProgress: parent.moleculeInProgress,
1994
+ moleculeGraph: new Junction(parent.moleculeGraph.toJSON(), {
1995
+ makeContentKey: parent.moleculeGraph.makeContentKey
1996
+ }),
1997
+ moleculeData: new Junction(parent.moleculeData.toJSON(), {
1998
+ makeContentKey: parent.moleculeData.makeContentKey
1999
+ }),
2000
+ moleculeJoins: new Junction(parent.moleculeJoins.toJSON(), {
2001
+ makeContentKey: parent.moleculeJoins.makeContentKey
2002
+ }),
2089
2003
  miscResources: new LazyMap(parent.miscResources)
2090
2004
  };
2091
2005
  const epoch = getEpochNumberOfAction(key, store);
@@ -2095,10 +2009,10 @@ var buildTransaction = (key, params, store, id) => {
2095
2009
  type: `transaction_update`,
2096
2010
  key,
2097
2011
  id,
2098
- epoch: epoch === void 0 ? Number.NaN : epoch + 1,
2012
+ epoch: epoch === undefined ? Number.NaN : epoch + 1,
2099
2013
  updates: [],
2100
2014
  params,
2101
- output: void 0
2015
+ output: undefined
2102
2016
  },
2103
2017
  toolkit: {
2104
2018
  get: (...ps) => getFromStore(child, ...ps),
@@ -2109,7 +2023,6 @@ var buildTransaction = (key, params, store, id) => {
2109
2023
  find: (token, k) => findInStore(child, token, k),
2110
2024
  seek: (token, k) => seekInStore(child, token, k),
2111
2025
  json: (token) => getJsonToken(child, token),
2112
- make: (context, family, k, ...args) => makeMoleculeInStore(child, context, family, k, ...args),
2113
2026
  dispose: (...ps) => {
2114
2027
  disposeFromStore(child, ...ps);
2115
2028
  },
@@ -2162,18 +2075,18 @@ function createTransaction(options, store) {
2162
2075
  // internal/src/transaction/get-epoch-number.ts
2163
2076
  function getContinuityKey(transactionKey, store) {
2164
2077
  const isRoot = isRootStore(store);
2165
- const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : void 0;
2078
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : undefined;
2166
2079
  return continuity;
2167
2080
  }
2168
2081
  function getEpochNumberOfContinuity(continuityKey, store) {
2169
2082
  const isRoot = isRootStore(store);
2170
- const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : void 0;
2083
+ const epoch = isRoot && continuityKey ? store.transactionMeta.epoch.get(continuityKey) : undefined;
2171
2084
  return epoch;
2172
2085
  }
2173
2086
  function getEpochNumberOfAction(transactionKey, store) {
2174
2087
  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;
2088
+ const continuity = isRoot ? store.transactionMeta.actionContinuities.getRelatedKey(transactionKey) : undefined;
2089
+ const epoch = isRoot && continuity !== undefined ? store.transactionMeta.epoch.get(continuity) : undefined;
2177
2090
  return epoch;
2178
2091
  }
2179
2092
 
@@ -2205,6 +2118,7 @@ var Store = class {
2205
2118
  );
2206
2119
  trackers = /* @__PURE__ */ new Map();
2207
2120
  families = /* @__PURE__ */ new Map();
2121
+ joins = /* @__PURE__ */ new Map();
2208
2122
  transactions = /* @__PURE__ */ new Map();
2209
2123
  transactionMeta = {
2210
2124
  epoch: /* @__PURE__ */ new Map(),
@@ -2220,8 +2134,33 @@ var Store = class {
2220
2134
  });
2221
2135
  disposalTraces = new CircularBuffer(100);
2222
2136
  molecules = /* @__PURE__ */ new Map();
2223
- moleculeFamilies = /* @__PURE__ */ new Map();
2224
- moleculeInProgress = null;
2137
+ moleculeJoins = new Junction(
2138
+ {
2139
+ between: [`moleculeKey`, `joinKey`],
2140
+ cardinality: `n:n`
2141
+ },
2142
+ {
2143
+ makeContentKey: (...keys) => keys.sort().join(`:`)
2144
+ }
2145
+ );
2146
+ moleculeGraph = new Junction(
2147
+ {
2148
+ between: [`upstreamMoleculeKey`, `downstreamMoleculeKey`],
2149
+ cardinality: `n:n`
2150
+ },
2151
+ {
2152
+ makeContentKey: (...keys) => keys.sort().join(`:`)
2153
+ }
2154
+ );
2155
+ moleculeData = new Junction(
2156
+ {
2157
+ between: [`moleculeKey`, `stateFamilyKey`],
2158
+ cardinality: `n:n`
2159
+ },
2160
+ {
2161
+ makeContentKey: (...keys) => keys.sort().join(`:`)
2162
+ }
2163
+ );
2225
2164
  miscResources = /* @__PURE__ */ new Map();
2226
2165
  on = {
2227
2166
  atomCreation: new Subject(),
@@ -2234,8 +2173,7 @@ var Store = class {
2234
2173
  null
2235
2174
  ),
2236
2175
  operationClose: new Subject(),
2237
- moleculeCreationStart: new Subject(),
2238
- moleculeCreationDone: new Subject(),
2176
+ moleculeCreation: new Subject(),
2239
2177
  moleculeDisposal: new Subject()
2240
2178
  };
2241
2179
  operation = { open: false };
@@ -2329,6 +2267,8 @@ var clearStore = (store) => {
2329
2267
  Object.assign(store, new Store(config));
2330
2268
  store.config = config;
2331
2269
  };
2270
+
2271
+ // internal/src/store/withdraw.ts
2332
2272
  function withdraw(token, store) {
2333
2273
  let withdrawn;
2334
2274
  let target = store;
@@ -2356,12 +2296,6 @@ function withdraw(token, store) {
2356
2296
  case `transaction`:
2357
2297
  withdrawn = target.transactions.get(token.key);
2358
2298
  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
2299
  }
2366
2300
  if (withdrawn) {
2367
2301
  return withdrawn;
@@ -2399,7 +2333,7 @@ var subscribeToRootAtoms = (selector, store) => {
2399
2333
  const dependencySubscriptions = traceAllSelectorAtoms(selector, store).map(
2400
2334
  (atomKey) => {
2401
2335
  const atom = target.atoms.get(atomKey);
2402
- if (atom === void 0) {
2336
+ if (atom === undefined) {
2403
2337
  throw new Error(
2404
2338
  `Atom "${atomKey}", a dependency of selector "${selector.key}", not found in store "${store.config.name}".`
2405
2339
  );
@@ -2532,7 +2466,7 @@ var Tracker = class {
2532
2466
  const familyMetaData = mutableState.family ? {
2533
2467
  key: `*${mutableState.family.key}`,
2534
2468
  subKey: mutableState.family.subKey
2535
- } : void 0;
2469
+ } : undefined;
2536
2470
  const latestUpdateState = createRegularAtom(
2537
2471
  store,
2538
2472
  {
@@ -2872,7 +2806,7 @@ function copyMutableIfNeeded(atom, origin, target) {
2872
2806
  const originValue = origin.valueMap.get(atom.key);
2873
2807
  const targetValue = target.valueMap.get(atom.key);
2874
2808
  if (originValue === targetValue) {
2875
- if (originValue === void 0) {
2809
+ if (originValue === undefined) {
2876
2810
  return typeof atom.default === `function` ? atom.default() : atom.default;
2877
2811
  }
2878
2812
  origin.logger.info(`\u{1F4C3}`, `atom`, atom.key, `copying`);
@@ -3020,11 +2954,11 @@ function createRegularAtom(store, options, family) {
3020
2954
  function createStandaloneAtom(store, options) {
3021
2955
  const isMutable = `mutable` in options;
3022
2956
  if (isMutable) {
3023
- const state2 = createMutableAtom(store, options, void 0);
2957
+ const state2 = createMutableAtom(store, options, undefined);
3024
2958
  store.on.atomCreation.next(state2);
3025
2959
  return state2;
3026
2960
  }
3027
- const state = createRegularAtom(store, options, void 0);
2961
+ const state = createRegularAtom(store, options, undefined);
3028
2962
  store.on.atomCreation.next(state);
3029
2963
  return state;
3030
2964
  }
@@ -3032,23 +2966,22 @@ function createStandaloneAtom(store, options) {
3032
2966
  // internal/src/atom/dispose-atom.ts
3033
2967
  function disposeAtom(atomToken, store) {
3034
2968
  const target = newest(store);
3035
- const { key } = atomToken;
2969
+ const { key, family } = atomToken;
3036
2970
  const atom = withdraw(atomToken, target);
3037
- if (!atom.family) {
2971
+ if (!family) {
3038
2972
  store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
3039
2973
  } else {
3040
2974
  atom.cleanup?.();
3041
2975
  const lastValue = store.valueMap.get(atom.key);
3042
- const family = withdraw({ key: atom.family.key, type: `atom_family` }, store);
3043
- family.subject.next({
2976
+ const atomFamily = withdraw({ key: family.key, type: `atom_family` }, store);
2977
+ const disposal = {
3044
2978
  type: `state_disposal`,
2979
+ subType: `atom`,
3045
2980
  token: atomToken,
3046
2981
  value: lastValue
3047
- });
3048
- const molecule = target.molecules.get(atom.family.subKey);
3049
- if (molecule) {
3050
- molecule.tokens.delete(key);
3051
- }
2982
+ };
2983
+ atomFamily.subject.next(disposal);
2984
+ const isChild = isChildStore(target);
3052
2985
  target.atoms.delete(key);
3053
2986
  target.valueMap.delete(key);
3054
2987
  target.selectorAtoms.delete(key);
@@ -3060,16 +2993,20 @@ function disposeAtom(atomToken, store) {
3060
2993
  store.trackers.delete(key);
3061
2994
  }
3062
2995
  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
- });
2996
+ if (isChild && target.transactionMeta.phase === `building`) {
2997
+ const mostRecentUpdate = target.transactionMeta.update.updates.at(-1);
2998
+ const wasMoleculeDisposal = mostRecentUpdate?.type === `molecule_disposal`;
2999
+ const updateAlreadyCaptured = wasMoleculeDisposal && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
3000
+ if (!updateAlreadyCaptured) {
3001
+ target.transactionMeta.update.updates.push(disposal);
3002
+ }
3068
3003
  } else {
3069
3004
  store.on.atomDisposal.next(atomToken);
3070
3005
  }
3071
3006
  }
3072
3007
  }
3008
+
3009
+ // internal/src/timeline/create-timeline.ts
3073
3010
  function createTimeline(options, store, data) {
3074
3011
  const tl = {
3075
3012
  type: `timeline`,
@@ -3140,23 +3077,6 @@ function createTimeline(options, store, data) {
3140
3077
  addAtomFamilyToTimeline(familyToken, tl, store);
3141
3078
  }
3142
3079
  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
3080
  }
3161
3081
  }
3162
3082
  store.timelines.set(options.key, tl);
@@ -3180,109 +3100,112 @@ function addAtomToTimeline(atomToken, tl, store) {
3180
3100
  );
3181
3101
  tl.subscriptions.set(
3182
3102
  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`) {
3103
+ atom.subject.subscribe(
3104
+ `timeline`,
3105
+ function timelineCapturesAtomUpdate(update) {
3106
+ const target = newest(store);
3107
+ const currentSelectorKey = store.operation.open && store.operation.token.type === `selector` ? store.operation.token.key : null;
3108
+ const currentSelectorTime = store.operation.open && store.operation.token.type === `selector` ? store.operation.time : null;
3109
+ const txUpdateInProgress = target.on.transactionApplying.state?.update;
3110
+ store.logger.info(
3111
+ `\u23F3`,
3112
+ `timeline`,
3113
+ tl.key,
3114
+ `atom`,
3115
+ atomToken.key,
3116
+ `went`,
3117
+ update.oldValue,
3118
+ `->`,
3119
+ update.newValue,
3120
+ txUpdateInProgress ? `in transaction "${txUpdateInProgress.key}"` : currentSelectorKey ? `in selector "${currentSelectorKey}"` : ``
3121
+ );
3122
+ if (tl.timeTraveling === null) {
3123
+ if (txUpdateInProgress) {
3124
+ joinTransaction(tl, txUpdateInProgress, store);
3125
+ } else if (currentSelectorKey && currentSelectorTime) {
3126
+ let latestUpdate = tl.history.at(-1);
3127
+ if (currentSelectorTime !== tl.selectorTime) {
3128
+ latestUpdate = {
3129
+ type: `selector_update`,
3130
+ timestamp: currentSelectorTime,
3131
+ key: currentSelectorKey,
3132
+ atomUpdates: []
3133
+ };
3232
3134
  latestUpdate.atomUpdates.push({
3233
3135
  key: atom.key,
3234
3136
  type: `atom_update`,
3235
3137
  ...update
3236
3138
  });
3139
+ if (tl.at !== tl.history.length) {
3140
+ tl.history.splice(tl.at);
3141
+ }
3142
+ tl.history.push(latestUpdate);
3237
3143
  store.logger.info(
3238
3144
  `\u231B`,
3239
3145
  `timeline`,
3240
3146
  tl.key,
3241
- `set selector_update "${currentSelectorKey}" to`,
3242
- latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
3147
+ `got a selector_update "${currentSelectorKey}" with`,
3148
+ latestUpdate.atomUpdates.map((atomUpdate) => atomUpdate.key)
3243
3149
  );
3244
- }
3245
- }
3246
- if (latestUpdate) {
3247
- const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
3248
- if (willCaptureSelectorUpdate) {
3249
- tl.subject.next(latestUpdate);
3150
+ tl.at = tl.history.length;
3151
+ tl.selectorTime = currentSelectorTime;
3250
3152
  } else {
3251
- tl.history.pop();
3153
+ if (latestUpdate?.type === `selector_update`) {
3154
+ latestUpdate.atomUpdates.push({
3155
+ key: atom.key,
3156
+ type: `atom_update`,
3157
+ ...update
3158
+ });
3159
+ store.logger.info(
3160
+ `\u231B`,
3161
+ `timeline`,
3162
+ tl.key,
3163
+ `set selector_update "${currentSelectorKey}" to`,
3164
+ latestUpdate?.atomUpdates.map((atomUpdate) => atomUpdate.key)
3165
+ );
3166
+ }
3167
+ }
3168
+ if (latestUpdate) {
3169
+ const willCaptureSelectorUpdate = tl.shouldCapture?.(latestUpdate, tl) ?? true;
3170
+ if (willCaptureSelectorUpdate) {
3171
+ tl.subject.next(latestUpdate);
3172
+ } else {
3173
+ tl.history.pop();
3174
+ tl.at = tl.history.length;
3175
+ }
3176
+ }
3177
+ } else {
3178
+ const timestamp = Date.now();
3179
+ tl.selectorTime = null;
3180
+ if (tl.at !== tl.history.length) {
3181
+ tl.history.splice(tl.at);
3182
+ }
3183
+ const atomUpdate = {
3184
+ type: `atom_update`,
3185
+ timestamp,
3186
+ key: atom.key,
3187
+ oldValue: update.oldValue,
3188
+ newValue: update.newValue
3189
+ };
3190
+ if (atom.family) {
3191
+ atomUpdate.family = atom.family;
3192
+ }
3193
+ const willCapture = tl.shouldCapture?.(atomUpdate, tl) ?? true;
3194
+ store.logger.info(
3195
+ `\u231B`,
3196
+ `timeline`,
3197
+ tl.key,
3198
+ `got an atom_update to "${atom.key}"`
3199
+ );
3200
+ if (willCapture) {
3201
+ tl.history.push(atomUpdate);
3252
3202
  tl.at = tl.history.length;
3203
+ tl.subject.next(atomUpdate);
3253
3204
  }
3254
3205
  }
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
3206
  }
3284
3207
  }
3285
- })
3208
+ )
3286
3209
  );
3287
3210
  }
3288
3211
  function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
@@ -3293,9 +3216,12 @@ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
3293
3216
  );
3294
3217
  tl.subscriptions.set(
3295
3218
  family.key,
3296
- family.subject.subscribe(`timeline`, (creationOrDisposal) => {
3297
- handleStateLifecycleEvent(creationOrDisposal, tl, store);
3298
- })
3219
+ family.subject.subscribe(
3220
+ `timeline`,
3221
+ function timelineCapturesStateLifecycleEvent(creationOrDisposal) {
3222
+ handleStateLifecycleEvent(creationOrDisposal, tl, store);
3223
+ }
3224
+ )
3299
3225
  );
3300
3226
  for (const atom of store.atoms.values()) {
3301
3227
  if (atom.family?.key === family.key) {
@@ -3303,99 +3229,6 @@ function addAtomFamilyToTimeline(atomFamilyToken, tl, store) {
3303
3229
  }
3304
3230
  }
3305
3231
  }
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
3232
  function joinTransaction(tl, txUpdateInProgress, store) {
3400
3233
  const currentTxKey = txUpdateInProgress.key;
3401
3234
  const currentTxInstanceId = txUpdateInProgress.id;
@@ -3451,14 +3284,9 @@ function filterTransactionUpdates(updates, timelineTopics) {
3451
3284
  break;
3452
3285
  case `molecule_creation`:
3453
3286
  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;
3287
+ case `molecule_transfer`:
3288
+ return true;
3289
+ // always include
3462
3290
  default:
3463
3291
  key = updateFromTx.key;
3464
3292
  familyKey = updateFromTx.family?.key;
@@ -3565,14 +3393,6 @@ var timeTravel = (store, action, token) => {
3565
3393
  ingestDisposalEvent(update, applying, store);
3566
3394
  break;
3567
3395
  }
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
3396
  }
3577
3397
  if (action === `redo`) {
3578
3398
  ++timelineData.at;
@@ -3587,4 +3407,4 @@ var timeTravel = (store, action, token) => {
3587
3407
  );
3588
3408
  };
3589
3409
 
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 };
3410
+ export { CircularBuffer, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Junction, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, claimWithinStore, clearStore, closeOperation, counterfeit, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, createWritableSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, evictCachedValue, findInStore, fuseWithinStore, 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, makeRootMoleculeInStore, 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 };