atom.io 0.14.7 → 0.15.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 (81) hide show
  1. package/README.md +5 -0
  2. package/data/dist/index.cjs +200 -218
  3. package/data/dist/index.cjs.map +1 -1
  4. package/data/dist/index.d.ts +16 -7
  5. package/data/dist/index.js +202 -221
  6. package/data/dist/index.js.map +1 -1
  7. package/data/src/join.ts +295 -292
  8. package/data/src/struct-family.ts +2 -2
  9. package/data/src/struct.ts +2 -2
  10. package/dist/chunk-S7R5MU6A.js +137 -0
  11. package/dist/chunk-S7R5MU6A.js.map +1 -0
  12. package/dist/index.cjs +3 -20
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.ts +15 -8
  15. package/dist/index.js +1 -151
  16. package/dist/index.js.map +1 -1
  17. package/internal/dist/index.cjs +275 -200
  18. package/internal/dist/index.cjs.map +1 -1
  19. package/internal/dist/index.d.ts +43 -36
  20. package/internal/dist/index.js +221 -193
  21. package/internal/dist/index.js.map +1 -1
  22. package/internal/src/atom/create-atom.ts +5 -86
  23. package/internal/src/atom/create-regular-atom.ts +92 -0
  24. package/internal/src/atom/index.ts +16 -0
  25. package/internal/src/atom/is-default.ts +0 -5
  26. package/internal/src/caching.ts +14 -16
  27. package/internal/src/families/create-atom-family.ts +20 -46
  28. package/internal/src/families/create-readonly-selector-family.ts +1 -0
  29. package/internal/src/families/create-regular-atom-family.ts +72 -0
  30. package/internal/src/families/create-selector-family.ts +2 -0
  31. package/internal/src/families/index.ts +1 -0
  32. package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
  33. package/internal/src/mutable/create-mutable-atom.ts +8 -3
  34. package/internal/src/mutable/get-update-family.ts +1 -1
  35. package/internal/src/mutable/is-mutable.ts +3 -30
  36. package/internal/src/mutable/tracker-family.ts +2 -2
  37. package/internal/src/mutable/tracker.ts +5 -5
  38. package/internal/src/operation.ts +14 -18
  39. package/internal/src/selector/create-read-write-selector.ts +2 -3
  40. package/internal/src/selector/create-selector.ts +1 -1
  41. package/internal/src/selector/register-selector.ts +9 -14
  42. package/internal/src/set-state/evict-downstream.ts +3 -5
  43. package/internal/src/set-state/set-atom.ts +14 -17
  44. package/internal/src/store/store.ts +23 -19
  45. package/internal/src/store/withdraw.ts +32 -70
  46. package/internal/src/subscribe/subscribe-to-root-atoms.ts +5 -3
  47. package/internal/src/subscribe/subscribe-to-state.ts +5 -3
  48. package/internal/src/transaction/apply-transaction.ts +20 -2
  49. package/internal/src/transaction/build-transaction.ts +19 -11
  50. package/internal/src/transaction/create-transaction.ts +6 -11
  51. package/internal/src/transaction/index.ts +2 -3
  52. package/introspection/dist/index.cjs +6 -6
  53. package/introspection/dist/index.cjs.map +1 -1
  54. package/introspection/dist/index.d.ts +3 -3
  55. package/introspection/dist/index.js +7 -7
  56. package/introspection/dist/index.js.map +1 -1
  57. package/introspection/src/attach-atom-index.ts +7 -2
  58. package/introspection/src/attach-selector-index.ts +7 -2
  59. package/introspection/src/attach-timeline-family.ts +5 -2
  60. package/introspection/src/attach-timeline-index.ts +2 -2
  61. package/introspection/src/attach-transaction-index.ts +2 -2
  62. package/introspection/src/attach-transaction-logs.ts +2 -2
  63. package/package.json +10 -8
  64. package/react/dist/index.cjs +9 -12
  65. package/react/dist/index.cjs.map +1 -1
  66. package/react/dist/index.js +9 -12
  67. package/react/dist/index.js.map +1 -1
  68. package/react/src/store-hooks.ts +10 -12
  69. package/react-devtools/dist/index.d.ts +17 -11
  70. package/src/atom.ts +8 -17
  71. package/src/selector.ts +3 -1
  72. package/src/set-state.ts +1 -3
  73. package/src/silo.ts +2 -14
  74. package/src/transaction.ts +17 -6
  75. package/transceivers/set-rtx/dist/index.cjs +2 -1
  76. package/transceivers/set-rtx/dist/index.cjs.map +1 -1
  77. package/transceivers/set-rtx/dist/index.js +2 -1
  78. package/transceivers/set-rtx/dist/index.js.map +1 -1
  79. package/transceivers/set-rtx/src/set-rtx.ts +2 -1
  80. package/internal/src/transaction/redo-transaction.ts +0 -27
  81. package/internal/src/transaction/undo-transaction.ts +0 -27
