atom.io 0.39.1 → 0.40.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 (88) hide show
  1. package/dist/internal/index.d.ts +68 -63
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +171 -161
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/introspection/index.d.ts +2 -2
  6. package/dist/introspection/index.d.ts.map +1 -1
  7. package/dist/introspection/index.js.map +1 -1
  8. package/dist/main/index.d.ts +19 -15
  9. package/dist/main/index.d.ts.map +1 -1
  10. package/dist/main/index.js +16 -13
  11. package/dist/main/index.js.map +1 -1
  12. package/dist/react/index.d.ts +3 -3
  13. package/dist/react/index.d.ts.map +1 -1
  14. package/dist/react/index.js.map +1 -1
  15. package/dist/react-devtools/index.js +9 -6
  16. package/dist/react-devtools/index.js.map +1 -1
  17. package/dist/realtime-client/index.d.ts +3 -3
  18. package/dist/realtime-client/index.d.ts.map +1 -1
  19. package/dist/realtime-client/index.js +3 -4
  20. package/dist/realtime-client/index.js.map +1 -1
  21. package/dist/realtime-server/index.d.ts +2 -2
  22. package/dist/realtime-server/index.d.ts.map +1 -1
  23. package/package.json +2 -2
  24. package/src/internal/atom/create-regular-atom.ts +3 -2
  25. package/src/internal/atom/dispose-atom.ts +6 -6
  26. package/src/internal/events/ingest-selector-update.ts +13 -4
  27. package/src/internal/families/create-readonly-held-selector-family.ts +3 -4
  28. package/src/internal/families/create-readonly-pure-selector-family.ts +4 -9
  29. package/src/internal/families/create-regular-atom-family.ts +3 -4
  30. package/src/internal/families/create-selector-family.ts +6 -6
  31. package/src/internal/families/create-writable-held-selector-family.ts +2 -2
  32. package/src/internal/families/create-writable-pure-selector-family.ts +3 -7
  33. package/src/internal/families/dispose-from-store.ts +9 -2
  34. package/src/internal/get-state/get-from-store.ts +10 -3
  35. package/src/internal/get-state/reduce-reference.ts +15 -2
  36. package/src/internal/index.ts +8 -8
  37. package/src/internal/install-into-store.ts +2 -1
  38. package/src/internal/join/create-join.ts +2 -2
  39. package/src/internal/join/find-relations-in-store.ts +2 -2
  40. package/src/internal/join/get-internal-relations-from-store.ts +2 -2
  41. package/src/internal/join/get-join.ts +5 -2
  42. package/src/internal/join/join-internal.ts +15 -20
  43. package/src/internal/lineage.ts +12 -1
  44. package/src/internal/molecule.ts +64 -36
  45. package/src/internal/mutable/create-mutable-atom-family.ts +4 -4
  46. package/src/internal/mutable/create-mutable-atom.ts +2 -2
  47. package/src/internal/mutable/tracker-family.ts +3 -3
  48. package/src/internal/operation.ts +3 -1
  49. package/src/internal/selector/create-readonly-held-selector.ts +2 -2
  50. package/src/internal/selector/create-readonly-pure-selector.ts +2 -2
  51. package/src/internal/selector/create-writable-held-selector.ts +2 -2
  52. package/src/internal/selector/create-writable-pure-selector.ts +2 -2
  53. package/src/internal/set-state/become.ts +1 -3
  54. package/src/internal/set-state/dispatch-state-update.ts +13 -11
  55. package/src/internal/set-state/reset-in-store.ts +11 -13
  56. package/src/internal/set-state/set-into-store.ts +27 -3
  57. package/src/internal/store/store.ts +14 -12
  58. package/src/internal/timeline/create-timeline.ts +136 -100
  59. package/src/internal/timeline/time-travel.ts +43 -31
  60. package/src/internal/transaction/abort-transaction.ts +3 -15
  61. package/src/internal/transaction/act-upon-store.ts +1 -5
  62. package/src/internal/transaction/apply-transaction.ts +5 -17
  63. package/src/internal/transaction/assign-transaction-to-continuity.ts +2 -7
  64. package/src/internal/transaction/build-transaction.ts +3 -4
  65. package/src/internal/transaction/create-transaction.ts +5 -6
  66. package/src/internal/transaction/get-epoch-number.ts +1 -7
  67. package/src/internal/transaction/set-epoch-number.ts +4 -12
  68. package/src/introspection/attach-introspection-states.ts +4 -2
  69. package/src/introspection/attach-timeline-family.ts +2 -2
  70. package/src/introspection/attach-transaction-logs.ts +2 -2
  71. package/src/introspection/attach-type-selectors.ts +2 -2
  72. package/src/main/dispose-state.ts +1 -5
  73. package/src/main/events.ts +8 -4
  74. package/src/main/get-state.ts +3 -6
  75. package/src/main/logger.ts +1 -1
  76. package/src/main/realm.ts +36 -12
  77. package/src/main/reset-state.ts +1 -5
  78. package/src/main/set-state.ts +4 -11
  79. package/src/main/silo.ts +4 -3
  80. package/src/main/timeline.ts +1 -7
  81. package/src/react/store-context.tsx +3 -3
  82. package/src/react-devtools/Button.tsx +3 -2
  83. package/src/react-devtools/TimelineIndex.tsx +0 -2
  84. package/src/react-devtools/Updates.tsx +14 -9
  85. package/src/react-devtools/store.ts +2 -2
  86. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +4 -8
  87. package/src/realtime-client/sync-continuity.ts +2 -2
  88. package/src/realtime-server/index.ts +2 -2
