atom.io 0.21.0 → 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 (99) hide show
  1. package/data/dist/index.cjs +139 -66
  2. package/data/dist/index.d.ts +6 -0
  3. package/data/dist/index.js +3 -3
  4. package/data/src/join.ts +135 -56
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/{chunk-RT43TVKP.js → chunk-GVHKIJ3G.js} +1 -1
  7. package/dist/{chunk-KGZGBCYS.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 +211 -194
  28. package/internal/dist/index.d.ts +30 -14
  29. package/internal/dist/index.js +210 -194
  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/future.ts +6 -20
  39. package/internal/src/get-state/get-from-store.ts +2 -3
  40. package/internal/src/mutable/create-mutable-atom-family.ts +17 -23
  41. package/internal/src/mutable/create-mutable-atom.ts +3 -1
  42. package/internal/src/mutable/get-json-family.ts +2 -2
  43. package/internal/src/mutable/get-json-token.ts +27 -12
  44. package/internal/src/mutable/tracker-family.ts +14 -12
  45. package/internal/src/mutable/tracker.ts +2 -24
  46. package/internal/src/not-found-error.ts +11 -3
  47. package/internal/src/operation.ts +0 -1
  48. package/internal/src/selector/create-readonly-selector.ts +2 -2
  49. package/internal/src/selector/create-writable-selector.ts +2 -2
  50. package/internal/src/selector/dispose-selector.ts +40 -23
  51. package/internal/src/selector/register-selector.ts +8 -5
  52. package/internal/src/set-state/set-into-store.ts +2 -2
  53. package/internal/src/store/index.ts +0 -1
  54. package/internal/src/store/store.ts +18 -5
  55. package/internal/src/subscribe/recall-state.ts +3 -3
  56. package/internal/src/subscribe/subscribe-to-state.ts +18 -5
  57. package/internal/src/transaction/build-transaction.ts +7 -2
  58. package/introspection/dist/index.cjs +39 -65
  59. package/introspection/dist/index.js +39 -65
  60. package/introspection/src/attach-atom-index.ts +38 -48
  61. package/introspection/src/attach-introspection-states.ts +0 -1
  62. package/introspection/src/attach-selector-index.ts +45 -50
  63. package/introspection/src/attach-timeline-family.ts +2 -17
  64. package/json/dist/index.cjs +38 -4
  65. package/json/dist/index.js +40 -6
  66. package/json/src/select-json-family.ts +46 -7
  67. package/package.json +31 -11
  68. package/react/dist/index.cjs +1 -1
  69. package/react/dist/index.js +1 -1
  70. package/react/src/use-json.ts +1 -1
  71. package/react-devtools/dist/index.cjs +11 -10
  72. package/react-devtools/dist/index.js +2 -1
  73. package/react-devtools/src/StateIndex.tsx +2 -1
  74. package/react-devtools/src/TimelineIndex.tsx +2 -1
  75. package/react-devtools/src/TransactionIndex.tsx +7 -7
  76. package/realtime-client/dist/index.cjs +3 -3
  77. package/realtime-client/dist/index.js +3 -3
  78. package/realtime-client/src/pull-mutable-atom-family-member.ts +1 -1
  79. package/realtime-client/src/pull-mutable-atom.ts +1 -1
  80. package/realtime-client/src/sync-continuity.ts +1 -2
  81. package/realtime-react/dist/index.cjs +1 -1
  82. package/realtime-react/dist/index.js +1 -1
  83. package/realtime-server/dist/index.cjs +18 -17
  84. package/realtime-server/dist/index.js +7 -6
  85. package/realtime-server/src/realtime-continuity-synchronizer.ts +5 -3
  86. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  87. package/realtime-server/src/realtime-mutable-provider.ts +1 -1
  88. package/realtime-testing/dist/index.cjs +6 -2
  89. package/realtime-testing/dist/index.js +8 -5
  90. package/realtime-testing/src/setup-realtime-test.tsx +5 -2
  91. package/src/atom.ts +10 -4
  92. package/src/index.ts +1 -2
  93. package/src/selector.ts +10 -4
  94. package/src/silo.ts +3 -3
  95. package/src/transaction.ts +5 -2
  96. package/src/validators.ts +0 -6
  97. package/internal/src/store/withdraw-new-family-member.ts +0 -69
  98. /package/{src → ephemeral/src}/find-state.ts +0 -0
  99. /package/src/{dispose.ts → dispose-state.ts} +0 -0
@@ -11,44 +11,30 @@ function arbitrary(random = Math.random) {
11
11
  // internal/src/future.ts
12
12
  var Future = class extends Promise {
13
13
  constructor(executor) {
14
- let promise;
15
14
  let superResolve;
16
15
  let superReject;
17
16
  super((resolve, reject) => {
18
17
  superResolve = resolve;
19
18
  superReject = reject;
20
- promise = executor instanceof Promise ? executor : new Promise(executor);
21
- promise.then(
22
- (value) => {
23
- if (promise) {
24
- this.pass(promise, value);
25
- }
26
- },
27
- (reason) => {
28
- if (promise) {
29
- this.fail(promise, reason);
30
- }
31
- }
32
- );
33
19
  });
34
- this.destiny = promise;
35
20
  this.resolve = superResolve;
36
21
  this.reject = superReject;
22
+ this.use(executor instanceof Promise ? executor : new Promise(executor));
37
23
  }
38
24
  pass(promise, value) {
39
- if (promise === this.destiny) {
25
+ if (promise === this.fate) {
40
26
  this.resolve(value);
41
27
  }
42
28
  }
43
29
  fail(promise, reason) {
44
- if (promise === this.destiny) {
30
+ if (promise === this.fate) {
45
31
  this.reject(reason);
46
32
  }
47
33
  }
48
34
  use(value) {
49
35
  if (value instanceof Promise) {
50
36
  const promise = value;
51
- this.destiny = promise;
37
+ this.fate = promise;
52
38
  promise.then(
53
39
  (resolved) => {
54
40
  this.pass(promise, resolved);
@@ -59,7 +45,7 @@ var Future = class extends Promise {
59
45
  );
60
46
  } else {
61
47
  this.resolve(value);
62
- this.destiny = void 0;
48
+ this.fate = void 0;
63
49
  }
64
50
  }
65
51
  };
@@ -127,7 +113,7 @@ function isChildStore(store) {
127
113
 
128
114
  // internal/src/store/store.ts
129
115
  var Store = class {
130
- constructor(name, store = null) {
116
+ constructor(config, store = null) {
131
117
  this.parent = null;
132
118
  this.child = null;
133
119
  this.valueMap = /* @__PURE__ */ new Map();
@@ -156,6 +142,8 @@ var Store = class {
156
142
  makeContentKey: (...keys) => keys.sort().join(`:`)
157
143
  }
158
144
  );
145
+ this.molecules = /* @__PURE__ */ new Map();
146
+ this.miscResources = /* @__PURE__ */ new Map();
159
147
  this.on = {
160
148
  atomCreation: new Subject(),
161
149
  atomDisposal: new Subject(),
@@ -177,7 +165,8 @@ var Store = class {
177
165
  })
178
166
  };
179
167
  this.config = {
180
- name: `IMPLICIT_STORE`
168
+ name: `IMPLICIT_STORE`,
169
+ lifespan: `ephemeral`
181
170
  };
182
171
  this.loggers = [
183
172
  new AtomIOLogger(`warn`, (_, __, key) => !key.includes(`\u{1F441}\u200D\u{1F5E8}`))
@@ -207,9 +196,7 @@ var Store = class {
207
196
  )
208
197
  };
209
198
  }
210
- this.config = __spreadProps(__spreadValues({}, store == null ? void 0 : store.config), {
211
- name
212
- });
199
+ this.config = __spreadValues(__spreadValues({}, store == null ? void 0 : store.config), config);
213
200
  for (const [, family] of store.families) {
214
201
  family.install(this);
215
202
  }
@@ -220,7 +207,7 @@ var Store = class {
220
207
  }
221
208
  atom.install(this);
222
209
  if (atom.type === `mutable_atom`) {
223
- const originalJsonToken = getJsonToken(atom);
210
+ const originalJsonToken = getJsonToken(atom, store);
224
211
  const originalUpdateToken = getUpdateToken(atom);
225
212
  mutableHelpers.add(originalJsonToken.key);
226
213
  mutableHelpers.add(originalUpdateToken.key);
@@ -248,12 +235,18 @@ var IMPLICIT = {
248
235
  STORE_INTERNAL: void 0,
249
236
  get STORE() {
250
237
  var _a;
251
- 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
+ });
252
242
  }
253
243
  };
254
244
  var clearStore = (store) => {
255
245
  const { config } = store;
256
- 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));
257
250
  store.config = config;
258
251
  };
259
252
 
@@ -294,36 +287,6 @@ function withdraw(token, store) {
294
287
  throw new NotFoundError(token, store);
295
288
  }
296
289
 
297
- // internal/src/store/withdraw-new-family-member.ts
298
- function withdrawOrCreate(token, store) {
299
- try {
300
- const state = withdraw(token, store);
301
- return state;
302
- } catch (notFoundError) {
303
- if (token.family) {
304
- store.logger.info(
305
- `\u{1F46A}`,
306
- token.type,
307
- token.key,
308
- `creating new family member in store "${store.config.name}"`
309
- );
310
- const target = newest(store);
311
- const family = target.families.get(token.family.key);
312
- if (family) {
313
- const jsonSubKey = JSON.parse(token.family.subKey);
314
- family(jsonSubKey);
315
- const state = withdraw(token, store);
316
- return state;
317
- }
318
- throw new NotFoundError(
319
- { key: token.family.key, type: `${token.type}_family` },
320
- store
321
- );
322
- }
323
- throw notFoundError;
324
- }
325
- }
326
-
327
290
  // internal/src/get-state/read-or-compute-value.ts
328
291
  var readOrComputeValue = (state, target) => {
329
292
  if (target.valueMap.has(state.key)) {
@@ -351,22 +314,17 @@ function createRegularAtomFamily(options, store) {
351
314
  const subKey = stringifyJson(key);
352
315
  const family = { key: options.key, subKey };
353
316
  const fullKey = `${options.key}(${subKey})`;
354
- const target2 = newest(store);
355
- const atomAlreadyCreated = target2.atoms.has(fullKey);
356
- let token;
357
- if (atomAlreadyCreated) {
358
- token = { type: `atom`, key: fullKey, family };
359
- } else {
360
- const individualOptions = {
361
- key: fullKey,
362
- default: options.default instanceof Function ? options.default(key) : options.default
363
- };
364
- if (options.effects) {
365
- individualOptions.effects = options.effects(key);
366
- }
367
- token = createRegularAtom(individualOptions, family, store);
368
- 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);
369
325
  }
326
+ const token = createRegularAtom(individualOptions, family, target);
327
+ subject.next(token);
370
328
  return token;
371
329
  },
372
330
  {
@@ -376,8 +334,7 @@ function createRegularAtomFamily(options, store) {
376
334
  install: (s) => createRegularAtomFamily(options, s)
377
335
  }
378
336
  );
379
- const target = newest(store);
380
- target.families.set(options.key, atomFamily);
337
+ store.families.set(options.key, atomFamily);
381
338
  return atomFamily;
382
339
  }
383
340
 
@@ -393,22 +350,20 @@ function createReadonlySelectorFamily(options, store) {
393
350
  const subject = new Subject();
394
351
  const readonlySelectorFamily = Object.assign(
395
352
  (key) => {
396
- const target = newest(store);
397
353
  const subKey = stringifyJson(key);
398
354
  const family = { key: options.key, subKey };
399
355
  const fullKey = `${options.key}(${subKey})`;
400
- const existing = target.readonlySelectors.get(fullKey);
401
- if (existing) {
402
- return deposit(existing);
403
- }
404
- return createReadonlySelector(
356
+ const target = newest(store);
357
+ const token = createReadonlySelector(
405
358
  {
406
359
  key: fullKey,
407
360
  get: options.get(key)
408
361
  },
409
362
  family,
410
- store
363
+ target
411
364
  );
365
+ subject.next(token);
366
+ return token;
412
367
  },
413
368
  {
414
369
  key: options.key,
@@ -427,10 +382,7 @@ function createWritableSelectorFamily(options, store) {
427
382
  const subKey = stringifyJson(key);
428
383
  const family = { key: options.key, subKey };
429
384
  const fullKey = `${options.key}(${subKey})`;
430
- const existing = store.selectors.get(fullKey);
431
- if (existing) {
432
- return deposit(existing);
433
- }
385
+ const target = newest(store);
434
386
  const token = createWritableSelector(
435
387
  {
436
388
  key: fullKey,
@@ -438,7 +390,7 @@ function createWritableSelectorFamily(options, store) {
438
390
  set: options.set(key)
439
391
  },
440
392
  family,
441
- store
393
+ target
442
394
  );
443
395
  subject.next(token);
444
396
  return token;
@@ -466,10 +418,18 @@ function createSelectorFamily(options, store) {
466
418
  // internal/src/not-found-error.ts
467
419
  var capitalize = (str) => str[0].toUpperCase() + str.slice(1);
468
420
  function prettyPrintTokenType(token) {
469
- if (token.type === `readonly_selector`) {
470
- 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);
471
432
  }
472
- return capitalize(token.type);
473
433
  }
474
434
  var NotFoundError = class extends Error {
475
435
  constructor(token, store) {
@@ -479,8 +439,8 @@ var NotFoundError = class extends Error {
479
439
  }
480
440
  };
481
441
 
482
- // internal/src/families/find-in-store.ts
483
- function findInStore(token, key, store) {
442
+ // internal/src/families/init-family-member.ts
443
+ function initFamilyMember(token, key, store) {
484
444
  const familyKey = token.key;
485
445
  const family = store.families.get(familyKey);
486
446
  if (family === void 0) {
@@ -489,6 +449,44 @@ function findInStore(token, key, store) {
489
449
  const state = family(key);
490
450
  return state;
491
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
+ }
492
490
 
493
491
  // internal/src/set-state/become.ts
494
492
  var become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(
@@ -731,7 +729,7 @@ function setIntoStore(token, value, store) {
731
729
  );
732
730
  return;
733
731
  }
734
- const state = withdrawOrCreate(token, store);
732
+ const state = withdraw(token, store);
735
733
  setAtomOrSelector(state, value, store);
736
734
  closeOperation(store);
737
735
  }
@@ -817,7 +815,7 @@ var updateSelectorAtoms = (selectorKey, dependency, store) => {
817
815
  var registerSelector = (selectorKey, store) => ({
818
816
  get: (dependency) => {
819
817
  const target = newest(store);
820
- const dependencyState = withdrawOrCreate(dependency, store);
818
+ const dependencyState = withdraw(dependency, store);
821
819
  const dependencyValue = readOrComputeValue(dependencyState, store);
822
820
  store.logger.info(
823
821
  `\u{1F50C}`,
@@ -840,19 +838,20 @@ var registerSelector = (selectorKey, store) => ({
840
838
  return dependencyValue;
841
839
  },
842
840
  set: (WritableToken, newValue) => {
843
- const state = withdrawOrCreate(WritableToken, store);
841
+ const state = withdraw(WritableToken, store);
844
842
  setAtomOrSelector(state, newValue, store);
845
843
  },
846
- find: (token, key) => findInStore(token, key, store)
844
+ find: (token, key) => findInStore(token, key, store),
845
+ seek: (token, key) => seekInStore(token, key, store)
847
846
  });
848
847
 
849
848
  // internal/src/selector/create-readonly-selector.ts
850
849
  var createReadonlySelector = (options, family, store) => {
851
850
  const target = newest(store);
852
851
  const subject = new Subject();
853
- const { get, find } = registerSelector(options.key, target);
852
+ const { get, find, seek } = registerSelector(options.key, target);
854
853
  const getSelf = () => {
855
- const value = options.get({ get, find });
854
+ const value = options.get({ get, find, seek });
856
855
  cacheValue(options.key, value, subject, newest(store));
857
856
  return value;
858
857
  };
@@ -887,8 +886,8 @@ var createWritableSelector = (options, family, store) => {
887
886
  const target = newest(store);
888
887
  const subject = new Subject();
889
888
  const transactors = registerSelector(options.key, target);
890
- const { find, get } = transactors;
891
- const readonlyTransactors = { find, get };
889
+ const { find, get, seek } = transactors;
890
+ const readonlyTransactors = { find, get, seek };
892
891
  const getSelf = () => {
893
892
  const value = options.get(readonlyTransactors);
894
893
  cacheValue(options.key, value, subject, newest(store));
@@ -946,41 +945,59 @@ function createStandaloneSelector(options, store) {
946
945
 
947
946
  // internal/src/selector/dispose-selector.ts
948
947
  function disposeSelector(selectorToken, store) {
948
+ var _a;
949
949
  const target = newest(store);
950
950
  const { key } = selectorToken;
951
- switch (selectorToken.type) {
952
- case `selector`:
953
- target.selectors.delete(key);
954
- break;
955
- case `readonly_selector`:
956
- target.readonlySelectors.delete(key);
957
- break;
958
- }
959
- target.valueMap.delete(key);
960
- target.selectorAtoms.delete(key);
961
- const downstreamTokens = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: key }).filter(([_, { source }]) => source === key).map(
962
- ([downstreamSelectorKey]) => {
963
- var _a;
964
- 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;
965
974
  }
966
- );
967
- for (const downstreamToken of downstreamTokens) {
968
- if (downstreamToken) {
969
- 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
+ }
970
987
  }
988
+ target.selectorGraph.delete(key);
989
+ store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
990
+ store.on.selectorDisposal.next(selectorToken);
971
991
  }
972
- target.selectorGraph.delete(key);
973
- store.logger.info(`\u{1F525}`, selectorToken.type, key, `deleted`);
974
- store.on.selectorDisposal.next(selectorToken);
975
992
  }
976
993
 
977
994
  // internal/src/subscribe/recall-state.ts
978
995
  var recallState = (state, store) => {
979
996
  const target = newest(store);
980
- if (!target.operation.open) {
981
- return target.valueMap.get(state.key);
997
+ if (target.operation.open) {
998
+ return target.operation.prev.get(state.key);
982
999
  }
983
- return target.operation.prev.get(state.key);
1000
+ return target.valueMap.get(state.key);
984
1001
  };
985
1002
 
986
1003
  // internal/src/subscribe/subscribe-to-root-atoms.ts
@@ -1029,11 +1046,24 @@ var subscribeToRootAtoms = (selector, store) => {
1029
1046
 
1030
1047
  // internal/src/subscribe/subscribe-to-state.ts
1031
1048
  function subscribeToState(token, handleUpdate, key, store) {
1032
- const state = withdrawOrCreate(token, store);
1049
+ function safelyHandleUpdate(update) {
1050
+ if (store.operation.open) {
1051
+ const unsubscribe2 = store.on.operationClose.subscribe(
1052
+ `state subscription ${key}`,
1053
+ () => {
1054
+ unsubscribe2();
1055
+ handleUpdate(update);
1056
+ }
1057
+ );
1058
+ } else {
1059
+ handleUpdate(update);
1060
+ }
1061
+ }
1062
+ const state = withdraw(token, store);
1033
1063
  store.logger.info(`\u{1F440}`, state.type, state.key, `Adding subscription "${key}"`);
1034
1064
  const isSelector = state.type === `selector` || state.type === `readonly_selector`;
1035
1065
  let dependencyUnsubFunctions = null;
1036
- let updateHandler = handleUpdate;
1066
+ let updateHandler = safelyHandleUpdate;
1037
1067
  if (isSelector) {
1038
1068
  dependencyUnsubFunctions = subscribeToRootAtoms(state, store);
1039
1069
  updateHandler = (update) => {
@@ -1041,7 +1071,7 @@ function subscribeToState(token, handleUpdate, key, store) {
1041
1071
  dependencyUnsubFunctions.length = 0;
1042
1072
  dependencyUnsubFunctions.push(...subscribeToRootAtoms(state, store));
1043
1073
  }
1044
- handleUpdate(update);
1074
+ safelyHandleUpdate(update);
1045
1075
  };
1046
1076
  }
1047
1077
  const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
@@ -1130,18 +1160,7 @@ var Tracker = class {
1130
1160
  this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
1131
1161
  subscriptionKey,
1132
1162
  (update) => {
1133
- if (target.operation.open) {
1134
- const unsubscribe = target.on.operationClose.subscribe(
1135
- subscriptionKey,
1136
- () => {
1137
- unsubscribe();
1138
- setIntoStore(latestUpdateState, update, target);
1139
- }
1140
- );
1141
- } else {
1142
- setIntoStore(mutableState, (current) => current, target);
1143
- setIntoStore(latestUpdateState, update, target);
1144
- }
1163
+ setIntoStore(latestUpdateState, update, target);
1145
1164
  }
1146
1165
  );
1147
1166
  this.unsubscribeFromState = subscribeToState(
@@ -1152,18 +1171,7 @@ var Tracker = class {
1152
1171
  this.unsubscribeFromInnerValue = update.newValue.subscribe(
1153
1172
  subscriptionKey,
1154
1173
  (transceiverUpdate) => {
1155
- if (target.operation.open) {
1156
- const unsubscribe = target.on.operationClose.subscribe(
1157
- subscriptionKey,
1158
- () => {
1159
- unsubscribe();
1160
- setIntoStore(latestUpdateState, transceiverUpdate, target);
1161
- }
1162
- );
1163
- } else {
1164
- setIntoStore(mutableState, (current) => current, target);
1165
- setIntoStore(latestUpdateState, transceiverUpdate, target);
1166
- }
1174
+ setIntoStore(latestUpdateState, transceiverUpdate, target);
1167
1175
  }
1168
1176
  );
1169
1177
  }
@@ -1312,37 +1320,41 @@ function createMutableAtom(options, family, store) {
1312
1320
  };
1313
1321
  }
1314
1322
  new Tracker(token, store);
1315
- selectJson(token, options, store);
1323
+ if (!family) {
1324
+ selectJson(token, options, store);
1325
+ }
1316
1326
  store.on.atomCreation.next(token);
1317
1327
  return token;
1318
1328
  }
1319
1329
  var FamilyTracker = class {
1320
- constructor(findMutableState, store) {
1321
- this.findLatestUpdateState = createRegularAtomFamily(
1330
+ constructor(mutableAtoms, store) {
1331
+ this.latestUpdateAtoms = createRegularAtomFamily(
1322
1332
  {
1323
- key: `*${findMutableState.key}`,
1333
+ key: `*${mutableAtoms.key}`,
1324
1334
  default: null
1325
1335
  },
1326
1336
  store
1327
1337
  );
1328
- this.findMutableState = findMutableState;
1329
- this.findMutableState.subject.subscribe(
1338
+ this.mutableAtoms = mutableAtoms;
1339
+ this.mutableAtoms.subject.subscribe(
1330
1340
  `store=${store.config.name}::tracker-atom-family`,
1331
1341
  (atomToken) => {
1332
1342
  if (atomToken.family) {
1333
1343
  const key = parseJson(atomToken.family.subKey);
1334
- this.findLatestUpdateState(key);
1344
+ seekInStore(this.latestUpdateAtoms, key, store);
1335
1345
  new Tracker(atomToken, store);
1336
1346
  }
1337
1347
  }
1338
1348
  );
1339
- this.findLatestUpdateState.subject.subscribe(
1349
+ this.latestUpdateAtoms.subject.subscribe(
1340
1350
  `store=${store.config.name}::tracker-atom-family`,
1341
1351
  (atomToken) => {
1342
1352
  if (atomToken.family) {
1343
1353
  const key = parseJson(atomToken.family.subKey);
1344
- const mutableAtomToken = this.findMutableState(key);
1345
- new Tracker(mutableAtomToken, store);
1354
+ const mutableAtomToken = seekInStore(this.mutableAtoms, key, store);
1355
+ if (mutableAtomToken) {
1356
+ new Tracker(mutableAtomToken, store);
1357
+ }
1346
1358
  }
1347
1359
  }
1348
1360
  );
@@ -1357,25 +1369,19 @@ function createMutableAtomFamily(options, store) {
1357
1369
  const subKey = stringifyJson(key);
1358
1370
  const family = { key: options.key, subKey };
1359
1371
  const fullKey = `${options.key}(${subKey})`;
1360
- const target2 = newest(store);
1361
- const atomAlreadyCreated = target2.atoms.has(fullKey);
1362
- let token;
1363
- if (atomAlreadyCreated) {
1364
- token = { type: `mutable_atom`, key: fullKey, family };
1365
- } else {
1366
- const individualOptions = {
1367
- key: fullKey,
1368
- default: () => options.default(key),
1369
- toJson: options.toJson,
1370
- fromJson: options.fromJson,
1371
- mutable: true
1372
- };
1373
- if (options.effects) {
1374
- individualOptions.effects = options.effects(key);
1375
- }
1376
- token = createMutableAtom(individualOptions, family, store);
1377
- 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);
1378
1382
  }
1383
+ const token = createMutableAtom(individualOptions, family, target);
1384
+ subject.next(token);
1379
1385
  return token;
1380
1386
  },
1381
1387
  {
@@ -1387,8 +1393,7 @@ function createMutableAtomFamily(options, store) {
1387
1393
  fromJson: options.fromJson
1388
1394
  }
1389
1395
  );
1390
- const target = newest(store);
1391
- target.families.set(options.key, atomFamily);
1396
+ store.families.set(options.key, atomFamily);
1392
1397
  selectJsonFamily(atomFamily, options, store);
1393
1398
  new FamilyTracker(atomFamily, store);
1394
1399
  return atomFamily;
@@ -1403,19 +1408,24 @@ var getJsonFamily = (mutableAtomFamily, store) => {
1403
1408
  };
1404
1409
 
1405
1410
  // internal/src/mutable/get-json-token.ts
1406
- var getJsonToken = (mutableAtomToken) => {
1407
- const key = mutableAtomToken.family ? `${mutableAtomToken.family.key}:JSON(${mutableAtomToken.family.subKey})` : `${mutableAtomToken.key}:JSON`;
1408
- const jsonToken = {
1409
- type: `selector`,
1410
- key
1411
- };
1411
+ var getJsonToken = (mutableAtomToken, store) => {
1412
1412
  if (mutableAtomToken.family) {
1413
- jsonToken.family = {
1414
- key: `${mutableAtomToken.family.key}:JSON`,
1415
- 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`
1416
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;
1417
1423
  }
1418
- return jsonToken;
1424
+ const token = {
1425
+ type: `selector`,
1426
+ key: `${mutableAtomToken.key}:JSON`
1427
+ };
1428
+ return token;
1419
1429
  };
1420
1430
 
1421
1431
  // internal/src/mutable/get-update-token.ts
@@ -1611,8 +1621,10 @@ function disposeAtom(atomToken, store) {
1611
1621
  `\u274C`,
1612
1622
  `atom`,
1613
1623
  key,
1614
- `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.`
1615
1625
  );
1626
+ } else if (!atom.family) {
1627
+ store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
1616
1628
  } else {
1617
1629
  (_a = atom.cleanup) == null ? void 0 : _a.call(atom);
1618
1630
  target.atoms.delete(key);
@@ -1632,6 +1644,7 @@ function disposeAtom(atomToken, store) {
1632
1644
  if (atomToken.type === `mutable_atom`) {
1633
1645
  const updateToken = getUpdateToken(atomToken);
1634
1646
  disposeAtom(updateToken, store);
1647
+ store.trackers.delete(key);
1635
1648
  }
1636
1649
  store.logger.info(`\u{1F525}`, `atom`, key, `deleted`);
1637
1650
  store.on.atomDisposal.next(atomToken);
@@ -1649,7 +1662,7 @@ function getEnvironmentData(store) {
1649
1662
 
1650
1663
  // internal/src/get-state/get-from-store.ts
1651
1664
  function getFromStore(token, store) {
1652
- const state = withdrawOrCreate(token, store);
1665
+ const state = withdraw(token, store);
1653
1666
  return readOrComputeValue(state, store);
1654
1667
  }
1655
1668
 
@@ -2203,7 +2216,9 @@ var buildTransaction = (key, params, store, id) => {
2203
2216
  makeContentKey: (...keys) => keys.sort().join(`:`)
2204
2217
  }),
2205
2218
  selectors: new LazyMap(parent.selectors),
2206
- valueMap: new LazyMap(parent.valueMap)
2219
+ valueMap: new LazyMap(parent.valueMap),
2220
+ molecules: new LazyMap(parent.molecules),
2221
+ miscResources: new LazyMap(parent.miscResources)
2207
2222
  };
2208
2223
  const epoch = getEpochNumberOfAction(key, store);
2209
2224
  const transactionMeta = {
@@ -2223,6 +2238,7 @@ var buildTransaction = (key, params, store, id) => {
2223
2238
  },
2224
2239
  run: (token, identifier = arbitrary()) => actUponStore(token, identifier, child),
2225
2240
  find: (token, k) => findInStore(token, k, child),
2241
+ seek: (token, k) => seekInStore(token, k, child),
2226
2242
  env: () => getEnvironmentData(child)
2227
2243
  }
2228
2244
  };
@@ -2290,4 +2306,4 @@ function getEpochNumberOfAction(transactionKey, store) {
2290
2306
  // internal/src/transaction/index.ts
2291
2307
  var TRANSACTION_PHASES = [`idle`, `building`, `applying`];
2292
2308
 
2293
- 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 };