atom.io 0.30.0 → 0.30.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/data/dist/index.d.ts +84 -51
- package/data/dist/index.js +45 -39
- package/data/src/join.ts +250 -142
- package/dist/chunk-ADMEAXYU.js +167 -0
- package/dist/{chunk-7PUUHSXC.js → chunk-LSCRHXLI.js} +67 -176
- package/dist/index.d.ts +53 -5
- package/dist/index.js +1 -1
- package/internal/dist/index.d.ts +64 -35
- package/internal/dist/index.js +2 -2
- package/internal/src/junction.ts +170 -86
- package/internal/src/molecule/make-molecule-in-store.ts +3 -1
- package/internal/src/molecule/molecule-internal.ts +1 -1
- package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
- package/internal/src/mutable/get-json-family.ts +2 -2
- package/internal/src/store/store.ts +4 -0
- package/internal/src/transaction/index.ts +1 -1
- package/json/dist/index.js +2 -2
- package/package.json +15 -15
- package/realtime/dist/index.d.ts +1 -1
- package/realtime/dist/index.js +3 -1
- package/realtime/src/shared-room-store.ts +2 -0
- package/realtime-server/dist/index.d.ts +15 -6
- package/realtime-server/dist/index.js +4 -2
- package/realtime-server/src/realtime-continuity-synchronizer.ts +2 -2
- package/realtime-server/src/realtime-server-stores/server-user-store.ts +21 -5
- package/realtime-testing/dist/index.d.ts +3 -0
- package/realtime-testing/dist/index.js +17 -6
- package/realtime-testing/src/setup-realtime-test.tsx +16 -6
- package/src/allocate.ts +7 -8
- package/src/index.ts +1 -0
- package/src/molecule.ts +5 -3
- package/dist/chunk-ZKG6ZA4I.js +0 -20
package/data/src/join.ts
CHANGED
|
@@ -19,10 +19,9 @@ import type { seekState } from "atom.io/immortal"
|
|
|
19
19
|
import type {
|
|
20
20
|
BaseExternalStoreConfiguration,
|
|
21
21
|
ExternalStoreConfiguration,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
JunctionEntriesBase,
|
|
23
|
+
JunctionSchemaBase,
|
|
24
24
|
Molecule,
|
|
25
|
-
// RelationCardinality,
|
|
26
25
|
Store,
|
|
27
26
|
} from "atom.io/internal"
|
|
28
27
|
import {
|
|
@@ -46,7 +45,9 @@ import {
|
|
|
46
45
|
setIntoStore,
|
|
47
46
|
withdraw,
|
|
48
47
|
} from "atom.io/internal"
|
|
49
|
-
import
|
|
48
|
+
import type { Refinement } from "atom.io/introspection"
|
|
49
|
+
import type { Json } from "atom.io/json"
|
|
50
|
+
import { stringifyJson } from "atom.io/json"
|
|
50
51
|
import type { SetRTXJson } from "atom.io/transceivers/set-rtx"
|
|
51
52
|
import { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
52
53
|
|
|
@@ -56,96 +57,122 @@ function capitalize<S extends string>(string: S): Capitalize<S> {
|
|
|
56
57
|
|
|
57
58
|
export interface JoinOptions<
|
|
58
59
|
ASide extends string,
|
|
60
|
+
AType extends string,
|
|
59
61
|
BSide extends string,
|
|
62
|
+
BType extends string,
|
|
60
63
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
61
64
|
Content extends Json.Object | null,
|
|
62
|
-
> extends
|
|
63
|
-
|
|
64
|
-
Partial<JunctionEntries<Content>> {
|
|
65
|
+
> extends JunctionSchemaBase<ASide, BSide>,
|
|
66
|
+
Partial<JunctionEntriesBase<AType, BType, Content>> {
|
|
65
67
|
readonly key: string
|
|
66
68
|
readonly cardinality: Cardinality
|
|
69
|
+
readonly isAType: Refinement<string, AType>
|
|
70
|
+
readonly isBType: Refinement<string, BType>
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
export type JoinStateFamilies<
|
|
70
74
|
ASide extends string,
|
|
75
|
+
AType extends string,
|
|
71
76
|
BSide extends string,
|
|
77
|
+
BType extends string,
|
|
72
78
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
73
79
|
Content extends Json.Object | null,
|
|
74
80
|
> = Cardinality extends `1:1`
|
|
75
81
|
? (Content extends Json.Object
|
|
76
82
|
? {
|
|
77
|
-
readonly [
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
84
|
+
[AType, Content] | null,
|
|
85
|
+
BType
|
|
86
|
+
>
|
|
87
|
+
} & {
|
|
88
|
+
readonly [B in BSide as `${B}EntryOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
89
|
+
[BType, Content] | null,
|
|
90
|
+
AType
|
|
82
91
|
>
|
|
83
92
|
}
|
|
84
93
|
: {}) & {
|
|
85
|
-
readonly [
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
95
|
+
AType | null,
|
|
96
|
+
BType
|
|
97
|
+
>
|
|
98
|
+
} & {
|
|
99
|
+
readonly [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
100
|
+
BType | null,
|
|
101
|
+
AType
|
|
90
102
|
>
|
|
91
103
|
}
|
|
92
104
|
: Cardinality extends `1:n`
|
|
93
105
|
? (Content extends Json.Object
|
|
94
106
|
? {
|
|
95
107
|
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
96
|
-
[
|
|
97
|
-
|
|
108
|
+
[AType, Content] | null,
|
|
109
|
+
BType
|
|
98
110
|
>
|
|
99
111
|
} & {
|
|
100
112
|
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
101
|
-
[
|
|
102
|
-
|
|
113
|
+
[BType, Content][],
|
|
114
|
+
AType
|
|
103
115
|
>
|
|
104
116
|
}
|
|
105
117
|
: {}) & {
|
|
106
118
|
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
107
|
-
|
|
108
|
-
|
|
119
|
+
AType | null,
|
|
120
|
+
BType
|
|
109
121
|
>
|
|
110
122
|
} & {
|
|
111
123
|
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
BType[],
|
|
125
|
+
AType
|
|
114
126
|
>
|
|
115
127
|
}
|
|
116
128
|
: Cardinality extends `n:n`
|
|
117
129
|
? (Content extends Json.Object
|
|
118
130
|
? {
|
|
119
|
-
readonly [
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
readonly [A in ASide as `${A}EntriesOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
132
|
+
[AType, Content][],
|
|
133
|
+
BType
|
|
134
|
+
>
|
|
135
|
+
} & {
|
|
136
|
+
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
137
|
+
[BType, Content][],
|
|
138
|
+
AType
|
|
124
139
|
>
|
|
125
140
|
}
|
|
126
141
|
: {}) & {
|
|
127
|
-
readonly [
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
readonly [A in ASide as `${A}KeysOf${Capitalize<BSide>}`]: ReadonlySelectorFamilyToken<
|
|
143
|
+
AType[],
|
|
144
|
+
BType
|
|
145
|
+
>
|
|
146
|
+
} & {
|
|
147
|
+
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorFamilyToken<
|
|
148
|
+
BType[],
|
|
149
|
+
AType
|
|
132
150
|
>
|
|
133
151
|
}
|
|
134
152
|
: never
|
|
135
153
|
|
|
136
154
|
export class Join<
|
|
137
155
|
const ASide extends string,
|
|
156
|
+
const AType extends string,
|
|
138
157
|
const BSide extends string,
|
|
158
|
+
const BType extends string,
|
|
139
159
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
140
160
|
const Content extends Json.Object | null = null,
|
|
141
161
|
> {
|
|
142
|
-
private options: JoinOptions<ASide, BSide, Cardinality, Content>
|
|
162
|
+
private options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>
|
|
143
163
|
private defaultContent: Content | undefined
|
|
144
164
|
private toolkit: SetterToolkit & { dispose: typeof disposeState }
|
|
145
165
|
public retrieve: typeof findState
|
|
146
166
|
public molecules: Map<string, Molecule<any>> = new Map()
|
|
147
|
-
public relations: Junction<ASide, BSide, Content>
|
|
148
|
-
public states: JoinStateFamilies<
|
|
167
|
+
public relations: Junction<ASide, AType, BSide, BType, Content>
|
|
168
|
+
public states: JoinStateFamilies<
|
|
169
|
+
ASide,
|
|
170
|
+
AType,
|
|
171
|
+
BSide,
|
|
172
|
+
BType,
|
|
173
|
+
Cardinality,
|
|
174
|
+
Content
|
|
175
|
+
>
|
|
149
176
|
public core: {
|
|
150
177
|
findRelatedKeysState: MutableAtomFamilyToken<
|
|
151
178
|
SetRTX<string>,
|
|
@@ -155,7 +182,7 @@ export class Join<
|
|
|
155
182
|
}
|
|
156
183
|
public transact(
|
|
157
184
|
toolkit: SetterToolkit & { dispose: typeof disposeState },
|
|
158
|
-
run: (join: Join<ASide, BSide, Cardinality, Content>) => void,
|
|
185
|
+
run: (join: Join<ASide, AType, BSide, BType, Cardinality, Content>) => void,
|
|
159
186
|
): void {
|
|
160
187
|
const originalToolkit = this.toolkit
|
|
161
188
|
this.toolkit = toolkit
|
|
@@ -164,12 +191,17 @@ export class Join<
|
|
|
164
191
|
}
|
|
165
192
|
|
|
166
193
|
public store: Store
|
|
167
|
-
public alternates: Map<
|
|
194
|
+
public alternates: Map<
|
|
195
|
+
string,
|
|
196
|
+
Join<ASide, AType, BSide, BType, Cardinality, Content>
|
|
197
|
+
>
|
|
168
198
|
public [Symbol.dispose](): void {
|
|
169
199
|
this.alternates.delete(this.store.config.name)
|
|
170
200
|
}
|
|
171
201
|
|
|
172
|
-
public in(
|
|
202
|
+
public in(
|
|
203
|
+
store: Store,
|
|
204
|
+
): Join<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
173
205
|
const key = store.config.name
|
|
174
206
|
const alternate = this.alternates.get(key)
|
|
175
207
|
if (alternate) {
|
|
@@ -182,10 +214,12 @@ export class Join<
|
|
|
182
214
|
}
|
|
183
215
|
|
|
184
216
|
public constructor(
|
|
185
|
-
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
217
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
186
218
|
defaultContent: Content | undefined,
|
|
187
219
|
store: Store = IMPLICIT.STORE,
|
|
188
220
|
) {
|
|
221
|
+
type AnyKey = AType & BType
|
|
222
|
+
|
|
189
223
|
this.store = store
|
|
190
224
|
this.options = options
|
|
191
225
|
this.defaultContent = defaultContent
|
|
@@ -202,7 +236,7 @@ export class Join<
|
|
|
202
236
|
if (maybeToken) {
|
|
203
237
|
return maybeToken
|
|
204
238
|
}
|
|
205
|
-
const molecule = this.molecules.get(stringifyJson(key))
|
|
239
|
+
const molecule = this.store.molecules.get(stringifyJson(key))
|
|
206
240
|
if (molecule) {
|
|
207
241
|
const family = withdraw(token, store)
|
|
208
242
|
return growMoleculeInStore(molecule, family, store)
|
|
@@ -245,10 +279,9 @@ export class Join<
|
|
|
245
279
|
[`join`, `relations`],
|
|
246
280
|
)
|
|
247
281
|
this.core = { findRelatedKeysState: relatedKeysAtoms }
|
|
248
|
-
const getRelatedKeys: Read<
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
) => get(this.retrieve(relatedKeysAtoms, key))
|
|
282
|
+
const getRelatedKeys: Read<
|
|
283
|
+
(key: string) => SetRTX<AType> | SetRTX<BType>
|
|
284
|
+
> = ({ get }, key) => get(this.retrieve(relatedKeysAtoms, key) as any)
|
|
252
285
|
const addRelation: Write<(a: string, b: string) => void> = (
|
|
253
286
|
toolkit,
|
|
254
287
|
a,
|
|
@@ -310,7 +343,7 @@ export class Join<
|
|
|
310
343
|
nextRelationsOfA.clear()
|
|
311
344
|
for (const newRelationB of newRelationsOfA) {
|
|
312
345
|
const relationsOfB = getRelatedKeys(toolkit, newRelationB)
|
|
313
|
-
const newRelationBIsAlreadyRelated = relationsOfB.has(a)
|
|
346
|
+
const newRelationBIsAlreadyRelated = relationsOfB.has(a as AnyKey)
|
|
314
347
|
if (this.relations.cardinality === `1:n`) {
|
|
315
348
|
const previousOwnersToDispose: string[] = []
|
|
316
349
|
for (const previousOwner of relationsOfB) {
|
|
@@ -321,7 +354,7 @@ export class Join<
|
|
|
321
354
|
toolkit,
|
|
322
355
|
previousOwner,
|
|
323
356
|
)
|
|
324
|
-
previousOwnerRelations.delete(newRelationB)
|
|
357
|
+
previousOwnerRelations.delete(newRelationB as AnyKey)
|
|
325
358
|
if (previousOwnerRelations.size === 0) {
|
|
326
359
|
previousOwnersToDispose.push(previousOwner)
|
|
327
360
|
}
|
|
@@ -336,7 +369,7 @@ export class Join<
|
|
|
336
369
|
}
|
|
337
370
|
}
|
|
338
371
|
if (!newRelationBIsAlreadyRelated) {
|
|
339
|
-
relationsOfB.add(a)
|
|
372
|
+
relationsOfB.add(a as AnyKey)
|
|
340
373
|
}
|
|
341
374
|
nextRelationsOfA.add(newRelationB)
|
|
342
375
|
}
|
|
@@ -370,7 +403,7 @@ export class Join<
|
|
|
370
403
|
}
|
|
371
404
|
const has: Read<(a: string, b?: string) => boolean> = (toolkit, a, b) => {
|
|
372
405
|
const aKeys = getRelatedKeys(toolkit, a)
|
|
373
|
-
return b ? aKeys.has(b) : aKeys.size > 0
|
|
406
|
+
return b ? aKeys.has(b as AnyKey) : aKeys.size > 0
|
|
374
407
|
}
|
|
375
408
|
const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
|
|
376
409
|
getRelatedKeys: (key) => getRelatedKeys(this.toolkit, key),
|
|
@@ -404,13 +437,6 @@ export class Join<
|
|
|
404
437
|
},
|
|
405
438
|
[`join`, `content`],
|
|
406
439
|
)
|
|
407
|
-
const joinToken = {
|
|
408
|
-
key: options.key,
|
|
409
|
-
type: `join`,
|
|
410
|
-
a: options.between[0],
|
|
411
|
-
b: options.between[1],
|
|
412
|
-
cardinality: options.cardinality,
|
|
413
|
-
} as const satisfies JoinToken<ASide, BSide, Cardinality, Content>
|
|
414
440
|
contentMolecules = createMoleculeFamily(store, {
|
|
415
441
|
key: `${options.key}/content-molecules`,
|
|
416
442
|
new: class ContentMolecule {
|
|
@@ -459,30 +485,35 @@ export class Join<
|
|
|
459
485
|
externalStore =
|
|
460
486
|
baseExternalStoreConfiguration as ExternalStoreConfiguration<Content>
|
|
461
487
|
}
|
|
462
|
-
const relations = new Junction<ASide, BSide, Content>(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
target,
|
|
474
|
-
[m0, m1],
|
|
475
|
-
contentMolecules,
|
|
476
|
-
compositeKey,
|
|
477
|
-
)
|
|
478
|
-
this.molecules.set(
|
|
479
|
-
`"${compositeKey}"`,
|
|
480
|
-
withdraw(moleculeToken, target),
|
|
488
|
+
const relations = new Junction<ASide, AType, BSide, BType, Content>(
|
|
489
|
+
options as any,
|
|
490
|
+
{
|
|
491
|
+
externalStore,
|
|
492
|
+
isAType: options.isAType,
|
|
493
|
+
isBType: options.isBType,
|
|
494
|
+
makeContentKey: (...args) => {
|
|
495
|
+
const sorted = args.sort()
|
|
496
|
+
const compositeKey = `${sorted[0]}:${sorted[1]}`
|
|
497
|
+
const [m0, m1] = sorted.map((key) =>
|
|
498
|
+
this.molecules.get(stringifyJson(key)),
|
|
481
499
|
)
|
|
482
|
-
|
|
483
|
-
|
|
500
|
+
if (store.config.lifespan === `immortal` && m0 && m1) {
|
|
501
|
+
const target = newest(store)
|
|
502
|
+
const moleculeToken = makeMoleculeInStore(
|
|
503
|
+
target,
|
|
504
|
+
[m0, m1],
|
|
505
|
+
contentMolecules,
|
|
506
|
+
compositeKey,
|
|
507
|
+
)
|
|
508
|
+
this.molecules.set(
|
|
509
|
+
`"${compositeKey}"`,
|
|
510
|
+
withdraw(moleculeToken, target),
|
|
511
|
+
)
|
|
512
|
+
}
|
|
513
|
+
return compositeKey
|
|
514
|
+
},
|
|
484
515
|
},
|
|
485
|
-
|
|
516
|
+
)
|
|
486
517
|
|
|
487
518
|
const createSingleKeyStateFamily = () =>
|
|
488
519
|
createReadonlySelectorFamily<string | null, string>(
|
|
@@ -525,15 +556,19 @@ export class Join<
|
|
|
525
556
|
{
|
|
526
557
|
key: `${options.key}/singleRelatedEntry`,
|
|
527
558
|
get:
|
|
528
|
-
(
|
|
559
|
+
(x) =>
|
|
529
560
|
({ get }) => {
|
|
530
|
-
const relatedKeysState = this.retrieve(relatedKeysAtoms,
|
|
561
|
+
const relatedKeysState = this.retrieve(relatedKeysAtoms, x)
|
|
531
562
|
const relatedKeys = get(relatedKeysState)
|
|
532
|
-
for (const
|
|
533
|
-
|
|
563
|
+
for (const y of relatedKeys) {
|
|
564
|
+
let a = relations.isAType?.(x) ? x : undefined
|
|
565
|
+
let b = a === undefined ? (x as BType) : undefined
|
|
566
|
+
a ??= y as AType
|
|
567
|
+
b ??= y as BType
|
|
568
|
+
const contentKey = relations.makeContentKey(a, b)
|
|
534
569
|
const contentState = this.retrieve(contentAtoms, contentKey)
|
|
535
570
|
const content = get(contentState)
|
|
536
|
-
return [
|
|
571
|
+
return [y, content]
|
|
537
572
|
}
|
|
538
573
|
return null
|
|
539
574
|
},
|
|
@@ -546,16 +581,20 @@ export class Join<
|
|
|
546
581
|
{
|
|
547
582
|
key: `${options.key}/multipleRelatedEntries`,
|
|
548
583
|
get:
|
|
549
|
-
(
|
|
584
|
+
(x) =>
|
|
550
585
|
({ get }) => {
|
|
551
586
|
const jsonFamily = getJsonFamily(relatedKeysAtoms, store)
|
|
552
|
-
const jsonState = this.retrieve(jsonFamily,
|
|
587
|
+
const jsonState = this.retrieve(jsonFamily, x)
|
|
553
588
|
const json = get(jsonState)
|
|
554
|
-
return json.members.map((
|
|
555
|
-
|
|
589
|
+
return json.members.map((y) => {
|
|
590
|
+
let a = relations.isAType?.(x) ? x : undefined
|
|
591
|
+
let b = a === undefined ? (x as BType) : undefined
|
|
592
|
+
a ??= y as AType
|
|
593
|
+
b ??= y as BType
|
|
594
|
+
const contentKey = relations.makeContentKey(a, b)
|
|
556
595
|
const contentState = this.retrieve(contentAtoms, contentKey)
|
|
557
596
|
const content = get(contentState)
|
|
558
|
-
return [
|
|
597
|
+
return [y, content]
|
|
559
598
|
})
|
|
560
599
|
},
|
|
561
600
|
},
|
|
@@ -570,8 +609,15 @@ export class Join<
|
|
|
570
609
|
const baseStates = {
|
|
571
610
|
[stateKeyA]: findSingleRelatedKeyState,
|
|
572
611
|
[stateKeyB]: findSingleRelatedKeyState,
|
|
573
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
574
|
-
let states: JoinStateFamilies<
|
|
612
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
613
|
+
let states: JoinStateFamilies<
|
|
614
|
+
ASide,
|
|
615
|
+
AType,
|
|
616
|
+
BSide,
|
|
617
|
+
BType,
|
|
618
|
+
Cardinality,
|
|
619
|
+
Content
|
|
620
|
+
>
|
|
575
621
|
if (defaultContent) {
|
|
576
622
|
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
577
623
|
const entriesStateKeyA = `${aSide}EntryOf${capitalize(bSide)}` as const
|
|
@@ -596,8 +642,15 @@ export class Join<
|
|
|
596
642
|
const baseStates = {
|
|
597
643
|
[stateKeyA]: findSingleRelatedKeyState,
|
|
598
644
|
[stateKeyB]: findMultipleRelatedKeysState,
|
|
599
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
600
|
-
let states: JoinStateFamilies<
|
|
645
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
646
|
+
let states: JoinStateFamilies<
|
|
647
|
+
ASide,
|
|
648
|
+
AType,
|
|
649
|
+
BSide,
|
|
650
|
+
BType,
|
|
651
|
+
Cardinality,
|
|
652
|
+
Content
|
|
653
|
+
>
|
|
601
654
|
if (defaultContent) {
|
|
602
655
|
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
603
656
|
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
@@ -624,8 +677,15 @@ export class Join<
|
|
|
624
677
|
const baseStates = {
|
|
625
678
|
[stateKeyA]: findMultipleRelatedKeysState,
|
|
626
679
|
[stateKeyB]: findMultipleRelatedKeysState,
|
|
627
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
628
|
-
let states: JoinStateFamilies<
|
|
680
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
681
|
+
let states: JoinStateFamilies<
|
|
682
|
+
ASide,
|
|
683
|
+
AType,
|
|
684
|
+
BSide,
|
|
685
|
+
BType,
|
|
686
|
+
Cardinality,
|
|
687
|
+
Content
|
|
688
|
+
>
|
|
629
689
|
if (defaultContent) {
|
|
630
690
|
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
631
691
|
const entriesStateKeyA = `${aSide}EntriesOf${capitalize(
|
|
@@ -651,7 +711,9 @@ export class Join<
|
|
|
651
711
|
|
|
652
712
|
export type JoinToken<
|
|
653
713
|
ASide extends string,
|
|
714
|
+
AType extends string,
|
|
654
715
|
BSide extends string,
|
|
716
|
+
BType extends string,
|
|
655
717
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
656
718
|
Content extends Json.Object | null = null,
|
|
657
719
|
> = {
|
|
@@ -660,41 +722,49 @@ export type JoinToken<
|
|
|
660
722
|
cardinality: Cardinality
|
|
661
723
|
a: ASide
|
|
662
724
|
b: BSide
|
|
725
|
+
__aType?: AType
|
|
726
|
+
__bType?: BType
|
|
663
727
|
__content?: Content
|
|
664
728
|
}
|
|
665
729
|
|
|
666
730
|
export function join<
|
|
667
731
|
const ASide extends string,
|
|
732
|
+
const AType extends string,
|
|
668
733
|
const BSide extends string,
|
|
734
|
+
const BType extends string,
|
|
669
735
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
670
736
|
>(
|
|
671
|
-
options: JoinOptions<ASide, BSide, Cardinality, null>,
|
|
737
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, null>,
|
|
672
738
|
defaultContent?: undefined,
|
|
673
739
|
store?: Store,
|
|
674
|
-
): JoinToken<ASide, BSide, Cardinality, null>
|
|
740
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, null>
|
|
675
741
|
export function join<
|
|
676
742
|
const ASide extends string,
|
|
743
|
+
const AType extends string,
|
|
677
744
|
const BSide extends string,
|
|
745
|
+
const BType extends string,
|
|
678
746
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
679
747
|
const Content extends Json.Object,
|
|
680
748
|
>(
|
|
681
|
-
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
749
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
682
750
|
defaultContent: Content,
|
|
683
751
|
store?: Store,
|
|
684
|
-
): JoinToken<ASide, BSide, Cardinality, Content>
|
|
752
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content>
|
|
685
753
|
export function join<
|
|
686
754
|
ASide extends string,
|
|
755
|
+
AType extends string,
|
|
687
756
|
BSide extends string,
|
|
757
|
+
BType extends string,
|
|
688
758
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
689
759
|
Content extends Json.Object,
|
|
690
760
|
>(
|
|
691
|
-
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
761
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
692
762
|
defaultContent: Content | undefined,
|
|
693
763
|
store: Store = IMPLICIT.STORE,
|
|
694
|
-
): JoinToken<ASide, BSide, Cardinality, Content> {
|
|
764
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
695
765
|
const joins = getJoinMap(store)
|
|
696
766
|
joins.set(options.key, new Join(options, defaultContent, store))
|
|
697
|
-
const token: JoinToken<ASide, BSide, Cardinality, Content> = {
|
|
767
|
+
const token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content> = {
|
|
698
768
|
key: options.key,
|
|
699
769
|
type: `join`,
|
|
700
770
|
a: options.between[0],
|
|
@@ -705,24 +775,26 @@ export function join<
|
|
|
705
775
|
}
|
|
706
776
|
|
|
707
777
|
export function getJoinMap(
|
|
708
|
-
store: Store & { joins?: Map<string, Join<any, any, any, any>> },
|
|
709
|
-
): Map<string, Join<any, any, any, any>> {
|
|
778
|
+
store: Store & { joins?: Map<string, Join<any, any, any, any, any, any>> },
|
|
779
|
+
): Map<string, Join<any, any, any, any, any, any>> {
|
|
710
780
|
if (`joins` in store && store.joins instanceof Map) {
|
|
711
781
|
return store.joins
|
|
712
782
|
}
|
|
713
|
-
const joins = new Map<string, Join<any, any, any, any>>()
|
|
783
|
+
const joins = new Map<string, Join<any, any, any, any, any, any>>()
|
|
714
784
|
store.joins = joins
|
|
715
785
|
return joins
|
|
716
786
|
}
|
|
717
787
|
export function getJoin<
|
|
718
788
|
ASide extends string,
|
|
789
|
+
AType extends string,
|
|
719
790
|
BSide extends string,
|
|
791
|
+
BType extends string,
|
|
720
792
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
721
793
|
Content extends Json.Object | null,
|
|
722
794
|
>(
|
|
723
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
795
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
724
796
|
store: Store,
|
|
725
|
-
): Join<ASide, BSide, Cardinality, Content> {
|
|
797
|
+
): Join<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
726
798
|
const joinMap = getJoinMap(store)
|
|
727
799
|
let myJoin = joinMap.get(token.key)
|
|
728
800
|
if (myJoin === undefined) {
|
|
@@ -740,71 +812,99 @@ export function getJoin<
|
|
|
740
812
|
|
|
741
813
|
export type JoinStates<
|
|
742
814
|
ASide extends string,
|
|
815
|
+
AType extends string,
|
|
743
816
|
BSide extends string,
|
|
817
|
+
BType extends string,
|
|
744
818
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
745
819
|
Content extends Json.Object | null,
|
|
746
820
|
> = Cardinality extends `1:1`
|
|
747
821
|
? (Content extends Json.Object
|
|
748
822
|
? {
|
|
749
|
-
readonly [
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
823
|
+
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
824
|
+
[AType, Content] | null,
|
|
825
|
+
BType
|
|
826
|
+
>
|
|
827
|
+
} & {
|
|
828
|
+
readonly [B in BSide as `${B}EntryOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
829
|
+
[BType, Content] | null,
|
|
830
|
+
AType
|
|
753
831
|
>
|
|
754
832
|
}
|
|
755
833
|
: {}) & {
|
|
756
|
-
readonly [
|
|
757
|
-
|
|
758
|
-
|
|
834
|
+
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
835
|
+
AType | null,
|
|
836
|
+
BType
|
|
837
|
+
>
|
|
838
|
+
} & {
|
|
839
|
+
readonly [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
840
|
+
BType | null,
|
|
841
|
+
AType
|
|
842
|
+
>
|
|
759
843
|
}
|
|
760
844
|
: Cardinality extends `1:n`
|
|
761
845
|
? (Content extends Json.Object
|
|
762
846
|
? {
|
|
763
847
|
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
764
|
-
[
|
|
848
|
+
[AType, Content] | null,
|
|
849
|
+
BType
|
|
765
850
|
>
|
|
766
851
|
} & {
|
|
767
852
|
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
768
|
-
[
|
|
853
|
+
[BType, Content][],
|
|
854
|
+
AType
|
|
769
855
|
>
|
|
770
856
|
}
|
|
771
857
|
: {}) & {
|
|
772
858
|
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
773
|
-
|
|
859
|
+
AType | null,
|
|
860
|
+
BType
|
|
774
861
|
>
|
|
775
862
|
} & {
|
|
776
863
|
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
777
|
-
|
|
864
|
+
BType[],
|
|
865
|
+
AType
|
|
778
866
|
>
|
|
779
867
|
}
|
|
780
868
|
: Cardinality extends `n:n`
|
|
781
869
|
? (Content extends Json.Object
|
|
782
870
|
? {
|
|
783
|
-
readonly [
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
871
|
+
readonly [A in ASide as `${A}EntriesOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
872
|
+
[AType, Content][],
|
|
873
|
+
BType
|
|
874
|
+
>
|
|
875
|
+
} & {
|
|
876
|
+
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
877
|
+
[BType, Content][],
|
|
878
|
+
AType
|
|
787
879
|
>
|
|
788
880
|
}
|
|
789
881
|
: {}) & {
|
|
790
|
-
readonly [
|
|
791
|
-
|
|
792
|
-
|
|
882
|
+
readonly [A in ASide as `${A}KeysOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
883
|
+
AType[],
|
|
884
|
+
BType
|
|
885
|
+
>
|
|
886
|
+
} & {
|
|
887
|
+
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
888
|
+
BType[],
|
|
889
|
+
AType
|
|
890
|
+
>
|
|
793
891
|
}
|
|
794
892
|
: never
|
|
795
893
|
|
|
796
894
|
export function findRelationsInStore<
|
|
797
895
|
ASide extends string,
|
|
896
|
+
AType extends string,
|
|
798
897
|
BSide extends string,
|
|
898
|
+
BType extends string,
|
|
799
899
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
800
900
|
Content extends Json.Object | null,
|
|
801
901
|
>(
|
|
802
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
803
|
-
key:
|
|
902
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
903
|
+
key: AType | BType,
|
|
804
904
|
store: Store,
|
|
805
|
-
): JoinStates<ASide, BSide, Cardinality, Content> {
|
|
905
|
+
): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
806
906
|
const myJoin = getJoin(token, store)
|
|
807
|
-
let relations: JoinStates<ASide, BSide, Cardinality, Content>
|
|
907
|
+
let relations: JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
808
908
|
switch (token.cardinality satisfies `1:1` | `1:n` | `n:n`) {
|
|
809
909
|
case `1:1`: {
|
|
810
910
|
const keyAB = `${token.a}KeyOf${capitalize(token.b)}`
|
|
@@ -820,7 +920,7 @@ export function findRelationsInStore<
|
|
|
820
920
|
const state = myJoin.retrieve(familyBA, key)
|
|
821
921
|
return state
|
|
822
922
|
},
|
|
823
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
923
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
824
924
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`
|
|
825
925
|
if (entryAB in myJoin.states) {
|
|
826
926
|
const entryBA = `${token.b}EntryOf${capitalize(token.a)}`
|
|
@@ -853,7 +953,7 @@ export function findRelationsInStore<
|
|
|
853
953
|
const state = myJoin.retrieve(familyBA, key)
|
|
854
954
|
return state
|
|
855
955
|
},
|
|
856
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
956
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
857
957
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`
|
|
858
958
|
if (entryAB in myJoin.states) {
|
|
859
959
|
const entriesBA = `${token.b}EntriesOf${capitalize(token.a)}`
|
|
@@ -886,7 +986,7 @@ export function findRelationsInStore<
|
|
|
886
986
|
const state = myJoin.retrieve(familyBA, key)
|
|
887
987
|
return state
|
|
888
988
|
},
|
|
889
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
989
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
890
990
|
const entriesAB = `${token.a}EntriesOf${capitalize(token.b)}`
|
|
891
991
|
if (entriesAB in myJoin.states) {
|
|
892
992
|
const entriesBA = `${token.b}EntriesOf${capitalize(token.a)}`
|
|
@@ -910,24 +1010,28 @@ export function findRelationsInStore<
|
|
|
910
1010
|
|
|
911
1011
|
export function findRelations<
|
|
912
1012
|
ASide extends string,
|
|
1013
|
+
AType extends string,
|
|
913
1014
|
BSide extends string,
|
|
1015
|
+
BType extends string,
|
|
914
1016
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
915
1017
|
Content extends Json.Object | null,
|
|
916
1018
|
>(
|
|
917
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
918
|
-
key:
|
|
919
|
-
): JoinStates<ASide, BSide, Cardinality, Content> {
|
|
1019
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1020
|
+
key: AType | BType,
|
|
1021
|
+
): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
920
1022
|
return findRelationsInStore(token, key, IMPLICIT.STORE)
|
|
921
1023
|
}
|
|
922
1024
|
|
|
923
1025
|
export function editRelationsInStore<
|
|
924
1026
|
ASide extends string,
|
|
1027
|
+
AType extends string,
|
|
925
1028
|
BSide extends string,
|
|
1029
|
+
BType extends string,
|
|
926
1030
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
927
1031
|
Content extends Json.Object | null,
|
|
928
1032
|
>(
|
|
929
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
930
|
-
change: (relations: Junction<ASide, BSide, Content>) => void,
|
|
1033
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1034
|
+
change: (relations: Junction<ASide, AType, BSide, BType, Content>) => void,
|
|
931
1035
|
store: Store,
|
|
932
1036
|
): void {
|
|
933
1037
|
const myJoin = getJoin(token, store)
|
|
@@ -944,18 +1048,20 @@ export function editRelationsInStore<
|
|
|
944
1048
|
|
|
945
1049
|
export function editRelations<
|
|
946
1050
|
ASide extends string,
|
|
1051
|
+
AType extends string,
|
|
947
1052
|
BSide extends string,
|
|
1053
|
+
BType extends string,
|
|
948
1054
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
949
1055
|
Content extends Json.Object | null,
|
|
950
1056
|
>(
|
|
951
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
952
|
-
change: (relations: Junction<ASide, BSide, Content>) => void,
|
|
1057
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1058
|
+
change: (relations: Junction<ASide, AType, BSide, BType, Content>) => void,
|
|
953
1059
|
): void {
|
|
954
1060
|
editRelationsInStore(token, change, IMPLICIT.STORE)
|
|
955
1061
|
}
|
|
956
1062
|
|
|
957
1063
|
export function getInternalRelationsFromStore(
|
|
958
|
-
token: JoinToken<any, any, any, any>,
|
|
1064
|
+
token: JoinToken<any, any, any, any, any, any>,
|
|
959
1065
|
store: Store,
|
|
960
1066
|
): MutableAtomFamilyToken<SetRTX<string>, SetRTXJson<string>, string> {
|
|
961
1067
|
const myJoin = getJoin(token, store)
|
|
@@ -965,11 +1071,13 @@ export function getInternalRelationsFromStore(
|
|
|
965
1071
|
|
|
966
1072
|
export function getInternalRelations<
|
|
967
1073
|
ASide extends string,
|
|
1074
|
+
AType extends string,
|
|
968
1075
|
BSide extends string,
|
|
1076
|
+
BType extends string,
|
|
969
1077
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
970
1078
|
Content extends Json.Object | null,
|
|
971
1079
|
>(
|
|
972
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
1080
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
973
1081
|
): MutableAtomFamilyToken<SetRTX<string>, SetRTXJson<string>, string> {
|
|
974
1082
|
return getInternalRelationsFromStore(token, IMPLICIT.STORE)
|
|
975
1083
|
}
|