atom.io 0.41.1 → 0.42.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 (59) hide show
  1. package/dist/internal/index.d.ts +30 -47
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +116 -287
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/main/index.d.ts +52 -56
  6. package/dist/main/index.d.ts.map +1 -1
  7. package/dist/main/index.js +45 -8
  8. package/dist/main/index.js.map +1 -1
  9. package/dist/realtime/index.d.ts +2 -3
  10. package/dist/realtime/index.d.ts.map +1 -1
  11. package/dist/realtime/index.js +1 -1
  12. package/dist/realtime/index.js.map +1 -1
  13. package/dist/realtime-server/index.js +1 -1
  14. package/dist/realtime-server/index.js.map +1 -1
  15. package/dist/realtime-testing/index.js +1 -1
  16. package/dist/struct/index.d.ts +14 -0
  17. package/dist/struct/index.d.ts.map +1 -0
  18. package/dist/struct/index.js +35 -0
  19. package/dist/struct/index.js.map +1 -0
  20. package/dist/transceivers/o-list/index.d.ts +8 -4
  21. package/dist/transceivers/o-list/index.d.ts.map +1 -1
  22. package/dist/transceivers/o-list/index.js +2 -1
  23. package/dist/transceivers/o-list/index.js.map +1 -1
  24. package/dist/transceivers/set-rtx/index.d.ts +1 -0
  25. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  26. package/dist/transceivers/set-rtx/index.js.map +1 -1
  27. package/dist/transceivers/u-list/index.d.ts +12 -4
  28. package/dist/transceivers/u-list/index.d.ts.map +1 -1
  29. package/dist/transceivers/u-list/index.js +34 -2
  30. package/dist/transceivers/u-list/index.js.map +1 -1
  31. package/dist/utility-types-aZkJVERa.d.ts +10 -0
  32. package/dist/utility-types-aZkJVERa.d.ts.map +1 -0
  33. package/package.json +20 -16
  34. package/src/internal/atom/create-regular-atom.ts +3 -1
  35. package/src/internal/index.ts +0 -1
  36. package/src/internal/join/create-join.ts +8 -11
  37. package/src/internal/join/edit-relations-in-store.ts +6 -8
  38. package/src/internal/join/find-relations-in-store.ts +11 -67
  39. package/src/internal/join/get-internal-relations-from-store.ts +11 -5
  40. package/src/internal/join/get-join.ts +7 -9
  41. package/src/internal/join/join-internal.ts +143 -412
  42. package/src/internal/molecule.ts +44 -25
  43. package/src/internal/mutable/create-mutable-atom.ts +15 -11
  44. package/src/internal/mutable/transceiver.ts +1 -5
  45. package/src/internal/set-state/dispatch-state-update.ts +1 -1
  46. package/src/internal/store/store.ts +16 -15
  47. package/src/internal/transaction/build-transaction.ts +1 -1
  48. package/src/main/atom.ts +15 -6
  49. package/src/main/join.ts +68 -151
  50. package/src/main/realm.ts +58 -17
  51. package/src/realtime/shared-room-store.ts +5 -15
  52. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +1 -1
  53. package/src/struct/index.ts +1 -0
  54. package/src/{internal → struct}/micro.ts +1 -1
  55. package/src/transceivers/o-list/o-list.ts +13 -9
  56. package/src/transceivers/set-rtx/set-rtx.ts +4 -0
  57. package/src/transceivers/u-list/index.ts +1 -0
  58. package/src/transceivers/u-list/u-list-disposed-key-cleanup-effect.ts +47 -0
  59. package/src/transceivers/u-list/u-list.ts +13 -9
