atom.io 0.41.0 → 0.42.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 (52) hide show
  1. package/dist/internal/index.d.ts +21 -38
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +82 -263
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/main/index.d.ts +18 -36
  6. package/dist/main/index.d.ts.map +1 -1
  7. package/dist/main/index.js +13 -2
  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 +10 -6
  21. package/dist/transceivers/o-list/index.d.ts.map +1 -1
  22. package/dist/transceivers/o-list/index.js +170 -169
  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 +10 -6
  28. package/dist/transceivers/u-list/index.d.ts.map +1 -1
  29. package/dist/transceivers/u-list/index.js +23 -22
  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 +13 -9
  34. package/src/internal/index.ts +0 -1
  35. package/src/internal/join/create-join.ts +8 -11
  36. package/src/internal/join/edit-relations-in-store.ts +6 -8
  37. package/src/internal/join/find-relations-in-store.ts +11 -67
  38. package/src/internal/join/get-internal-relations-from-store.ts +11 -5
  39. package/src/internal/join/get-join.ts +7 -9
  40. package/src/internal/join/join-internal.ts +154 -394
  41. package/src/internal/mutable/transceiver.ts +1 -5
  42. package/src/internal/set-state/dispatch-state-update.ts +1 -1
  43. package/src/internal/store/store.ts +1 -1
  44. package/src/main/join.ts +68 -151
  45. package/src/main/realm.ts +4 -4
  46. package/src/realtime/shared-room-store.ts +5 -15
  47. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +1 -1
  48. package/src/struct/index.ts +1 -0
  49. package/src/{internal → struct}/micro.ts +1 -1
  50. package/src/transceivers/o-list/o-list.ts +175 -171
  51. package/src/transceivers/set-rtx/set-rtx.ts +4 -0
  52. package/src/transceivers/u-list/u-list.ts +37 -33
@@ -1,152 +1,83 @@
1
1
  import type {
2
- CompoundTypedKey,
3
2
  findState,
4
3
  getState,
5
4
  JoinOptions,
6
5
  MutableAtomFamilyToken,
7
- Read,
8
6
  ReadonlyPureSelectorFamilyToken,
9
- RegularAtomFamilyToken,
10
7
  setState,
11
- ViewOf,
12
8
  Write,
13
9
  WriterToolkit,
14
10
  } from "atom.io"
15
11
  import { Anarchy } from "atom.io"
16
- import type { Json } from "atom.io/json"
17
12
  import { stringifyJson } from "atom.io/json"
18
- import { SetRTX } from "atom.io/transceivers/set-rtx"
13
+ import { UList } from "atom.io/transceivers/u-list"
19
14
 
20
15
  import { capitalize } from "../capitalize"
21
- import {
22
- createReadonlyPureSelectorFamily,
23
- createRegularAtomFamily,
24
- findInStore,
25
- } from "../families"
16
+ import { createReadonlyPureSelectorFamily, findInStore } from "../families"
26
17
  import { getFromStore } from "../get-state"
27
- import type {
28
- BaseExternalStoreConfiguration,
29
- ExternalStoreConfiguration,
30
- } from "../junction"
18
+ import type { BaseExternalStoreConfiguration } from "../junction"
31
19
  import { Junction } from "../junction"
32
20
  import { createMutableAtomFamily, getJsonFamily, getJsonToken } from "../mutable"
33
- import { setIntoStore } from "../set-state"
21
+ import { JOIN_OP, operateOnStore, setIntoStore } from "../set-state"
34
22
  import type { Store } from "../store"
35
23
  import { IMPLICIT } from "../store"
36
24
  import type { RootStore } from "../transaction"
37
25
 
38
26
  export type JoinStateFamilies<
39
- ASide extends string,
40
- AType extends string,
41
- BSide extends string,
42
- BType extends string,
27
+ AName extends string,
28
+ A extends string,
29
+ BName extends string,
30
+ B extends string,
43
31
  Cardinality extends `1:1` | `1:n` | `n:n`,
44
- Content extends Json.Object | null,
45
32
  > = 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