@@ -2,6 +2,7 @@ import type { AtomIOToken } from "atom.io"
2
2
 
3
3
  import { newest } from "./lineage"
4
4
  import { type Store, withdraw } from "./store"
5
+ import type { RootStore } from "./transaction"
5
6
  import { isChildStore } from "./transaction"
6
7
 
7
8
  /**
@@ -14,7 +15,7 @@ import { isChildStore } from "./transaction"
14
15
  */
15
16
  export function installIntoStore(
16
17
  tokens: AtomIOToken[],
17
- target: Store,
18
+ target: RootStore,
18
19
  source: Store,
19
20
  ): void {
20
21
  const sourceNewest = newest(source)
@@ -1,7 +1,7 @@
1
1
  import type { JoinOptions, JoinToken } from "atom.io"
2
2
  import type { Json } from "atom.io/json"
3
3
 
4
- import type { Store } from "../store"
4
+ import type { RootStore } from "../transaction"
5
5
  import { Join } from "./join-internal"
6
6
 
7
7
  export function createJoin<
@@ -12,7 +12,7 @@ export function createJoin<
12
12
  Cardinality extends `1:1` | `1:n` | `n:n`,
13
13
  Content extends Json.Object,
14
14
  >(
15
- store: Store,
15
+ store: RootStore,
16
16
  options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
17
17
  defaultContent: Content | undefined,
18
18
  ): JoinToken<ASide, AType, BSide, BType, Cardinality, Content> {
@@ -3,7 +3,7 @@ import type { Json } from "atom.io/json"
3
3
 
4
4
  import { capitalize } from "../capitalize"
5
5
  import { findInStore } from "../families"
6
- import type { Store } from "../store"
6
+ import type { RootStore } from "../transaction"
7
7
  import { getJoin } from "./get-join"
8
8
 
9
9
  export function findRelationsInStore<
@@ -16,7 +16,7 @@ export function findRelationsInStore<
16
16
  >(
17
17
  token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
18
18
  key: AType | BType,
19
- store: Store,
19
+ store: RootStore,
20
20
  ): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
21
21
  const myJoin = getJoin(token, store)
22
22
  let relations: JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
@@ -1,12 +1,12 @@
1
1
  import type { JoinToken, MutableAtomFamilyToken } from "atom.io"
2
2
  import type { SetRTX } from "atom.io/transceivers/set-rtx"
3
3
 
4
- import type { Store } from "../store"
4
+ import type { RootStore } from "../transaction"
5
5
  import { getJoin } from "./get-join"
6
6
 
7
7
  export function getInternalRelationsFromStore(
8
8
  token: JoinToken<any, any, any, any, any, any>,
9
- store: Store,
9
+ store: RootStore,
10
10
  ): MutableAtomFamilyToken<SetRTX<string>, string> {
11
11
  const myJoin = getJoin(token, store)
12
12
  const family = myJoin.core.relatedKeysAtoms
@@ -1,7 +1,9 @@
1
1
  import type { JoinToken } from "atom.io"
2
2
  import type { Json } from "atom.io/json"
3
3
 
4
- import { IMPLICIT, type Store } from "../store"
4
+ import { eldest } from "../lineage"
5
+ import type { Store } from "../store"
6
+ import { IMPLICIT } from "../store"
5
7
  import { Join } from "./join-internal"
6
8
 
7
9
  export function getJoin<
@@ -24,7 +26,8 @@ export function getJoin<
24
26
  `Join "${token.key}" not found in store "${store.config.name}"`,
25
27
  )
26
28
  }
27
- myJoin = new Join(rootJoin.options, rootJoin.defaultContent, store)
29
+ const root = eldest(store)
30
+ myJoin = new Join(rootJoin.options, rootJoin.defaultContent, root)
28
31
  store.joins.set(token.key, myJoin)
29
32
  }
