atom.io 0.21.1 → 0.22.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 (92) hide show
  1. package/data/dist/index.cjs +136 -63
  2. package/data/dist/index.d.ts +6 -0
  3. package/data/dist/index.js +3 -3
  4. package/data/src/join.ts +135 -51
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/{chunk-RT43TVKP.js → chunk-GVHKIJ3G.js} +1 -1
  7. package/dist/{chunk-HITX3MO4.js → chunk-JA4V7TJY.js} +135 -62
  8. package/dist/index.cjs +2 -7
  9. package/dist/index.d.ts +29 -14
  10. package/dist/index.js +4 -8
  11. package/ephemeral/dist/index.cjs +11 -0
  12. package/ephemeral/dist/index.js +9 -0
  13. package/ephemeral/package.json +16 -0
  14. package/ephemeral/src/index.ts +1 -0
  15. package/eslint-plugin/dist/index.cjs +156 -1
  16. package/eslint-plugin/dist/index.js +156 -1
  17. package/eslint-plugin/src/rules/index.ts +1 -0
  18. package/eslint-plugin/src/rules/lifespan.ts +204 -0
  19. package/eslint-plugin/src/rules/synchronous-selector-dependencies.ts +1 -65
  20. package/eslint-plugin/src/walk.ts +73 -0
  21. package/immortal/dist/index.cjs +100 -0
  22. package/immortal/dist/index.js +97 -0
  23. package/immortal/package.json +16 -0
  24. package/immortal/src/index.ts +2 -0
  25. package/immortal/src/molecule.ts +134 -0
  26. package/immortal/src/seek-state.ts +60 -0
  27. package/internal/dist/index.cjs +186 -146
  28. package/internal/dist/index.d.ts +29 -13
  29. package/internal/dist/index.js +185 -146
  30. package/internal/src/atom/dispose-atom.ts +4 -1
  31. package/internal/src/families/create-readonly-selector-family.ts +9 -9
  32. package/internal/src/families/create-regular-atom-family.ts +15 -20
  33. package/internal/src/families/create-writable-selector-family.ts +6 -7
  34. package/internal/src/families/find-in-store.ts +11 -5
  35. package/internal/src/families/index.ts +2 -0
  36. package/internal/src/families/init-family-member.ts +91 -0
  37. package/internal/src/families/seek-in-store.ts +106 -0
  38. package/internal/src/get-state/get-from-store.ts +2 -2
  39. package/internal/src/mutable/create-mutable-atom-family.ts +17 -23
  40. package/internal/src/mutable/create-mutable-atom.ts +3 -1
  41. package/internal/src/mutable/get-json-family.ts +2 -2
  42. package/internal/src/mutable/get-json-token.ts +27 -12
  43. package/internal/src/mutable/tracker-family.ts +14 -12
  44. package/internal/src/not-found-error.ts +11 -3
  45. package/internal/src/selector/create-readonly-selector.ts +2 -2
  46. package/internal/src/selector/create-writable-selector.ts +2 -2
  47. package/internal/src/selector/dispose-selector.ts +40 -23
  48. package/internal/src/selector/register-selector.ts +8 -5
  49. package/internal/src/set-state/set-into-store.ts +2 -2
  50. package/internal/src/store/index.ts +0 -1
  51. package/internal/src/store/store.ts +18 -5
  52. package/internal/src/subscribe/subscribe-to-state.ts +2 -2
  53. package/internal/src/transaction/build-transaction.ts +7 -2
  54. package/introspection/dist/index.cjs +38 -52
  55. package/introspection/dist/index.js +38 -52
  56. package/introspection/src/attach-atom-index.ts +38 -48
  57. package/introspection/src/attach-selector-index.ts +45 -50
  58. package/json/dist/index.cjs +38 -4
  59. package/json/dist/index.js +40 -6
  60. package/json/src/select-json-family.ts +46 -7
  61. package/package.json +30 -10
  62. package/react/dist/index.cjs +1 -1
  63. package/react/dist/index.js +1 -1
  64. package/react/src/use-json.ts +1 -1
  65. package/react-devtools/dist/index.cjs +11 -10
  66. package/react-devtools/dist/index.js +2 -1
  67. package/react-devtools/src/StateIndex.tsx +2 -1
  68. package/react-devtools/src/TimelineIndex.tsx +2 -1
  69. package/react-devtools/src/TransactionIndex.tsx +7 -7
  70. package/realtime-client/dist/index.cjs +3 -3
  71. package/realtime-client/dist/index.js +3 -3
  72. package/realtime-client/src/pull-mutable-atom-family-member.ts +1 -1
  73. package/realtime-client/src/pull-mutable-atom.ts +1 -1
  74. package/realtime-client/src/sync-continuity.ts +1 -2
  75. package/realtime-react/dist/index.cjs +1 -1
  76. package/realtime-react/dist/index.js +1 -1
  77. package/realtime-server/dist/index.cjs +18 -17
  78. package/realtime-server/dist/index.js +7 -6
  79. package/realtime-server/src/realtime-continuity-synchronizer.ts +5 -3
  80. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  81. package/realtime-server/src/realtime-mutable-provider.ts +1 -1
  82. package/realtime-testing/dist/index.cjs +6 -2
  83. package/realtime-testing/dist/index.js +8 -5
  84. package/realtime-testing/src/setup-realtime-test.tsx +5 -2
  85. package/src/atom.ts +10 -4
  86. package/src/index.ts +1 -2
  87. package/src/selector.ts +10 -4
  88. package/src/silo.ts +3 -3
  89. package/src/transaction.ts +5 -2
  90. package/internal/src/store/withdraw-new-family-member.ts +0 -69
  91. /package/{src → ephemeral/src}/find-state.ts +0 -0
  92. /package/src/{dispose.ts → dispose-state.ts} +0 -0