@@ -1,15 +1,17 @@
1
- import type {
2
- Above,
3
- Claim,
4
- CompoundFrom,
5
- CompoundTypedKey,
6
- Hierarchy,
7
- MoleculeCreationEvent,
8
- MoleculeDisposalEvent,
9
- MoleculeTransferEvent,
10
- SingularTypedKey,
11
- TransactionToken,
12
- Vassal,
1
+ import {
2
+ type Above,
3
+ type CompoundFrom,
4
+ type CompoundTypedKey,
5
+ decomposeCompound,
6
+ type Hierarchy,
7
+ type MoleculeCreationEvent,
8
+ type MoleculeDisposalEvent,
9
+ type MoleculeTransferEvent,
10
+ simpleCompound,
11
+ type SingularTypedKey,
12
+ type TransactionToken,
13
+ type ValidKey,
14
+ type Vassal,
13
15
  } from "atom.io"
14
16
  import type { Canonical, stringified } from "atom.io/json"
15
17
  import { parseJson, stringifyJson } from "atom.io/json"
@@ -19,6 +21,7 @@ import { getFromStore } from "./get-state"
19
21
  import { getTrace } from "./get-trace"
20
22
  import { newest } from "./lineage"
21
23
  import type { Store } from "./store"
24
+ import { Subject } from "./subject"
22
25
  import type { RootStore } from "./transaction"
23
26
  import { createTransaction, isChildStore } from "./transaction"
24
27
 
@@ -26,6 +29,7 @@ export type Molecule<K extends Canonical> = {
26
29
  readonly key: K
27
30
  readonly stringKey: stringified<K>
28
31
  readonly dependsOn: `all` | `any`
32
+ readonly subject: Subject<void>
29
33
  }
30
34
 
31
35
  export function makeRootMoleculeInStore<S extends string>(
@@ -36,6 +40,7 @@ export function makeRootMoleculeInStore<S extends string>(
36
40
  key,
37
41
  stringKey: stringifyJson(key),
38
42
  dependsOn: `any`,
43
+ subject: new Subject(),
39
44
  } satisfies Molecule<S>
40
45
  store.molecules.set(stringifyJson(key), molecule)
41
46
  return key
@@ -50,7 +55,7 @@ export function allocateIntoStore<
50
55
  provenance: A,
51
56
  key: V,
52
57
  dependsOn: `all` | `any` = `any`,
53
- ): Claim<V> {
58
+ ): ValidKey<V> {
54
59
  const origin = provenance as Canonical | [Canonical, Canonical]
55
60
  const stringKey = stringifyJson(key)
56
61
  const invalidKeys: stringified<Canonical>[] = []
@@ -75,8 +80,9 @@ export function allocateIntoStore<
75
80
  invalidKeys.push(claimString)
76
81
  }
77
82
  }
83
+ const subject = new Subject<void>()
78
84
  if (invalidKeys.length === 0) {
79
- target.molecules.set(stringKey, { key, stringKey, dependsOn })
85
+ target.molecules.set(stringKey, { key, stringKey, dependsOn, subject })
80
86
  }
81
87
 
82
88
  const creationEvent: MoleculeCreationEvent = {
@@ -109,7 +115,7 @@ export function allocateIntoStore<
109
115
  )
110
116
  }
111
117
 
112
- return key as Claim<V>
118
+ return key as ValidKey<V>
113
119
  }
114
120
 
115
121
  export function fuseWithinStore<
@@ -123,7 +129,7 @@ export function fuseWithinStore<
123
129
  type: T,
124
130
  sideA: SingularTypedKey<A>,
125
131
  sideB: SingularTypedKey<B>,