30
33
  return myJoin
@@ -13,7 +13,7 @@ import type {
13
13
  WriterToolkit,
14
14
  } from "atom.io"
15
15
  import { Anarchy } from "atom.io"
16
- import type { Canonical, Json, stringified } from "atom.io/json"
16
+ import type { Json } from "atom.io/json"
17
17
  import { stringifyJson } from "atom.io/json"
18
18
  import { SetRTX } from "atom.io/transceivers/set-rtx"
19
19
 
@@ -29,11 +29,11 @@ import type {
29
29
  ExternalStoreConfiguration,
30
30
  } from "../junction"
31
31
  import { Junction } from "../junction"
32
- import type { Molecule } from "../molecule"
33
32
  import { createMutableAtomFamily, getJsonFamily, getJsonToken } from "../mutable"
34
33
  import { setIntoStore } from "../set-state"
35
34
  import type { Store } from "../store"
36
35
  import { IMPLICIT } from "../store"
36
+ import type { RootStore } from "../transaction"
37
37
 
38
38
  export type JoinStateFamilies<
39
39
  ASide extends string,
@@ -132,7 +132,6 @@ export class Join<
132
132
  private toolkit: WriterToolkit
133
133
  public options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>
134
134
  public defaultContent: Content | undefined
135
- public molecules: Map<string, Molecule<any>> = new Map()
136
135
  public relations: Junction<ASide, AType, BSide, BType, Content>
137
136
  public states: JoinStateFamilies<
138
137
  ASide,
@@ -163,7 +162,7 @@ export class Join<
163
162
  public constructor(
164
163
  options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
165
164
  defaultContent: Content | undefined,
166
- store: Store = IMPLICIT.STORE,
165
+ store: RootStore = IMPLICIT.STORE,
167
166
  ) {
168
167
  type AnyKey = AType & BType
169
168
 
@@ -225,6 +224,9 @@ export class Join<
225
224
  bKeys.delete(a)
226
225
  return bKeys
227
226
  })
227
+ const [x, y] = [a, b].sort()
228
+ const compositeKey = `${x}:${y}`
229
+ this.store.moleculeJoins.delete(compositeKey)
228
230
  }
229
231
  const replaceRelationsSafely: Write<
230
232
  (a: string, newRelationsOfA: string[]) => void
@@ -267,9 +269,9 @@ export class Join<
267
269
  relationsOfB.clear()
268
270
  }
269
271
  for (const previousOwner of previousOwnersToDispose) {
270
- const sorted = [newRelationB, previousOwner].sort()
271
- const compositeKey = `"${sorted[0]}:${sorted[1]}"`
272
- this.molecules.delete(compositeKey)
272
+ const [x, y] = [newRelationB, previousOwner].sort()
273
+ const compositeKey = `${x}:${y}`
274
+ store.moleculeJoins.delete(compositeKey)
273
275
  }
274
276
  }
