atom.io 0.35.0 → 0.36.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 (133) hide show
  1. package/dist/eslint-plugin/index.d.ts +2 -18
  2. package/dist/eslint-plugin/index.d.ts.map +1 -1
  3. package/dist/eslint-plugin/index.js +4 -141
  4. package/dist/eslint-plugin/index.js.map +1 -1
  5. package/dist/internal/index.d.ts +100 -78
  6. package/dist/internal/index.d.ts.map +1 -1
  7. package/dist/internal/index.js +180 -163
  8. package/dist/internal/index.js.map +1 -1
  9. package/dist/introspection/index.d.ts +5 -6
  10. package/dist/introspection/index.d.ts.map +1 -1
  11. package/dist/introspection/index.js +2 -3
  12. package/dist/introspection/index.js.map +1 -1
  13. package/dist/json/index.d.ts +2 -10
  14. package/dist/json/index.d.ts.map +1 -1
  15. package/dist/json/index.js +1 -31
  16. package/dist/json/index.js.map +1 -1
  17. package/dist/main/index.d.ts +38 -39
  18. package/dist/main/index.d.ts.map +1 -1
  19. package/dist/main/index.js +15 -16
  20. package/dist/main/index.js.map +1 -1
  21. package/dist/react/index.d.ts +4 -4
  22. package/dist/react/index.d.ts.map +1 -1
  23. package/dist/react/index.js.map +1 -1
  24. package/dist/react-devtools/index.js.map +1 -1
  25. package/dist/realtime/index.d.ts +4 -4
  26. package/dist/realtime/index.d.ts.map +1 -1
  27. package/dist/realtime/index.js +2 -6
  28. package/dist/realtime/index.js.map +1 -1
  29. package/dist/realtime-client/index.d.ts +7 -8
  30. package/dist/realtime-client/index.d.ts.map +1 -1
  31. package/dist/realtime-client/index.js +3 -4
  32. package/dist/realtime-client/index.js.map +1 -1
  33. package/dist/realtime-react/index.d.ts +4 -4
  34. package/dist/realtime-react/index.d.ts.map +1 -1
  35. package/dist/realtime-react/index.js.map +1 -1
  36. package/dist/realtime-server/index.d.ts +18 -18
  37. package/dist/realtime-server/index.d.ts.map +1 -1
  38. package/dist/realtime-server/index.js +5 -9
  39. package/dist/realtime-server/index.js.map +1 -1
  40. package/dist/transceivers/set-rtx/index.d.ts +9 -2
  41. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  42. package/dist/transceivers/set-rtx/index.js +3 -0
  43. package/dist/transceivers/set-rtx/index.js.map +1 -1
  44. package/package.json +6 -6
  45. package/src/eslint-plugin/index.ts +0 -1
  46. package/src/eslint-plugin/rules/explicit-state-types.ts +8 -1
  47. package/src/eslint-plugin/rules/index.ts +0 -1
  48. package/src/internal/atom/create-regular-atom.ts +5 -5
  49. package/src/internal/atom/dispose-atom.ts +1 -0
  50. package/src/internal/atom/has-role.ts +12 -0
  51. package/src/internal/atom/index.ts +1 -0
  52. package/src/internal/caching.ts +38 -16
  53. package/src/internal/families/find-in-store.ts +4 -5
  54. package/src/internal/families/get-family-of-token.ts +4 -5
  55. package/src/internal/families/init-family-member.ts +3 -4
  56. package/src/internal/families/seek-in-store.ts +4 -5
  57. package/src/internal/get-state/read-or-compute-value.ts +37 -16
  58. package/src/internal/index.ts +19 -21
  59. package/src/internal/ingest-updates/ingest-creation-disposal.ts +18 -15
  60. package/src/internal/ingest-updates/ingest-selector-update.ts +9 -5
  61. package/src/internal/join/get-internal-relations-from-store.ts +2 -2
  62. package/src/internal/join/join-internal.ts +10 -18
  63. package/src/internal/molecule.ts +1 -0
  64. package/src/internal/mutable/create-mutable-atom-family.ts +40 -22
  65. package/src/internal/mutable/create-mutable-atom.ts +16 -12
  66. package/src/internal/mutable/get-json-family.ts +7 -6
  67. package/src/internal/mutable/get-json-token.ts +6 -13
  68. package/src/internal/mutable/get-update-family.ts +7 -8
  69. package/src/internal/mutable/get-update-token.ts +5 -9
  70. package/src/internal/mutable/tracker-family.ts +31 -38
  71. package/src/internal/mutable/tracker.ts +86 -104
  72. package/src/internal/mutable/transceiver.ts +37 -9
  73. package/src/internal/selector/create-readonly-held-selector.ts +2 -2
  74. package/src/internal/selector/create-readonly-pure-selector.ts +2 -2
  75. package/src/internal/selector/create-writable-held-selector.ts +3 -3
  76. package/src/internal/selector/create-writable-pure-selector.ts +3 -3
  77. package/src/internal/selector/dispose-selector.ts +9 -9
  78. package/src/internal/set-state/reset-atom-or-selector.ts +11 -4
  79. package/src/internal/set-state/set-atom.ts +15 -22
  80. package/src/internal/set-state/set-into-store.ts +5 -4
  81. package/src/internal/store/counterfeit.ts +3 -4
  82. package/src/internal/store/deposit.ts +8 -11
  83. package/src/internal/store/store.ts +7 -7
  84. package/src/internal/store/withdraw.ts +8 -12
  85. package/src/internal/subscribe/subscribe-in-store.ts +2 -2
  86. package/src/internal/subscribe/subscribe-to-transaction.ts +2 -2
  87. package/src/internal/timeline/create-timeline.ts +3 -3
  88. package/src/internal/transaction/act-upon-store.ts +2 -2
  89. package/src/internal/transaction/apply-transaction.ts +2 -2
  90. package/src/internal/transaction/build-transaction.ts +2 -2
  91. package/src/internal/transaction/create-transaction.ts +3 -3
  92. package/src/internal/transaction/index.ts +2 -2
  93. package/src/internal/transaction/is-root-store.ts +4 -2
  94. package/src/internal/utility-types.ts +1 -1
  95. package/src/introspection/attach-introspection-states.ts +3 -3
  96. package/src/introspection/attach-transaction-index.ts +4 -4
  97. package/src/introspection/attach-transaction-logs.ts +4 -4
  98. package/src/introspection/auditor.ts +3 -3
  99. package/src/json/index.ts +0 -2
  100. package/src/main/atom.ts +24 -36
  101. package/src/main/dispose-state.ts +6 -5
  102. package/src/main/find-state.ts +3 -4
  103. package/src/main/get-state.ts +6 -5
  104. package/src/main/join.ts +2 -2
  105. package/src/main/logger.ts +7 -7
  106. package/src/main/reset-state.ts +3 -3
  107. package/src/main/set-state.ts +3 -3
  108. package/src/main/subscribe.ts +3 -3
  109. package/src/main/tokens.ts +8 -14
  110. package/src/main/transaction.ts +17 -13
  111. package/src/main/validators.ts +1 -1
  112. package/src/react/use-json.ts +14 -24
  113. package/src/react-devtools/TransactionIndex.tsx +3 -3
  114. package/src/react-devtools/Updates.tsx +2 -2
  115. package/src/realtime/shared-room-store.ts +11 -22
  116. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +2 -2
  117. package/src/realtime-client/pull-mutable-atom-family-member.ts +8 -17
  118. package/src/realtime-client/pull-mutable-atom.ts +7 -14
  119. package/src/realtime-client/push-state.ts +6 -5
  120. package/src/realtime-client/server-action.ts +5 -4
  121. package/src/realtime-react/use-pull-mutable-atom.ts +3 -5
  122. package/src/realtime-react/use-pull-mutable-family-member.ts +3 -4
  123. package/src/realtime-react/use-server-action.ts +2 -2
  124. package/src/realtime-server/realtime-mutable-family-provider.ts +3 -4
  125. package/src/realtime-server/realtime-mutable-provider.ts +2 -3
  126. package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +6 -5
  127. package/src/realtime-server/realtime-server-stores/server-user-store.ts +8 -15
  128. package/src/transceivers/set-rtx/set-rtx.ts +14 -1
  129. package/src/eslint-plugin/rules/synchronous-selector-dependencies.ts +0 -140
  130. package/src/eslint-plugin/walk.ts +0 -81
  131. package/src/internal/set-state/copy-mutable-if-needed.ts +0 -27
  132. package/src/json/select-json-family.ts +0 -55
  133. package/src/json/select-json.ts +0 -19