package/data/src/join.ts CHANGED
@@ -6,12 +6,12 @@ import type {
6
6
  Transactors,
7
7
  Write,
8
8
  } from "atom.io"
9
- import { getState, setState } from "atom.io"
9
+ import { dispose, getState, setState } from "atom.io"
10
10
  import type { Store } from "atom.io/internal"
11
11
  import {
12
12
  IMPLICIT,
13
- createAtomFamily,
14
13
  createMutableAtomFamily,
14
+ createRegularAtomFamily,
15
15
  createSelectorFamily,
16
16
  getJsonFamily,
17
17
  } from "atom.io/internal"
@@ -21,7 +21,6 @@ import { SetRTX } from "atom.io/transceivers/set-rtx"
21
21
  import type {
22
22
  BaseExternalStoreConfiguration,
23
23
  ExternalStoreConfiguration,
24
- ExternalStoreWithContentConfiguration,
25
24
  JunctionEntries,
26
25
  JunctionSchema,
27
26
  } from "~/packages/rel8/junction/src"
@@ -113,338 +112,342 @@ export type JoinState<
113
112
  }
114
113
  : never
115
114
 
116
- export function join<
115
+ export class Join<
117
116
  const ASide extends string,
118
117
  const BSide extends string,
119
- const Cardinality extends Rel8.Cardinality,
120
- >(
121
- options: JoinOptions<ASide, BSide, Cardinality, null>,
122
- defaultContent?: undefined,
123
- store?: Store,
124
- ): {
125
- relations: Junction<ASide, BSide>
126
- findState: JoinState<ASide, BSide, Cardinality, null>
127
- }
128
- export function join<
129
- const ASide extends string,
130
118
  const Cardinality extends `1:1` | `1:n` | `n:n`,