@@ -113,7 +113,7 @@ function isChildStore(store) {
113
113
 
114
114
  // internal/src/store/store.ts
115
115
  var Store = class {
116
- constructor(name, store = null) {
116
+ constructor(config, store = null) {
117
117
  this.parent = null;
118
118
  this.child = null;
119
119
  this.valueMap = /* @__PURE__ */ new Map();
@@ -142,6 +142,8 @@ var Store = class {
142
142
  makeContentKey: (...keys) => keys.sort().join(`:`)
143
143
  }
144
144
  );
145
+ this.molecules = /* @__PURE__ */ new Map();
146
+ this.miscResources = /* @__PURE__ */ new Map();
145
147
  this.on = {
146
148
  atomCreation: new Subject(),
147
149
  atomDisposal: new Subject(),
@@ -163,7 +165,8 @@ var Store = class {
163
165
  })
164
166
  };
165
167
  this.config = {
166
- name: `IMPLICIT_STORE`
168
+ name: `IMPLICIT_STORE`,
169
+ lifespan: `ephemeral`
167
170
  };
168
171
  this.loggers = [
169
172
  new AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
@@ -193,9 +196,7 @@ var Store = class {
193
196
  )
194
197
  };
195
198
  }
196
- this.config = __spreadProps(__spreadValues({}, store == null ? void 0 : store.config), {
197
- name
198
- });
199
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
199
200
  for (const [, family] of store.families) {
200
201
  family.install(this);
201
202
  }
@@ -206,7 +207,7 @@ var Store = class {
206
207
  }
207
208
  atom.install(this);
208
209
  if (atom.type === `mutable_atom`) {
209
- const originalJsonToken = getJsonToken(atom);
210
+ const originalJsonToken = getJsonToken(atom, store);
210
211
  const originalUpdateToken = getUpdateToken(atom);
211
212
  mutableHelpers.add(originalJsonToken.key);
212
213
  mutableHelpers.add(originalUpdateToken.key);
@@ -234,12 +235,18 @@ var IMPLICIT = {
234
235
  STORE_INTERNAL: void 0,
235
236
  get STORE() {
236
237
  var _a;
237
- return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store(`IMPLICIT_STORE`);
238
+ return (_a = this.STORE_INTERNAL) != null ? _a : this.STORE_INTERNAL = new Store({
239
+ name: `IMPLICIT_STORE`,
240
+ lifespan: `ephemeral`
241
+ });
238
242
  }
239
243
  };
240
244
  var clearStore = (store) => {
241
245
  const { config } = store;
242
- Object.assign(store, new Store(config.name));
246
+ for (const disposable of store.miscResources.values()) {
247
+ disposable[Symbol.dispose]();
248
+ }
249
+ Object.assign(store, new Store(config));
243
250
  store.config = config;
244
251
  };
245
252
 
@@ -280,36 +287,6 @@ function withdraw(token, store) {
280
287
  throw new NotFoundError(token, store);
281
288
  }
282
289
 
283
- // internal/src/store/withdraw-new-family-member.ts
284
- function withdrawOrCreate(token, store) {
285
- try {
286
- const state = withdraw(token, store);
287
- return state;
288
- } catch (notFoundError) {
289
- if (token.family) {
290
- store.logger.info(
291
- `\u{1F46A}`,
292
- token.type,
293
- token.key,
294
- `creating new family member in store "${store.config.name}"`
295
- );
296
- const target = newest(store);
297
- const family = target.families.get(token.family.key);
298
- if (family) {
299
- const jsonSubKey = JSON.parse(token.family.subKey);
300
- family(jsonSubKey);
301
- const state = withdraw(token, store);
302
- return state;
303
- }
304
- throw new NotFoundError(
305
- { key: token.family.key, type: `${token.type}_family` },
306
- store
307
- );
308
- }
309
- throw notFoundError;
310
- }
311
- }
312
-
313
290
  // internal/src/get-state/read-or-compute-value.ts
314
291
  var readOrComputeValue = (state, target) => {
315
292
  if (target.valueMap.has(state.key)) {
@@ -337,22 +314,17 @@ function createRegularAtomFamily(options, store) {
337
314
  const subKey = stringifyJson(key);
338
315
  const family = { key: options.key, subKey };
339
316
  const fullKey = `${options.key}(${subKey})`;
340
- const target2 = newest(store);
341
- const atomAlreadyCreated = target2.atoms.has(fullKey);
342
- let token;
343
- if (atomAlreadyCreated) {
344
- token = { type: `atom`, key: fullKey, family };
345
- } else {
346
- const individualOptions = {
347
- key: fullKey,
348
- default: options.default instanceof Function ? options.default(key) : options.default
349
- };
350
- if (options.effects) {
351
- individualOptions.effects = options.effects(key);
352
- }
353
- token = createRegularAtom(individualOptions, family, store);
354
- subject.next(token);
317
+ const target = newest(store);
318
+ const def = options.default;
319
+ const individualOptions = {
320
+ key: fullKey,
321
+ default: def instanceof Function ? def(key) : def
322
+ };
323
+ if (options.effects) {
324
+ individualOptions.effects = options.effects(key);
355
325
  }
326
+ const token = createRegularAtom(individualOptions, family, target);
327
+ subject.next(token);
356
328
  return token;
357
329
  },
358
330
  {
@@ -362,8 +334,7 @@ function createRegularAtomFamily(options, store) {
362
334
  install: (s) => createRegularAtomFamily(options, s)
363
335
  }
364
336
  );
365
- const target = newest(store);
366
- target.families.set(options.key, atomFamily);
337
+ store.families.set(options.key, atomFamily);
367
338
  return atomFamily;
368
339
  }
369
340
 
@@ -379,22 +350,20 @@ function createReadonlySelectorFamily(options, store) {
379
350
  const subject = new Subject();
380
351
  const readonlySelectorFamily = Object.assign(
381
352
  (key) => {
382
- const target = newest(store);
383
353
  const subKey = stringifyJson(key);
384
354
  const family = { key: options.key, subKey };
385
355
  const fullKey = `${options.key}(${subKey})`;
386
- const existing = target.readonlySelectors.get(fullKey);
387
- if (existing) {
388
- return deposit(existing);
389
- }
390
- return createReadonlySelector(
356
+ const target = newest(store);
357
+ const token = createReadonlySelector(
391
358
  {
392
359
  key: fullKey,
393
360
  get: options.get(key)
394
361
  },
395
362
  family,
396
- store
363
+ target
397
364
  );
365
+ subject.next(token);
366
+ return token;
398
367
  },
399
368
  {
400
369
  key: options.key,
@@ -413,10 +382,7 @@ function createWritableSelectorFamily(options, store) {
413
382
  const subKey = stringifyJson(key);
414
383
  const family = { key: options.key, subKey };
415
384
  const fullKey = `${options.key}(${subKey})`;
416
- const existing = store.selectors.get(fullKey);
417
- if (existing) {
418
- return deposit(existing);
419
- }
385
+ const target = newest(store);
420
386
  const token = createWritableSelector(
421
387
  {
422
388
  key: fullKey,
@@ -424,7 +390,7 @@ function createWritableSelectorFamily(options, store) {
424
390
  set: options.set(key)
425
391
  },
426
392
  family,
427
- store
393
+ target
428
394
  );
429
395
  subject.next(token);
430
396
  return token;
@@ -452,10 +418,18 @@ function createSelectorFamily(options, store) {
452
418
  // internal/src/not-found-error.ts
453
419
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
454
420
  function prettyPrintTokenType(token) {
455
- if (token.type === `readonly_selector`) {
456
- return `Readonly Selector`;
421
+ switch (token.type) {
422
+ case `atom_family`:
423
+ return `Atom Family`;
424
+ case `readonly_selector`:
425
+ return `Readonly Selector`;
426
+ case `readonly_selector_family`:
427
+ return `Readonly Selector Family`;
428
+ case `selector_family`:
429
+ return `Selector Family`;
430
+ default:
431
+ return capitalize(token.type);
457
432
  }
458
- return capitalize(token.type);
459
433
  }
460
434
  var NotFoundError = class extends Error {
461
435
  constructor(token, store) {
@@ -465,8 +439,8 @@ var NotFoundError = class extends Error {
465
439
  }
466
440
  };
467
441
 
468
- // internal/src/families/find-in-store.ts
469
- function findInStore(token, key, store) {
442
+ // internal/src/families/init-family-member.ts
443
+ function initFamilyMember(token, key, store) {
470
444
  const familyKey = token.key;
471
445
  const family = store.families.get(familyKey);
472
446
  if (family === void 0) {
@@ -475,6 +449,44 @@ function findInStore(token, key, store) {
475
449
  const state = family(key);
476
450
  return state;
477
451
  }
452
+ function seekInStore(token, key, store) {
453
+ const subKey = stringifyJson(key);
454
+ const fullKey = `${token.key}(${subKey})`;
455
+ const target = newest(store);
456
+ let state;
457
+ switch (token.type) {
458
+ case `atom_family`:
459
+ case `mutable_atom_family`:
460
+ state = target.atoms.get(fullKey);
461
+ break;
462
+ case `selector_family`: {
463
+ state = target.selectors.get(fullKey);
464
+ break;
465
+ }
466
+ case `readonly_selector_family`:
467
+ state = target.readonlySelectors.get(fullKey);
468
+ break;
469
+ }
470
+ if (state) {
471
+ return deposit(state);
472
+ }
473
+ return state;
474
+ }
475
+
476
+ // internal/src/families/find-in-store.ts
477
+ function findInStore(token, key, store) {
478
+ if (store.config.lifespan === `immortal`) {
479
+ throw new Error(
480
+ `Do not use \`find\` or \`findState\` in an immortal store. Prefer \`seek\` or \`seekState\`.`
481
+ );
482
+ }
483
+ let state = seekInStore(token, key, store);
484
+ if (state) {
485
+ return state;
486
+ }
487
+ state = initFamilyMember(token, key, store);
488
+ return state;
489
+ }
478
490
 
479
491
  // internal/src/set-state/become.ts
480
492
  var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
@@ -717,7 +729,7 @@ function setIntoStore(token, value, store) {
717
729
  );
718
730
  return;
719
731
  }
720
- const state = withdrawOrCreate(token, store);
732
+ const state = withdraw(token, store);
721
733
  setAtomOrSelector(state, value, store);
722
734
  closeOperation(store);
723
735
  }
@@ -803,7 +815,7 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
803
815
  var registerSelector = (selectorKey, store) => ({
804
816
  get: (dependency) => {
805
817
  const target = newest(store);
806
- const dependencyState = withdrawOrCreate(dependency, store);
818
+ const dependencyState = withdraw(dependency, store);
807
819
  const dependencyValue = readOrComputeValue(dependencyState, store);
808
820
  store.logger.info(
809
821
  `\u{1F50C}`,
@@ -826,19 +838,20 @@ var registerSelector = (selectorKey, store) => ({
826
838
  return dependencyValue;
827
839
  },
828
840
  set: (WritableToken, newValue) => {
829
- const state = withdrawOrCreate(WritableToken, store);
841
+ const state = withdraw(WritableToken, store);
830
842
  setAtomOrSelector(state, newValue, store);
831
843
  },
832
- find: (token, key) => findInStore(token, key, store)
844
+ find: (token, key) => findInStore(token, key, store),
845
+ seek: (token, key) => seekInStore(token, key, store)
833
846
  });
834
847
 
835
848
  // internal/src/selector/create-readonly-selector.ts
836
849
  var createReadonlySelector = (options, family, store) => {
837
850
  const target = newest(store);
838
851
  const subject = new Subject();
839
- const { get, find } = registerSelector(options.key, target);
852
+ const { get, find, seek } = registerSelector(options.key, target);
840
853
  const getSelf = () => {
841
- const value = options.get({ get, find });
854
+ const value = options.get({ get, find, seek });
842
855
  cacheValue(options.key, value, subject, newest(store));
843
856
  return value;
844
857
  };
@@ -873,8 +886,8 @@ var createWritableSelector = (options, family, store) => {
873
886
  const target = newest(store);
874
887
  const subject = new Subject();
875
888
  const transactors = registerSelector(options.key, target);
876
- const { find, get } = transactors;
877
- const readonlyTransactors = { find, get };
889
+ const { find, get, seek } = transactors;
890
+ const readonlyTransactors = { find, get, seek };
878
891
  const getSelf = () => {
879
892
  const value = options.get(readonlyTransactors);
880
893
  cacheValue(options.key, value, subject, newest(store));
@@ -932,32 +945,50 @@ function createStandaloneSelector(options, store) {
932
945
 
933
946
  // internal/src/selector/dispose-selector.ts
934
947
  function disposeSelector(selectorToken, store) {
948
+ var _a;
935
949
  const target = newest(store);
936
950
  const { key } = selectorToken;
937
- switch (selectorToken.type) {
938
- case `selector`:
939
- target.selectors.delete(key);
940
- break;
941
- case `readonly_selector`:
942
- target.readonlySelectors.delete(key);
943
- break;
944
- }
945
- target.valueMap.delete(key);
946
- target.selectorAtoms.delete(key);
947
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
948
- ([downstreamSelectorKey]) => {
949
- var _a;
950
- return (_a = target.selectors.get(downstreamSelectorKey)) != null ? _a : target.readonlySelectors.get(downstreamSelectorKey);
951
+ const selector = (_a = target.selectors.get(key)) != null ? _a : target.readonlySelectors.get(key);
952
+ if (!selector) {
953
+ store.logger.error(
954
+ `\u274C`,
955
+ `selector`,
956
+ key,
957
+ `Tried to dispose selector, but it does not exist in the store.`
958
+ );
959
+ } else if (!selector.family) {
960
+ store.logger.error(
961
+ `\u274C`,
962
+ `selector`,
963
+ key,
964
+ `Standalone selectors cannot be disposed.`
965
+ );
966
+ } else {
967
+ switch (selectorToken.type) {
968
+ case `selector`:
969
+ target.selectors.delete(key);
970
+ break;
971
+ case `readonly_selector`:
972
+ target.readonlySelectors.delete(key);
973
+ break;
951
974
  }
952
- );
953
- for (const downstreamToken of downstreamTokens) {
954
- if (downstreamToken) {
955
- disposeSelector(downstreamToken, store);
975
+ target.valueMap.delete(key);
976
+ target.selectorAtoms.delete(key);
977
+ const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
978
+ ([downstreamSelectorKey]) => {
979
+ var _a2;
980
+ return (_a2 = target.selectors.get(downstreamSelectorKey)) != null ? _a2 : target.readonlySelectors.get(downstreamSelectorKey);
981
+ }
982
+ );
983
+ for (const downstreamToken of downstreamTokens) {
984
+ if (downstreamToken) {
985
+ disposeSelector(downstreamToken, store);
986
+ }
956
987
  }
988
+ target.selectorGraph.delete(key);
989
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
990
+ store.on.selectorDisposal.next(selectorToken);
957
991
  }
958
- target.selectorGraph.delete(key);
959
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
960
- store.on.selectorDisposal.next(selectorToken);
961
992
  }
962
993
 
963
994
  // internal/src/subscribe/recall-state.ts
@@ -1028,7 +1059,7 @@ function subscribeToState(token, handleUpdate, key, store) {
1028
1059
  handleUpdate(update);
1029
1060
  }
1030
1061
  }
1031
- const state = withdrawOrCreate(token, store);
1062
+ const state = withdraw(token, store);
1032
1063
  store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
1033
1064
  const isSelector = state.type === `selector` || state.type === `readonly_selector`;
1034
1065
  let dependencyUnsubFunctions = null;
@@ -1289,37 +1320,41 @@ function createMutableAtom(options, family, store) {
1289
1320
  };
1290
1321
  }
1291
1322
  new Tracker(token, store);
1292
- selectJson(token, options, store);
1323
+ if (!family) {
1324
+ selectJson(token, options, store);
1325
+ }
1293
1326
  store.on.atomCreation.next(token);
1294
1327
  return token;
1295
1328
  }
1296
1329
  var FamilyTracker = class {
1297
- constructor(findMutableState, store) {
1298
- this.findLatestUpdateState = createRegularAtomFamily(
1330
+ constructor(mutableAtoms, store) {
1331
+ this.latestUpdateAtoms = createRegularAtomFamily(
1299
1332
  {
1300
- key: `*${findMutableState.key}`,
1333
+ key: `*${mutableAtoms.key}`,
1301
1334
  default: null
1302
1335
  },
1303
1336
  store
1304
1337
  );
1305
- this.findMutableState = findMutableState;
1306
- this.findMutableState.subject.subscribe(
1338
+ this.mutableAtoms = mutableAtoms;
1339
+ this.mutableAtoms.subject.subscribe(
1307
1340
  `store=${store.config.name}::tracker-atom-family`,
1308
1341
  (atomToken) => {
1309
1342
  if (atomToken.family) {
1310
1343
  const key = parseJson(atomToken.family.subKey);
1311
- this.findLatestUpdateState(key);
1344
+ seekInStore(this.latestUpdateAtoms, key, store);
1312
1345
  new Tracker(atomToken, store);
1313
1346
  }
1314
1347
  }
1315
1348
  );
1316
- this.findLatestUpdateState.subject.subscribe(
1349
+ this.latestUpdateAtoms.subject.subscribe(
1317
1350
  `store=${store.config.name}::tracker-atom-family`,
1318
1351
  (atomToken) => {
1319
1352
  if (atomToken.family) {
1320
1353
  const key = parseJson(atomToken.family.subKey);
1321
- const mutableAtomToken = this.findMutableState(key);
1322
- new Tracker(mutableAtomToken, store);
1354
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
1355
+ if (mutableAtomToken) {
1356
+ new Tracker(mutableAtomToken, store);
1357
+ }
1323
1358
  }
1324
1359
  }
1325
1360
  );
@@ -1334,25 +1369,19 @@ function createMutableAtomFamily(options, store) {
1334
1369
  const subKey = stringifyJson(key);
1335
1370
  const family = { key: options.key, subKey };
1336
1371
  const fullKey = `${options.key}(${subKey})`;
1337
- const target2 = newest(store);
1338
- const atomAlreadyCreated = target2.atoms.has(fullKey);
1339
- let token;
1340
- if (atomAlreadyCreated) {
1341
- token = { type: `mutable_atom`, key: fullKey, family };
1342
- } else {
1343
- const individualOptions = {
1344
- key: fullKey,
1345
- default: () => options.default(key),
1346
- toJson: options.toJson,
1347
- fromJson: options.fromJson,
1348
- mutable: true
1349
- };
1350
- if (options.effects) {
1351
- individualOptions.effects = options.effects(key);
1352
- }
1353
- token = createMutableAtom(individualOptions, family, store);
1354
- subject.next(token);
1372
+ const target = newest(store);
1373
+ const individualOptions = {
1374
+ key: fullKey,
1375
+ default: () => options.default(key),
1376
+ toJson: options.toJson,
1377
+ fromJson: options.fromJson,
1378
+ mutable: true
1379
+ };
1380
+ if (options.effects) {
1381
+ individualOptions.effects = options.effects(key);
1355
1382
  }
1383
+ const token = createMutableAtom(individualOptions, family, target);
1384
+ subject.next(token);
1356
1385
  return token;
1357
1386
  },
1358
1387
  {
@@ -1364,8 +1393,7 @@ function createMutableAtomFamily(options, store) {
1364
1393
  fromJson: options.fromJson
1365
1394
  }
1366
1395
  );
1367
- const target = newest(store);
1368
- target.families.set(options.key, atomFamily);
1396
+ store.families.set(options.key, atomFamily);
1369
1397
  selectJsonFamily(atomFamily, options, store);
1370
1398
  new FamilyTracker(atomFamily, store);
1371
1399
  return atomFamily;
@@ -1380,19 +1408,24 @@ var getJsonFamily = (mutableAtomFamily, store) => {
1380
1408
  };
1381
1409
 
1382
1410
  // internal/src/mutable/get-json-token.ts
1383
- var getJsonToken = (mutableAtomToken) => {
1384
- const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1385
- const jsonToken = {
1386
- type: `selector`,
1387
- key
1388
- };
1411
+ var getJsonToken = (mutableAtomToken, store) => {
1389
1412
  if (mutableAtomToken.family) {
1390
- jsonToken.family = {
1391
- key: `${mutableAtomToken.family.key}:JSON`,
1392
- subKey: mutableAtomToken.family.subKey
1413
+ const target = newest(store);
1414
+ const jsonFamilyKey = `${mutableAtomToken.family.key}:JSON`;
1415
+ const jsonFamilyToken = {
1416
+ key: jsonFamilyKey,
1417
+ type: `selector_family`
1393
1418
  };
1419
+ const family = withdraw(jsonFamilyToken, target);
1420
+ const subKey = JSON.parse(mutableAtomToken.family.subKey);
1421
+ const jsonToken = findInStore(family, subKey, store);
1422
+ return jsonToken;
1394
1423
  }
1395
- return jsonToken;
1424
+ const token = {
1425
+ type: `selector`,
1426
+ key: `${mutableAtomToken.key}:JSON`
1427
+ };
1428
+ return token;
1396
1429
  };
1397
1430
 
1398
1431
  // internal/src/mutable/get-update-token.ts
@@ -1588,8 +1621,10 @@ function disposeAtom(atomToken, store) {
1588
1621
  `\u274C`,
1589
1622
  `atom`,
1590
1623
  key,
1591
- `Tried to delete atom, but it does not exist in the store.`
1624
+ `Tried to dispose atom, but it does not exist in the store.`
1592
1625
  );
1626
+ } else if (!atom.family) {
1627
+ store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1593
1628
  } else {
1594
1629
  (_a = atom.cleanup) == null ? void 0 : _a.call(atom);
1595
1630
  target.atoms.delete(key);
@@ -1609,6 +1644,7 @@ function disposeAtom(atomToken, store) {
1609
1644
  if (atomToken.type === `mutable_atom`) {
1610
1645
  const updateToken = getUpdateToken(atomToken);
1611
1646
  disposeAtom(updateToken, store);
1647
+ store.trackers.delete(key);
1612
1648
  }
1613
1649
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1614
1650
  store.on.atomDisposal.next(atomToken);
@@ -1626,7 +1662,7 @@ function getEnvironmentData(store) {
1626
1662
 
1627
1663
  // internal/src/get-state/get-from-store.ts
1628
1664
  function getFromStore(token, store) {
1629
- const state = withdrawOrCreate(token, store);
1665
+ const state = withdraw(token, store);
1630
1666
  return readOrComputeValue(state, store);
1631
1667
  }
1632
1668
 
@@ -2180,7 +2216,9 @@ var buildTransaction = (key, params, store, id) => {
2180
2216
  makeContentKey: (...keys) => keys.sort().join(`:`)
2181
2217
  }),
2182
2218
  selectors: new LazyMap(parent.selectors),
2183
- valueMap: new LazyMap(parent.valueMap)
2219
+ valueMap: new LazyMap(parent.valueMap),
2220
+ molecules: new LazyMap(parent.molecules),
2221
+ miscResources: new LazyMap(parent.miscResources)
2184
2222
  };
2185
2223
  const epoch = getEpochNumberOfAction(key, store);
2186
2224
  const transactionMeta = {
@@ -2200,6 +2238,7 @@ var buildTransaction = (key, params, store, id) => {
2200
2238
  },
2201
2239
  run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2202
2240
  find: (token, k) => findInStore(token, k, child),
2241
+ seek: (token, k) => seekInStore(token, k, child),
2203
2242
  env: () => getEnvironmentData(child)
2204
2243
  }
2205
2244
  };
@@ -2267,4 +2306,4 @@ function getEpochNumberOfAction(transactionKey, store) {
2267
2306
  // internal/src/transaction/index.ts
2268
2307
  var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2269
2308
 
2270
- export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, addAtomToTimeline, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeSelector, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, ingestAtomUpdate, ingestSelectorUpdate, ingestTransactionUpdate, isAtomDefault, isAtomKey, isChildStore, isDone, isMutable, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, readCachedValue, readOrComputeValue, registerSelector, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw, withdrawOrCreate };
2309
+ export { FamilyTracker, Future, IMPLICIT, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, addAtomToTimeline, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, createAtomFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeSelector, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateToken, ingestAtomUpdate, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMember, isAtomDefault, isAtomKey, isChildStore, isDone, isMutable, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, readCachedValue, readOrComputeValue, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };
@@ -12,8 +12,10 @@ export function disposeAtom(atomToken: AtomToken<unknown>, store: Store): void {
12
12
  `❌`,
13
13
  `atom`,
14
14
  key,
15
- `Tried to delete atom, but it does not exist in the store.`,
15
+ `Tried to dispose atom, but it does not exist in the store.`,
16
16
  )
17
+ } else if (!atom.family) {
18
+ store.logger.error(`❌`, `atom`, key, `Standalone atoms cannot be disposed.`)
17
19
  } else {
18
20
  atom.cleanup?.()
19
21
  target.atoms.delete(key)
@@ -35,6 +37,7 @@ export function disposeAtom(atomToken: AtomToken<unknown>, store: Store): void {
35
37
  if (atomToken.type === `mutable_atom`) {
36
38
  const updateToken = getUpdateToken(atomToken)
37
39
  disposeAtom(updateToken, store)
40
+ store.trackers.delete(key)
38
41
  }
39
42
  store.logger.info(`🔥`, `atom`, key, `deleted`)
40
43
  store.on.atomDisposal.next(atomToken)
@@ -10,7 +10,6 @@ import { stringifyJson } from "atom.io/json"
10
10
  import { newest } from "../lineage"
11
11
  import { createReadonlySelector } from "../selector"
12
12
  import type { Store } from "../store"
13
- import { deposit } from "../store"
14
13
  import { Subject } from "../subject"
15
14
 
16
15
  export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
@@ -18,24 +17,25 @@ export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
18
17
  store: Store,
19
18
  ): ReadonlySelectorFamily<T, K> {
20
19
  const subject = new Subject<ReadonlySelectorToken<T>>()
20
+
21
21
  const readonlySelectorFamily = Object.assign(
22
22
  (key: K): ReadonlySelectorToken<T> => {
23
- const target = newest(store)
24
23
  const subKey = stringifyJson(key)
25
24
  const family: FamilyMetadata = { key: options.key, subKey }
26
25
  const fullKey = `${options.key}(${subKey})`
27
- const existing = target.readonlySelectors.get(fullKey)
28
- if (existing) {
29
- return deposit(existing)
30
- }
31
- return createReadonlySelector(
26
+ const target = newest(store)
27
+
28
+ const token = createReadonlySelector(
32
29
  {
33
30
  key: fullKey,
34
31
  get: options.get(key),
35
32
  },
36
33
  family,
37
- store,
34
+ target,
38
35
  )
36
+
37
+ subject.next(token)
38
+ return token
39
39
  },
40
40
  {
41
41
  key: options.key,
@@ -43,7 +43,7 @@ export function createReadonlySelectorFamily<T, K extends Json.Serializable>(
43
43
  subject,
44
44
  install: (s: Store) => createReadonlySelectorFamily(options, s),
45
45
  } as const,
46
- ) as ReadonlySelectorFamily<T, K>
46
+ ) satisfies ReadonlySelectorFamily<T, K>
47
47
  store.families.set(options.key, readonlySelectorFamily)
48
48
  return readonlySelectorFamily
49
49
  }