126
- ): Claim<CompoundTypedKey<T, A, B>> {
132
+ ): ValidKey<CompoundTypedKey<T, A, B>> {
127
133
  const compoundKey: CompoundTypedKey<T, A, B> =
128
134
  `T$--${type}==${sideA}++${sideB}`
129
135
  const above = [sideA, sideB] as Above<Vassal<H>, H>
@@ -139,10 +145,10 @@ export function fuseWithinStore<
139
145
  export function createDeallocateTX<
140
146
  H extends Hierarchy,
141
147
  V extends Exclude<Vassal<H>, CompoundTypedKey>,
142
- >(store: RootStore): TransactionToken<(claim: Claim<V>) => void> {
148
+ >(store: RootStore): TransactionToken<(claim: ValidKey<V>) => void> {
143
149
  return createTransaction(store, {
144
150
  key: `[Internal] deallocate`,
145
- do: (_, claim: Claim<V>): void => {
151
+ do: (_, claim: ValidKey<V>): void => {
146
152
  deallocateFromStore<H, V>(newest(store), claim)
147
153
  },
148
154
  })
@@ -150,7 +156,7 @@ export function createDeallocateTX<
150
156
 
151
157
  export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
152
158
  target: Store,
153
- claim: Claim<V>,
159
+ claim: ValidKey<V>,
154
160
  ): void {
155
161
  const stringKey = stringifyJson(claim)
156
162
 
@@ -171,8 +177,9 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
171
177
  )
172
178
  return
173
179
  }
180
+ molecule.subject.next()
174
181
 
175
- const joinKeys = target.moleculeJoins.getRelatedKeys(stringKey)
182
+ const joinKeys = target.keyRefsInJoins.getRelatedKeys(stringKey)
176
183
  if (joinKeys) {
177
184
  for (const joinKey of joinKeys) {
178
185
  const join = target.joins.get(joinKey)
@@ -180,8 +187,20 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
180
187
  join.relations.delete(claim)
181
188
  }
182
189
  }
190
+ } else {
191
+ const compound = decomposeCompound(claim)
192
+ if (compound) {
193
+ const [, a, b] = compound
194
+ const joinKey = target.keyRefsInJoins.getRelatedKey(simpleCompound(a, b))
195
+ if (joinKey) {
196
+ const join = target.joins.get(joinKey)
197
+ if (join) {
198
+ join.relations.delete(a, b)
199
+ }
200
+ }
201
+ }
183
202
  }
184
- target.moleculeJoins.delete(stringKey)
203
+ target.keyRefsInJoins.delete(stringKey)
185
204
 
186
205
  const provenance: stringified<Canonical>[] = []
187
206
 
@@ -225,7 +244,7 @@ export function deallocateFromStore<H extends Hierarchy, V extends Vassal<H>>(
225
244
  }
226
245
 
227
246
  target.moleculeGraph.delete(molecule.stringKey)
228
- target.moleculeJoins.delete(molecule.stringKey)
247
+ target.keyRefsInJoins.delete(molecule.stringKey)
229
248
  target.moleculeData.delete(molecule.stringKey)
230
249
 
231
250
  if (!isTransaction) {
@@ -244,7 +263,7 @@ export function createClaimTX<
244
263
  >(
245
264
  store: RootStore,
246
265
  ): TransactionToken<
247
- (newProvenance: A, claim: Claim<V>, exclusive?: `exclusive`) => void
266
+ (newProvenance: A, claim: ValidKey<V>, exclusive?: `exclusive`) => void
248
267
  > {
249
268
  return createTransaction(store, {
250
269
  key: `[Internal] claim`,
@@ -261,9 +280,9 @@ export function claimWithinStore<
261
280
  >(
262
281
  store: Store,
263
282
  newProvenance: A,
264
- claim: Claim<V>,
283
+ claim: ValidKey<V>,
265
284
  exclusive?: `exclusive`,
266
- ): Claim<V> {
285
+ ): ValidKey<V> {
267
286
  const stringKey = stringifyJson(claim)
268
287
  const target = newest(store)
269
288
  const molecule = target.molecules.get(stringKey)
@@ -5,7 +5,7 @@ import type {
5
5
  UpdateHandler,
6
6
  } from "atom.io"
7
7
 
8
- import { newest } from "../lineage"
8
+ import { eldest, newest } from "../lineage"
9
9
  import { createStandaloneSelector } from "../selector"
10
10
  import { resetInStore, setIntoStore } from "../set-state"
11
11
  import type { MutableAtom } from "../state-types"
@@ -58,6 +58,18 @@ export function createMutableAtom<T extends Transceiver<any, any, any>>(
58
58
  }
59
59
  target.atoms.set(newAtom.key, newAtom)
60
60
  const token = deposit(newAtom)
61
+
62
+ new Tracker(token, store)
63
+ if (!family) {
64
+ createStandaloneSelector(store, {
65
+ key: `${key}:JSON`,
66
+ get: ({ get }) => get(token).toJSON(),
67
+ set: ({ set }, newValue) => {
68
+ set(token, options.class.fromJSON(newValue))
69
+ },
70
+ })
71
+ }
72
+
61
73
  if (options.effects) {
62
74
  let effectIndex = 0
63
75
  const cleanupFunctions: (() => void)[] = []
@@ -71,6 +83,8 @@ export function createMutableAtom<T extends Transceiver<any, any, any>>(
71
83
  },
72
84
  onSet: (handle: UpdateHandler<T>) =>
73
85
  subscribeToState(store, token, `effect[${effectIndex}]`, handle),
86
+ token: token as any,
87
+ store: eldest(store),
74
88
  })
75
89
  if (cleanup) {
76
90
  cleanupFunctions.push(cleanup)
@@ -84,16 +98,6 @@ export function createMutableAtom<T extends Transceiver<any, any, any>>(
84
98
  }
85
99
  }
86
100
 
87
- new Tracker(token, store)
88
- if (!family) {
89
- createStandaloneSelector(store, {
90
- key: `${key}:JSON`,
91
- get: ({ get }) => get(token).toJSON(),
92
- set: ({ set }, newValue) => {
93
- set(token, options.class.fromJSON(newValue))
94
- },
95
- })
96
- }
97
101
  store.on.atomCreation.next(token)
98
102
  return token
99
103
  }
@@ -1,7 +1,7 @@
1
1
  import type { Json } from "atom.io/json"
2
2
 
3
3
  export interface Transceiver<
4
- V,
4
+ V extends { subscribe: (key: string, fn: (update: S) => void) => () => void },
5
5
  S extends Json.Serializable,
6
6
  J extends Json.Serializable,
7
7
  > {
@@ -9,8 +9,6 @@ export interface Transceiver<
9
9
  do: (update: S) => number | `OUT_OF_RANGE` | null
10
10
  undo: (update: S) => void
11
11
  subscribe: (key: string, fn: (update: S) => void) => () => void
12
- // cacheUpdateNumber: number
13
- // getUpdateNumber: (update: S) => number
14
12
  toJSON: () => J
15
13
  }
16
14
 
@@ -31,8 +29,6 @@ export function isTransceiver(
31
29
  `do` in value &&
32
30
  `undo` in value &&
33
31
  `subscribe` in value &&
34
- // `cacheUpdateNumber` in value &&
35
- // `getUpdateNumber` in value &&
36
32
  `READONLY_VIEW` in value &&
37
33
  `toJSON` in value
38
34
  )
@@ -127,7 +127,7 @@ export function dispatchOrDeferStateUpdate<T, E>(
127
127
  if (hasRole(state, `tracker:signal`)) {
128
128
  const keyOfMutable = key.slice(1)
129
129
  const mutable = target.atoms.get(keyOfMutable) as MutableAtom<
130
- Transceiver<unknown, any, any>
130
+ Transceiver<any, any, any>
131
131
  >
132
132
  const transceiver = readOrComputeValue<Transceiver<any, any, any>, never>(
133
133
  target,
@@ -80,7 +80,7 @@ export class Store implements Lineage {
80
80
  | PureSelectorFamily<any, any, any>
81
81
  | RegularAtomFamily<any, any, any>
82
82
  > = new Map()
83
- public joins: Map<string, Join<any, any, any, any, any, any>> = new Map()
83
+ public joins: Map<string, Join<any, any, any, any, any>> = new Map()
84
84
 
85
85
  public transactions: Map<string, Transaction<Fn>> = new Map()
86
86
  public transactionMeta: TransactionEpoch | TransactionProgress<Fn> = {
@@ -107,20 +107,7 @@ export class Store implements Lineage {
107
107
  new CircularBuffer(100)
108
108
 
109
109
  public molecules: Map<string, Molecule<Canonical>> = new Map()
110
- public moleculeJoins: Junction<
111
- `moleculeKey`,
112
- stringified<Canonical>,
113
- `joinKey`,
114
- string
115
- > = new Junction(
116
- {
117
- between: [`moleculeKey`, `joinKey`],
118
- cardinality: `n:n`,
119
- },
120
- {
121
- makeContentKey: (...keys) => keys.sort().join(`:`),
122
- },
123
- )
110
+
124
111
  public moleculeGraph: Junction<
125
112
  `upstreamMoleculeKey`,
126
113
  stringified<Canonical> | `"root"`,
@@ -150,6 +137,20 @@ export class Store implements Lineage {
150
137
  makeContentKey: (...keys) => keys.sort().join(`:`),
151
138
  },
152
139
  )
140
+ public keyRefsInJoins: Junction<
141
+ `moleculeKey`,
142
+ stringified<Canonical>,
143
+ `joinKey`,
144
+ string
145
+ > = new Junction(
146
+ {
147
+ between: [`moleculeKey`, `joinKey`],
148
+ cardinality: `n:n`,
149
+ },
150
+ {
151
+ makeContentKey: (...keys) => keys.sort().join(`:`),
152
+ },
153
+ )
153
154
  public miscResources: Map<string, Disposable> = new Map()
154
155
 
155
156
  public on: StoreEventCarrier = {
@@ -54,7 +54,7 @@ export const buildTransaction = (
54
54
  molecules: new MapOverlay(parent.molecules),
55
55
  moleculeGraph: parent.moleculeGraph.overlay(),
56
56
  moleculeData: parent.moleculeData.overlay(),
57
- moleculeJoins: parent.moleculeJoins.overlay(),
57
+ keyRefsInJoins: parent.keyRefsInJoins.overlay(),
58
58
  miscResources: new MapOverlay(parent.miscResources),
59
59
  }
60
60
  const epoch = getEpochNumberOfAction(store, token.key)
package/src/main/atom.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ConstructorOf, Ctor, Transceiver } from "atom.io/internal"
1
+ import type { ConstructorOf, Ctor, Store, Transceiver } from "atom.io/internal"
2
2
  import {
3
3
  createMutableAtom,
4
4
  createMutableAtomFamily,
@@ -10,6 +10,7 @@ import type { Canonical } from "atom.io/json"
10
10
 
11
11
  import type { StateUpdate } from "./events"
12
12
  import type {
13
+ AtomToken,
13
14
  MutableAtomFamilyToken,
14
15
  MutableAtomToken,
15
16
  RegularAtomFamilyToken,
@@ -22,7 +23,7 @@ export type RegularAtomOptions<T, E = never> = {
22
23
  /** The starting value of the atom */
23
24
  default: T | (() => T)
24
25
  /** Hooks used to run side effects when the atom is set */
25
- effects?: readonly AtomEffect<T>[]
26
+ effects?: readonly AtomEffect<T, E>[]
26
27
  /** The classes of errors that might be thrown when deriving the atom's default value */
27
28
  catch?: readonly Ctor<E>[]
28
29
  }
@@ -67,8 +68,10 @@ export function mutableAtom<T extends Transceiver<any, any, any>>(
67
68
  * @returns
68
69
  * Optionally, a cleanup function that will be called when the atom is disposed
69
70
  */
70
- export type AtomEffect<T> = (tools: Effectors<T>) => (() => void) | void
71
- export type Effectors<T> = {
71
+ export type AtomEffect<T, E = never> = (
72
+ tools: Effectors<T, E>,
73
+ ) => (() => void) | void
74
+ export type Effectors<T, E = never> = {
72
75
  /**
73
76
  * Reset the value of the atom to its default
74
77
  */
@@ -79,7 +82,13 @@ export type Effectors<T> = {
79
82
  */
80
83
  setSelf: <New extends T>(next: New | ((old: T) => New)) => void
81
84
  /** Subscribe to changes to the atom */
82
- onSet: (callback: (options: StateUpdate<T>) => void) => void
85
+ onSet: (callback: (options: StateUpdate<E | T>) => void) => void
86
+ /** The token of the atom */
87
+ token: T extends Transceiver<any, any, any>
88
+ ? MutableAtomToken<T>
89
+ : AtomToken<T, any, E>
90
+ /** The store in which the atom exists */
91
+ store: Store
83
92
  }
84
93
 
85
94
  export type RegularAtomFamilyOptions<T, K extends Canonical, E = never> = {
@@ -88,7 +97,7 @@ export type RegularAtomFamilyOptions<T, K extends Canonical, E = never> = {
88
97
  /** The starting value of the atom family */
89
98
  default: T | ((key: K) => T)
90
99
  /** Hooks used to run side effects when an atom in the family is set */
91
- effects?: (key: K) => AtomEffect<T>[]
100
+ effects?: (key: K) => AtomEffect<T, E>[]
92
101
  /** The classes of errors that might be thrown when deriving the atom's default value */
93
102
  catch?: readonly Ctor<E>[]
94
103
  }