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,152 +1,82 @@
1
- import type {
2
- CompoundTypedKey,
3
- findState,
4
- getState,
5
- JoinOptions,
6
- MutableAtomFamilyToken,
7
- Read,
8
- ReadonlyPureSelectorFamilyToken,
9
- RegularAtomFamilyToken,
10
- setState,
11
- ViewOf,
12
- Write,
13
- WriterToolkit,
1
+ import {
2
+ type findState,
3
+ type getState,
4
+ type JoinOptions,
5
+ type MutableAtomFamilyToken,
6
+ type ReadonlyPureSelectorFamilyToken,
7
+ type setState,
8
+ simpleCompound,
9
+ type Write,
10
+ type WriterToolkit,
14
11
  } from "atom.io"
15
- import { Anarchy } from "atom.io"
16
- import type { Json } from "atom.io/json"
17
- import { stringifyJson } from "atom.io/json"
18
- import { SetRTX } from "atom.io/transceivers/set-rtx"
12
+ import { UList } from "atom.io/transceivers/u-list"
19
13
 
20
14
  import { capitalize } from "../capitalize"
21
- import {
22
- createReadonlyPureSelectorFamily,
23
- createRegularAtomFamily,
24
- findInStore,
25
- } from "../families"
15
+ import { createReadonlyPureSelectorFamily, findInStore } from "../families"
26
16
  import { getFromStore } from "../get-state"
27
- import type {
28
- BaseExternalStoreConfiguration,
29
- ExternalStoreConfiguration,
30
- } from "../junction"
17
+ import type { BaseExternalStoreConfiguration } from "../junction"
31
18
  import { Junction } from "../junction"
32
19
  import { createMutableAtomFamily, getJsonFamily, getJsonToken } from "../mutable"
33
- import { setIntoStore } from "../set-state"
20
+ import { JOIN_OP, operateOnStore, setIntoStore } from "../set-state"
34
21
  import type { Store } from "../store"
35
22
  import { IMPLICIT } from "../store"
36
23
  import type { RootStore } from "../transaction"
37
24
 
38
25
  export type JoinStateFamilies<
39
- ASide extends string,
40
- AType extends string,
41
- BSide extends string,
42
- BType extends string,
26
+ AName extends string,
27
+ A extends string,
28
+ BName extends string,
29
+ B extends string,
43
30
  Cardinality extends `1:1` | `1:n` | `n:n`,
44
- Content extends Json.Object | null,
45
31
  > = Cardinality extends `1:1`
46
- ? (Content extends Json.Object
47
- ? {
48
- readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
49
- [AType, Content] | null,
50
- BType
51
- >
52
- } & {
53
- readonly [B in BSide as `${B}EntryOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
54
- [BType, Content] | null,
55
- AType
56
- >
57
- }
58
- : {}) & {
59
- readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
60
- AType | null,
61
- BType
32
+ ? {
33
+ readonly [N in AName as `${N}KeyOf${Capitalize<BName>}`]: ReadonlyPureSelectorFamilyToken<
34
+ A | null,
35
+ B
62
36
  >
63
37
  } & {
64
- readonly [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
65
- BType | null,
66
- AType
38
+ readonly [N in BName as `${N}KeyOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
39
+ B | null,
40
+ A
67
41
  >
68
42
  }
69
43
  : Cardinality extends `1:n`
70
- ? (Content extends Json.Object
71
- ? {
72
- readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
73
- [AType, Content] | null,
74
- BType
75
- >
76
- } & {
77
- readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
78
- [BType, Content][],
79
- AType
80
- >
81
- }
82
- : {}) & {
83
- readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
84
- AType | null,
85
- BType
86
- >
87
- } & {
88
- readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
89
- BType[],
90
- AType
44
+ ? {
45
+ readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
46
+ B[],
47
+ A
91
48
  >
92
49
  }
93
50
  : Cardinality extends `n:n`
94
- ? (Content extends Json.Object
95
- ? {
96
- readonly [A in ASide as `${A}EntriesOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
97
- [AType, Content][],
98
- BType
99
- >
100
- } & {
101
- readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
102
- [BType, Content][],
103
- AType
104
- >
105
- }
106
- : {}) & {
107
- readonly [A in ASide as `${A}KeysOf${Capitalize<BSide>}`]: ReadonlyPureSelectorFamilyToken<
108
- AType[],
109
- BType
51
+ ? {
52
+ readonly [N in AName as `${N}KeysOf${Capitalize<BName>}`]: ReadonlyPureSelectorFamilyToken<
53
+ A[],
54
+ B
110
55
  >
111
56
  } & {
112
- readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
113
- BType[],
114
- AType
57
+ readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
58
+ B[],
59
+ A
115
60
  >
116
61
  }
117
62
  : never
118
63
 
119
64
  export class Join<
120
- const ASide extends string,
121
- const AType extends string,
122
- const BSide extends string,
123
- const BType extends string,
65
+ const AName extends string,
66
+ const A extends string,
67
+ const BName extends string,
68
+ const B extends string,
124
69
  const Cardinality extends `1:1` | `1:n` | `n:n`,
125
- const Content extends Json.Object | null = null,
126
- const ContentKey extends CompoundTypedKey<
127
- `content`,
128
- ASide,
129
- BSide
130
- > = CompoundTypedKey<`content`, ASide, BSide>,
131
70
  > {
132
71
  private toolkit: WriterToolkit
133
- public options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>
134
- public defaultContent: Content | undefined
135
- public relations: Junction<ASide, AType, BSide, BType, Content>
136
- public states: JoinStateFamilies<
137
- ASide,
138
- AType,
139
- BSide,
140
- BType,
141
- Cardinality,
142
- Content
143
- >
144
- public core: {
145
- relatedKeysAtoms: MutableAtomFamilyToken<SetRTX<string>, string>
146
- }
72
+ public options: JoinOptions<AName, A, BName, B, Cardinality>
73
+ public relations: Junction<AName, A, BName, B>
74
+ public states: JoinStateFamilies<AName, A, BName, B, Cardinality>
75
+ public relatedKeysAtoms: MutableAtomFamilyToken<UList<string>, string>
76
+
147
77
  public transact(
148
78
  toolkit: WriterToolkit,
149
- run: (join: Join<ASide, AType, BSide, BType, Cardinality, Content>) => void,
79
+ run: (join: Join<AName, A, BName, B, Cardinality>) => void,
150
80
  ): void {
151
81
  const originalToolkit = this.toolkit
152
82
  this.toolkit = toolkit
@@ -155,26 +85,20 @@ export class Join<
155
85
  }
156
86
 
157
87
  public store: Store
158
- public realm: Anarchy
159
88
 
160
89
  public [Symbol.dispose](): void {}
161
90
 
162
91
  public constructor(
163
- options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
164
- defaultContent: Content | undefined,
92
+ options: JoinOptions<AName, A, BName, B, Cardinality>,
165
93
  store: RootStore = IMPLICIT.STORE,
166
94
  ) {
167
- type AnyKey = AType & BType
95
+ type AB = A & B
168
96
 
169
97
  this.store = store
170
- this.realm = new Anarchy(store)
171
98
  this.options = options
172
- this.defaultContent = defaultContent
173
99
 
174
100
  this.store.miscResources.set(`join:${options.key}`, this)
175
101
 
176
- this.realm.allocate(`root`, options.key)
177
-
178
102
  this.toolkit = {
179
103
  get: ((...ps: Parameters<typeof getState>) =>
180
104
  getFromStore(store, ...ps)) as typeof getState,
@@ -186,49 +110,18 @@ export class Join<
186
110
  json: (token) => getJsonToken(store, token),
187
111
  }
188
112
 
189
- const aSide: ASide = options.between[0]
190
- const bSide: BSide = options.between[1]
191
- const relatedKeysAtoms = createMutableAtomFamily<SetRTX<string>, string>(
113
+ const aSide: AName = options.between[0]
114
+ const bSide: BName = options.between[1]
115
+ const relatedKeysAtoms = createMutableAtomFamily<UList<string>, string>(
192
116
  store,
193
117
  {
194
118
  key: `${options.key}/relatedKeys`,
195
- class: SetRTX,
119
+ class: UList,
196
120
  },
197
121
  [`join`, `relations`],
198
122
  )
199
- this.core = { relatedKeysAtoms }
200
- const getRelatedKeys: Read<
201
- (key: string) => SetRTX<AType> | SetRTX<BType>
202
- > = ({ get }, key) =>
203
- get(relatedKeysAtoms, key) as SetRTX<AType> | SetRTX<BType>
204
- const addRelation: Write<(a: string, b: string) => void> = (
205
- { set },
206
- a,
207
- b,
208
- ) => {
209
- if (!this.store.molecules.has(stringifyJson(a))) {
210
- this.realm.allocate(options.key, a)
211
- }
212
- set(relatedKeysAtoms, a, (aKeys) => aKeys.add(b))
213
- set(relatedKeysAtoms, b, (bKeys) => bKeys.add(a))
214
- }
215
- const deleteRelation: Write<(a: string, b: string) => void> = (
216
- { set },
217
- a,
218
- b,
219
- ) => {
220
- set(relatedKeysAtoms, a, (aKeys) => {
221
- aKeys.delete(b)
222
- return aKeys
223
- })
224
- set(relatedKeysAtoms, b, (bKeys) => {
225
- bKeys.delete(a)
226
- return bKeys
227
- })
228
- const [x, y] = [a, b].sort()
229
- const compositeKey = `${x}:${y}`
230
- this.store.moleculeJoins.delete(compositeKey)
231
- }
123
+ this.relatedKeysAtoms = relatedKeysAtoms
124
+
232
125
  const replaceRelationsSafely: Write<
233
126
  (a: string, newRelationsOfA: string[]) => void
234
127
  > = (toolkit, a, newRelationsOfA) => {
@@ -246,42 +139,56 @@ export class Join<
246
139
  })
247
140
  }
248
141
  set(relationsOfAState, (relationsOfA) => {
249
- relationsOfA.transaction((nextRelationsOfA) => {
250
- nextRelationsOfA.clear()
251
- for (const newRelationB of newRelationsOfA) {
252
- const relationsOfB = getRelatedKeys(toolkit, newRelationB)
253
- const newRelationBIsAlreadyRelated = relationsOfB.has(a as AnyKey)
254
- if (this.relations.cardinality === `1:n`) {
255
- const previousOwnersToDispose: string[] = []
256
- for (const previousOwner of relationsOfB) {
257
- if (previousOwner === a) {
258
- continue
259
- }
260
- const previousOwnerRelations = getRelatedKeys(
261
- toolkit,
262
- previousOwner,
263
- )
264
- previousOwnerRelations.delete(newRelationB as AnyKey)
265
- if (previousOwnerRelations.size === 0) {
266
- previousOwnersToDispose.push(previousOwner)
267
- }
142
+ // relationsOfA.transaction((nextRelationsOfA) => {
143
+ relationsOfA.clear()
144
+ for (const newRelationB of newRelationsOfA) {
145
+ const relationsOfBAtom = find(relatedKeysAtoms, newRelationB)
146
+ const relationsOfB = get(relationsOfBAtom)
147
+ const newRelationBIsAlreadyRelated = relationsOfB.has(a as AB)
148
+ if (this.relations.cardinality === `1:n`) {
149
+ const previousOwnersToDispose: string[] = []
150
+ for (const previousOwner of relationsOfB) {
151
+ if (previousOwner === a) {
152
+ continue
268
153
  }
269
- if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0) {
270
- relationsOfB.clear()
271
- }
272
- for (const previousOwner of previousOwnersToDispose) {
273
- const [x, y] = [newRelationB, previousOwner].sort()
274
- const compositeKey = `${x}:${y}`
275
- store.moleculeJoins.delete(compositeKey)
154
+ let previousOwnerSize: number | undefined
155
+ operateOnStore(
156
+ JOIN_OP,
157
+ this.store,
158
+ relatedKeysAtoms,
159
+ previousOwner,
160
+ (relations) => {
161
+ relations.delete(newRelationB as AB)
162
+ previousOwnerSize = relations.size
163
+ return relations
164
+ },
165
+ )
166
+ if (previousOwnerSize === 0) {
167
+ previousOwnersToDispose.push(previousOwner)
276
168
  }
277
169
  }
278
- if (!newRelationBIsAlreadyRelated) {
279
- relationsOfB.add(a as AnyKey)
170
+ if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0) {
171
+ set(relationsOfBAtom, (relations) => {
172
+ relations.clear()
173
+ return relations
174
+ })
175
+ }
176
+ for (const previousOwner of previousOwnersToDispose) {
177
+ store.keyRefsInJoins.delete(
178
+ simpleCompound(newRelationB, previousOwner),
179
+ )
280
180
  }
281
- nextRelationsOfA.add(newRelationB)
282
181
  }
283
- return true
284
- })
182
+ if (!newRelationBIsAlreadyRelated) {
183
+ set(relationsOfBAtom, (relations) => {
184
+ relations.add(a as AB)
185
+ return relations
186
+ })
187
+ }
188
+ relationsOfA.add(newRelationB)
189
+ }
190
+ // return true
191
+ // })
285
192
  return relationsOfA
286
193
  })
287
194
  }
@@ -290,12 +197,12 @@ export class Join<
290
197
  > = (toolkit, a, newRelationsOfA) => {
291
198
  const { set } = toolkit
292
199
  set(relatedKeysAtoms, a, (relationsOfA) => {
293
- relationsOfA.transaction((nextRelationsOfA) => {
294
- for (const newRelationB of newRelationsOfA) {
295
- nextRelationsOfA.add(newRelationB)
296
- }
297
- return true
298
- })
200
+ // relationsOfA.transaction((nextRelationsOfA) => {
201
+ for (const newRelationB of newRelationsOfA) {
202
+ relationsOfA.add(newRelationB)
203
+ }
204
+ // return true
205
+ // })
299
206
  return relationsOfA
300
207
  })
301
208
  for (const newRelationB of newRelationsOfA) {
@@ -306,19 +213,27 @@ export class Join<
306
213
  }
307
214
  return true
308
215
  }
309
- const has: Read<(a: string, b?: string) => boolean> = (toolkit, a, b) => {
310
- const aKeys = getRelatedKeys(toolkit, a)
311
- return b ? aKeys.has(b as AnyKey) : aKeys.size > 0
312
- }
313
216
  const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
314
- getRelatedKeys: (key) => getRelatedKeys(this.toolkit, key),
217
+ getRelatedKeys: (key) =>
218
+ this.toolkit.get(relatedKeysAtoms, key) as UList<A> | UList<B>,
315
219
  addRelation: (a, b) => {
316
- this.store.moleculeJoins.set(`"${a}"`, options.key)
317
- this.store.moleculeJoins.set(`"${b}"`, options.key)
318
- addRelation(this.toolkit, a, b)
220
+ this.store.keyRefsInJoins.set(`"${a}"`, options.key)
221
+ this.store.keyRefsInJoins.set(`"${b}"`, options.key)
222
+ this.store.keyRefsInJoins.set(simpleCompound(a, b), options.key)
223
+ this.toolkit.set(relatedKeysAtoms, a, (aKeys) => aKeys.add(b))
224
+ this.toolkit.set(relatedKeysAtoms, b, (bKeys) => bKeys.add(a))
319
225
  },
320
226
  deleteRelation: (a, b) => {
321
- deleteRelation(this.toolkit, a, b)
227
+ this.toolkit.set(relatedKeysAtoms, a, (aKeys) => {
228
+ aKeys.delete(b)
229
+ return aKeys
230
+ })
231
+ this.toolkit.set(relatedKeysAtoms, b, (bKeys) => {
232
+ bKeys.delete(a)
233
+ return bKeys
234
+ })
235
+ const compositeKey = simpleCompound(a, b)
236
+ this.store.keyRefsInJoins.delete(compositeKey)
322
237
  },
323
238
  replaceRelationsSafely: (a, bs) => {
324
239
  replaceRelationsSafely(this.toolkit, a, bs)
@@ -326,77 +241,17 @@ export class Join<
326
241
  replaceRelationsUnsafely: (a, bs) => {
327
242
  replaceRelationsUnsafely(this.toolkit, a, bs)
328
243
  },
329
- has: (a, b) => has(this.toolkit, a, b),
330
- }
331
- let externalStore: ExternalStoreConfiguration<Content>
332
- let contentAtoms: RegularAtomFamilyToken<Content, string>
333
-
334
- if (defaultContent) {
335
- contentAtoms = createRegularAtomFamily<Content, ContentKey, never>(
336
- store,
337
- {
338
- key: `${options.key}/content`,
339
- default: defaultContent,
340
- },
341
- [`join`, `content`],
342
- )
343
-
344
- const getContent: Read<(key: string) => ViewOf<Content> | null> = (
345
- { get },
346
- key,
347
- ) => get(contentAtoms, key)
348
- const setContent: Write<(key: string, content: Content) => void> = (
349
- { set },
350
- key,
351
- content,
352
- ) => {
353
- set(contentAtoms, key, content)
354
- }
355
-
356
- const externalStoreWithContentConfiguration = {
357
- getContent: (contentKey: ContentKey) => {
358
- const content = getContent(this.toolkit, contentKey)
359
- return content
360
- },
361
- setContent: (contentKey: ContentKey, content: Content) => {
362
- setContent(this.toolkit, contentKey, content)
363
- },
364
- deleteContent: (_: ContentKey) => {},
365
- }
366
- externalStore = Object.assign(
367
- baseExternalStoreConfiguration,
368
- externalStoreWithContentConfiguration,
369
- ) as ExternalStoreConfiguration<Content>
370
- } else {
371
- externalStore =
372
- baseExternalStoreConfiguration as ExternalStoreConfiguration<Content>
373
- }
374
- const relations = new Junction<ASide, AType, BSide, BType, Content>(
375
- options as any,
376
- {
377
- externalStore,
378
- isAType: options.isAType,
379
- isBType: options.isBType,
380
- makeContentKey: (...args) => {
381
- const [a, b] = args
382
- const [x, y] = args.sort()
383
- const compositeKey = `${x}:${y}`
384
- const aMolecule = store.molecules.get(stringifyJson(a))
385
- const bMolecule = store.molecules.get(stringifyJson(b))
386
- if (!aMolecule) {
387
- this.realm.allocate(options.key, a)
388
- }
389
- if (!bMolecule) {
390
- this.realm.allocate(options.key, b)
391
- }
392
-
393
- this.realm.allocate(a, compositeKey, `all`)
394
- this.realm.claim(b, compositeKey)
395
- this.store.moleculeJoins.set(compositeKey, options.key)
396
- return compositeKey
397
- },
244
+ has: (a, b) => {
245
+ const aKeys = this.toolkit.get(relatedKeysAtoms, a)
246
+ return b ? aKeys.has(b as AB) : aKeys.size > 0
398
247
  },
399
- )
248
+ }
249
+ const externalStore = baseExternalStoreConfiguration
250
+ const relations = new Junction<AName, A, BName, B>(options as any, {
251
+ externalStore,
252
+ isAType: options.isAType,
253
+ isBType: options.isBType,
254
+ })
400
255
 
401
256
  const createSingleKeySelectorFamily = () =>
402
257
  createReadonlyPureSelectorFamily<string | null, string, never>(
@@ -416,7 +271,7 @@ export class Join<
416
271
  [`join`, `keys`],
417
272
  )
418
273
  const getMultipleKeySelectorFamily = () => {
419
- return createReadonlyPureSelectorFamily<string[], string, never>(
274
+ return createReadonlyPureSelectorFamily<readonly string[], string, never>(
420
275
  store,
421
276
  {
422
277
  key: `${options.key}/multipleRelatedKeys`,
@@ -425,98 +280,23 @@ export class Join<
425
280
  ({ get }) => {
426
281
  const jsonFamily = getJsonFamily(relatedKeysAtoms, store)
427
282
  const json = get(jsonFamily, key)
428
- return json.members
283
+ return json
429
284
  },
430
285
  },
431
286
  [`join`, `keys`],
432
287
  )
433
288
  }
434
- const createSingleEntrySelectorFamily = () =>
435
- createReadonlyPureSelectorFamily<
436
- [string, ViewOf<Content>] | null,
437
- string,
438
- never
439
- >(
440
- store,
441
- {
442
- key: `${options.key}/singleRelatedEntry`,
443
- get:
444
- (x) =>
445
- ({ get }) => {
446
- const relatedKeys = get(relatedKeysAtoms, x)
447
- for (const y of relatedKeys) {
448
- let a = relations.isAType?.(x) ? x : undefined
449
- let b = a === undefined ? (x as BType) : undefined
450
- a ??= y as AType
451
- b ??= y as BType
452
- const contentKey = relations.makeContentKey(a, b)
453
- const content = get(contentAtoms, contentKey)
454
- return [y, content]
455
- }
456
- return null
457
- },
458
- },
459
- [`join`, `entries`],
460
- )
461
- const getMultipleEntrySelectorFamily = () =>
462
- createReadonlyPureSelectorFamily<
463
- [string, ViewOf<Content>][],
464
- string,
465
- never
466
- >(
467
- store,
468
- {
469
- key: `${options.key}/multipleRelatedEntries`,
470
- get:
471
- (x) =>
472
- ({ get }) => {
473
- const jsonFamily = getJsonFamily(relatedKeysAtoms, store)
474
- const json = get(jsonFamily, x)
475
- return json.members.map((y) => {
476
- let a = relations.isAType?.(x) ? x : undefined
477
- let b = a === undefined ? (x as BType) : undefined
478
- a ??= y as AType
479
- b ??= y as BType
480
- const contentKey = relations.makeContentKey(a, b)
481
- const content = get(contentAtoms, contentKey)
482
- return [y, content]
483
- })
484
- },
485
- },
486
- [`join`, `entries`],
487
- )
488
289
 
489
290
  switch (options.cardinality) {
490
291
  case `1:1`: {
491
292
  const singleRelatedKeySelectors = createSingleKeySelectorFamily()
492
293
  const stateKeyA = `${aSide}KeyOf${capitalize(bSide)}` as const
493
294
  const stateKeyB = `${bSide}KeyOf${capitalize(aSide)}` as const
494
- const baseStates = {
295
+ this.relations = relations
296
+ this.states = {
495
297
  [stateKeyA]: singleRelatedKeySelectors,
496
298
  [stateKeyB]: singleRelatedKeySelectors,
497
- } as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
498
- let states: JoinStateFamilies<
499
- ASide,
500
- AType,
501
- BSide,
502
- BType,
503
- Cardinality,
504
- Content
505
- >
506
- if (defaultContent) {
507
- const singleEntrySelectors = createSingleEntrySelectorFamily()
508
- const entriesStateKeyA = `${aSide}EntryOf${capitalize(bSide)}` as const
509
- const entriesStateKeyB = `${bSide}EntryOf${capitalize(aSide)}` as const
510
- const contentStates = {
511
- [entriesStateKeyA]: singleEntrySelectors,
512
- [entriesStateKeyB]: singleEntrySelectors,
513
- }
514
- states = Object.assign(baseStates, contentStates)
515
- } else {
516
- states = baseStates
517
- }
518
- this.relations = relations
519
- this.states = states
299
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
520
300
  break
521
301
  }
522
302
  case `1:n`: {
@@ -527,70 +307,21 @@ export class Join<
527
307
  const baseStates = {
528
308
  [stateKeyA]: singleRelatedKeySelectors,
529
309
  [stateKeyB]: multipleRelatedKeysSelectors,
530
- } as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
531
- let states: JoinStateFamilies<
532
- ASide,
533
- AType,
534
- BSide,
535
- BType,
536
- Cardinality,
537
- Content
538
- >
539
- if (defaultContent) {
540
- const singleRelatedEntrySelectors = createSingleEntrySelectorFamily()
541
- const multipleRelatedEntriesSelectors =
542
- getMultipleEntrySelectorFamily()
543
- const entriesStateKeyA = `${aSide}EntryOf${capitalize(bSide)}` as const
544
- const entriesStateKeyB = `${bSide}EntriesOf${capitalize(
545
- aSide,
546
- )}` as const
547
- const contentStates = {
548
- [entriesStateKeyA]: singleRelatedEntrySelectors,
549
- [entriesStateKeyB]: multipleRelatedEntriesSelectors,
550
- }
551
- states = Object.assign(baseStates, contentStates)
552
- } else {
553
- states = baseStates
554
- }
310
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
311
+
555
312
  this.relations = relations
556
- this.states = states
313
+ this.states = baseStates
557
314
  break
558
315
  }
559
316
  case `n:n`: {
560
317
  const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily()
561
318
  const stateKeyA = `${aSide}KeysOf${capitalize(bSide)}` as const
562
319
  const stateKeyB = `${bSide}KeysOf${capitalize(aSide)}` as const
563
- const baseStates = {
320
+ this.relations = relations
321
+ this.states = {
564
322
  [stateKeyA]: multipleRelatedKeysSelectors,
565
323
  [stateKeyB]: multipleRelatedKeysSelectors,
566
- } as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
567
- let states: JoinStateFamilies<
568
- ASide,
569
- AType,
570
- BSide,
571
- BType,
572
- Cardinality,
573
- Content
574
- >
575
- if (defaultContent) {
576
- const multipleRelatedEntriesSelectors =
577
- getMultipleEntrySelectorFamily()
578
- const entriesStateKeyA = `${aSide}EntriesOf${capitalize(
579
- bSide,
580
- )}` as const
581
- const entriesStateKeyB = `${bSide}EntriesOf${capitalize(
582
- aSide,
583
- )}` as const
584
- const contentStates = {
585
- [entriesStateKeyA]: multipleRelatedEntriesSelectors,
586
- [entriesStateKeyB]: multipleRelatedEntriesSelectors,
587
- }
588
- states = Object.assign(baseStates, contentStates)
589
- } else {
590
- states = baseStates
591
- }
592
- this.relations = relations
593
- this.states = states
324
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
594
325
  }
595
326
  }
596
327
  }