atom.io 0.34.0 → 0.34.2

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.
package/src/main/atom.ts CHANGED
@@ -22,7 +22,6 @@ import type { AtomToken, MutableAtomToken, RegularAtomToken, Setter } from "."
22
22
  export function atom<T extends Transceiver<any>, J extends Json.Serializable>(
23
23
  options: MutableAtomOptions<T, J>,
24
24
  ): MutableAtomToken<T, J>
25
-
26
25
  /**
27
26
  * @public
28
27
  * Create a regular atom, a global reactive variable in the implicit store
@@ -71,14 +70,24 @@ export type RegularAtomOptions<T> = {
71
70
  /** Hooks used to run side effects when the atom is set */
72
71
  effects?: AtomEffect<T>[]
73
72
  }
74
- // biome-ignore format: complex intersection
75
- export type MutableAtomOptions<T extends Transceiver<any>, J extends Json.Serializable> =
73
+
74
+ /** @public */
75
+ // biome-ignore format: intersection
76
+ export type MutableAtomOptions<
77
+ T extends Transceiver<any>,
78
+ J extends Json.Serializable,
79
+ > =
76
80
  & JsonInterface<T, J>
77
- & Omit<RegularAtomOptions<T>, `default`>
78
- & {
79
- default: () => T
80
- mutable: true
81
- }
81
+ & {
82
+ /** Used to signal that the atom is mutable */
83
+ mutable: true
84
+ /** The unique identifier of the atom */
85
+ key: string
86
+ /** A function to create an initial value for the atom */
87
+ default: () => T
88
+ /** Hooks used to run side effects when the atom is set */
89
+ effects?: AtomEffect<T>[]
90
+ }
82
91
 
83
92
  /** @public */
