atom.io 0.27.4 → 0.28.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 (134) hide show
  1. package/data/dist/index.d.ts +31 -29
  2. package/data/dist/index.js +65 -81
  3. package/data/src/dict.ts +9 -12
  4. package/data/src/join.ts +30 -33
  5. package/data/src/struct-family.ts +17 -23
  6. package/data/src/struct.ts +9 -12
  7. package/dist/{chunk-JRENM6KL.js → chunk-BX3MTH2Z.js} +482 -385
  8. package/dist/chunk-D52JNVER.js +721 -0
  9. package/dist/chunk-EUVKUTW3.js +89 -0
  10. package/dist/index.d.ts +4 -3
  11. package/dist/index.js +35 -53
  12. package/ephemeral/dist/index.js +1 -1
  13. package/ephemeral/src/find-state.ts +1 -1
  14. package/immortal/dist/index.js +2 -2
  15. package/immortal/src/seek-state.ts +2 -2
  16. package/internal/dist/index.d.ts +141 -87
  17. package/internal/dist/index.js +1 -1
  18. package/internal/src/atom/create-regular-atom.ts +3 -3
  19. package/internal/src/atom/create-standalone-atom.ts +7 -5
  20. package/internal/src/atom/dispose-atom.ts +2 -9
  21. package/internal/src/families/create-atom-family.ts +5 -5
  22. package/internal/src/families/create-readonly-selector-family.ts +20 -9
  23. package/internal/src/families/create-regular-atom-family.ts +15 -6
  24. package/internal/src/families/create-selector-family.ts +5 -5
  25. package/internal/src/families/create-writable-selector-family.ts +20 -10
  26. package/internal/src/families/dispose-from-store.ts +43 -29
  27. package/internal/src/families/find-in-store.ts +28 -18
  28. package/internal/src/families/init-family-member.ts +9 -9
  29. package/internal/src/families/seek-in-store.ts +10 -10
  30. package/internal/src/get-state/get-from-store.ts +70 -47
  31. package/internal/src/ingest-updates/ingest-atom-update.ts +1 -1
  32. package/internal/src/ingest-updates/ingest-creation-disposal.ts +15 -6
  33. package/internal/src/molecule/create-molecule-family.ts +1 -1
  34. package/internal/src/molecule/dispose-molecule.ts +7 -18
  35. package/internal/src/molecule/grow-molecule-in-store.ts +1 -1
  36. package/internal/src/molecule/make-molecule-in-store.ts +5 -5
  37. package/internal/src/mutable/create-mutable-atom-family.ts +15 -6
  38. package/internal/src/mutable/create-mutable-atom.ts +3 -3
  39. package/internal/src/mutable/get-json-token.ts +2 -2
  40. package/internal/src/mutable/tracker-family.ts +3 -3
  41. package/internal/src/mutable/tracker.ts +14 -18
  42. package/internal/src/pretty-print.ts +1 -16
  43. package/internal/src/selector/create-readonly-selector.ts +2 -2
  44. package/internal/src/selector/create-standalone-selector.ts +5 -5
  45. package/internal/src/selector/create-writable-selector.ts +2 -2
  46. package/internal/src/selector/dispose-selector.ts +2 -9
  47. package/internal/src/selector/register-selector.ts +9 -9
  48. package/internal/src/set-state/set-into-store.ts +23 -33
  49. package/internal/src/store/circular-buffer.ts +34 -0
  50. package/internal/src/store/counterfeit.ts +109 -0
  51. package/internal/src/store/deposit.ts +67 -13
  52. package/internal/src/store/index.ts +1 -0
  53. package/internal/src/store/store.ts +4 -1
  54. package/internal/src/store/withdraw.ts +15 -10
  55. package/internal/src/subscribe/index.ts +2 -0
  56. package/internal/src/subscribe/subscribe-in-store.ts +62 -0
  57. package/internal/src/timeline/time-travel.ts +1 -1
  58. package/internal/src/transaction/build-transaction.ts +7 -6
  59. package/introspection/dist/index.d.ts +84 -4
  60. package/introspection/dist/index.js +1 -413
  61. package/introspection/src/attach-atom-index.ts +5 -8
  62. package/introspection/src/attach-introspection-states.ts +7 -4
  63. package/introspection/src/attach-selector-index.ts +6 -8
  64. package/introspection/src/attach-timeline-family.ts +25 -28
  65. package/introspection/src/attach-timeline-index.ts +5 -8
  66. package/introspection/src/attach-transaction-index.ts +5 -8
  67. package/introspection/src/attach-transaction-logs.ts +21 -27
  68. package/introspection/src/attach-type-selectors.ts +26 -0
  69. package/introspection/src/differ.ts +167 -0
  70. package/introspection/src/index.ts +2 -0
  71. package/introspection/src/refinery.ts +100 -0
  72. package/json/dist/index.d.ts +31 -30
  73. package/json/dist/index.js +2 -80
  74. package/json/src/entries.ts +6 -0
  75. package/json/src/index.ts +47 -6
  76. package/json/src/select-json-family.ts +4 -4
  77. package/json/src/select-json.ts +6 -9
  78. package/package.json +17 -8
  79. package/react/dist/index.js +7 -7
  80. package/react/src/parse-state-overloads.ts +2 -2
  81. package/react/src/use-i.ts +1 -1
  82. package/react/src/use-json.ts +2 -2
  83. package/react/src/use-o.ts +2 -2
  84. package/react-devtools/dist/index.d.ts +1 -91
  85. package/react-devtools/dist/index.js +285 -414
  86. package/react-devtools/src/AtomIODevtools.tsx +2 -2
  87. package/react-devtools/src/StateEditor.tsx +20 -12
  88. package/react-devtools/src/StateIndex.tsx +8 -26
  89. package/react-devtools/src/TimelineIndex.tsx +3 -3
  90. package/react-devtools/src/TransactionIndex.tsx +6 -6
  91. package/react-devtools/src/Updates.tsx +1 -4
  92. package/react-devtools/src/index.ts +0 -71
  93. package/react-devtools/src/store.ts +51 -0
  94. package/realtime/dist/index.d.ts +7 -7
  95. package/realtime/dist/index.js +18 -22
  96. package/realtime/src/realtime-continuity.ts +27 -35
  97. package/realtime-client/dist/index.js +59 -65
  98. package/realtime-client/src/pull-atom-family-member.ts +1 -1
  99. package/realtime-client/src/pull-atom.ts +1 -1
  100. package/realtime-client/src/pull-mutable-atom-family-member.ts +3 -3
  101. package/realtime-client/src/pull-mutable-atom.ts +3 -3
  102. package/realtime-client/src/realtime-client-stores/client-main-store.ts +6 -6
  103. package/realtime-client/src/sync-continuity.ts +55 -53
  104. package/realtime-react/dist/index.js +3 -3
  105. package/realtime-react/src/use-pull-atom-family-member.ts +1 -1
  106. package/realtime-react/src/use-pull-mutable-family-member.ts +1 -1
  107. package/realtime-react/src/use-pull-selector-family-member.ts +1 -1
  108. package/realtime-server/dist/index.js +72 -36
  109. package/realtime-server/src/realtime-continuity-synchronizer.ts +57 -93
  110. package/realtime-server/src/realtime-family-provider.ts +3 -3
  111. package/realtime-server/src/realtime-mutable-family-provider.ts +5 -5
  112. package/realtime-server/src/realtime-mutable-provider.ts +2 -2
  113. package/realtime-server/src/realtime-state-provider.ts +1 -1
  114. package/realtime-server/src/realtime-state-receiver.ts +1 -1
  115. package/realtime-testing/dist/index.d.ts +2 -0
  116. package/realtime-testing/dist/index.js +57 -15
  117. package/realtime-testing/src/setup-realtime-test.tsx +66 -16
  118. package/src/atom.ts +2 -2
  119. package/src/dispose-state.ts +2 -2
  120. package/src/get-state.ts +9 -13
  121. package/src/molecule.ts +1 -1
  122. package/src/selector.ts +2 -2
  123. package/src/set-state.ts +10 -7
  124. package/src/silo.ts +29 -55
  125. package/src/subscribe.ts +3 -23
  126. package/src/timeline.ts +2 -2
  127. package/web/dist/index.d.ts +9 -0
  128. package/{dist/chunk-H6EDLPKH.js → web/dist/index.js} +5 -4
  129. package/web/package.json +13 -0
  130. package/web/src/index.ts +1 -0
  131. package/web/src/persist-sync.ts +25 -0
  132. package/dist/chunk-AK23DRMD.js +0 -21
  133. package/dist/chunk-IW6WYRS7.js +0 -140
  134. package/internal/src/families/throw-in-case-of-conflicting-family.ts +0 -18