@@ -1,5 +1,5 @@
1
1
  import { Join as Join$1, arbitrary as arbitrary$1, subscribeToState as subscribeToState$1, subscribeToTimeline as subscribeToTimeline$1, subscribeToTransaction as subscribeToTransaction$1 } from "atom.io/internal";
2
- import { parseJson, selectJson, selectJsonFamily, stringifyJson } from "atom.io/json";
2
+ import { parseJson, stringifyJson } from "atom.io/json";
3
3
  import { Anarchy, AtomIOLogger } from "atom.io";
4
4
  import { SetRTX } from "atom.io/transceivers/set-rtx";
5
5
 
@@ -454,21 +454,6 @@ var Future = class extends Promise {
454
454
  }
455
455
  };
456
456
 
457
- //#endregion
458
- //#region src/internal/set-state/copy-mutable-if-needed.ts
459
- function copyMutableIfNeeded(target, atom, origin) {
460
- const originValue = origin.valueMap.get(atom.key);
461
- const targetValue = target.valueMap.get(atom.key);
462
- if (originValue !== targetValue) return targetValue;
463
- if (originValue === void 0) return atom.default();
464
- origin.logger.info(`📃`, `atom`, atom.key, `copying`);
465
- const jsonValue = atom.toJson(originValue);
466
- const copiedValue = atom.fromJson(jsonValue);
467
- target.valueMap.set(atom.key, copiedValue);
468
- new Tracker(atom, origin);
469
- return copiedValue;
470
- }
471
-
472
457
  //#endregion
473
458
  //#region src/internal/transaction/is-root-store.ts