84
93
  export type RegularAtomFamilyOptions<T, K extends Canonical> = {
@@ -91,24 +100,33 @@ export type RegularAtomFamilyOptions<T, K extends Canonical> = {
91
100
  }
92
101
 
93
102
  export type RegularAtomFamilyToken<T, K extends Canonical> = {
103
+ /** The unique identifier of the atom family */
94
104
  key: string
105
+ /** Discriminator */
95
106
  type: `atom_family`
107
+ /** Never present. This is a marker that preserves the type of atoms in this family */
96
108
  __T?: T
109
+ /** Never present. This is a marker that preserves the type of keys used for atoms in this family */
97
110
  __K?: K
98
111
  }
99
112
 
113
+ /** @public */
100
114
  // biome-ignore format: intersection
101
115
  export type MutableAtomFamilyOptions<
102
116
  T extends Transceiver<any>,
103
117
  J extends Json.Serializable,
104
118
  K extends Canonical,
105
- > =
119
+ > =
106
120
  & JsonInterface<T, J>
107
- & {
121
+ & {
122
+ /** Used to signal that the atoms created from this family are mutable */
123
+ mutable: true
124
+ /** The unique identifier of the atom family */
108
125
  key: string
126
+ /** A function to create an initial value for each atom in the family */
109
127
  default: (key: K) => T
128
+ /** Hooks used to run side effects when an atom in the family is set */
110
129
  effects?: (key: K) => AtomEffect<T>[]
111
- mutable: true,
112
130
  }
113
131
 
114
132
  export type MutableAtomFamilyToken<
@@ -116,22 +134,45 @@ export type MutableAtomFamilyToken<
116
134
  J extends Json.Serializable,
117
135
  K extends Canonical,
118
136
  > = {
137
+ /** The unique identifier of the atom family */
119
138
  key: string
139
+ /** Discriminator */
120
140
  type: `mutable_atom_family`
141
+ /** Never present. This is a marker that preserves the type of atoms in this family */
121
142
  __T?: T
143
+ /** Never present. This is a marker that preserves the type of the JSON form of atoms in this family */
122
144
  __J?: J
145
+ /** Never present. This is a marker that preserves the type of keys used for atoms in this family */
123
146
  __K?: K
124
147
  }
125
-
126
148
  export type AtomFamilyToken<T, K extends Canonical = Canonical> =
127
149
  | MutableAtomFamilyToken<T extends Transceiver<any> ? T : never, any, K>
128
150
  | RegularAtomFamilyToken<T, K>
129
151
 
152
+ /**
153
+ * @public
154
+ * Create a family of mutable atoms, allowing for the dynamic creation and disposal of atoms.
155
+ *
156
+ * The value of a mutable atom must be some kind of {@link Transceiver}.
157
+ *
158
+ * @param options - {@link MutableAtomFamilyOptions}
159
+ * @returns
160
+ * A reference to the atom family created: a {@link MutableAtomFamilyToken}
161
+ * @overload Mutable
162
+ */
130
163
  export function atomFamily<
131
164
  T extends Transceiver<any>,
132
165
  J extends Json.Serializable,
133
166
  K extends Canonical,
134
167
  >(options: MutableAtomFamilyOptions<T, J, K>): MutableAtomFamilyToken<T, J, K>
168
+ /**
169
+ * @public
170
+ * Create a family of regular atoms, allowing for the dynamic creation and disposal of atoms.
171
+ * @param options - {@link RegularAtomFamilyOptions}
172
+ * @returns
173
+ * A reference to the atom family created: a {@link RegularAtomFamilyToken}
174
+ * @overload Regular
175
+ */
135
176
  export function atomFamily<T, K extends Canonical>(
136
177
  options: RegularAtomFamilyOptions<T, K>,
137
178
  ): RegularAtomFamilyToken<T, K>
@@ -5,14 +5,20 @@ import type { ReadableFamilyToken, ReadableToken } from "."
5
5
 
6
6
  /**
7
7
  * @public
8
- * Disposes of a state in the implicit store
8
+ * Disposes of a state in the implicit store.
9
+ *
10
+ * Only family members can be disposed of.
11
+ *
9
12
  * @param token - The token of the state to dispose
10
13
  * @overload Default
11
14
  */
12
15
  export function disposeState(token: ReadableToken<any>): void
13
16
  /**
14
17
  * @public
15
- * Disposes of a state family in the implicit store
18
+ * Disposes of a state in the implicit store.
19
+ *
20
+ * Only family members can be disposed of.
21
+ *
16
22
  * @param token - The token of the state family to dispose
17
23
  * @param key - The unique key of the state to dispose
18
24
  */
@@ -3,13 +3,13 @@ import type {
3
3
  MutableAtomToken,
4
4
  ReadableFamilyToken,
5
5
  ReadableToken,
6
- ReadonlyPureSelectorFamilyToken,
7
- ReadonlyPureSelectorToken,
6
+ ReadonlySelectorFamilyToken,
7
+ ReadonlySelectorToken,
8
8
  RegularAtomFamilyToken,
9
9
  RegularAtomToken,
10
10
  WritableFamilyToken,
11
- WritablePureSelectorFamilyToken,
12
- WritablePureSelectorToken,
11
+ WritableSelectorFamilyToken,
12
+ WritableSelectorToken,
13
13
  WritableToken,
14
14
  } from "atom.io"
15
15
  import type { Transceiver } from "atom.io/internal"
@@ -18,7 +18,12 @@ import type { Canonical, Json } from "atom.io/json"
18
18
 
19
19
  /**
20
20
  * @public
21
- * Finds a {@link MutableAtomToken} in the store
21
+ * Finds a {@link MutableAtomToken} in the store, without accessing its value.
22
+ *
23
+ * In an ephemeral store, this will create a new atom if one does not exist with the given key.
24
+ *
25
+ * In an immortal store, a "counterfeit" atom token will be returned in this case and a warning will be logged.
26
+ *
22
27
  * @param token - A {@link MutableAtomFamilyToken}
23
28
  * @param key - The key of the state
24
29
  * @returns
@@ -33,7 +38,12 @@ export function findState<
33
38
  >(token: MutableAtomFamilyToken<T, J, K>, key: Key): MutableAtomToken<T, J, K>
34
39
  /**
35
40
  * @public
36
- * Finds a state in the store
41
+ * Finds a {@link RegularAtomToken} in the store, without accessing its value.
42
+ *
43
+ * In an ephemeral store, this will create a new atom if one does not exist with the given key.
44
+ *
45
+ * In an immortal store, a "counterfeit" atom token will be returned in this case and a warning will be logged.
46
+ *
37
47
  * @param token - The token of the state family
38
48
  * @param key - The key of the state
39
49
  * @returns
@@ -46,7 +56,12 @@ export function findState<T, K extends Canonical, Key extends K>(
46
56
  ): RegularAtomToken<T, K>
47
57
  /**
48
58
  * @public
49
- * Finds a state in the store
59
+ * Finds a {@link WritableSelectorToken} in the store, without accessing its value.
60
+ *
61
+ * In an ephemeral store, this will create a new selector if one does not exist with the given key.
62
+ *
63
+ * In an immortal store, a "counterfeit" selector token will be returned in this case and a warning will be logged.
64
+ *
50
65
  * @param token - The token of the state family
51
66
  * @param key - The key of the state
52
67
  * @returns
@@ -54,12 +69,17 @@ export function findState<T, K extends Canonical, Key extends K>(
54
69
  * @overload Writable Selector
55
70
  */
56
71
  export function findState<T, K extends Canonical, Key extends K>(
57
- token: WritablePureSelectorFamilyToken<T, K>,
72
+ token: WritableSelectorFamilyToken<T, K>,
58
73
  key: Key,
59
- ): WritablePureSelectorToken<T, K>
74
+ ): WritableSelectorToken<T, K>
60
75
  /**
61
76
  * @public
62
- * Finds a state in the store
77
+ * Finds a {@link ReadonlySelectorToken} in the store, without accessing its value.
78
+ *
79
+ * In an ephemeral store, this will create a new selector if one does not exist with the given key.
80
+ *
81
+ * In an immortal store, a "counterfeit" selector token will be returned in this case and a warning will be logged.
82
+ *
63
83
  * @param token - The token of the state family
64
84
  * @param key - The key of the state
65
85
  * @returns
@@ -67,12 +87,17 @@ export function findState<T, K extends Canonical, Key extends K>(
67
87
  * @overload Readonly Selector
68
88
  */
69
89
  export function findState<T, K extends Canonical, Key extends K>(
70
- token: ReadonlyPureSelectorFamilyToken<T, K>,
90
+ token: ReadonlySelectorFamilyToken<T, K>,
71
91
  key: Key,
72
- ): ReadonlyPureSelectorToken<T, K>
92
+ ): ReadonlySelectorToken<T, K>
73
93
  /**
74
94
  * @public
75
- * Finds a state in the store
95
+ * Finds a {@link WritableToken} in the store, without accessing its value.
96
+ *
97
+ * In an ephemeral store, this will create a new atom or selector if one does not exist with the given key.
98
+ *
99
+ * In an immortal store, a "counterfeit" token will be returned in this case and a warning will be logged.
100
+ *
76
101
  * @param token - The token of the state family
77
102
  * @param key - The key of the state
78
103
  * @returns
@@ -85,7 +110,12 @@ export function findState<T, K extends Canonical, Key extends K>(
85
110
  ): WritableToken<T, K>
86
111
  /**
87
112
  * @public
88
- * Finds a {@link ReadableToken} in the store
113
+ * Finds a {@link MutableAtomToken} in the store, without accessing its value.
114
+ *
115
+ * In an ephemeral store, this will create a new atom or selector if one does not exist with the given key.
116
+ *
117
+ * In an immortal store, a "counterfeit" token will be returned in this case and a warning will be logged.
118
+ *
89
119
  * @param token - A {@link ReadableFamilyToken}
90
120
  * @param key - The key of the state
91
121
  * @returns
@@ -5,7 +5,7 @@ import type { ReadableFamilyToken, ReadableToken } from "."
5
5
 
6
6
  /**
7
7
  * @public
8
- * Get the current value of a state
8
+ * Read or compute the current value of a state
9
9
  * @param token - The token of the state to get
10
10
  * @return The current value of the state
11
11
  * @overload Default
@@ -15,7 +15,7 @@ export function getState<T>(token: ReadableToken<T>): T
15
15
 
16
16
  /**
17
17
  * @public
18
- * Get the current value of a state family
18
+ * Read or compute the current value of a state
19
19
  * @param token - The token of a state family
20
20
  * @param key - The unique key of the state to get
21
21
  * @return The current value of the state
package/src/main/index.ts CHANGED
@@ -189,4 +189,12 @@ export type FamilyMetadata<K extends Canonical = any> = {
189
189
  subKey: stringified<K>
190
190
  }
191
191
 
192
+ /**
193
+ * @public
194
+ * Loadable is used to type atoms or selectors that may at some point be initialized to or set to a {@link Promise}.
195
+ *
196
+ * When a Promise is cached as the value of a state in atom.io, that state will be automatically set to the resolved value of the Promise when it is resolved.
197
+ *
198
+ * As a result, we consider any state that can be a set to a Promise to be a "loadable" state, whose value may or may not be a Promise at any given time.
199
+ */
192
200
  export type Loadable<T> = Promise<T> | T