275
277
  if (!newRelationBIsAlreadyRelated) {
@@ -310,14 +312,8 @@ export class Join<
310
312
  const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
311
313
  getRelatedKeys: (key) => getRelatedKeys(this.toolkit, key),
312
314
  addRelation: (a, b) => {
313
- this.store.moleculeJoins.set(
314
- a as stringified<Canonical> /* 💥 RECONCILE */,
315
- options.key,
316
- )
317
- this.store.moleculeJoins.set(
318
- b as stringified<Canonical> /* 💥 RECONCILE */,
319
- options.key,
320
- )
315
+ this.store.moleculeJoins.set(`"${a}"`, options.key)
316
+ this.store.moleculeJoins.set(`"${b}"`, options.key)
321
317
  addRelation(this.toolkit, a, b)
322
318
  },
323
319
  deleteRelation: (a, b) => {
@@ -364,9 +360,7 @@ export class Join<
364
360
  setContent: (contentKey: ContentKey, content: Content) => {
365
361
  setContent(this.toolkit, contentKey, content)
366
362
  },
367
- deleteContent: (contentKey: ContentKey) => {
368
- this.realm.deallocate(contentKey)
369
- },
363
+ deleteContent: (_: ContentKey) => {},
370
364
  }
371
365
  externalStore = Object.assign(
372
366
  baseExternalStoreConfiguration,
@@ -384,8 +378,8 @@ export class Join<
384
378
  isBType: options.isBType,
385
379
  makeContentKey: (...args) => {
386
380
  const [a, b] = args
387
- const sorted = args.sort()
388
- const compositeKey = `${sorted[0]}:${sorted[1]}`
381
+ const [x, y] = args.sort()
382
+ const compositeKey = `${x}:${y}`
389
383
  const aMolecule = store.molecules.get(stringifyJson(a))
390
384
  const bMolecule = store.molecules.get(stringifyJson(b))
391
385
  if (!aMolecule) {
@@ -394,6 +388,7 @@ export class Join<
394
388
  if (!bMolecule) {
395
389
  this.realm.allocate(options.key, b)
396
390
  }
391
+
397
392
  this.realm.allocate(a, compositeKey, `all`)
398
393
  this.realm.claim(b, compositeKey)
399
394
  this.store.moleculeJoins.set(compositeKey, options.key)
@@ -4,9 +4,20 @@ export interface Lineage {
4
4
  child: typeof this | null
5
5
  }
6
6
 
7
- export function newest<T extends Lineage>(scion: T): T {
7
+ export function newest<T extends Lineage>(
8
+ scion: T,
9
+ ): Exclude<T[`child`], null> | T {
8
10
  while (scion.child !== null) {
9
11
  scion = scion.child
10
12
  }
11
13
  return scion
12
14
  }
15
+
16
+ export function eldest<T extends Lineage>(
17
+ scion: T,
18
+ ): Exclude<T[`parent`], T[`child`] | null> {
19
+ while (scion.parent !== null) {
20
+ scion = scion.parent
21
+ }
22
+ return scion as Exclude<T[`parent`], T[`child`] | null>
23
+ }
@@ -8,18 +8,20 @@ import type {
8
8
  MoleculeDisposalEvent,
9
9
  MoleculeTransferEvent,
10
10
  SingularTypedKey,
11
+ TransactionToken,
11
12
  Vassal,
12
13
  } from "atom.io"
13
14
  import type { Canonical, stringified } from "atom.io/json"
14
15
  import { parseJson, stringifyJson } from "atom.io/json"
15
16
 
16
- import { disposeFromStore, findInStore } from "./families"
17
+ import { disposeFromStore } from "./families"
17
18
  import { getFromStore } from "./get-state"
18
19
  import { getTrace } from "./get-trace"
19
20
  import { newest } from "./lineage"
20
21
  import type { Store } from "./store"
21
22
  import { IMPLICIT } from "./store"
22
- import { isChildStore } from "./transaction"
23
+ import type { RootStore } from "./transaction"
24
+ import { createTransaction, isChildStore } from "./transaction"
23
25
 
24
26
  export type Molecule<K extends Canonical> = {
25
27
  readonly key: K
@@ -135,23 +137,35 @@ export function fuseWithinStore<
135
137
  return compoundKey
136
138
  }
137
139
 
140
+ export function createDeallocateTX<
141
+ H extends Hierarchy,
142
+ V extends Exclude<Vassal<H>, CompoundTypedKey>,
143
+ >(store: RootStore): TransactionToken<(claim: Claim<V>) => void> {
144
+ return createTransaction(store, {
145
+ key: `[Internal] deallocate`,
146
+ do: (_, claim: Claim<V>): void => {
147
+ deallocateFromStore<H, V>(newest(store), claim)
148
+ },
149
+ })
150
+ }
151
+
138
152
  export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
139
- store: Store,
153
+ target: Store,
140
154
  claim: Claim<V>,
141
155
  ): void {
142
156
  const stringKey = stringifyJson(claim)
143
157
 
144
- const molecule = store.molecules.get(stringKey)
158
+ const molecule = target.molecules.get(stringKey)
145
159
  if (!molecule) {
146
- const disposal = store.disposalTraces.buffer.find(
160
+ const disposal = target.disposalTraces.buffer.find(
147
161
  (item) => item?.key === stringKey,
148
162
  )
149
- store.logger.error(
163
+ target.logger.error(
150
164
  `❌`,
151
165
  `key`,
152
166
  claim,
153
167
  `deallocation failed:`,
154
- `Could not find allocation for ${stringKey} in store "${store.config.name}".`,
168
+ `Could not find allocation for ${stringKey} in store "${target.config.name}".`,
155
169
  disposal
156
170
  ? `\n This state was most recently deallocated\n${disposal.trace}`
157
171
  : `No previous disposal trace for ${stringKey} was found.`,
@@ -159,45 +173,29 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
159
173
  return
160
174
  }
161
175
 
162
- const joinKeys = store.moleculeJoins.getRelatedKeys(
163
- molecule.key as string /* 💥 RECONCILE */,
164
- )
176
+ const joinKeys = target.moleculeJoins.getRelatedKeys(stringKey)
165
177
  if (joinKeys) {
166
178
  for (const joinKey of joinKeys) {
167
- const join = store.joins.get(joinKey)
179
+ const join = target.joins.get(joinKey)
168
180
  if (join) {
169
- join.relations.delete(molecule.key)
170
- join.molecules.delete(molecule.stringKey) // get rid of
181
+ join.relations.delete(claim)
171
182
  }
172
183
  }
173
184
  }
174
- store.moleculeJoins.delete(molecule.stringKey)
185
+ target.moleculeJoins.delete(stringKey)
175
186
 
176
187
  const provenance: stringified<Canonical>[] = []
177
188
 
178
189
  const values: [string, any][] = []
179
- const disposalEvent: MoleculeDisposalEvent = {
180
- type: `molecule_disposal`,
181
- key: molecule.key,
182
- values,
183
- provenance,
184
- timestamp: Date.now(),
185
- }
186
- const target = newest(store)
187
- target.molecules.delete(stringKey)
188
- const isTransaction =
189
- isChildStore(target) && target.transactionMeta.phase === `building`
190
- if (isTransaction) {
191
- target.transactionMeta.update.subEvents.push(disposalEvent)
192
- }
193
- const relatedMolecules = store.moleculeGraph.getRelationEntries({
194
- downstreamMoleculeKey: molecule.stringKey,
190
+
191
+ const relatedMolecules = target.moleculeGraph.getRelationEntries({
192
+ downstreamMoleculeKey: stringKey,
195
193
  })
196
194
  if (relatedMolecules) {
197
195
  for (const [relatedStringKey, { source }] of relatedMolecules) {
198
- if (source === molecule.stringKey) {
196
+ if (source === stringKey) {
199
197
  const relatedKey = parseJson(relatedStringKey)
200
- deallocateFromStore<any, any>(store, relatedKey)
198
+ deallocateFromStore<any, any>(target, relatedKey)
201
199
  } else {
202
200
  provenance.push(source)
203
201
  }
@@ -208,12 +206,24 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
208
206
  for (const familyKey of familyKeys) {
209
207
  // biome-ignore lint/style/noNonNullAssertion: tokens of molecules must have a family
210
208
  const family = target.families.get(familyKey)!
211
- const token = findInStore(store, family, molecule.key)
212
- const value = getFromStore(store, token)
209
+ const value = getFromStore(target, family, claim)
213
210
  values.push([family.key, value])
214
- disposeFromStore(store, token)
211
+ disposeFromStore(target, family, claim)
215
212
  }
216
213
  }
214
+ const disposalEvent: MoleculeDisposalEvent = {
215
+ type: `molecule_disposal`,
216
+ key: molecule.key,
217
+ values,
218
+ provenance,
219
+ timestamp: Date.now(),
220
+ }
221
+ target.molecules.delete(stringKey)
222
+ const isTransaction =
223
+ isChildStore(target) && target.transactionMeta.phase === `building`
224
+ if (isTransaction) {
225
+ target.transactionMeta.update.subEvents.push(disposalEvent)
226
+ }
217
227
 
218
228
  target.moleculeGraph.delete(molecule.stringKey)
219
229
  target.moleculeJoins.delete(molecule.stringKey)
@@ -225,8 +235,26 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
225
235
  target.molecules.delete(molecule.stringKey)
226
236
 
227
237
  const trace = getTrace(new Error())
228
- store.disposalTraces.add({ key: stringKey, trace })
238
+ target.disposalTraces.add({ key: stringKey, trace })
239
+ }
240
+
241
+ export function createClaimTX<
242
+ H extends Hierarchy,
243
+ V extends Exclude<Vassal<H>, CompoundTypedKey>,
244
+ A extends Above<V, H>,
245
+ >(
246
+ store: RootStore,
247
+ ): TransactionToken<
248
+ (newProvenance: A, claim: Claim<V>, exclusive?: `exclusive`) => void
249
+ > {
250
+ return createTransaction(store, {
251
+ key: `[Internal] claim`,
252
+ do: (_, newProvenance, claim, exclusive) => {
253
+ claimWithinStore<H, V, A>(store, newProvenance, claim, exclusive)
254
+ },
255
+ })
229
256
  }
257
+
230
258
  export function claimWithinStore<
231
259
  H extends Hierarchy,
232
260
  V extends Exclude<Vassal<H>, CompoundTypedKey>,
@@ -10,10 +10,10 @@ import { PRETTY_TOKEN_TYPES } from "atom.io"
10
10
  import type { Canonical } from "atom.io/json"
11
11
  import { stringifyJson } from "atom.io/json"
12
12
 
13
- import { createWritablePureSelectorFamily, type MutableAtomFamily } from ".."
13
+ import type { MutableAtomFamily, RootStore } from ".."
14
+ import { createWritablePureSelectorFamily } from ".."
14
15
  import { newest } from "../lineage"
15
16
  import { createMutableAtom } from "../mutable"
16
- import type { Store } from "../store"
17
17
  import { Subject } from "../subject"
18
18
  import { FamilyTracker } from "./tracker-family"
19
19
  import type { AsJSON, Transceiver } from "./transceiver"
@@ -22,7 +22,7 @@ export function createMutableAtomFamily<
22
22
  T extends Transceiver<any, any, any>,
23
23
  K extends Canonical,
24
24
  >(
25
- store: Store,
25
+ store: RootStore,
26
26
  options: MutableAtomFamilyOptions<T, K>,
27
27
  internalRoles?: string[],
28
28
  ): MutableAtomFamilyToken<T, K> {
@@ -67,7 +67,7 @@ export function createMutableAtomFamily<
67
67
  const atomFamily = Object.assign(familyFunction, familyToken, {
68
68
  class: options.class,
69
69
  subject,
70
- install: (s: Store) => createMutableAtomFamily(s, options),
70
+ install: (s: RootStore) => createMutableAtomFamily(s, options),
71
71
  internalRoles,
72
72
  }) satisfies MutableAtomFamily<T, K>
73
73
 
@@ -5,7 +5,7 @@ import type {
5
5
  UpdateHandler,
6
6
  } from "atom.io"
7
7
 
8
- import type { MutableAtom } from ".."
8
+ import type { MutableAtom, RootStore } from ".."
9
9
  import { createStandaloneSelector, resetInStore, setIntoStore } from ".."
10
10
  import { newest } from "../lineage"
11
11
  import { deposit, type Store } from "../store"
@@ -45,7 +45,7 @@ export function createMutableAtom<T extends Transceiver<any, any, any>>(
45
45
  const newAtom: MutableAtom<T> = {
46
46
  ...options,
47
47
  type,
48
- install: (s: Store) => {
48
+ install: (s: RootStore) => {
49
49
  s.logger.info(`🛠️`, `atom`, key, `installing in store "${s.config.name}"`)
50
50
  return createMutableAtom(s, options, family)
51
51
  },
@@ -2,9 +2,9 @@ import type { MutableAtomToken, StateLifecycleEvent } from "atom.io"
2
2
  import type { Canonical } from "atom.io/json"
3
3
  import { parseJson } from "atom.io/json"
4
4
 
5
- import type { MutableAtomFamily, RegularAtomFamily } from ".."
5
+ import type { MutableAtomFamily, RegularAtomFamily, RootStore } from ".."
6
6
  import { createRegularAtomFamily } from "../families"
7
- import { type Store, withdraw } from "../store"
7
+ import { withdraw } from "../store"
8
8
  import { Tracker } from "./tracker"
9
9
  import type { SignalFrom, Transceiver } from "./transceiver"
10
10
 
@@ -17,7 +17,7 @@ export class FamilyTracker<
17
17
  public readonly latestSignalAtoms: RegularAtomFamily<SignalFrom<T> | null, K>
18
18
  public readonly mutableAtoms: MutableAtomFamily<T, K>
19
19
 
20
- public constructor(mutableAtoms: MutableAtomFamily<T, K>, store: Store) {
20
+ public constructor(mutableAtoms: MutableAtomFamily<T, K>, store: RootStore) {
21
21
  const latestSignalAtoms = createRegularAtomFamily<SignalFrom<T> | null, K>(
22
22
  store,
23
23
  {
@@ -1,4 +1,4 @@
1
- import type { ReadableToken } from "atom.io"
1
+ import type { AtomUpdateEvent, ReadableToken, StateCreationEvent } from "atom.io"
2
2
 
3
3
  import type { Store } from "./store"
4
4
  import { isChildStore } from "./transaction/is-root-store"
@@ -14,6 +14,7 @@ export type OpenOperation<R extends ReadableToken<any> = ReadableToken<any>> = {
14
14
  done: Set<string>
15
15
  prev: Map<string, any>
16
16
  timestamp: number
17
+ subEvents: (AtomUpdateEvent<any> | StateCreationEvent<any>)[]
17
18
  }
18
19
 
19
20
  export function openOperation(
@@ -36,6 +37,7 @@ export function openOperation(
36
37
  prev: new Map(),
37
38
  timestamp: Date.now(),
38
39
  token,
40
+ subEvents: [],
39
41
  }
40
42
  store.logger.info(
41
43
  `⭕`,
@@ -4,7 +4,7 @@ import type {
4
4
  ReadonlyHeldSelectorToken,
5
5
  } from "atom.io"
6
6
 
7
- import type { ReadonlyHeldSelector } from ".."
7
+ import type { ReadonlyHeldSelector, RootStore } from ".."
8
8
  import { writeToCache } from "../caching"
9
9
  import { newest } from "../lineage"
10
10
  import type { Store } from "../store"
@@ -47,7 +47,7 @@ export function createReadonlyHeldSelector<T extends object>(
47
47
  type,
48
48
  subject,
49
49
  getFrom,
50
- install: (s: Store) => createReadonlyHeldSelector(s, options, family),
50
+ install: (s: RootStore) => createReadonlyHeldSelector(s, options, family),
51
51
  }
52
52
  if (family) readonlySelector.family = family
53
53
 
@@ -4,7 +4,7 @@ import type {
4
4
  ReadonlyPureSelectorToken,
5
5
  } from "atom.io"
6
6
 
7
- import type { ReadonlyPureSelector } from ".."
7
+ import type { ReadonlyPureSelector, RootStore } from ".."
8
8
  import { writeToCache } from "../caching"
9
9
  import { newest } from "../lineage"
10
10
  import type { Store } from "../store"
@@ -48,7 +48,7 @@ export function createReadonlyPureSelector<T>(
48
48
  type,
49
49
  subject,
50
50
  getFrom,
51
- install: (s: Store) => createReadonlyPureSelector(s, options, family),
51
+ install: (s: RootStore) => createReadonlyPureSelector(s, options, family),
52
52
  }
53
53
  if (family) readonlySelector.family = family
54
54
 
@@ -4,7 +4,7 @@ import type {
4
4
  WritableHeldSelectorToken,
5
5
  } from "atom.io"
6
6
 
7
- import type { WritableHeldSelector } from ".."
7
+ import type { RootStore, WritableHeldSelector } from ".."
8
8
  import { writeToCache } from "../caching"
9
9
  import { newest } from "../lineage"
10
10
  import type { Store } from "../store"
@@ -54,7 +54,7 @@ export function createWritableHeldSelector<T extends object>(
54
54
  subject,
55
55
  getFrom,
56
56
  setSelf,
57
- install: (s: Store) => createWritableHeldSelector(s, options, family),
57
+ install: (s: RootStore) => createWritableHeldSelector(s, options, family),
58
58
  }
59
59
  if (family) mySelector.family = family
60
60
 
@@ -4,7 +4,7 @@ import type {
4
4
  WritablePureSelectorToken,
5
5
  } from "atom.io"
6
6
 
7
- import type { WritablePureSelector } from ".."
7
+ import type { RootStore, WritablePureSelector } from ".."
8
8
  import { writeToCache } from "../caching"
9
9
  import { newest } from "../lineage"
10
10
  import type { Store } from "../store"
@@ -54,7 +54,7 @@ export function createWritablePureSelector<T>(
54
54
  subject,
55
55
  getFrom,
56
56
  setSelf,
57
- install: (s: Store) => createWritablePureSelector(s, options, family),
57
+ install: (s: RootStore) => createWritablePureSelector(s, options, family),
58
58
  }
59
59
  if (family) mySelector.family = family
60
60
 
@@ -1,9 +1,7 @@
1
1
  import { isFn } from "../is-fn"
2
2
 
3
- export type Modify<T> = (thing: T) => T
4
-
5
3
  export function become<T>(
6
- nextVersionOfThing: Modify<T> | T,
4
+ nextVersionOfThing: T | ((prev: T) => T),
7
5
  originalThing: T,
8
6
  ): T {
9
7
  if (isFn(nextVersionOfThing)) {
@@ -1,12 +1,12 @@
1
- import type { AtomUpdateEvent, StateCreationEvent, StateUpdate } from "atom.io"
1
+ import type {
2
+ AtomUpdateEvent,
3
+ StateCreationEvent,
4
+ StateUpdate,
5
+ TimelineEvent,
6
+ } from "atom.io"
2
7
 
3
- import {
4
- type MutableAtom,
5
- newest,
6
- type Subject,
7
- type WritableFamily,
8
- type WritableState,
9
- } from ".."
8
+ import type { MutableAtom, Subject, WritableFamily, WritableState } from ".."
9
+ import { newest } from ".."
10
10
  import { hasRole } from "../atom"
11
11
  import { readOrComputeValue } from "../get-state"
12
12
  import type { Transceiver } from "../mutable"
@@ -27,13 +27,15 @@ export function dispatchOrDeferStateUpdate<T>(
27
27
  const token = deposit(state)
28
28
  if (stateIsNewlyCreated && family) {
29
29
  state.subject.next({ newValue })
30
- const stateCreationEvent: StateCreationEvent<any> = {
30
+ const stateCreationEvent: StateCreationEvent<any> & TimelineEvent<any> = {
31
+ checkpoint: true,
31
32
  type: `state_creation`,
32
33
  subType: `writable`,
33
34
  token,
34
35
  timestamp: Date.now(),
35
36
  value: newValue,
36
37
  }
38
+ target.operation.subEvents.push(stateCreationEvent)
37
39
  const familySubject = family.subject as Subject<StateCreationEvent<any>>
38
40
  familySubject.next(stateCreationEvent)
39
41
  const innerTarget = newest(target)
@@ -75,7 +77,7 @@ export function dispatchOrDeferStateUpdate<T>(
75
77
  `is now (`,
76
78
  newValue,
77
79
  `) subscribers:`,
78
- subject.subscribers,
80
+ subject.subscribers.keys(),
79
81
  )
80
82
  break
81
83
  case `atom`:
@@ -90,7 +92,7 @@ export function dispatchOrDeferStateUpdate<T>(
90
92
  `->`,
91
93
  newValue,
92
94
  `) subscribers:`,
93
- subject.subscribers,
95
+ subject.subscribers.keys(),
94
96
  )
95
97
  }
96
98
  subject.next(update)
@@ -14,21 +14,19 @@ export function resetInStore<K extends Canonical>(
14
14
  key: K,
15
15
  ): void
16
16
 
17
- export function resetInStore<T>(
17
+ export function resetInStore<T, K extends Canonical, Key extends K>(
18
18
  store: Store,
19
19
  ...params:
20
- | [token: WritableFamilyToken<T, Canonical>, key: Canonical]
20
+ | [token: WritableFamilyToken<T, K>, key: Key]
21
+ | [token: WritableToken<T>]
22
+ ): void
23
+
24
+ export function resetInStore<T, K extends Canonical, Key extends K>(
25
+ store: Store,
26
+ ...params:
27
+ | [token: WritableFamilyToken<T, K>, key: Key]
21
28
  | [token: WritableToken<T>]
22
29
  ): void {
23
- let token: WritableToken<T>
24
- let family: WritableFamilyToken<T, Canonical> | null
25
- let key: Canonical | null
26
- if (params.length === 1) {
27
- token = params[0]
28
- setIntoStore(store, token, RESET_STATE)
29
- } else {
30
- family = params[0]
31
- key = params[1]
32
- setIntoStore(store, family, key, RESET_STATE)
33
- }
30
+ const subParams = [...params, RESET_STATE] as const
31
+ setIntoStore(store, ...subParams)
34
32
  }