474
459
  function isRootStore(store) {
@@ -542,7 +527,7 @@ function evictDownStreamFromSelector(store, selector) {
542
527
 
543
528
  //#endregion
544
529
  //#region src/internal/caching.ts
545
- function cacheValue(target, key, value, subject) {
530
+ function writeToCache(target, key, value, subject) {
546
531
  const currentValue = target.valueMap.get(key);
547
532
  if (currentValue instanceof Future && !currentValue.done) {
548
533
  const future = currentValue;
@@ -559,7 +544,7 @@ function cacheValue(target, key, value, subject) {
559
544
  future.then(function handleResolvedFuture(resolved) {
560
545
  const current = target.valueMap.get(key);
561
546
  if (current === future) {
562
- cacheValue(target, key, resolved, subject);
547
+ writeToCache(target, key, resolved, subject);
563
548
  const atom = target.atoms.get(key);
564
549
  if (atom) {
565
550
  openOperation(target, atom);
@@ -586,17 +571,31 @@ function cacheValue(target, key, value, subject) {
586
571
  target.valueMap.set(key, value);
587
572
  return value;
588
573
  }
589
- const readCachedValue = (state, target) => {
574
+ /**
575
+ * @param target - the newest layer of the store
576
+ * @param state - the state to read from cache
577
+ * @param mut - whether the value is intended to be mutable
578
+ * @returns the state's current value
579
+ */
580
+ function readFromCache(target, state, mut) {
590
581
  target.logger.info(`📖`, state.type, state.key, `reading cached value`);
591
582
  let value = target.valueMap.get(state.key);
592
- if (state.type === `mutable_atom` && isChildStore(target)) {
583
+ const mayNeedToBeCopied = mut === `mut` && state.type === `mutable_atom` && isChildStore(target);
584
+ if (mayNeedToBeCopied) {
585
+ const mutableAtom$1 = state;
593
586
  const { parent } = target;
594
- const copiedValue = copyMutableIfNeeded(target, state, parent);
587
+ if (target.valueMap.hasOwn(mutableAtom$1.key)) return value;
588
+ const parentValue = parent.valueMap.get(mutableAtom$1.key);
589
+ target.logger.info(`📃`, `atom`, mutableAtom$1.key, `copying`);
590
+ const jsonValue = parentValue.toJSON();
591
+ const copiedValue = mutableAtom$1.class.fromJSON(jsonValue);
592
+ target.valueMap.set(mutableAtom$1.key, copiedValue);
593
+ new Tracker(mutableAtom$1, parent);
595
594
  value = copiedValue;
596
595
  }
597
596
  return value;
598
- };
599
- const evictCachedValue = (target, key) => {
597
+ }
598
+ function evictCachedValue(target, key) {
600
599
  const currentValue = target.valueMap.get(key);
601
600
  if (currentValue instanceof Future) {
602
601
  const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
@@ -606,12 +605,12 @@ const evictCachedValue = (target, key) => {
606
605
  if (target.operation.open) target.operation.prev.set(key, currentValue);
607
606
  target.valueMap.delete(key);
608
607
  target.logger.info(`🗑`, `state`, key, `evicted`);
609
- };
608
+ }
610
609
 
611
610
  //#endregion
612
611
  //#region src/internal/get-state/read-or-compute-value.ts
613
- const readOrComputeValue = (target, state) => {
614
- if (target.valueMap.has(state.key)) return readCachedValue(state, target);
612
+ function readOrComputeValue(target, state, mut) {
613
+ if (target.valueMap.has(state.key)) return readFromCache(target, state, mut);
615
614
  switch (state.type) {
616
615
  case `readonly_held_selector`:
617
616
  case `readonly_pure_selector`:
@@ -619,18 +618,22 @@ const readOrComputeValue = (target, state) => {
619
618
  case `writable_pure_selector`:
620
619
  target.logger.info(`🧮`, state.type, state.key, `computing value`);
621
620
  return state.get();
622
- case `atom`:
621
+ case `atom`: {
622
+ let def;
623
+ if (state.default instanceof Function) def = state.default();
624
+ else def = state.default;
625
+ const cachedValue = writeToCache(target, state.key, def, state.subject);
626
+ target.logger.info(`💁`, `atom`, state.key, `could not find cached value; using default`, def);
627
+ return cachedValue;
628
+ }
623
629
  case `mutable_atom`: {
624
- const def = state.default;
625
- let defaultValue;
626
- if (def instanceof Function) defaultValue = def();
627
- else defaultValue = def;
628
- const cachedValue = cacheValue(target, state.key, defaultValue, state.subject);
629
- target.logger.info(`💁`, `atom`, state.key, `could not find cached value; using default`, defaultValue);
630
+ const instance = new state.class();
631
+ const cachedValue = writeToCache(target, state.key, instance, state.subject);
632
+ target.logger.info(`💁`, `mutable_atom`, state.key, `could not find cached value; using default`, instance);
630
633
  return cachedValue;
631
634
  }
632
635
  }
633
- };
636
+ }
634
637
 
635
638
  //#endregion
636
639
  //#region src/internal/subscribe/subscribe-to-root-atoms.ts
@@ -651,6 +654,14 @@ const subscribeToRootDependency = (target, selector, atom) => {
651
654
  //#region src/internal/set-state/become.ts
652
655
  const become = (nextVersionOfThing) => (originalThing) => nextVersionOfThing instanceof Function ? nextVersionOfThing(originalThing) : nextVersionOfThing;
653
656
 
657
+ //#endregion
658
+ //#region src/internal/atom/has-role.ts
659
+ const INTERNAL_ROLES = [`tracker:signal`];
660
+ function hasRole(atom, role) {
661
+ if (`internalRoles` in atom === false) return false;
662
+ return atom.internalRoles.includes(role);
663
+ }
664
+
654
665
  //#endregion
655
666
  //#region src/internal/set-state/emit-update.ts
656
667
  const emitUpdate = (store, state, update) => {
@@ -670,16 +681,10 @@ const emitUpdate = (store, state, update) => {
670
681
  //#endregion
671
682
  //#region src/internal/set-state/set-atom.ts
672
683
  const setAtom = (target, atom, next) => {
673
- const oldValue = readOrComputeValue(target, atom);
674
- let newValue = oldValue;
675
- if (atom.type === `mutable_atom` && isChildStore(target)) {
676
- const { parent } = target;
677
- const copiedValue = copyMutableIfNeeded(target, atom, parent);
678
- newValue = copiedValue;
679
- }
680
- newValue = become(next)(newValue);
684
+ const oldValue = readOrComputeValue(target, atom, `mut`);
685
+ let newValue = become(next)(oldValue);
681
686
  target.logger.info(`📝`, `atom`, atom.key, `set to`, newValue);
682
- newValue = cacheValue(target, atom.key, newValue, atom.subject);
687
+ newValue = writeToCache(target, atom.key, newValue, atom.subject);
683
688
  markDone(target, atom.key);
684
689
  evictDownStream(target, atom);
685
690
  const update = {
@@ -701,26 +706,28 @@ const setAtom = (target, atom, next) => {
701
706
  if (atom.family) atomUpdate.family = atom.family;
702
707
  target.transactionMeta.update.updates.push(atomUpdate);
703
708
  target.logger.info(`📁`, `atom`, key, `stowed (`, update.oldValue, `->`, update.newValue, `)`);
704
- } else if (atom.key.startsWith(`*`)) {
705
- const mutableKey = atom.key.slice(1);
706
- const mutableAtom$1 = target.atoms.get(mutableKey);
707
- let transceiver = target.valueMap.get(mutableKey);
708
- if (mutableAtom$1.type === `mutable_atom` && isChildStore(target)) {
709
- const { parent } = target;
710
- const copiedValue = copyMutableIfNeeded(target, mutableAtom$1, parent);
711
- transceiver = copiedValue;
712
- }
709
+ } else if (hasRole(atom, `tracker:signal`)) {
710
+ const key = atom.key.slice(1);
711
+ const mutable = target.atoms.get(key);
712
+ const transceiver = readOrComputeValue(target, mutable, `mut`);
713
713
  const accepted = transceiver.do(update.newValue) === null;
714
- if (accepted) evictDownStream(target, mutableAtom$1);
714
+ if (accepted === true) evictDownStream(target, mutable);
715
715
  }
716
716
  };
717
717
 
718
718
  //#endregion
719
719
  //#region src/internal/set-state/reset-atom-or-selector.ts
720
720
  function resetAtom(store, state) {
721
- let def = state.default;
722
- if (def instanceof Function) def = def();
723
- setAtom(store, state, def);
721
+ switch (state.type) {
722
+ case `mutable_atom`:
723
+ setAtom(store, state, new state.class());
724
+ return;
725
+ case `atom`: {
726
+ let def = state.default;
727
+ if (def instanceof Function) def = def();
728
+ setAtom(store, state, def);
729
+ }
730
+ }
724
731
  }
725
732
  function resetAtomOrSelector(store, state) {
726
733
  switch (state.type) {
@@ -810,9 +817,9 @@ function setIntoStore(store, ...params) {
810
817
  if (params.length === 2) {
811
818
  token = params[0];
812
819
  value = params[1];
813
- family = getFamilyOfToken(store, token) ?? null;
814
- if (family) {
815
- key = token.family ? parseJson(token.family.subKey) : null;
820
+ if (token.family) {
821
+ family = getFamilyOfToken(store, token);
822
+ key = parseJson(token.family.subKey);
816
823
  token = findInStore(store, family, key);
817
824
  }
818
825
  } else {
@@ -829,7 +836,7 @@ function setIntoStore(store, ...params) {
829
836
  }
830
837
  const rejectionTime = openOperation(store, token);
831
838
  if (rejectionTime) {
832
- const unsubscribe = store.on.operationClose.subscribe(`waiting to set "${token.key}" at T-${rejectionTime}`, () => {
839
+ const unsubscribe = store.on.operationClose.subscribe(`waiting to set "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
833
840
  unsubscribe();
834
841
  store.logger.info(`🟢`, token.type, token.key, `resuming deferred setState from T-${rejectionTime}`);
835
842
  setIntoStore(store, token, value);
@@ -954,7 +961,7 @@ const createReadonlyHeldSelector = (store, options, family) => {
954
961
  find,
955
962
  json
956
963
  }, constant);
957
- cacheValue(newest(store), key, constant, subject);
964
+ writeToCache(newest(store), key, constant, subject);
958
965
  covered.clear();
959
966
  return constant;
960
967
  };
@@ -995,7 +1002,7 @@ const createReadonlyPureSelector = (store, options, family) => {
995
1002
  find,
996
1003
  json
997
1004
  });
998
- const cached = cacheValue(innerTarget, key, value, subject);
1005
+ const cached = writeToCache(innerTarget, key, value, subject);
999
1006
  store.logger.info(`✨`, type, key, `=`, cached);
1000
1007
  covered.clear();
1001
1008
  return cached;
@@ -1210,6 +1217,7 @@ function claimWithinStore(store, newProvenance, claim, exclusive) {
1210
1217
  const transferEvent = {
1211
1218
  type: `molecule_transfer`,
1212
1219
  key: molecule.key,
1220
+ exclusive: Boolean(exclusive),
1213
1221
  from: priorProvenance,
1214
1222
  to: [newProvenanceMolecule.key]
1215
1223
  };
@@ -1282,15 +1290,15 @@ function ingestMoleculeDisposalEvent(update, applying, store) {
1282
1290
  function ingestMoleculeTransferEvent(update, applying, store) {
1283
1291
  switch (applying) {
1284
1292
  case `newValue`:
1285
- {
1286
- const provenance = update.to.length === 1 ? update.to[0] : update.to;
1287
- claimWithinStore(store, provenance, update.key, `exclusive`);
1288
- }
1293
+ for (const newOwner of update.to) claimWithinStore(store, newOwner, update.key, update.exclusive ? `exclusive` : void 0);
1289
1294
  break;
1290
1295
  case `oldValue`:
1291
1296
  {
1292
- const provenance = update.from.length === 1 ? update.from[0] : update.from;
1293
- claimWithinStore(store, provenance, update.key, `exclusive`);
1297
+ let exclusivity = `exclusive`;
1298
+ for (const previousOwner of update.from) {
1299
+ claimWithinStore(store, previousOwner, update.key, exclusivity);
1300
+ exclusivity = void 0;
1301
+ }
1294
1302
  }
1295
1303
  break;
1296
1304
  }
@@ -1299,7 +1307,9 @@ function ingestMoleculeTransferEvent(update, applying, store) {
1299
1307
  //#endregion
1300
1308
  //#region src/internal/ingest-updates/ingest-selector-update.ts
1301
1309
  function ingestSelectorUpdate(applying, selectorUpdate, store) {
1302
- const updates = applying === `newValue` ? selectorUpdate.atomUpdates : selectorUpdate.atomUpdates.toReversed();
1310
+ let updates;
1311
+ if (applying === `newValue`) updates = selectorUpdate.atomUpdates;
1312
+ else updates = selectorUpdate.atomUpdates.toReversed();
1303
1313
  for (const atomUpdate of updates) ingestAtomUpdate(applying, atomUpdate, store);
1304
1314
  }
1305
1315
 
@@ -1570,7 +1580,7 @@ const createWritableHeldSelector = (store, options, family) => {
1570
1580
  for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
1571
1581
  innerTarget.selectorAtoms.delete(key);
1572
1582
  getFn(getterToolkit, constant);
1573
- cacheValue(innerTarget, key, constant, subject);
1583
+ writeToCache(innerTarget, key, constant, subject);
1574
1584
  store.logger.info(`✨`, type, key, `=`, constant);
1575
1585
  covered.clear();
1576
1586
  return constant;
@@ -1580,7 +1590,7 @@ const createWritableHeldSelector = (store, options, family) => {
1580
1590
  const oldValue = getSelf(options.get, innerTarget);
1581
1591
  const newValue = become(next)(oldValue);
1582
1592
  store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
1583
- cacheValue(innerTarget, key, newValue, subject);
1593
+ writeToCache(innerTarget, key, newValue, subject);
1584
1594
  markDone(innerTarget, key);
1585
1595
  if (isRootStore(innerTarget)) subject.next({
1586
1596
  newValue,
@@ -1626,7 +1636,7 @@ const createWritablePureSelector = (store, options, family) => {
1626
1636
  for (const [downstreamSelectorKey, { source }] of upstreamStates) if (source !== key) innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
1627
1637
  innerTarget.selectorAtoms.delete(key);
1628
1638
  const value = getFn(getterToolkit);
1629
- const cached = cacheValue(innerTarget, key, value, subject);
1639
+ const cached = writeToCache(innerTarget, key, value, subject);
1630
1640
  store.logger.info(`✨`, type, key, `=`, cached);
1631
1641
  covered.clear();
1632
1642
  return value;
@@ -1636,7 +1646,7 @@ const createWritablePureSelector = (store, options, family) => {
1636
1646
  const oldValue = getSelf(options.get, innerTarget);
1637
1647
  const newValue = become(next)(oldValue);
1638
1648
  store.logger.info(`📝`, type, key, `set (`, oldValue, `->`, newValue, `)`);
1639
- cacheValue(innerTarget, options.key, newValue, subject);
1649
+ writeToCache(innerTarget, options.key, newValue, subject);
1640
1650
  markDone(innerTarget, options.key);
1641
1651
  if (isRootStore(innerTarget)) subject.next({
1642
1652
  newValue,
@@ -1693,19 +1703,18 @@ function createStandaloneSelector(store, options) {
1693
1703
  //#region src/internal/selector/dispose-selector.ts
1694
1704
  function disposeSelector(store, selectorToken) {
1695
1705
  const target = newest(store);
1696
- const { key, type } = selectorToken;
1697
- const selector = withdraw(target, selectorToken);
1698
- if (!selector.family) store.logger.error(`❌`, type, key, `Standalone selectors cannot be disposed.`);
1706
+ const { key, type, family: familyMeta } = selectorToken;
1707
+ if (!familyMeta) store.logger.error(`❌`, type, key, `Standalone selectors cannot be disposed.`);
1699
1708
  else {
1700
- const molecule = target.molecules.get(selector.family.subKey);
1701
- if (molecule) target.moleculeData.delete(selector.family.subKey, selector.family.key);
1709
+ const molecule = target.molecules.get(familyMeta.subKey);
1710
+ if (molecule) target.moleculeData.delete(familyMeta.subKey, familyMeta.key);
1702
1711
  let familyToken;
1703
1712
  switch (selectorToken.type) {
1704
1713
  case `writable_held_selector`:
1705
1714
  {
1706
1715
  target.writableSelectors.delete(key);
1707
1716
  familyToken = {
1708
- key: selector.family.key,
1717
+ key: familyMeta.key,
1709
1718
  type: `writable_held_selector_family`
1710
1719
  };
1711
1720
  const family = withdraw(store, familyToken);
@@ -1720,7 +1729,7 @@ function disposeSelector(store, selectorToken) {
1720
1729
  {
1721
1730
  target.writableSelectors.delete(key);
1722
1731
  familyToken = {
1723
- key: selector.family.key,
1732
+ key: familyMeta.key,
1724
1733
  type: `writable_pure_selector_family`
1725
1734
  };
1726
1735
  const family = withdraw(store, familyToken);
@@ -1735,7 +1744,7 @@ function disposeSelector(store, selectorToken) {
1735
1744
  {
1736
1745
  target.readonlySelectors.delete(key);
1737
1746
  familyToken = {
1738
- key: selector.family.key,
1747
+ key: familyMeta.key,
1739
1748
  type: `readonly_held_selector_family`
1740
1749
  };
1741
1750
  const family = withdraw(store, familyToken);
@@ -1750,7 +1759,7 @@ function disposeSelector(store, selectorToken) {
1750
1759
  {
1751
1760
  target.readonlySelectors.delete(key);
1752
1761
  familyToken = {
1753
- key: selector.family.key,
1762
+ key: familyMeta.key,
1754
1763
  type: `readonly_pure_selector_family`
1755
1764
  };
1756
1765
  const family = withdraw(store, familyToken);
@@ -1765,6 +1774,7 @@ function disposeSelector(store, selectorToken) {
1765
1774
  target.valueMap.delete(key);
1766
1775
  target.selectorAtoms.delete(key);
1767
1776
  target.selectorGraph.delete(key);
1777
+ target.moleculeData.delete(familyMeta.key, familyMeta.subKey);
1768
1778
  store.logger.info(`🔥`, selectorToken.type, key, `deleted`);
1769
1779
  if (isChildStore(target) && target.transactionMeta.phase === `building`) target.transactionMeta.update.updates.push({
1770
1780
  type: `state_disposal`,
@@ -2217,86 +2227,86 @@ const subscribeToTransaction = (store, token, key, handleUpdate) => {
2217
2227
  * the tracker will update its own state to reflect the change.
2218
2228
  */
2219
2229
  var Tracker = class {
2220
- initializeState(mutableState, store) {
2221
- const latestUpdateStateKey = `*${mutableState.key}`;
2222
- store.atoms.delete(latestUpdateStateKey);
2223
- store.valueMap.delete(latestUpdateStateKey);
2230
+ initializeSignalAtom(mutableState, store) {
2231
+ const latestSignalStateKey = `*${mutableState.key}`;
2232
+ store.atoms.delete(latestSignalStateKey);
2233
+ store.valueMap.delete(latestSignalStateKey);
2224
2234
  const familyMetaData = mutableState.family ? {
2225
2235
  key: `*${mutableState.family.key}`,
2226
2236
  subKey: mutableState.family.subKey
2227
2237
  } : void 0;
2228
- const latestUpdateState = createRegularAtom(store, {
2229
- key: latestUpdateStateKey,
2238
+ const latestSignalState = createRegularAtom(store, {
2239
+ key: latestSignalStateKey,
2230
2240
  default: null
2231
- }, familyMetaData);
2232
- if (store.parent?.valueMap.has(latestUpdateStateKey)) {
2233
- const parentValue = store.parent.valueMap.get(latestUpdateStateKey);
2234
- store.valueMap.set(latestUpdateStateKey, parentValue);
2241
+ }, familyMetaData, [`tracker:signal`]);
2242
+ if (store.parent?.valueMap.has(latestSignalStateKey)) {
2243
+ const parentValue = store.parent.valueMap.get(latestSignalStateKey);
2244
+ store.valueMap.set(latestSignalStateKey, parentValue);
2235
2245
  }
2236
- return latestUpdateState;
2246
+ return latestSignalState;
2237
2247
  }
2238
2248
  unsubscribeFromInnerValue;
2239
2249
  unsubscribeFromState;
2240
- observeCore(mutableState, latestUpdateState, target) {
2241
- const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
2250
+ captureSignalsFromCore(mutableState, latestSignalState, target) {
2251
+ const stateKey = mutableState.key;
2252
+ const storeName = target.config.name;
2253
+ const storeStatus = isChildStore(target) ? target.transactionMeta.update.key : `main`;
2254
+ const subscriptionKey = `tracker:${storeName}:${storeStatus}:${stateKey}`;
2255
+ const trackerCapturesOutboundSignal = (update) => {
2256
+ setIntoStore(target, latestSignalState, update);
2257
+ };
2242
2258
  const originalInnerValue = getFromStore(target, mutableState);
2243
- this.unsubscribeFromInnerValue = originalInnerValue.subscribe(subscriptionKey, (update) => {
2244
- setIntoStore(target, latestUpdateState, update);
2245
- });
2246
- this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, (update) => {
2259
+ this.unsubscribeFromInnerValue = originalInnerValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
2260
+ this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, function trackerLooksForNewReference(update) {
2247
2261
  if (update.newValue !== update.oldValue) {
2248
2262
  this.unsubscribeFromInnerValue();
2249
- this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, (transceiverUpdate) => {
2250
- setIntoStore(target, latestUpdateState, transceiverUpdate);
2251
- });
2263
+ this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
2252
2264
  }
2253
- });
2265
+ }.bind(this));
2254
2266
  }
2255
- updateCore(mutableState, latestUpdateState, target) {
2267
+ supplySignalsToCore(mutableState, latestSignalState, target) {
2256
2268
  const subscriptionKey = `tracker:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.key : `main`}:${mutableState.key}`;
2257
- subscribeToState(target, latestUpdateState, subscriptionKey, ({ newValue, oldValue }) => {
2258
- const timelineId = target.timelineTopics.getRelatedKey(latestUpdateState.key);
2259
- if (timelineId) {
2260
- const timelineData = target.timelines.get(timelineId);
2261
- if (timelineData?.timeTraveling) {
2262
- const unsubscribe$1 = subscribeToTimeline(target, {
2263
- key: timelineId,
2264
- type: `timeline`
2265
- }, subscriptionKey, (update) => {
2266
- unsubscribe$1();
2267
- setIntoStore(target, mutableState, (transceiver) => {
2268
- if (update === `redo` && newValue) transceiver.do(newValue);
2269
- else if (update === `undo` && oldValue) transceiver.undo(oldValue);
2270
- return transceiver;
2271
- });
2269
+ subscribeToState(target, latestSignalState, subscriptionKey, function trackerCapturesInboundSignal({ newValue, oldValue }) {
2270
+ const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
2271
+ if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
2272
+ const unsubscribe = subscribeToTimeline(target, {
2273
+ key: timelineId,
2274
+ type: `timeline`
2275
+ }, subscriptionKey, function trackerWaitsForTimeTravelToFinish(update) {
2276
+ unsubscribe();
2277
+ setIntoStore(target, mutableState, (transceiver) => {
2278
+ if (update === `redo` && newValue) transceiver.do(newValue);
2279
+ else if (update === `undo` && oldValue) transceiver.undo(oldValue);
2280
+ return transceiver;
2272
2281
  });
2273
- return;
2274
- }
2282
+ });
2283
+ return;
2284
+ }
2285
+ const mutable = getFromStore(target, mutableState);
2286
+ const updateNumber = mutable.getUpdateNumber(newValue);
2287
+ const eventOffset = updateNumber - mutable.cacheUpdateNumber;
2288
+ if (newValue && eventOffset === 1) setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
2289
+ else {
2290
+ const expected = mutable.cacheUpdateNumber + 1;
2291
+ target.logger.info(`❌`, `mutable_atom`, mutableState.key, `could not be updated. Expected update number`, expected, `but got`, updateNumber);
2275
2292
  }
2276
- const unsubscribe = target.on.operationClose.subscribe(subscriptionKey, () => {
2277
- unsubscribe();
2278
- const mutable = getFromStore(target, mutableState);
2279
- const updateNumber = newValue === null ? -1 : mutable.getUpdateNumber(newValue);
2280
- const eventOffset = updateNumber - mutable.cacheUpdateNumber;
2281
- if (newValue && eventOffset === 1) setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
2282
- else target.logger.info(`❌`, `mutable_atom`, mutableState.key, `could not be updated. Expected update number ${mutable.cacheUpdateNumber + 1}, but got ${updateNumber}`);
2283
- });
2284
2293
  });
2285
2294
  }
2286
- mutableState;
2287
- latestUpdateState;
2295
+ mutableAtomToken;
2296
+ latestSignalToken;
2288
2297
  [Symbol.dispose];
2289
- constructor(mutableState, store) {
2290
- this.mutableState = mutableState;
2298
+ constructor(mutableAtomToken, store) {
2291
2299
  const target = newest(store);
2292
- this.latestUpdateState = this.initializeState(mutableState, target);
2293
- this.observeCore(mutableState, this.latestUpdateState, target);
2294
- this.updateCore(mutableState, this.latestUpdateState, target);
2295
- target.trackers.set(mutableState.key, this);
2300
+ const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target);
2301
+ this.mutableAtomToken = mutableAtomToken;
2302
+ this.latestSignalToken = latestSignalToken;
2303
+ this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target);
2304
+ this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target);
2305
+ target.trackers.set(mutableAtomToken.key, this);
2296
2306
  this[Symbol.dispose] = () => {
2297
2307
  this.unsubscribeFromInnerValue();
2298
2308
  this.unsubscribeFromState();
2299
- target.trackers.delete(mutableState.key);
2309
+ target.trackers.delete(mutableAtomToken.key);
2300
2310
  };
2301
2311
  }
2302
2312
  };
@@ -2347,7 +2357,13 @@ function createMutableAtom(store, options, family) {
2347
2357
  };
2348
2358
  }
2349
2359
  new Tracker(token, store);
2350
- if (!family) selectJson(token, options, store);
2360
+ if (!family) createStandaloneSelector(store, {
2361
+ key: `${key}:JSON`,
2362
+ get: ({ get }) => get(token).toJSON(),
2363
+ set: ({ set }, newValue) => {
2364
+ set(token, options.class.fromJSON(newValue));
2365
+ }
2366
+ });
2351
2367
  store.on.atomCreation.next(token);
2352
2368
  return token;
2353
2369
  }
@@ -2356,16 +2372,16 @@ function createMutableAtom(store, options, family) {
2356
2372
  //#region src/internal/mutable/tracker-family.ts
2357
2373
  var FamilyTracker = class {
2358
2374
  trackers = /* @__PURE__ */ new Map();
2359
- latestUpdateAtoms;
2375
+ latestSignalAtoms;
2360
2376
  mutableAtoms;
2361
2377
  constructor(mutableAtoms, store) {
2362
- const updateAtoms = createRegularAtomFamily(store, {
2378
+ const latestSignalAtoms = createRegularAtomFamily(store, {
2363
2379
  key: `*${mutableAtoms.key}`,
2364
2380
  default: null
2365
2381
  }, [`mutable`, `updates`]);
2366
- this.latestUpdateAtoms = withdraw(store, updateAtoms);
2382
+ this.latestSignalAtoms = withdraw(store, latestSignalAtoms);
2367
2383
  this.mutableAtoms = mutableAtoms;
2368
- this.mutableAtoms.subject.subscribe(`store=${store.config.name}::tracker-atom-family`, (event) => {
2384
+ const trackerFamilyWatchesForCreationAndDisposalEvents = (event) => {
2369
2385
  const { type, token } = event;
2370
2386
  if (token.family) {
2371
2387
  const key = parseJson(token.family.subKey);
@@ -2373,18 +2389,17 @@ var FamilyTracker = class {
2373
2389
  case `state_creation`:
2374
2390
  this.trackers.set(key, new Tracker(token, store));
2375
2391
  break;
2376
- case `state_disposal`:
2377
- {
2378
- const tracker = this.trackers.get(key);
2379
- if (tracker) {
2380
- tracker[Symbol.dispose]();
2381
- this.trackers.delete(key);
2382
- }
2392
+ case `state_disposal`: {
2393
+ const tracker = this.trackers.get(key);
2394
+ if (tracker) {
2395
+ tracker[Symbol.dispose]();
2396
+ this.trackers.delete(key);
2383
2397
  }
2384
- break;
2398
+ }
2385
2399
  }
2386
2400
  }
2387
- });
2401
+ };
2402
+ this.mutableAtoms.subject.subscribe(`store=${store.config.name}::tracker-atom-family`, trackerFamilyWatchesForCreationAndDisposalEvents);
2388
2403
  }
2389
2404
  };
2390
2405
 
@@ -2408,9 +2423,7 @@ function createMutableAtomFamily(store, options, internalRoles) {
2408
2423
  const target = newest(store);
2409
2424
  const individualOptions = {
2410
2425
  key: fullKey,
2411
- default: () => options.default(key),
2412
- toJson: options.toJson,
2413
- fromJson: options.fromJson
2426
+ class: options.class
2414
2427
  };
2415
2428
  if (options.effects) individualOptions.effects = options.effects(key);
2416
2429
  const token = createMutableAtom(target, individualOptions, family);
@@ -2423,12 +2436,16 @@ function createMutableAtomFamily(store, options, internalRoles) {
2423
2436
  const atomFamily$1 = Object.assign(familyFunction, familyToken, {
2424
2437
  subject,
2425
2438
  install: (s) => createMutableAtomFamily(s, options),
2426
- toJson: options.toJson,
2427
- fromJson: options.fromJson,
2428
2439
  internalRoles
2429
2440
  });
2430
2441
  store.families.set(options.key, atomFamily$1);
2431
- selectJsonFamily(store, atomFamily$1, options);
2442
+ createWritablePureSelectorFamily(store, {
2443
+ key: `${options.key}:JSON`,
2444
+ get: (key) => ({ get }) => get(familyToken, key).toJSON(),
2445
+ set: (key) => ({ set }, newValue) => {
2446
+ set(familyToken, key, options.class.fromJSON(newValue));
2447
+ }
2448
+ }, [`mutable`, `json`]);
2432
2449
  new FamilyTracker(atomFamily$1, store);
2433
2450
  return familyToken;
2434
2451
  }
@@ -2665,7 +2682,7 @@ function withdraw(store, token) {
2665
2682
 
2666
2683
  //#endregion
2667
2684
  //#region src/internal/atom/create-regular-atom.ts
2668
- function createRegularAtom(store, options, family) {
2685
+ function createRegularAtom(store, options, family, internalRoles) {
2669
2686
  const type = `atom`;
2670
2687
  const { key } = options;
2671
2688
  store.logger.info(`🔨`, `atom`, key, `creating in store "${store.config.name}"`);
@@ -2686,6 +2703,7 @@ function createRegularAtom(store, options, family) {
2686
2703
  subject
2687
2704
  };
2688
2705
  if (family) newAtom.family = family;
2706
+ if (internalRoles) newAtom.internalRoles = internalRoles;
2689
2707
  target.atoms.set(key, newAtom);
2690
2708
  const token = deposit(newAtom);
2691
2709
  if (options.effects) {
@@ -2738,6 +2756,7 @@ function disposeAtom(store, atomToken) {
2738
2756
  target.valueMap.delete(key);
2739
2757
  target.selectorAtoms.delete(key);
2740
2758
  target.atomsThatAreDefault.delete(key);
2759
+ target.moleculeData.delete(family.key, family.subKey);
2741
2760
  store.timelineTopics.delete(key);
2742
2761
  if (atomToken.type === `mutable_atom`) {
2743
2762
  const updateToken = getUpdateToken(atomToken);
@@ -2833,9 +2852,7 @@ var Join = class {
2833
2852
  const bSide = options.between[1];
2834
2853
  const relatedKeysAtoms = createMutableAtomFamily(store, {
2835
2854
  key: `${options.key}/relatedKeys`,
2836
- default: () => new SetRTX(),
2837
- fromJson: (json) => SetRTX.fromJSON(json),
2838
- toJson: (set) => set.toJSON()
2855
+ class: SetRTX
2839
2856
  }, [`join`, `relations`]);
2840
2857
  this.core = { relatedKeysAtoms };
2841
2858
  const getRelatedKeys = ({ get }, key) => get(relatedKeysAtoms, key);
@@ -3530,5 +3547,5 @@ const timeTravel = (store, action, token) => {
3530
3547
  };
3531
3548
 
3532
3549
  //#endregion
3533
- export { CircularBuffer, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Join, Junction, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, capitalize, claimWithinStore, clearStore, closeOperation, counterfeit, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, evictCachedValue, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, installIntoStore, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw };
3550
+ export { CircularBuffer, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, INTERNAL_ROLES, Join, Junction, LazyMap, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, allocateIntoStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, capitalize, claimWithinStore, clearStore, closeOperation, counterfeit, createJoin, createMutableAtom, createMutableAtomFamily, createReadonlyHeldSelector, createReadonlyPureSelector, createReadonlyPureSelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneSelector, createTimeline, createTransaction, createWritableHeldSelector, createWritablePureSelector, createWritablePureSelectorFamily, deallocateFromStore, deposit, disposeAtom, disposeFromStore, disposeSelector, editRelationsInStore, evictCachedValue, findInStore, findRelationsInStore, fuseWithinStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getInternalRelationsFromStore, getJoin, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getTrace, getUpdateFamily, getUpdateToken, hasRole, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestMoleculeTransferEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, installIntoStore, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isReservedIntrospectionKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeRootMoleculeInStore, markDone, newest, openOperation, prettyPrintTokenType, readFromCache, readOrComputeValue, recallState, registerSelector, resetAtomOrSelector, resetInStore, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootDependency, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceRootSelectorAtoms, updateSelectorAtoms, withdraw, writeToCache };
3534
3551
  //# sourceMappingURL=index.js.map