package/src/main/join.ts CHANGED
@@ -1,36 +1,46 @@
1
1
  import type { MutableAtomFamilyToken, ReadonlyPureSelectorToken } from "atom.io"
2
2
  import type {
3
+ Flat,
3
4
  Junction,
4
5
  JunctionEntriesBase,
5
6
  JunctionSchemaBase,
6
7
  Refinement,
7
- Store,
8
8
  } from "atom.io/internal"
9
9
  import {
10
+ createJoin,
10
11
  editRelationsInStore,
11
12
  findRelationsInStore,
12
13
  getInternalRelationsFromStore,
13
14
  IMPLICIT,
14
- Join,
15
15
  } from "atom.io/internal"
16
16
  import type { Json } from "atom.io/json"
17
17
  import type { SetRTX, SetRTXJson } from "atom.io/transceivers/set-rtx"
18
18
 
19
- export interface JoinOptions<
19
+ /** @public */
20
+ // biome-ignore format: intersection
21
+ export type JoinOptions<
20
22
  ASide extends string,
21
23
  AType extends string,
22
24
  BSide extends string,
23
25
  BType extends string,
24
26
  Cardinality extends `1:1` | `1:n` | `n:n`,
25
27
  Content extends Json.Object | null,
26
- > extends JunctionSchemaBase<ASide, BSide>,
27
- Partial<JunctionEntriesBase<AType, BType, Content>> {
28
- readonly key: string
29
- readonly cardinality: Cardinality
30
- readonly isAType: Refinement<string, AType>
31
- readonly isBType: Refinement<string, BType>
32
- }
28
+ > =
29
+ Flat<
30
+ & JunctionSchemaBase<ASide, BSide>
31
+ & {
32
+ /** Unique identifier of the join */
33
+ readonly key: string
34
+ /** How many relations are allowed in each direction? */
35
+ readonly cardinality: Cardinality
36
+ /** Type guard for the type of the left side */
37
+ readonly isAType: Refinement<string, AType>
38
+ /** Type guard for the type of the right side */
39
+ readonly isBType: Refinement<string, BType>
40
+ }
41
+ > & Partial<JunctionEntriesBase<AType, BType, Content>>
33
42
 