@@ -14,5 +14,5 @@ export function ingestAtomUpdate(
14
14
  if (atomUpdate.family) {
15
15
  Object.assign(token, { family: atomUpdate.family })
16
16
  }
17
- setIntoStore(token, value, store)
17
+ setIntoStore(store, token, value)
18
18
  }
@@ -22,7 +22,7 @@ export function ingestCreationEvent(
22
22
  break
23
23
  }
24
24
  case `oldValue`: {
25
- disposeFromStore(update.token, store)
25
+ disposeFromStore(store, update.token)
26
26
  break
27
27
  }
28
28
  }
@@ -35,7 +35,7 @@ export function ingestDisposalEvent(
35
35
  ): void {
36
36
  switch (applying) {
37
37
  case `newValue`: {
38
- disposeFromStore(update.token, store)
38
+ disposeFromStore(store, update.token)
39
39
  break
40
40
  }
41
41
  case `oldValue`: {
@@ -56,9 +56,18 @@ function createInStore(token: ReadableToken<any>, store: Store): void {
56
56
  return
57
57
  }
58
58
  if (store.config.lifespan === `immortal`) {
59
- throw new Error(`No molecule found for key "${token.family.subKey}"`)
59
+ store.logger.error(
60
+ `🐞`,
61
+ `atom`,
62
+ token.family.key,
63
+ `tried to create member`,
64
+ `"${token.family.subKey}"`,
65
+ `but a molecule with that key was not found in store`,
66
+ `"${store.config.name}"`,
67
+ )
68
+ return
60
69
  }
61
- initFamilyMemberInStore(family, parseJson(token.family.subKey), store)
70
+ initFamilyMemberInStore(store, family, parseJson(token.family.subKey))
62
71
  }
63
72
  }
64
73
  }