33
+ ? {
34
+ readonly [N in AName as `${N}KeyOf${Capitalize<BName>}`]: ReadonlyPureSelectorFamilyToken<
35
+ A | null,
36
+ B
62
37
  >
63
38
  } & {
64
- readonly [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
65
- BType | null,
66
- AType
39
+ readonly [N in BName as `${N}KeyOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
40
+ B | null,
41
+ A
67
42
  >
68
43
  }
69
44
  : 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
45
+ ? {
46
+ readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
47
+ B[],
48
+ A
91
49
  >
92
50
  }
93
51
  : 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
52
+ ? {
53
+ readonly [N in AName as `${N}KeysOf${Capitalize<BName>}`]: ReadonlyPureSelectorFamilyToken<
54
+ A[],
55
+ B
110
56
  >
111
57
  } & {
112
- readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlyPureSelectorFamilyToken<
113
- BType[],
114
- AType
58
+ readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorFamilyToken<
59
+ B[],
60
+ A
115
61
  >
116
62
  }
117
63
  : never
118
64
 
119
65
  export class Join<
120
- const ASide extends string,
121
- const AType extends string,
122
- const BSide extends string,
123
- const BType extends string,
66
+ const AName extends string,
67
+ const A extends string,
68
+ const BName extends string,
69
+ const B extends string,
124
70
  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
71
  > {
132
72
  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
- }
73
+ public options: JoinOptions<AName, A, BName, B, Cardinality>
74
+ public relations: Junction<AName, A, BName, B>
75
+ public states: JoinStateFamilies<AName, A, BName, B, Cardinality>
76
+ public relatedKeysAtoms: MutableAtomFamilyToken<UList<string>, string>
77
+
147
78
  public transact(
148
79
  toolkit: WriterToolkit,
149
- run: (join: Join<ASide, AType, BSide, BType, Cardinality, Content>) => void,
80
+ run: (join: Join<AName, A, BName, B, Cardinality>) => void,
150
81
  ): void {
151
82
  const originalToolkit = this.toolkit
152
83
  this.toolkit = toolkit
@@ -160,16 +91,14 @@ export class Join<
160
91
  public [Symbol.dispose](): void {}
161
92
 
162
93
  public constructor(
163
- options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
164
- defaultContent: Content | undefined,
94
+ options: JoinOptions<AName, A, BName, B, Cardinality>,
165
95
  store: RootStore = IMPLICIT.STORE,
166
96
  ) {
167
- type AnyKey = AType & BType
97
+ type AB = A & B
168
98
 
169
99
  this.store = store
170
100
  this.realm = new Anarchy(store)
171
101
  this.options = options
172
- this.defaultContent = defaultContent
173
102
 
174
103
  this.store.miscResources.set(`join:${options.key}`, this)
175
104
 
@@ -186,49 +115,18 @@ export class Join<
186
115
  json: (token) => getJsonToken(store, token),
187
116
  }
188
117
 
189
- const aSide: ASide = options.between[0]
190
- const bSide: BSide = options.between[1]
191
- const relatedKeysAtoms = createMutableAtomFamily<SetRTX<string>, string>(
118
+ const aSide: AName = options.between[0]
119
+ const bSide: BName = options.between[1]
120
+ const relatedKeysAtoms = createMutableAtomFamily<UList<string>, string>(
192
121
  store,
193
122
  {
194
123
  key: `${options.key}/relatedKeys`,
195
- class: SetRTX,
124
+ class: UList,
196
125
  },
197
126
  [`join`, `relations`],
198
127
  )
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
- }
128
+ this.relatedKeysAtoms = relatedKeysAtoms
129
+
232
130
  const replaceRelationsSafely: Write<
233
131
  (a: string, newRelationsOfA: string[]) => void
234
132
  > = (toolkit, a, newRelationsOfA) => {
@@ -246,42 +144,56 @@ export class Join<
246
144
  })
247
145
  }
248
146
  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
- }
268
- }
269
- if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0) {
270
- relationsOfB.clear()
147
+ // relationsOfA.transaction((nextRelationsOfA) => {
148
+ relationsOfA.clear()
149
+ for (const newRelationB of newRelationsOfA) {
150
+ const relationsOfBAtom = find(relatedKeysAtoms, newRelationB)
151
+ const relationsOfB = get(relationsOfBAtom)
152
+ const newRelationBIsAlreadyRelated = relationsOfB.has(a as AB)
153
+ if (this.relations.cardinality === `1:n`) {
154
+ const previousOwnersToDispose: string[] = []
155
+ for (const previousOwner of relationsOfB) {
156
+ if (previousOwner === a) {
157
+ continue
271
158
  }
272
- for (const previousOwner of previousOwnersToDispose) {
273
- const [x, y] = [newRelationB, previousOwner].sort()
274
- const compositeKey = `${x}:${y}`
275
- store.moleculeJoins.delete(compositeKey)
159
+ let previousOwnerSize: number | undefined
160
+ operateOnStore(
161
+ JOIN_OP,
162
+ this.store,
163
+ relatedKeysAtoms,
164
+ previousOwner,
165
+ (relations) => {
166
+ relations.delete(newRelationB as AB)
167
+ previousOwnerSize = relations.size
168
+ return relations
169
+ },
170
+ )
171
+ if (previousOwnerSize === 0) {
172
+ previousOwnersToDispose.push(previousOwner)
276
173
  }
277
174
  }
278
- if (!newRelationBIsAlreadyRelated) {
279
- relationsOfB.add(a as AnyKey)
175
+ if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0) {
176
+ set(relationsOfBAtom, (relations) => {
177
+ relations.clear()
178
+ return relations
179
+ })
180
+ }
181
+ for (const previousOwner of previousOwnersToDispose) {
182
+ const [x, y] = [newRelationB, previousOwner].sort()
183
+ const compositeKey = `${x}:${y}`
184
+ store.moleculeJoins.delete(compositeKey)
280
185
  }
281
- nextRelationsOfA.add(newRelationB)
282
186
  }
283
- return true
284
- })
187
+ if (!newRelationBIsAlreadyRelated) {
188
+ set(relationsOfBAtom, (relations) => {
189
+ relations.add(a as AB)
190
+ return relations
191
+ })
192
+ }
193
+ relationsOfA.add(newRelationB)
194
+ }
195
+ // return true
196
+ // })
285
197
  return relationsOfA
286
198
  })
287
199
  }
@@ -290,12 +202,12 @@ export class Join<
290
202
  > = (toolkit, a, newRelationsOfA) => {
291
203
  const { set } = toolkit
292
204
  set(relatedKeysAtoms, a, (relationsOfA) => {
293
- relationsOfA.transaction((nextRelationsOfA) => {
294
- for (const newRelationB of newRelationsOfA) {
295
- nextRelationsOfA.add(newRelationB)
296
- }
297
- return true
298
- })
205
+ // relationsOfA.transaction((nextRelationsOfA) => {
206
+ for (const newRelationB of newRelationsOfA) {
207
+ relationsOfA.add(newRelationB)
208
+ }
209
+ // return true
210
+ // })
299
211
  return relationsOfA
300
212
  })
301
213
  for (const newRelationB of newRelationsOfA) {
@@ -306,19 +218,33 @@ export class Join<
306
218
  }
307
219
  return true
308
220
  }
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
221
  const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
314
- getRelatedKeys: (key) => getRelatedKeys(this.toolkit, key),
222
+ getRelatedKeys: (key) =>
223
+ this.toolkit.get(relatedKeysAtoms, key) as UList<A> | UList<B>,
315
224
  addRelation: (a, b) => {
316
225
  this.store.moleculeJoins.set(`"${a}"`, options.key)
317
226
  this.store.moleculeJoins.set(`"${b}"`, options.key)
318
- addRelation(this.toolkit, a, b)
227
+ if (!this.store.molecules.has(stringifyJson(a))) {
228
+ this.realm.allocate(options.key, a)
229
+ }
230
+ if (!this.store.molecules.has(stringifyJson(b))) {
231
+ this.realm.allocate(options.key, b)
232
+ }
233
+ this.toolkit.set(relatedKeysAtoms, a, (aKeys) => aKeys.add(b))
234
+ this.toolkit.set(relatedKeysAtoms, b, (bKeys) => bKeys.add(a))
319
235
  },
320
236
  deleteRelation: (a, b) => {
321
- deleteRelation(this.toolkit, a, b)
237
+ this.toolkit.set(relatedKeysAtoms, a, (aKeys) => {
238
+ aKeys.delete(b)
239
+ return aKeys
240
+ })
241
+ this.toolkit.set(relatedKeysAtoms, b, (bKeys) => {
242
+ bKeys.delete(a)
243
+ return bKeys
244
+ })
245
+ const [x, y] = [a, b].sort()
246
+ const compositeKey = `${x}:${y}`
247
+ this.store.moleculeJoins.delete(compositeKey)
322
248
  },
323
249
  replaceRelationsSafely: (a, bs) => {
324
250
  replaceRelationsSafely(this.toolkit, a, bs)
@@ -326,77 +252,35 @@ export class Join<
326
252
  replaceRelationsUnsafely: (a, bs) => {
327
253
  replaceRelationsUnsafely(this.toolkit, a, bs)
328
254
  },
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>
255
+ has: (a, b) => {
256
+ const aKeys = this.toolkit.get(relatedKeysAtoms, a)
257
+ return b ? aKeys.has(b as AB) : aKeys.size > 0
258
+ },
373
259
  }
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
- }
260
+ const externalStore = baseExternalStoreConfiguration
261
+ const relations = new Junction<AName, A, BName, B>(options as any, {
262
+ externalStore,
263
+ isAType: options.isAType,
264
+ isBType: options.isBType,
265
+ // makeContentKey: (...args) => {
266
+ // const [a, b] = args
267
+ // const [x, y] = args.sort()
268
+ // const compositeKey = `${x}:${y}`
269
+ // const aMolecule = store.molecules.get(stringifyJson(a))
270
+ // const bMolecule = store.molecules.get(stringifyJson(b))
271
+ // if (!aMolecule) {
272
+ // this.realm.allocate(options.key, a)
273
+ // }
274
+ // if (!bMolecule) {
275
+ // this.realm.allocate(options.key, b)
276
+ // }
392
277
 
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
- },
398
- },
399
- )
278
+ // this.realm.allocate(a, compositeKey, `all`)
279
+ // this.realm.claim(b, compositeKey)
280
+ // this.store.moleculeJoins.set(compositeKey, options.key)
281
+ // return compositeKey
282
+ // },
283
+ })
400
284
 
401
285
  const createSingleKeySelectorFamily = () =>
402
286
  createReadonlyPureSelectorFamily<string | null, string, never>(
@@ -416,7 +300,7 @@ export class Join<
416
300
  [`join`, `keys`],
417
301
  )
418
302
  const getMultipleKeySelectorFamily = () => {
419
- return createReadonlyPureSelectorFamily<string[], string, never>(
303
+ return createReadonlyPureSelectorFamily<readonly string[], string, never>(
420
304
  store,
421
305
  {
422
306
  key: `${options.key}/multipleRelatedKeys`,
@@ -425,98 +309,23 @@ export class Join<
425
309
  ({ get }) => {
426
310
  const jsonFamily = getJsonFamily(relatedKeysAtoms, store)
427
311
  const json = get(jsonFamily, key)
428
- return json.members
312
+ return json
429
313
  },
430
314
  },
431
315
  [`join`, `keys`],
432
316
  )
433
317
  }
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
318
 
489
319
  switch (options.cardinality) {
490
320
  case `1:1`: {
491
321
  const singleRelatedKeySelectors = createSingleKeySelectorFamily()
492
322
  const stateKeyA = `${aSide}KeyOf${capitalize(bSide)}` as const
493
323
  const stateKeyB = `${bSide}KeyOf${capitalize(aSide)}` as const
494
- const baseStates = {
324
+ this.relations = relations
325
+ this.states = {
495
326
  [stateKeyA]: singleRelatedKeySelectors,
496
327
  [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
328
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
520
329
  break
521
330
  }
522
331
  case `1:n`: {
@@ -527,70 +336,21 @@ export class Join<
527
336
  const baseStates = {
528
337
  [stateKeyA]: singleRelatedKeySelectors,
529
338
  [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
- }
339
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
340
+
555
341
  this.relations = relations
556
- this.states = states
342
+ this.states = baseStates
557
343
  break
558
344
  }
559
345
  case `n:n`: {
560
346
  const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily()
561
347
  const stateKeyA = `${aSide}KeysOf${capitalize(bSide)}` as const
562
348
  const stateKeyB = `${bSide}KeysOf${capitalize(aSide)}` as const
563
- const baseStates = {
349
+ this.relations = relations
350
+ this.states = {
564
351
  [stateKeyA]: multipleRelatedKeysSelectors,
565
352
  [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
353
+ } as JoinStateFamilies<AName, A, BName, B, Cardinality>
594
354
  }
595
355
  }
596
356
  }