131
- const BSide extends string,
132
- const Content extends Json.Object,
133
- >(
134
- options: JoinOptions<ASide, BSide, Cardinality, Content>,
135
- defaultContent: Content,
136
- store?: Store,
137
- ): {
138
- relations: Junction<ASide, BSide, Content>
139
- findState: JoinState<ASide, BSide, Cardinality, Content>
140
- }
141
- export function join<
142
- ASide extends string,
143
- BSide extends string,
144
- Cardinality extends Rel8.Cardinality,
145
- Content extends Json.Object,
146
- >(
147
- options: JoinOptions<ASide, BSide, Cardinality, Content>,
148
- defaultContent: Content | undefined,
149
- store: Store = IMPLICIT.STORE,
150
- ): {
151
- relations: Junction<ASide, BSide, Content>
152
- findState: JoinState<ASide, BSide, Cardinality, Content>
153
- } {
154
- const a: ASide = options.between[0]
155
- const b: BSide = options.between[1]
156
- const findRelatedKeysState = createMutableAtomFamily<
157
- SetRTX<string>,
158
- string[],
159
- string
160
- >(
161
- {
162
- key: `${options.key}/relatedKeys`,
163
- default: () => new SetRTX(),
164
- mutable: true,
165
- fromJson: (json) => new SetRTX(json),
166
- toJson: (set) => [...set],
167
- },
168
- store,
169
- )
170
- const getRelatedKeys: Read<(key: string) => Set<string> | undefined> = (
171
- { get },
172
- key,
173
- ) => get(findRelatedKeysState(key))
174
- const addRelation: Write<(a: string, b: string) => void> = (
175
- transactors,
176
- a,
177
- b,
178
- ) => {
179
- const aKeys = getRelatedKeys(transactors, a)
180
- const bKeys = getRelatedKeys(transactors, b)
181
- if (aKeys) {
119
+ const Content extends Json.Object | null = null,
120
+ > {
121
+ private transactors: Transactors = TRANSACTORS
122
+ public relations: Junction<ASide, BSide, Content>
123
+ public findState: JoinState<ASide, BSide, Cardinality, Content>
124
+ public transact(
125
+ transactors: Transactors,
126
+ run: (join: Join<ASide, BSide, Cardinality, Content>) => void,
127
+ ): void {
128
+ this.transactors = transactors
129
+ run(this)
130
+ this.transactors = TRANSACTORS
131
+ }
132
+ public constructor(
133
+ options: JoinOptions<ASide, BSide, Cardinality, Content>,
134
+ defaultContent: Content | undefined,
135
+ store: Store = IMPLICIT.STORE,
136
+ ) {
137
+ const a: ASide = options.between[0]
138
+ const b: BSide = options.between[1]
139
+ const findRelatedKeysState = createMutableAtomFamily<
140
+ SetRTX<string>,
141
+ string[],
142
+ string
143
+ >(
144
+ {
145
+ key: `${options.key}/relatedKeys`,
146
+ default: () => new SetRTX(),
147
+ mutable: true,
148
+ fromJson: (json) => new SetRTX(json),
149
+ toJson: (set) => [...set],
150
+ },
151
+ store,
152
+ )
153
+ const getRelatedKeys: Read<(key: string) => SetRTX<string>> = (
154
+ { get },
155
+ key,
156
+ ) => get(findRelatedKeysState(key))
157
+ const addRelation: Write<(a: string, b: string) => void> = (
158
+ transactors,
159
+ a,
160
+ b,
161
+ ) => {
162
+ const aKeys = getRelatedKeys(transactors, a)
163
+ const bKeys = getRelatedKeys(transactors, b)
182
164
  transactors.set(findRelatedKeysState(a), aKeys.add(b))
183
- } else {
184
- transactors.set(findRelatedKeysState(a), new SetRTX([b]))
185
- }
186
- if (bKeys) {
187
165
  transactors.set(findRelatedKeysState(b), bKeys.add(a))
188
- } else {
189
- transactors.set(findRelatedKeysState(b), new SetRTX([a]))
190
166
  }
191
- }
192
- const deleteRelation: Write<(a: string, b: string) => void> = (
193
- transactors,
194
- a,
195
- b,
196
- ) => {
197
- const aKeys = getRelatedKeys(transactors, a)
198
- if (aKeys) {
167
+ const deleteRelation: Write<(a: string, b: string) => void> = (
168
+ transactors,
169
+ a,
170
+ b,
171
+ ) => {
172
+ const aKeys = getRelatedKeys(transactors, a)
199
173
  aKeys.delete(b)
200
174
  if (aKeys.size === 0) {
201
- transactors.set(findRelatedKeysState(a), undefined)
175
+ dispose(findRelatedKeysState(a))
202
176
  }
203
177
  const bKeys = getRelatedKeys(transactors, b)
204
- if (bKeys) {
205
- bKeys.delete(a)
206
- if (bKeys.size === 0) {
207
- transactors.set(findRelatedKeysState(b), undefined)
208
- }
178
+ bKeys.delete(a)
179
+ if (bKeys.size === 0) {
180
+ dispose(findRelatedKeysState(b))
209
181
  }
210
182
  }
211
- }
212
- const replaceRelationsSafely: Write<(a: string, bs: string[]) => void> = (
213
- transactors,
214
- a,
215
- bs,
216
- ) => {
217
- const aRelations = getRelatedKeys(transactors, a)
218
- if (aRelations) {
183
+ const replaceRelationsSafely: Write<(a: string, bs: string[]) => void> = (
184
+ transactors,
185
+ a,
186
+ bs,
187
+ ) => {
188
+ const aRelations = getRelatedKeys(transactors, a)
219
189
  for (const b of aRelations) {
220
190
  const bKeys = getRelatedKeys(transactors, b)
221
191
  if (bKeys) {
222
192
  bKeys.delete(a)
223
193
  if (bKeys.size === 0) {
224
- transactors.set(findRelatedKeysState(b), undefined)
194
+ dispose(findRelatedKeysState(b))
225
195
  }
226
196
  }
227
197
  }
228
- }
229
- transactors.set(findRelatedKeysState(a), new SetRTX(bs))
230
- for (const b of bs) {
231
- const bKeys = getRelatedKeys(transactors, b)
232
- if (bKeys) {
198
+ transactors.set(findRelatedKeysState(a), new SetRTX(bs))
199
+ for (const b of bs) {
200
+ const bKeys = getRelatedKeys(transactors, b)
233
201
  bKeys.add(a)
234
- } else {
235
- transactors.set(findRelatedKeysState(b), new SetRTX([a]))
236
202
  }
237
203
  }
238
- }
239
- const replaceRelationsUnsafely: Write<(a: string, bs: string[]) => void> = (
240
- transactors,
241
- a,
242
- bs,
243
- ) => {
244
- transactors.set(findRelatedKeysState(a), new SetRTX(bs))
245
- for (const b of bs) {
246
- let bKeys = getRelatedKeys(transactors, b)
247
- if (bKeys) {
204
+ const replaceRelationsUnsafely: Write<(a: string, bs: string[]) => void> = (
205
+ transactors,
206
+ a,
207
+ bs,
208
+ ) => {
209
+ transactors.set(findRelatedKeysState(a), new SetRTX(bs))
210
+ for (const b of bs) {
211
+ const bKeys = getRelatedKeys(transactors, b)
248
212
  bKeys.add(a)
249
- } else {
250
- bKeys = new SetRTX([a])
251
- transactors.set(findRelatedKeysState(b), bKeys)
252
213
  }
253
214
  }
254
- }
255
- const has: Read<(a: string, b?: string) => boolean> = (transactors, a, b) => {
256
- const aKeys = getRelatedKeys(transactors, a)
257
- return b ? aKeys?.has(b) ?? false : (aKeys?.size ?? 0) > 0 ?? false
258
- }
259
- const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
260
- getRelatedKeys: (key) => getRelatedKeys(TRANSACTORS, key),
261
- addRelation: (a, b) => addRelation(TRANSACTORS, a, b),
262
- deleteRelation: (a, b) => deleteRelation(TRANSACTORS, a, b),
263
- replaceRelationsSafely: (a, bs) =>
264
- replaceRelationsSafely(TRANSACTORS, a, bs),
265
- replaceRelationsUnsafely: (a, bs) =>
266
- replaceRelationsUnsafely(TRANSACTORS, a, bs),
267
- has: (a, b) => has(TRANSACTORS, a, b),
268
- }
269
- let externalStore: ExternalStoreConfiguration<Content>
270
- let findContentState: AtomFamily<Content, string>
271
- if (defaultContent) {
272
- findContentState = createAtomFamily<Content, string>(
273
- {
274
- key: `${options.key}/content`,
275
- default: defaultContent,
276
- },
277
- store,
278
- )
279
- const getContent: Read<(key: string) => Content | undefined> = (
280
- { get },
281
- key,
282
- ) => get(findContentState(key))
283
- const setContent: Write<(key: string, content: Content) => void> = (
215
+ const has: Read<(a: string, b?: string) => boolean> = (
284
216
  transactors,
285
- key,
286
- content,
287
- ) => transactors.set(findContentState(key), content)
288
- const deleteContent: Write<(key: string) => void> = (transactors, key) =>
289
- transactors.set(findContentState(key), undefined)
290
- const externalStoreWithContentConfiguration: ExternalStoreWithContentConfiguration<Content> =
291
- {
217
+ a,
218
+ b,
219
+ ) => {
220
+ const aKeys = getRelatedKeys(transactors, a)
221
+ return b ? aKeys.has(b) : aKeys.size > 0
222
+ }
223
+ const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
224
+ getRelatedKeys: (key) => getRelatedKeys(this.transactors, key),
225
+ addRelation: (a, b) => addRelation(this.transactors, a, b),
226
+ deleteRelation: (a, b) => deleteRelation(this.transactors, a, b),
227
+ replaceRelationsSafely: (a, bs) =>
228
+ replaceRelationsSafely(this.transactors, a, bs),
229
+ replaceRelationsUnsafely: (a, bs) =>
230
+ replaceRelationsUnsafely(this.transactors, a, bs),
231
+ has: (a, b) => has(this.transactors, a, b),
232
+ }
233
+ let externalStore: ExternalStoreConfiguration<Content>
234
+ let findContentState: AtomFamily<Content, string>
235
+ if (defaultContent) {
236
+ findContentState = createRegularAtomFamily<Content, string>(
237
+ {
238
+ key: `${options.key}/content`,
239
+ default: defaultContent,
240
+ },
241
+ store,
242
+ )
243
+ const getContent: Read<(key: string) => Content | undefined> = (
244
+ { get },
245
+ key,
246
+ ) => get(findContentState(key))
247
+ const setContent: Write<(key: string, content: Content) => void> = (
248
+ transactors,
249
+ key,
250
+ content,
251
+ ) => transactors.set(findContentState(key), content)
252
+ const deleteContent: Write<(key: string) => void> = (_, key) =>
253
+ dispose(findContentState(key))
254
+ const externalStoreWithContentConfiguration = {
292
255
  getContent: (contentKey: string) => {
293
- const content = getContent(TRANSACTORS, contentKey)
256
+ const content = getContent(this.transactors, contentKey)
294
257
  return content
295
258
  },
296
259
  setContent: (contentKey: string, content: Content) => {
297
- setContent(TRANSACTORS, contentKey, content)
260
+ setContent(this.transactors, contentKey, content)
298
261
  },
299
262
  deleteContent: (contentKey: string) => {
300
- deleteContent(TRANSACTORS, contentKey)
263
+ deleteContent(this.transactors, contentKey)
301
264
  },
302
265
  }
303
- externalStore = Object.assign(
304
- baseExternalStoreConfiguration,
305
- externalStoreWithContentConfiguration,
306
- ) as ExternalStoreConfiguration<Content>
307
- } else {
308
- externalStore =
309
- baseExternalStoreConfiguration as ExternalStoreConfiguration<Content>
310
- }
311
- const relations = new Junction<ASide, BSide, Content>(options, {
312
- externalStore,
313
- makeContentKey: (...args) => args.sort().join(`:`),
314
- })
266
+ externalStore = Object.assign(
267
+ baseExternalStoreConfiguration,
268
+ externalStoreWithContentConfiguration,
269
+ ) as ExternalStoreConfiguration<Content>
270
+ } else {
271
+ externalStore =
272
+ baseExternalStoreConfiguration as ExternalStoreConfiguration<Content>
273
+ }
274
+ const relations = new Junction<ASide, BSide, Content>(options, {
275
+ externalStore,
276
+ makeContentKey: (...args) => args.sort().join(`:`),
277
+ })
315
278
 
316
- const createSingleKeyStateFamily = () =>
317
- createSelectorFamily<string | undefined, string>(
318
- {
319
- key: `${options.key}/singleRelatedKey`,
320
- get:
321
- (key) =>
322
- ({ get }) => {
323
- const relatedKeys = get(findRelatedKeysState(key))
324
- for (const relatedKey of relatedKeys) {
325
- return relatedKey
326
- }
327
- },
328
- },
329
- store,
330
- )
331
- const getMultipleKeyStateFamily = () =>
332
- getJsonFamily(findRelatedKeysState, store)
333
- const createSingleEntryStateFamily = () =>
334
- createSelectorFamily<[string, Content] | undefined, string>(
335
- {
336
- key: `${options.key}/singleRelatedEntry`,
337
- get:
338
- (key) =>
339
- ({ get }) => {
340
- const relatedKeys = get(findRelatedKeysState(key))
341
- for (const relatedKey of relatedKeys) {
342
- const contentKey = relations.makeContentKey(key, relatedKey)
343
- return [relatedKey, get(findContentState(contentKey))]
344
- }
345
- },
346
- },
347
- store,
348
- )
349
- const getMultipleEntryStateFamily = () =>
350
- createSelectorFamily<[string, Content][], string>(
351
- {
352
- key: `${options.key}/multipleRelatedEntries`,
353
- get:
354
- (key) =>
355
- ({ get }) => {
356
- const relatedKeys = get(findRelatedKeysState(key))
357
- return [...relatedKeys].map((relatedKey) => {
358
- const contentKey = relations.makeContentKey(key, relatedKey)
359
- return [relatedKey, get(findContentState(contentKey))]
360
- })
361
- },
362
- },
363
- store,
364
- )
279
+ const createSingleKeyStateFamily = () =>
280
+ createSelectorFamily<string | undefined, string>(
281
+ {
282
+ key: `${options.key}/singleRelatedKey`,
283
+ get:
284
+ (key) =>
285
+ ({ get }) => {
286
+ const relatedKeys = get(findRelatedKeysState(key))
287
+ for (const relatedKey of relatedKeys) {
288
+ return relatedKey
289
+ }
290
+ },
291
+ },
292
+ store,
293
+ )
294
+ const getMultipleKeyStateFamily = () =>
295
+ getJsonFamily(findRelatedKeysState, store)
296
+ const createSingleEntryStateFamily = () =>
297
+ createSelectorFamily<[string, Content] | undefined, string>(
298
+ {
299
+ key: `${options.key}/singleRelatedEntry`,
300
+ get:
301
+ (key) =>
302
+ ({ get }) => {
303
+ const relatedKeys = get(findRelatedKeysState(key))
304
+ for (const relatedKey of relatedKeys) {
305
+ const contentKey = relations.makeContentKey(key, relatedKey)
306
+ return [relatedKey, get(findContentState(contentKey))]
307
+ }
308
+ },
309
+ },
310
+ store,
311
+ )
312
+ const getMultipleEntryStateFamily = () =>
313
+ createSelectorFamily<[string, Content][], string>(
314
+ {
315
+ key: `${options.key}/multipleRelatedEntries`,
316
+ get:
317
+ (key) =>
318
+ ({ get }) => {
319
+ const relatedKeys = get(findRelatedKeysState(key))
320
+ return [...relatedKeys].map((relatedKey) => {
321
+ const contentKey = relations.makeContentKey(key, relatedKey)
322
+ return [relatedKey, get(findContentState(contentKey))]
323
+ })
324
+ },
325
+ },
326
+ store,
327
+ )
365
328
 
366
- switch (options.cardinality) {
367
- case `1:1`: {
368
- const findSingleRelatedKeyState = createSingleKeyStateFamily()
369
- const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
370
- const stateKeyB = `${b}KeyOf${capitalize(a)}` as const
371
- const findStateBase = {
372
- [stateKeyA]: findSingleRelatedKeyState,
373
- [stateKeyB]: findSingleRelatedKeyState,
374
- } as JoinState<ASide, BSide, Cardinality, Content>
375
- let findState: JoinState<ASide, BSide, Cardinality, Content>
376
- if (defaultContent) {
377
- const findSingleRelatedEntryState = createSingleEntryStateFamily()
378
- const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
379
- const entriesStateKeyB = `${b}EntryOf${capitalize(a)}` as const
380
- const findStateWithContent = {
381
- [entriesStateKeyA]: findSingleRelatedEntryState,
382
- [entriesStateKeyB]: findSingleRelatedEntryState,
329
+ switch (options.cardinality) {
330
+ case `1:1`: {
331
+ const findSingleRelatedKeyState = createSingleKeyStateFamily()
332
+ const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
333
+ const stateKeyB = `${b}KeyOf${capitalize(a)}` as const
334
+ const findStateBase = {
335
+ [stateKeyA]: findSingleRelatedKeyState,
336
+ [stateKeyB]: findSingleRelatedKeyState,
337
+ } as JoinState<ASide, BSide, Cardinality, Content>
338
+ let findState: JoinState<ASide, BSide, Cardinality, Content>
339
+ if (defaultContent) {
340
+ const findSingleRelatedEntryState = createSingleEntryStateFamily()
341
+ const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
342
+ const entriesStateKeyB = `${b}EntryOf${capitalize(a)}` as const
343
+ const findStateWithContent = {
344
+ [entriesStateKeyA]: findSingleRelatedEntryState,
345
+ [entriesStateKeyB]: findSingleRelatedEntryState,
346
+ }
347
+ findState = Object.assign(findStateBase, findStateWithContent)
348
+ } else {
349
+ findState = findStateBase
383
350
  }
384
- findState = Object.assign(findStateBase, findStateWithContent)
385
- } else {
386
- findState = findStateBase
387
- }
388
- return {
389
- relations,
390
- findState,
351
+ this.relations = relations
352
+ this.findState = findState
353
+ break
391
354
  }
392
- }
393
- case `1:n`: {
394
- const findSingleRelatedKeyState = createSingleKeyStateFamily()
395
- const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
396
- const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
397
- const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
398
- const findStateBase = {
399
- [stateKeyA]: findSingleRelatedKeyState,
400
- [stateKeyB]: findMultipleRelatedKeysState,
401
- } as JoinState<ASide, BSide, Cardinality, Content>
402
- let findState: JoinState<ASide, BSide, Cardinality, Content>
403
- if (defaultContent) {
404
- const findSingleRelatedEntryState = createSingleEntryStateFamily()
405
- const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
406
- const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
407
- const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
408
- const findStateWithContent = {
409
- [entriesStateKeyA]: findSingleRelatedEntryState,
410
- [entriesStateKeyB]: findMultipleRelatedEntriesState,
355
+ case `1:n`: {
356
+ const findSingleRelatedKeyState = createSingleKeyStateFamily()
357
+ const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
358
+ const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
359
+ const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
360
+ const findStateBase = {
361
+ [stateKeyA]: findSingleRelatedKeyState,
362
+ [stateKeyB]: findMultipleRelatedKeysState,
363
+ } as JoinState<ASide, BSide, Cardinality, Content>
364
+ let findState: JoinState<ASide, BSide, Cardinality, Content>
365
+ if (defaultContent) {
366
+ const findSingleRelatedEntryState = createSingleEntryStateFamily()
367
+ const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
368
+ const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
369
+ const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
370
+ const findStateWithContent = {
371
+ [entriesStateKeyA]: findSingleRelatedEntryState,
372
+ [entriesStateKeyB]: findMultipleRelatedEntriesState,
373
+ }
374
+ findState = Object.assign(findStateBase, findStateWithContent)
375
+ } else {
376
+ findState = findStateBase
411
377
  }
412
- findState = Object.assign(findStateBase, findStateWithContent)
413
- } else {
414
- findState = findStateBase
378
+ this.relations = relations
379
+ this.findState = findState
380
+ break
415
381
  }
416
- return {
417
- relations,
418
- findState,
419
- }
420
- }
421
- case `n:n`: {
422
- const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
423
- const stateKeyA = `${a}KeysOf${capitalize(b)}` as const
424
- const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
425
- const findStateBase = {
426
- [stateKeyA]: findMultipleRelatedKeysState,
427
- [stateKeyB]: findMultipleRelatedKeysState,
428
- } as JoinState<ASide, BSide, Cardinality, Content>
429
- let findState: JoinState<ASide, BSide, Cardinality, Content>
430
- if (defaultContent) {
431
- const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
432
- const entriesStateKeyA = `${a}EntriesOf${capitalize(b)}` as const
433
- const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
434
- const findStateWithContent = {
435
- [entriesStateKeyA]: findMultipleRelatedEntriesState,
436
- [entriesStateKeyB]: findMultipleRelatedEntriesState,
382
+ default: {
383
+ const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
384
+ const stateKeyA = `${a}KeysOf${capitalize(b)}` as const
385
+ const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
386
+ const findStateBase = {
387
+ [stateKeyA]: findMultipleRelatedKeysState,
388
+ [stateKeyB]: findMultipleRelatedKeysState,
389
+ } as JoinState<ASide, BSide, Cardinality, Content>
390
+ let findState: JoinState<ASide, BSide, Cardinality, Content>
391
+ if (defaultContent) {
392
+ const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
393
+ const entriesStateKeyA = `${a}EntriesOf${capitalize(b)}` as const
394
+ const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
395
+ const findStateWithContent = {
396
+ [entriesStateKeyA]: findMultipleRelatedEntriesState,
397
+ [entriesStateKeyB]: findMultipleRelatedEntriesState,
398
+ }
399
+ findState = Object.assign(findStateBase, findStateWithContent)
400
+ } else {
401
+ findState = findStateBase
437
402
  }
438
- findState = Object.assign(findStateBase, findStateWithContent)
439
- } else {
440
- findState = findStateBase
441
- }
442
- return {
443
- relations,
444
- findState,
403
+ this.relations = relations
404
+ this.findState = findState
445
405
  }
446
406
  }
447
- default:
448
- throw new Error(`Invalid cardinality: ${options.cardinality}`)
449
407
  }
450
408
  }
409
+ export function join<
410
+ const ASide extends string,
411
+ const BSide extends string,
412
+ const Cardinality extends `1:1` | `1:n` | `n:n`,
413
+ >(
414
+ options: JoinOptions<ASide, BSide, Cardinality, null>,
415
+ defaultContent?: undefined,
416
+ store?: Store,
417
+ ): {
418
+ relations: Junction<ASide, BSide, null>
419
+ findState: JoinState<ASide, BSide, Cardinality, null>
420
+ transact: (
421
+ transactors: Transactors,
422
+ run: (join: Join<ASide, BSide, Cardinality, null>) => void,
423
+ ) => void
424
+ }
425
+ export function join<
426
+ const ASide extends string,
427
+ const BSide extends string,
428
+ const Cardinality extends `1:1` | `1:n` | `n:n`,
429
+ const Content extends Json.Object,
430
+ >(
431
+ options: JoinOptions<ASide, BSide, Cardinality, Content>,
432
+ defaultContent: Content,
433
+ store?: Store,
434
+ ): {
435
+ readonly relations: Junction<ASide, BSide, Content>
436
+ readonly findState: JoinState<ASide, BSide, Cardinality, Content>
437
+ readonly transact: (
438
+ transactors: Transactors,
439
+ run: (join: Join<ASide, BSide, Cardinality, Content>) => void,
440
+ ) => void
441
+ }
442
+ export function join<
443
+ ASide extends string,
444
+ BSide extends string,
445
+ Cardinality extends `1:1` | `1:n` | `n:n`,
446
+ Content extends Json.Object,
447
+ >(
448
+ options: JoinOptions<ASide, BSide, Cardinality, Content>,
449
+ defaultContent: Content | undefined,
450
+ store: Store = IMPLICIT.STORE,
451
+ ): Join<ASide, BSide, Cardinality, Content> {
452
+ return new Join(options, defaultContent, store)
453
+ }
@@ -1,7 +1,7 @@
1
1
  import type * as AtomIO from "atom.io"
2
2
  import {
3
3
  IMPLICIT,
4
- createAtomFamily,
4
+ createRegularAtomFamily,
5
5
  createSelectorFamily,
6
6
  } from "atom.io/internal"
7
7
 
@@ -29,7 +29,7 @@ export function structFamily<
29
29
  >}State`]: AtomIO.AtomFamily<Struct[K], string>
30
30
  } = Object.keys(options.default).reduce((acc, subKey) => {
31
31
  const atomFamilyName = nameFamily(options.key, subKey)
32
- acc[atomFamilyName] = createAtomFamily(
32
+ acc[atomFamilyName] = createRegularAtomFamily(
33
33
  {
34
34
  key: `${options.key}.${subKey}`,
35
35
  default: (options.default as any)[subKey],