43
+ /** @public */
34
44
  export type JoinToken<
35
45
  ASide extends string,
36
46
  AType extends string,
@@ -39,16 +49,38 @@ export type JoinToken<
39
49
  Cardinality extends `1:1` | `1:n` | `n:n`,
40
50
  Content extends Json.Object | null = null,
41
51
  > = {
52
+ /** Unique identifier of the join */
42
53
  key: string
54
+ /** Discriminator */
43
55
  type: `join`
56
+ /** How many relations are allowed in each direction? */
44
57
  cardinality: Cardinality
58
+ /** Name of the join's left side */
45
59
  a: ASide
60
+ /** Name of the join's right side */
46
61
  b: BSide
62
+ /** Never present. This is a marker that preserves the type of the left side's keys */
47
63
  __aType?: AType
64
+ /** Never present. This is a marker that preserves the type of the right side's keys */
48
65
  __bType?: BType
66
+ /** Never present. This is a marker that preserves the type of the data present for each relation */
49
67
  __content?: Content
50
68
  }
51
69
 
70
+ /**
71
+ * @public
72
+ * Create a join, an interface for managing relations between two sets of keys.
73
+ *
74
+ * Use joins when it is important to view relationships from either side.
75
+ *
76
+ * Under the hood, joins coordinate changes of multiple atoms to support that the desired relationships stay consistent.
77
+ *
78
+ * @param options - {@link JoinOptions}
79
+ * @param defaultContent - (undefined)
80
+ * @returns
81
+ * A reference to the join created: a {@link JoinToken}
82
+ * @overload No Content
83
+ */
52
84
  export function join<