@@ -79,7 +88,7 @@ export function ingestMoleculeCreationEvent(
79
88
  )
80
89
  break
81
90
  case `oldValue`:
82
- disposeFromStore(update.token, store)
91
+ disposeFromStore(store, update.token)
83
92
  break
84
93
  }
85
94
  }
@@ -90,7 +99,7 @@ export function ingestMoleculeDisposalEvent(
90
99
  ): void {
91
100
  switch (applying) {
92
101
  case `newValue`:
93
- disposeFromStore(update.token, store)
102
+ disposeFromStore(store, update.token)
94
103
  break
95
104
  case `oldValue`:
96
105
  {
@@ -10,8 +10,8 @@ import type { Store } from "../store"
10
10
  import { Subject } from "../subject"
11
11
 
12
12
  export function createMoleculeFamily<M extends MoleculeConstructor>(
13
- options: MoleculeFamilyOptions<M>,
14
13
  store: Store,
14
+ options: MoleculeFamilyOptions<M>,
15
15
  ): MoleculeFamilyToken<M> {
16
16
  const subject = new Subject<MoleculeCreation<M>>()
17
17
 
@@ -15,22 +15,14 @@ export function disposeMolecule<M extends MoleculeConstructor>(
15
15
  store: Store,
16
16
  ): void {
17
17
  let molecule: Molecule<M>
18
- try {
19
- molecule = withdraw(token, store)
20
- } catch (thrown) {
21
- if (thrown instanceof Error) {
22
- store.logger.error(
23
- `🐞`,
24
- `molecule`,
25
- JSON.stringify(token.key),
26
- `Failed to dispose molecule, because it was not found in the store.`,
27
- thrown.message,
28
- )
29
- }
30
- return
31
- }
18
+ molecule = withdraw(token, store)
32
19
  const { family } = token
33
20
 
21
+ for (const join of molecule.joins.values()) {
22
+ join.relations.delete(molecule.key)
23
+ join.molecules.delete(molecule.stringKey)
24
+ }
25
+
34
26
  const context: MoleculeToken<any>[] = []
35
27
  for (const above of molecule.above.values()) {
36
28
  context.push(deposit(above))
@@ -55,7 +47,7 @@ export function disposeMolecule<M extends MoleculeConstructor>(
55
47
  disposalEvent.family = token.family
56
48
  }
57
49
  for (const state of molecule.tokens.values()) {
58
- disposeFromStore(state, store)
50
+ disposeFromStore(store, state)
59
51
  }
60
52
  for (const child of molecule.below.values()) {
61
53
  if (child.family?.dependsOn === `all`) {
@@ -79,9 +71,6 @@ export function disposeMolecule<M extends MoleculeConstructor>(
79
71
  store.molecules.delete(molecule.stringKey)
80
72
  }
81
73
 
82
- for (const join of molecule.joins.values()) {
83
- join.molecules.delete(molecule.stringKey)
84
- }
85
74
  for (const parent of molecule.above.values()) {
86
75
  parent.below.delete(molecule.stringKey)
87
76
  }
@@ -83,7 +83,7 @@ export function growMoleculeInStore(
83
83
  family: ReadableFamilyToken<any, any>,
84
84
  store: Store,
85
85
  ): ReadableToken<any> {
86
- const stateToken = initFamilyMemberInStore(family, molecule.key, store)
86
+ const stateToken = initFamilyMemberInStore(store, family, molecule.key)
87
87
  molecule.tokens.set(stateToken.key, stateToken)
88
88
  const isTransaction =
89
89
  isChildStore(store) && store.transactionMeta.phase === `building`
@@ -68,17 +68,17 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
68
68
 
69
69
  const toolkit = {
70
70
  get: ((...ps: Parameters<typeof getState>) =>
71
- getFromStore(...ps, newest(rootStore))) as typeof getState,
71
+ getFromStore(newest(rootStore), ...ps)) as typeof getState,
72
72
  set: ((...ps: Parameters<typeof setState>) => {
73
- setIntoStore(...ps, newest(rootStore))
73
+ setIntoStore(newest(rootStore), ...ps)
74
74
  }) as typeof setState,
75
- seek: ((t, k) => seekInStore(t, k, newest(rootStore))) as typeof seekState,
76
- json: (t) => getJsonToken(t, newest(rootStore)),
75
+ seek: ((t, k) => seekInStore(newest(rootStore), t, k)) as typeof seekState,
76
+ json: (t) => getJsonToken(newest(rootStore), t),
77
77
  run: (t, i = arbitrary()) => actUponStore(t, i, newest(store)),
78
78
  make: (ctx, f, k, ...args) =>
79
79
  makeMoleculeInStore(newest(rootStore), ctx, f, k, ...args),
80
80
  dispose: (t) => {
81
- disposeFromStore(t, newest(rootStore))
81
+ disposeFromStore(newest(rootStore), t)
82
82
  },
83
83
  env: () => getEnvironmentData(newest(rootStore)),
84
84
  bond: ((
@@ -10,8 +10,7 @@ import type {
10
10
  import type { Json } from "atom.io/json"
11
11
  import { selectJsonFamily, stringifyJson } from "atom.io/json"
12
12
 
13
- import type { MutableAtomFamily } from ".."
14
- import { throwInCaseOfConflictingFamily } from "../families/throw-in-case-of-conflicting-family"
13
+ import { type MutableAtomFamily, prettyPrintTokenType } from ".."
15
14
  import { newest } from "../lineage"
16
15
  import { createMutableAtom } from "../mutable"
17
16
  import type { Store } from "../store"
@@ -24,8 +23,8 @@ export function createMutableAtomFamily<
24
23
  J extends Json.Serializable,
25
24
  K extends string,
26
25
  >(
27
- options: MutableAtomFamilyOptions<T, J, K>,
28
26
  store: Store,
27
+ options: MutableAtomFamilyOptions<T, J, K>,
29
28
  internalRoles?: string[],
30
29
  ): MutableAtomFamilyToken<T, J, K> {
31
30
  const familyToken = {
@@ -33,7 +32,17 @@ export function createMutableAtomFamily<
33
32
  type: `mutable_atom_family`,
34
33
  } as const satisfies MutableAtomFamilyToken<T, J, K>
35
34
 
36
- throwInCaseOfConflictingFamily(familyToken, store)
35
+ const existing = store.families.get(options.key)
36
+ if (existing) {
37
+ store.logger.error(
38
+ `❗`,
39
+ `mutable_atom_family`,
40
+ options.key,
41
+ `Overwriting an existing ${prettyPrintTokenType(
42
+ existing,
43
+ )} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`,
44
+ )
45
+ }
37
46
 
38
47
  const subject = new Subject<
39
48
  StateCreation<MutableAtomToken<T, J>> | StateDisposal<MutableAtomToken<T, J>>
@@ -56,7 +65,7 @@ export function createMutableAtomFamily<
56
65
  individualOptions.effects = options.effects(key)
57
66
  }
58
67
 
59
- const token = createMutableAtom(individualOptions, family, target)
68
+ const token = createMutableAtom(target, individualOptions, family)
60
69
 
61
70
  subject.next({ type: `state_creation`, token })
62
71
  return token
@@ -64,7 +73,7 @@ export function createMutableAtomFamily<
64
73
 
65
74
  const atomFamily = Object.assign(familyFunction, familyToken, {
66
75
  subject,
67
- install: (s: Store) => createMutableAtomFamily(options, s),
76
+ install: (s: Store) => createMutableAtomFamily(s, options),
68
77
  toJson: options.toJson,
69
78
  fromJson: options.fromJson,
70
79
  internalRoles,
@@ -20,9 +20,9 @@ export function createMutableAtom<
20
20
  T extends Transceiver<any>,
21
21
  J extends Json.Serializable,
22
22
  >(
23
+ store: Store,
23
24
  options: MutableAtomOptions<T, J>,
24
25
  family: FamilyMetadata | undefined,
25
- store: Store,
26
26
  ): MutableAtomToken<T, J> {
27
27
  store.logger.info(
28
28
  `🔨`,
@@ -52,7 +52,7 @@ export function createMutableAtom<
52
52
  options.key,
53
53
  `installing in store "${s.config.name}"`,
54
54
  )
55
- return createMutableAtom(options, family, s)
55
+ return createMutableAtom(s, options, family)
56
56
  },
57
57
  subject,
58
58
  } as const
@@ -70,7 +70,7 @@ export function createMutableAtom<
70
70
  for (const effect of options.effects) {
71
71
  const cleanup = effect({
72
72
  setSelf: (next) => {
73
- setIntoStore(token, next, store)
73
+ setIntoStore(store, token, next)
74
74
  },
75
75
  onSet: (handle: UpdateHandler<T>) =>
76
76
  subscribeToState(token, handle, `effect[${effectIndex}]`, store),
@@ -14,8 +14,8 @@ export const getJsonToken = <
14
14
  Core extends Transceiver<any>,
15
15
  SerializableCore extends Json.Serializable,
16
16
  >(
17
- mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
18
17
  store: Store,
18
+ mutableAtomToken: MutableAtomToken<Core, SerializableCore>,
19
19
  ): WritableSelectorToken<SerializableCore> => {
20
20
  if (mutableAtomToken.family) {
21
21
  const target = newest(store)
@@ -29,7 +29,7 @@ export const getJsonToken = <
29
29
  }
30
30
  const family = withdraw(jsonFamilyToken, target)
31
31
  const subKey = JSON.parse(mutableAtomToken.family.subKey)
32
- const jsonToken = findInStore(family, subKey, store)
32
+ const jsonToken = findInStore(store, family, subKey)
33
33
  return jsonToken
34
34
  }
35
35
  const token: WritableSelectorToken<SerializableCore> = {
@@ -29,11 +29,11 @@ export class FamilyTracker<
29
29
  typeof this.Update | null,
30
30
  FamilyMemberKey
31
31
  >(
32
+ store,
32
33
  {
33
34
  key: `*${mutableAtoms.key}`,
34
35
  default: null,
35
36
  },
36
- store,
37
37
  [`mutable`, `updates`],
38
38
  )
39
39
  this.latestUpdateAtoms = withdraw(updateAtoms, store)
@@ -43,7 +43,7 @@ export class FamilyTracker<
43
43
  (event) => {
44
44
  if (event.token.family) {
45
45
  const key = parseJson(event.token.family.subKey) as FamilyMemberKey
46
- seekInStore(this.latestUpdateAtoms, key, store)
46
+ seekInStore(store, this.latestUpdateAtoms, key)
47
47
  new Tracker<Core>(event.token, store)
48
48
  }
49
49
  },
@@ -53,7 +53,7 @@ export class FamilyTracker<
53
53
  (event) => {
54
54
  if (event.token.family) {
55
55
  const key = parseJson(event.token.family.subKey) as FamilyMemberKey
56
- const mutableAtomToken = seekInStore(this.mutableAtoms, key, store)
56
+ const mutableAtomToken = seekInStore(store, this.mutableAtoms, key)
57
57
  if (mutableAtomToken) {
58
58
  new Tracker<Core>(mutableAtomToken, store)
59
59
  }
@@ -37,12 +37,12 @@ export class Tracker<Mutable extends Transceiver<any>> {
37
37
  const latestUpdateState = createRegularAtom<
38
38
  (Mutable extends Transceiver<infer Signal> ? Signal : never) | null
39
39
  >(
40
+ store,
40
41
  {
41
42
  key: latestUpdateStateKey,
42
43
  default: null,
43
44
  },
44
45
  familyMetaData,
45
- store,
46
46
  )
47
47
  if (store.parent?.valueMap.has(latestUpdateStateKey)) {
48
48
  const parentValue = store.parent.valueMap.get(latestUpdateStateKey)
@@ -62,11 +62,11 @@ export class Tracker<Mutable extends Transceiver<any>> {
62
62
  const subscriptionKey = `tracker:${target.config.name}:${
63
63
  isChildStore(target) ? target.transactionMeta.update.key : `main`
64
64
  }:${mutableState.key}`
65
- const originalInnerValue = getFromStore(mutableState, target)
65
+ const originalInnerValue = getFromStore(target, mutableState)
66
66
  this.unsubscribeFromInnerValue = originalInnerValue.subscribe(
67
67
  subscriptionKey,
68
68
  (update) => {
69
- setIntoStore(latestUpdateState, update, target)
69
+ setIntoStore(target, latestUpdateState, update)
70
70
  },
71
71
  )
72
72
  this.unsubscribeFromState = subscribeToState(
@@ -77,7 +77,7 @@ export class Tracker<Mutable extends Transceiver<any>> {
77
77
  this.unsubscribeFromInnerValue = update.newValue.subscribe(
78
78
  subscriptionKey,
79
79
  (transceiverUpdate) => {
80
- setIntoStore(latestUpdateState, transceiverUpdate, target)
80
+ setIntoStore(target, latestUpdateState, transceiverUpdate)
81
81
  },
82
82
  )
83
83
  }
@@ -109,18 +109,14 @@ export class Tracker<Mutable extends Transceiver<any>> {
109
109
  { key: timelineId, type: `timeline` },
110
110
  (update) => {
111
111
  unsubscribe()
112
- setIntoStore(
113
- mutableState,
114
- (transceiver) => {
115
- if (update === `redo` && newValue) {
116
- transceiver.do(newValue)
117
- } else if (update === `undo` && oldValue) {
118
- transceiver.undo(oldValue)
119
- }
120
- return transceiver
121
- },
122
- target,
123
- )
112
+ setIntoStore(target, mutableState, (transceiver) => {
113
+ if (update === `redo` && newValue) {
114
+ transceiver.do(newValue)
115
+ } else if (update === `undo` && oldValue) {
116
+ transceiver.undo(oldValue)
117
+ }
118
+ return transceiver
119
+ })
124
120
  },
125
121
  subscriptionKey,
126
122
  target,
@@ -133,15 +129,15 @@ export class Tracker<Mutable extends Transceiver<any>> {
133
129
  subscriptionKey,
134
130
  () => {
135
131
  unsubscribe()
136
- const mutable = getFromStore(mutableState, target)
132
+ const mutable = getFromStore(target, mutableState)
137
133
  const updateNumber =
138
134
  newValue === null ? -1 : mutable.getUpdateNumber(newValue)
139
135
  const eventOffset = updateNumber - mutable.cacheUpdateNumber
140
136
  if (newValue && eventOffset === 1) {
141
137
  setIntoStore(
138
+ target,
142
139
  mutableState,
143
140
  (transceiver) => (transceiver.do(newValue), transceiver),
144
- target,
145
141
  )
146
142
  } else {
147
143
  target.logger.info(
@@ -18,20 +18,5 @@ export type AtomIOToken =
18
18
  | TransactionToken<any>
19
19
 
20
20
  export function prettyPrintTokenType(token: AtomIOToken): string {
21
- switch (token.type) {
22
- case `atom_family`:
23
- return `Atom Family`
24
- case `molecule_family`:
25
- return `Molecule Family`
26
- case `mutable_atom_family`:
27
- return `Mutable Atom Family`
28
- case `readonly_selector`:
29
- return `Readonly Selector`
30
- case `readonly_selector_family`:
31
- return `Readonly Selector Family`
32
- case `selector_family`:
33
- return `Selector Family`
34
- default:
35
- return capitalize(token.type)
36
- }
21
+ return token.type.split(`_`).map(capitalize).join(` `)
37
22
  }
@@ -12,9 +12,9 @@ import { Subject } from "../subject"
12
12
  import { registerSelector } from "./register-selector"
13
13
 
14
14
  export const createReadonlySelector = <T>(
15
+ store: Store,
15
16
  options: ReadonlySelectorOptions<T>,
16
17
  family: FamilyMetadata | undefined,
17
- store: Store,
18
18
  ): ReadonlySelectorToken<T> => {
19
19
  const target = newest(store)
20
20
  const subject = new Subject<{ newValue: T; oldValue: T }>()
@@ -34,7 +34,7 @@ export const createReadonlySelector = <T>(
34
34
  const readonlySelector: ReadonlySelector<T> = {
35
35
  ...options,
36
36
  subject,
37
- install: (s: Store) => createReadonlySelector(options, family, s),
37
+ install: (s: Store) => createReadonlySelector(s, options, family),
38
38
  get: getSelf,
39
39
  type: `readonly_selector`,
40
40
  ...(family && { family }),
@@ -10,25 +10,25 @@ import { createReadonlySelector } from "./create-readonly-selector"
10
10
  import { createWritableSelector } from "./create-writable-selector"
11
11
 
12
12
  export function createStandaloneSelector<T>(
13
- options: WritableSelectorOptions<T>,
14
13
  store: Store,
14
+ options: WritableSelectorOptions<T>,
15
15
  ): WritableSelectorToken<T>
16
16
  export function createStandaloneSelector<T>(
17
- options: ReadonlySelectorOptions<T>,
18
17
  store: Store,
18
+ options: ReadonlySelectorOptions<T>,
19
19
  ): ReadonlySelectorToken<T>
20
20
  export function createStandaloneSelector<T>(
21
- options: ReadonlySelectorOptions<T> | WritableSelectorOptions<T>,
22
21
  store: Store,
22
+ options: ReadonlySelectorOptions<T> | WritableSelectorOptions<T>,
23
23
  ): ReadonlySelectorToken<T> | WritableSelectorToken<T> {
24
24
  const isWritable = `set` in options
25
25
 
26
26
  if (isWritable) {
27
- const state = createWritableSelector(options, undefined, store)
27
+ const state = createWritableSelector(store, options, undefined)
28
28
  store.on.selectorCreation.next(state)
29
29
  return state
30
30
  }
31
- const state = createReadonlySelector(options, undefined, store)
31
+ const state = createReadonlySelector(store, options, undefined)
32
32
  store.on.selectorCreation.next(state)
33
33
  return state
34
34
  }
@@ -15,9 +15,9 @@ import { isRootStore } from "../transaction"
15
15
  import { registerSelector } from "./register-selector"
16
16
 
17
17
  export const createWritableSelector = <T>(
18
+ store: Store,
18
19
  options: WritableSelectorOptions<T>,
19
20
  family: FamilyMetadata | undefined,
20
- store: Store,
21
21
  ): WritableSelectorToken<T> => {
22
22
  const target = newest(store)
23
23
  const subject = new Subject<{ newValue: T; oldValue: T }>()
@@ -57,7 +57,7 @@ export const createWritableSelector = <T>(
57
57
  const mySelector: WritableSelector<T> = {
58
58
  ...options,
59
59
  subject,
60
- install: (s: Store) => createWritableSelector(options, family, s),
60
+ install: (s: Store) => createWritableSelector(s, options, family),
61
61
  get: getSelf,
62
62
  set: setSelf,
63
63
  type: `selector`,
@@ -9,15 +9,8 @@ export function disposeSelector(
9
9
  ): void {
10
10
  const target = newest(store)
11
11
  const { key } = selectorToken
12
- const selector = target.selectors.get(key) ?? target.readonlySelectors.get(key)
13
- if (!selector) {
14
- store.logger.info(
15
- `❌`,
16
- `selector`,
17
- key,
18
- `Tried to dispose selector, but it does not exist in the store.`,
19
- )
20
- } else if (!selector.family) {
12
+ const selector = withdraw(selectorToken, target)
13
+ if (!selector.family) {
21
14
  store.logger.error(
22
15
  `❌`,
23
16
  `selector`,
@@ -43,12 +43,12 @@ export const registerSelector = (
43
43
  const [family, key] = params
44
44
  switch (family.type) {
45
45
  case `molecule_family`:
46
- return getFromStore(family, key, store)
46
+ return getFromStore(store, family, key)
47
47
  default:
48
48
  if (store.config.lifespan === `ephemeral`) {
49
- dependency = findInStore(family, key, store)
49
+ dependency = findInStore(store, family, key)
50
50
  } else {
51
- const maybeDependency = seekInStore(family, key, store)
51
+ const maybeDependency = seekInStore(store, family, key)
52
52
  if (maybeDependency) {
53
53
  dependency = maybeDependency
54
54
  } else {
@@ -61,7 +61,7 @@ export const registerSelector = (
61
61
  }
62
62
 
63
63
  if (dependency.type === `molecule`) {
64
- return getFromStore(dependency, store)
64
+ return getFromStore(store, dependency)
65
65
  }
66
66
 
67
67
  const dependencyState = withdraw(dependency, store)
@@ -108,8 +108,8 @@ export const registerSelector = (
108
108
  value = params[2]
109
109
  const maybeToken =
110
110
  store.config.lifespan === `ephemeral`
111
- ? findInStore(family, key, store)
112
- : seekInStore(family, key, store)
111
+ ? findInStore(store, family, key)
112
+ : seekInStore(store, family, key)
113
113
  if (!maybeToken) {
114
114
  throw new NotFoundError(family, key, store)
115
115
  }
@@ -119,7 +119,7 @@ export const registerSelector = (
119
119
  const state = withdraw(token, target)
120
120
  setAtomOrSelector(state, value, target)
121
121
  }) as typeof setState,
122
- find: ((token, key) => findInStore(token, key, store)) as typeof findState,
123
- seek: ((token, key) => seekInStore(token, key, store)) as typeof seekState,
124
- json: (token) => getJsonToken(token, store),
122
+ find: ((token, key) => findInStore(store, token, key)) as typeof findState,
123
+ seek: ((token, key) => seekInStore(store, token, key)) as typeof seekState,
124
+ json: (token) => getJsonToken(store, token),
125
125
  })
@@ -1,72 +1,62 @@
1
1
  import type { WritableFamilyToken, WritableToken } from "atom.io"
2
2
  import { type Canonical, stringifyJson } from "atom.io/json"
3
3
 
4
- import { findInStore, seekInStore } from "../families"
5
- import { NotFoundError } from "../not-found-error"
4
+ import { findInStore } from "../families"
6
5
  import { closeOperation, openOperation } from "../operation"
7
6
  import type { Store } from "../store"
8
7
  import { withdraw } from "../store"
9
8
  import { setAtomOrSelector } from "./set-atom-or-selector"
10
9
 
11
10
  export function setIntoStore<T, New extends T>(
11
+ store: Store,
12
12
  token: WritableToken<T>,
13
13
  value: New | ((oldValue: T) => New),
14
- store: Store,
15
14
  ): void
16
15
 
17
16
  export function setIntoStore<T, K extends Canonical, New extends T>(
17
+ store: Store,
18
18
  token: WritableFamilyToken<T, K>,
19
19
  key: K,
20
20
  value: New | ((oldValue: T) => New),
21
- store: Store,
22
21
  ): void
23
22
 
24
23
  export function setIntoStore<T, New extends T>(
24
+ store: Store,
25
25
  ...params:
26
26
  | [
27
27
  token: WritableFamilyToken<T, Canonical>,
28
28
  key: Canonical,
29
29
  value: New | ((oldValue: T) => New),
30
- store: Store,
31
- ]
32
- | [
33
- token: WritableToken<T>,
34
- value: New | ((oldValue: T) => New),
35
- store: Store,
36
30
  ]
31
+ | [token: WritableToken<T>, value: New | ((oldValue: T) => New)]
37
32
  ): void {
38
33
  let token: WritableToken<T>
39
34
  let value: New | ((oldValue: T) => New)
40
- let store: Store
41
- if (params.length === 3) {
35
+ if (params.length === 2) {
42
36
  token = params[0]
43
37
  value = params[1]
44
- store = params[2]
45
38
  } else {
46
39
  const family = params[0]
47
40
  const key = params[1]
48
41
  value = params[2]
49
- store = params[3]
50
- const maybeToken =
51
- store.config.lifespan === `ephemeral`
52
- ? findInStore(family, key, store)
53
- : seekInStore(family, key, store)
54
- if (!maybeToken) {
55
- store.logger.error(
56
- `❗`,
57
- family.type,
58
- family.key,
59
- `tried to set member`,
60
- stringifyJson(key),
61
- `to`,
62
- value,
63
- `but it was not found in store`,
64
- store.config.name,
65
- )
66
- return
67
- }
42
+ const maybeToken = findInStore(store, family, key)
68
43
  token = maybeToken
69
44
  }
45
+ if (`counterfeit` in token) {
46
+ const disposal = store.disposalTraces.buffer.find(
47
+ (item) => item?.key === token.key,
48
+ )
49
+ store.logger.error(
50
+ `❌`,
51
+ token.type,
52
+ token.key,
53
+ `could not be set because it was not found in the store "${store.config.name}".`,
54
+ disposal
55
+ ? `This state was previously disposed:\n${disposal.trace}`
56
+ : `No previous disposal trace was found.`,
57
+ )
58
+ return
59
+ }
70
60
 
71
61
  const rejectionTime = openOperation(token, store)
72
62
  if (rejectionTime) {
@@ -80,7 +70,7 @@ export function setIntoStore<T, New extends T>(
80
70
  token.key,
81
71
  `resuming deferred setState from T-${rejectionTime}`,
82
72
  )
83
- setIntoStore(token, value, store)
73
+ setIntoStore(store, token, value)
84
74
  },
85
75
  )
86
76
  return
@@ -0,0 +1,34 @@
1
+ export class CircularBuffer<T> {
2
+ protected _buffer: T[]
3
+ protected _index = 0
4
+ public constructor(array: T[])
5
+ public constructor(length: number)
6
+ public constructor(lengthOrArray: T[] | number) {
7
+ let length: number
8
+ if (typeof lengthOrArray === `number`) {
9
+ length = lengthOrArray
10
+ } else {
11
+ length = lengthOrArray.length
12
+ }
13
+ this._buffer = Array.from({ length })
14
+ }
15
+
16
+ public get buffer(): ReadonlyArray<T | undefined> {
17
+ return this._buffer
18
+ }
19
+
20
+ public get index(): number {
21
+ return this._index
22
+ }
23
+
24
+ public add(item: T): void {
25
+ this._buffer[this._index] = item
26
+ this._index = (this._index + 1) % this._buffer.length
27
+ }
28
+
29
+ public copy(): CircularBuffer<T> {
30
+ const copy = new CircularBuffer<T>([...this._buffer])
31
+ copy._index = this._index
32
+ return copy
33
+ }
34
+ }