53
85
  const ASide extends string,
54
86
  const AType extends string,
@@ -58,8 +90,21 @@ export function join<
58
90
  >(
59
91
  options: JoinOptions<ASide, AType, BSide, BType, Cardinality, null>,
60
92
  defaultContent?: undefined,
61
- store?: Store,
62
93
  ): JoinToken<ASide, AType, BSide, BType, Cardinality, null>
94
+ /**
95
+ * @public
96
+ * Create a join, an interface for managing relations between two sets of keys.
97
+ *
98
+ * Use joins when it is important to view relationships from either side.
99
+ *
100
+ * Under the hood, joins coordinate changes of multiple atoms to support that the desired relationships stay consistent.
101
+ *
102
+ * @param options - {@link JoinOptions}
103
+ * @param defaultContent - The default value for the content of each relation
104
+ * @returns
105
+ * A reference to the join created: a {@link JoinToken}
106
+ * @overload With Content
107
+ */
63
108
  export function join<
64
109
  const ASide extends string,
65
110
  const AType extends string,
@@ -70,7 +115,6 @@ export function join<
70
115
  >(
71
116
  options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
72
117
  defaultContent: Content,
73
- store?: Store,
74
118
  ): JoinToken<ASide, AType, BSide, BType, Cardinality, Content>
75
119
  export function join<
76
120
  ASide extends string,
@@ -82,17 +126,8 @@ export function join<
82
126
  >(
83
127
  options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
84
128
  defaultContent: Content | undefined,
85
- store: Store = IMPLICIT.STORE,
86
129
  ): JoinToken<ASide, AType, BSide, BType, Cardinality, Content> {
87
- store.joins.set(options.key, new Join(options, defaultContent, store))
88
- const token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content> = {
89
- key: options.key,
90
- type: `join`,
91
- a: options.between[0],
92
- b: options.between[1],
93
- cardinality: options.cardinality,
94
- }
95
- return token
130
+ return createJoin(IMPLICIT.STORE, options, defaultContent)
96
131
  }
97
132
 
98
133
  export type JoinStates<
@@ -176,6 +211,15 @@ export type JoinStates<
176
211
  }
177
212
  : never
178
213
 
214
+ /**
215
+ * @public
216
+ * Find the current value of a relation owned by a {@link join}
217
+ * @param token - The token of the join
218
+ * @param key - The key of the relation to find
219
+ * @returns
220
+ * A {@link JoinStates} interface to access the relation
221
+ * @overload Default
222
+ */
179
223
  export function findRelations<
180
224
  ASide extends string,
181
225
  AType extends string,
@@ -190,6 +234,12 @@ export function findRelations<
190
234
  return findRelationsInStore(token, key, IMPLICIT.STORE)
191
235
  }
192
236
 
237
+ /**
238
+ * @public
239
+ * Change one or multiple relations owned by a {@link join}
240
+ * @param token - The token of the join
241
+ * @param change - A function that takes a {@link Junction} interface to edit the relations
242
+ */
193
243
  export function editRelations<
194
244
  ASide extends string,
195
245
  AType extends string,
@@ -204,6 +254,12 @@ export function editRelations<
204
254
  editRelationsInStore(token, change, IMPLICIT.STORE)
205
255
  }
206
256
 
257
+ /**
258
+ * @public
259
+ * @param token - The token of the join
260
+ * @returns
261
+ * A {@link MutableAtomFamilyToken} to access the internal relations
262
+ */
207
263
  export function getInternalRelations<
208
264
  ASide extends string,
209
265
  AType extends string,
package/src/main/realm.ts CHANGED
@@ -14,10 +14,21 @@ export type Claim<K extends Canonical> = K & { [$claim]?: true }
14
14
 
15
15
  export class Realm<H extends Hierarchy> {
16
16
  public store: Store
17
+ /**
18
+ * @param store - The store to which the realm will be attached
19
+ */
17
20
  public constructor(store: Store = IMPLICIT.STORE) {
18
21
  this.store = store
19
22
  makeRootMoleculeInStore(`root`, store)
20
23
  }
24
+ /**
25
+ * Make space for a new subject of the realm
26
+ * @param provenance - A key for an owner {@link Above} the new subject in the realm's {@link Hierarchy}
27
+ * @param key - A unique identifier for the new subject
28
+ * @param attachmentStyle - The attachment style of new subject to its owner(s). `any` means that if any owners remain, the subject will be retained. `all` means that the subject be retained only if all owners remain .
29
+ * @returns
30
+ * The subject's key, given status as a true {@link Claim}
31
+ */
21
32
  public allocate<V extends Vassal<H>, A extends Above<V, H>>(
22
33
  provenance: A,
23
34
  key: V,
@@ -30,6 +41,14 @@ export class Realm<H extends Hierarchy> {
30
41
  attachmentStyle,
31
42
  )
32
43
  }
44
+ /**
45
+ * Fuse two reagents into a compound
46
+ * @param type - the name of the compound that is being fused
47
+ * @param reagentA - the left reagent of the compound
48
+ * @param reagentB - the right reagent of the compound
49
+ * @returns
50
+ * The compound's key, given status as a true {@link Claim}
51
+ */
33
52
  public fuse<
34
53
  C extends CompoundFrom<H>,
35
54
  T extends C extends CompoundTypedKey<infer t, any, any> ? t : never,
@@ -42,10 +61,21 @@ export class Realm<H extends Hierarchy> {
42
61
  ): Claim<CompoundTypedKey<T, A, B>> {
43
62
  return fuseWithinStore<H, C, T, A, B>(this.store, type, reagentA, reagentB)
44
63
  }
45
-
64
+ /**
65
+ * Remove a subject from the realm
66
+ * @param claim - The subject to be deallocated
67
+ */
46
68
  public deallocate<V extends Vassal<H>>(claim: Claim<V>): void {
47
69
  deallocateFromStore<H, V>(this.store, claim)
48
70
  }
71
+ /**
72
+ * Transfer a subject of the realm from one owner to another
73
+ * @param newProvenance - A key for an owner {@link Above} the new subject in the realm's {@link Hierarchy}
74
+ * @param claim - The subject to be claimed
75
+ * @param exclusive - Whether the subjects previous owners should be detached from it
76
+ * @returns
77
+ * The subject's key, given status as a true {@link Claim}
78
+ */
49
79
  public claim<
50
80
  V extends Exclude<Vassal<H>, CompoundTypedKey>,
51
81
  A extends Above<V, H>,
@@ -58,11 +88,19 @@ export class Anarchy {
58
88
  public store: Store
59
89
  public realm: Realm<any>
60
90
 
91
+ /**
92
+ * @param store - The store to which the anarchy-realm will be attached
93
+ */
61
94
  public constructor(store: Store = IMPLICIT.STORE) {
62
95
  this.store = store
63
96
  this.realm = new Realm(store)
64
97
  }
65
-
98
+ /**
99
+ * Declare a new entity
100
+ * @param provenance - A key for an owner of the entity
101
+ * @param key - A unique identifier for the new entity
102
+ * @param attachmentStyle - The attachment style of new entity to its owner(s). `any` means that if any owners remain, the subject will be retained. `all` means that the subject be retained only if all owners remain .
103
+ */
66
104
  public allocate(
67
105
  provenance: Canonical,
68
106
  key: Canonical,
@@ -75,11 +113,19 @@ export class Anarchy {
75
113
  attachmentStyle,
76
114
  )
77
115
  }
78
-
116
+ /**
117
+ * Remove an entity
118
+ * @param key - The entity to be deallocated
119
+ */
79
120
  public deallocate(key: Canonical): void {
80
121
  deallocateFromStore<any, any>(this.store, key)
81
122
  }
82
-
123
+ /**
124
+ * Transfer an entity from one owner to another
125
+ * @param newProvenance - A key for an owner of the entity
126
+ * @param key - The entity to be claimed
127
+ * @param exclusive - Whether the entity's previous owners should be detached from it
128
+ */
83
129
  public claim(
84
130
  newProvenance: Canonical,
85
131
  key: Canonical,