atom.io 0.30.0 → 0.30.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.
- package/data/dist/index.d.ts +84 -51
- package/data/dist/index.js +35 -31
- package/data/src/join.ts +240 -134
- package/dist/chunk-ADMEAXYU.js +167 -0
- package/dist/{chunk-7PUUHSXC.js → chunk-SMKF3ZNG.js} +45 -171
- package/dist/index.d.ts +53 -5
- package/dist/index.js +1 -1
- package/internal/dist/index.d.ts +62 -35
- package/internal/dist/index.js +2 -2
- package/internal/src/junction.ts +152 -84
- 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 +13 -4
- 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 +17 -1
- package/realtime-testing/dist/index.d.ts +3 -0
- package/realtime-testing/dist/index.js +11 -4
- package/realtime-testing/src/setup-realtime-test.tsx +12 -4
- 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>(
|
|
@@ -530,7 +561,10 @@ export class Join<
|
|
|
530
561
|
const relatedKeysState = this.retrieve(relatedKeysAtoms, key)
|
|
531
562
|
const relatedKeys = get(relatedKeysState)
|
|
532
563
|
for (const relatedKey of relatedKeys) {
|
|
533
|
-
const contentKey = relations.makeContentKey(
|
|
564
|
+
const contentKey = relations.makeContentKey(
|
|
565
|
+
key as any,
|
|
566
|
+
relatedKey as any,
|
|
567
|
+
) // sort XY to AB ❗
|
|
534
568
|
const contentState = this.retrieve(contentAtoms, contentKey)
|
|
535
569
|
const content = get(contentState)
|
|
536
570
|
return [relatedKey, content]
|
|
@@ -552,7 +586,10 @@ export class Join<
|
|
|
552
586
|
const jsonState = this.retrieve(jsonFamily, key)
|
|
553
587
|
const json = get(jsonState)
|
|
554
588
|
return json.members.map((relatedKey) => {
|
|
555
|
-
const contentKey = relations.makeContentKey(
|
|
589
|
+
const contentKey = relations.makeContentKey(
|
|
590
|
+
key as any,
|
|
591
|
+
relatedKey as any,
|
|
592
|
+
) // sort XY to AB ❗
|
|
556
593
|
const contentState = this.retrieve(contentAtoms, contentKey)
|
|
557
594
|
const content = get(contentState)
|
|
558
595
|
return [relatedKey, content]
|
|
@@ -570,8 +607,15 @@ export class Join<
|
|
|
570
607
|
const baseStates = {
|
|
571
608
|
[stateKeyA]: findSingleRelatedKeyState,
|
|
572
609
|
[stateKeyB]: findSingleRelatedKeyState,
|
|
573
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
574
|
-
let states: JoinStateFamilies<
|
|
610
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
611
|
+
let states: JoinStateFamilies<
|
|
612
|
+
ASide,
|
|
613
|
+
AType,
|
|
614
|
+
BSide,
|
|
615
|
+
BType,
|
|
616
|
+
Cardinality,
|
|
617
|
+
Content
|
|
618
|
+
>
|
|
575
619
|
if (defaultContent) {
|
|
576
620
|
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
577
621
|
const entriesStateKeyA = `${aSide}EntryOf${capitalize(bSide)}` as const
|
|
@@ -596,8 +640,15 @@ export class Join<
|
|
|
596
640
|
const baseStates = {
|
|
597
641
|
[stateKeyA]: findSingleRelatedKeyState,
|
|
598
642
|
[stateKeyB]: findMultipleRelatedKeysState,
|
|
599
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
600
|
-
let states: JoinStateFamilies<
|
|
643
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
644
|
+
let states: JoinStateFamilies<
|
|
645
|
+
ASide,
|
|
646
|
+
AType,
|
|
647
|
+
BSide,
|
|
648
|
+
BType,
|
|
649
|
+
Cardinality,
|
|
650
|
+
Content
|
|
651
|
+
>
|
|
601
652
|
if (defaultContent) {
|
|
602
653
|
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
603
654
|
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
@@ -624,8 +675,15 @@ export class Join<
|
|
|
624
675
|
const baseStates = {
|
|
625
676
|
[stateKeyA]: findMultipleRelatedKeysState,
|
|
626
677
|
[stateKeyB]: findMultipleRelatedKeysState,
|
|
627
|
-
} as JoinStateFamilies<ASide, BSide, Cardinality, Content>
|
|
628
|
-
let states: JoinStateFamilies<
|
|
678
|
+
} as JoinStateFamilies<ASide, AType, BSide, BType, Cardinality, Content>
|
|
679
|
+
let states: JoinStateFamilies<
|
|
680
|
+
ASide,
|
|
681
|
+
AType,
|
|
682
|
+
BSide,
|
|
683
|
+
BType,
|
|
684
|
+
Cardinality,
|
|
685
|
+
Content
|
|
686
|
+
>
|
|
629
687
|
if (defaultContent) {
|
|
630
688
|
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
631
689
|
const entriesStateKeyA = `${aSide}EntriesOf${capitalize(
|
|
@@ -651,7 +709,9 @@ export class Join<
|
|
|
651
709
|
|
|
652
710
|
export type JoinToken<
|
|
653
711
|
ASide extends string,
|
|
712
|
+
AType extends string,
|
|
654
713
|
BSide extends string,
|
|
714
|
+
BType extends string,
|
|
655
715
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
656
716
|
Content extends Json.Object | null = null,
|
|
657
717
|
> = {
|
|
@@ -660,41 +720,49 @@ export type JoinToken<
|
|
|
660
720
|
cardinality: Cardinality
|
|
661
721
|
a: ASide
|
|
662
722
|
b: BSide
|
|
723
|
+
__aType?: AType
|
|
724
|
+
__bType?: BType
|
|
663
725
|
__content?: Content
|
|
664
726
|
}
|
|
665
727
|
|
|
666
728
|
export function join<
|
|
667
729
|
const ASide extends string,
|
|
730
|
+
const AType extends string,
|
|
668
731
|
const BSide extends string,
|
|
732
|
+
const BType extends string,
|
|
669
733
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
670
734
|
>(
|
|
671
|
-
options: JoinOptions<ASide, BSide, Cardinality, null>,
|
|
735
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, null>,
|
|
672
736
|
defaultContent?: undefined,
|
|
673
737
|
store?: Store,
|
|
674
|
-
): JoinToken<ASide, BSide, Cardinality, null>
|
|
738
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, null>
|
|
675
739
|
export function join<
|
|
676
740
|
const ASide extends string,
|
|
741
|
+
const AType extends string,
|
|
677
742
|
const BSide extends string,
|
|
743
|
+
const BType extends string,
|
|
678
744
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
679
745
|
const Content extends Json.Object,
|
|
680
746
|
>(
|
|
681
|
-
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
747
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
682
748
|
defaultContent: Content,
|
|
683
749
|
store?: Store,
|
|
684
|
-
): JoinToken<ASide, BSide, Cardinality, Content>
|
|
750
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content>
|
|
685
751
|
export function join<
|
|
686
752
|
ASide extends string,
|
|
753
|
+
AType extends string,
|
|
687
754
|
BSide extends string,
|
|
755
|
+
BType extends string,
|
|
688
756
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
689
757
|
Content extends Json.Object,
|
|
690
758
|
>(
|
|
691
|
-
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
759
|
+
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
692
760
|
defaultContent: Content | undefined,
|
|
693
761
|
store: Store = IMPLICIT.STORE,
|
|
694
|
-
): JoinToken<ASide, BSide, Cardinality, Content> {
|
|
762
|
+
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
695
763
|
const joins = getJoinMap(store)
|
|
696
764
|
joins.set(options.key, new Join(options, defaultContent, store))
|
|
697
|
-
const token: JoinToken<ASide, BSide, Cardinality, Content> = {
|
|
765
|
+
const token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content> = {
|
|
698
766
|
key: options.key,
|
|
699
767
|
type: `join`,
|
|
700
768
|
a: options.between[0],
|
|
@@ -705,24 +773,26 @@ export function join<
|
|
|
705
773
|
}
|
|
706
774
|
|
|
707
775
|
export function getJoinMap(
|
|
708
|
-
store: Store & { joins?: Map<string, Join<any, any, any, any>> },
|
|
709
|
-
): Map<string, Join<any, any, any, any>> {
|
|
776
|
+
store: Store & { joins?: Map<string, Join<any, any, any, any, any, any>> },
|
|
777
|
+
): Map<string, Join<any, any, any, any, any, any>> {
|
|
710
778
|
if (`joins` in store && store.joins instanceof Map) {
|
|
711
779
|
return store.joins
|
|
712
780
|
}
|
|
713
|
-
const joins = new Map<string, Join<any, any, any, any>>()
|
|
781
|
+
const joins = new Map<string, Join<any, any, any, any, any, any>>()
|
|
714
782
|
store.joins = joins
|
|
715
783
|
return joins
|
|
716
784
|
}
|
|
717
785
|
export function getJoin<
|
|
718
786
|
ASide extends string,
|
|
787
|
+
AType extends string,
|
|
719
788
|
BSide extends string,
|
|
789
|
+
BType extends string,
|
|
720
790
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
721
791
|
Content extends Json.Object | null,
|
|
722
792
|
>(
|
|
723
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
793
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
724
794
|
store: Store,
|
|
725
|
-
): Join<ASide, BSide, Cardinality, Content> {
|
|
795
|
+
): Join<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
726
796
|
const joinMap = getJoinMap(store)
|
|
727
797
|
let myJoin = joinMap.get(token.key)
|
|
728
798
|
if (myJoin === undefined) {
|
|
@@ -740,71 +810,99 @@ export function getJoin<
|
|
|
740
810
|
|
|
741
811
|
export type JoinStates<
|
|
742
812
|
ASide extends string,
|
|
813
|
+
AType extends string,
|
|
743
814
|
BSide extends string,
|
|
815
|
+
BType extends string,
|
|
744
816
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
745
817
|
Content extends Json.Object | null,
|
|
746
818
|
> = Cardinality extends `1:1`
|
|
747
819
|
? (Content extends Json.Object
|
|
748
820
|
? {
|
|
749
|
-
readonly [
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
821
|
+
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
822
|
+
[AType, Content] | null,
|
|
823
|
+
BType
|
|
824
|
+
>
|
|
825
|
+
} & {
|
|
826
|
+
readonly [B in BSide as `${B}EntryOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
827
|
+
[BType, Content] | null,
|
|
828
|
+
AType
|
|
753
829
|
>
|
|
754
830
|
}
|
|
755
831
|
: {}) & {
|
|
756
|
-
readonly [
|
|
757
|
-
|
|
758
|
-
|
|
832
|
+
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
833
|
+
AType | null,
|
|
834
|
+
BType
|
|
835
|
+
>
|
|
836
|
+
} & {
|
|
837
|
+
readonly [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
838
|
+
BType | null,
|
|
839
|
+
AType
|
|
840
|
+
>
|
|
759
841
|
}
|
|
760
842
|
: Cardinality extends `1:n`
|
|
761
843
|
? (Content extends Json.Object
|
|
762
844
|
? {
|
|
763
845
|
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
764
|
-
[
|
|
846
|
+
[AType, Content] | null,
|
|
847
|
+
BType
|
|
765
848
|
>
|
|
766
849
|
} & {
|
|
767
850
|
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
768
|
-
[
|
|
851
|
+
[BType, Content][],
|
|
852
|
+
AType
|
|
769
853
|
>
|
|
770
854
|
}
|
|
771
855
|
: {}) & {
|
|
772
856
|
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
773
|
-
|
|
857
|
+
AType | null,
|
|
858
|
+
BType
|
|
774
859
|
>
|
|
775
860
|
} & {
|
|
776
861
|
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
777
|
-
|
|
862
|
+
BType[],
|
|
863
|
+
AType
|
|
778
864
|
>
|
|
779
865
|
}
|
|
780
866
|
: Cardinality extends `n:n`
|
|
781
867
|
? (Content extends Json.Object
|
|
782
868
|
? {
|
|
783
|
-
readonly [
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
869
|
+
readonly [A in ASide as `${A}EntriesOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
870
|
+
[AType, Content][],
|
|
871
|
+
BType
|
|
872
|
+
>
|
|
873
|
+
} & {
|
|
874
|
+
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
875
|
+
[BType, Content][],
|
|
876
|
+
AType
|
|
787
877
|
>
|
|
788
878
|
}
|
|
789
879
|
: {}) & {
|
|
790
|
-
readonly [
|
|
791
|
-
|
|
792
|
-
|
|
880
|
+
readonly [A in ASide as `${A}KeysOf${Capitalize<BSide>}`]: ReadonlySelectorToken<
|
|
881
|
+
AType[],
|
|
882
|
+
BType
|
|
883
|
+
>
|
|
884
|
+
} & {
|
|
885
|
+
readonly [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlySelectorToken<
|
|
886
|
+
BType[],
|
|
887
|
+
AType
|
|
888
|
+
>
|
|
793
889
|
}
|
|
794
890
|
: never
|
|
795
891
|
|
|
796
892
|
export function findRelationsInStore<
|
|
797
893
|
ASide extends string,
|
|
894
|
+
AType extends string,
|
|
798
895
|
BSide extends string,
|
|
896
|
+
BType extends string,
|
|
799
897
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
800
898
|
Content extends Json.Object | null,
|
|
801
899
|
>(
|
|
802
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
803
|
-
key:
|
|
900
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
901
|
+
key: AType | BType,
|
|
804
902
|
store: Store,
|
|
805
|
-
): JoinStates<ASide, BSide, Cardinality, Content> {
|
|
903
|
+
): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
806
904
|
const myJoin = getJoin(token, store)
|
|
807
|
-
let relations: JoinStates<ASide, BSide, Cardinality, Content>
|
|
905
|
+
let relations: JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
808
906
|
switch (token.cardinality satisfies `1:1` | `1:n` | `n:n`) {
|
|
809
907
|
case `1:1`: {
|
|
810
908
|
const keyAB = `${token.a}KeyOf${capitalize(token.b)}`
|
|
@@ -820,7 +918,7 @@ export function findRelationsInStore<
|
|
|
820
918
|
const state = myJoin.retrieve(familyBA, key)
|
|
821
919
|
return state
|
|
822
920
|
},
|
|
823
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
921
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
824
922
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`
|
|
825
923
|
if (entryAB in myJoin.states) {
|
|
826
924
|
const entryBA = `${token.b}EntryOf${capitalize(token.a)}`
|
|
@@ -853,7 +951,7 @@ export function findRelationsInStore<
|
|
|
853
951
|
const state = myJoin.retrieve(familyBA, key)
|
|
854
952
|
return state
|
|
855
953
|
},
|
|
856
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
954
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
857
955
|
const entryAB = `${token.a}EntryOf${capitalize(token.b)}`
|
|
858
956
|
if (entryAB in myJoin.states) {
|
|
859
957
|
const entriesBA = `${token.b}EntriesOf${capitalize(token.a)}`
|
|
@@ -886,7 +984,7 @@ export function findRelationsInStore<
|
|
|
886
984
|
const state = myJoin.retrieve(familyBA, key)
|
|
887
985
|
return state
|
|
888
986
|
},
|
|
889
|
-
} as JoinStates<ASide, BSide, Cardinality, Content>
|
|
987
|
+
} as JoinStates<ASide, AType, BSide, BType, Cardinality, Content>
|
|
890
988
|
const entriesAB = `${token.a}EntriesOf${capitalize(token.b)}`
|
|
891
989
|
if (entriesAB in myJoin.states) {
|
|
892
990
|
const entriesBA = `${token.b}EntriesOf${capitalize(token.a)}`
|
|
@@ -910,24 +1008,28 @@ export function findRelationsInStore<
|
|
|
910
1008
|
|
|
911
1009
|
export function findRelations<
|
|
912
1010
|
ASide extends string,
|
|
1011
|
+
AType extends string,
|
|
913
1012
|
BSide extends string,
|
|
1013
|
+
BType extends string,
|
|
914
1014
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
915
1015
|
Content extends Json.Object | null,
|
|
916
1016
|
>(
|
|
917
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
918
|
-
key:
|
|
919
|
-
): JoinStates<ASide, BSide, Cardinality, Content> {
|
|
1017
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1018
|
+
key: AType | BType,
|
|
1019
|
+
): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
920
1020
|
return findRelationsInStore(token, key, IMPLICIT.STORE)
|
|
921
1021
|
}
|
|
922
1022
|
|
|
923
1023
|
export function editRelationsInStore<
|
|
924
1024
|
ASide extends string,
|
|
1025
|
+
AType extends string,
|
|
925
1026
|
BSide extends string,
|
|
1027
|
+
BType extends string,
|
|
926
1028
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
927
1029
|
Content extends Json.Object | null,
|
|
928
1030
|
>(
|
|
929
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
930
|
-
change: (relations: Junction<ASide, BSide, Content>) => void,
|
|
1031
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1032
|
+
change: (relations: Junction<ASide, AType, BSide, BType, Content>) => void,
|
|
931
1033
|
store: Store,
|
|
932
1034
|
): void {
|
|
933
1035
|
const myJoin = getJoin(token, store)
|
|
@@ -944,18 +1046,20 @@ export function editRelationsInStore<
|
|
|
944
1046
|
|
|
945
1047
|
export function editRelations<
|
|
946
1048
|
ASide extends string,
|
|
1049
|
+
AType extends string,
|
|
947
1050
|
BSide extends string,
|
|
1051
|
+
BType extends string,
|
|
948
1052
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
949
1053
|
Content extends Json.Object | null,
|
|
950
1054
|
>(
|
|
951
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
952
|
-
change: (relations: Junction<ASide, BSide, Content>) => void,
|
|
1055
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
1056
|
+
change: (relations: Junction<ASide, AType, BSide, BType, Content>) => void,
|
|
953
1057
|
): void {
|
|
954
1058
|
editRelationsInStore(token, change, IMPLICIT.STORE)
|
|
955
1059
|
}
|
|
956
1060
|
|
|
957
1061
|
export function getInternalRelationsFromStore(
|
|
958
|
-
token: JoinToken<any, any, any, any>,
|
|
1062
|
+
token: JoinToken<any, any, any, any, any, any>,
|
|
959
1063
|
store: Store,
|
|
960
1064
|
): MutableAtomFamilyToken<SetRTX<string>, SetRTXJson<string>, string> {
|
|
961
1065
|
const myJoin = getJoin(token, store)
|
|
@@ -965,11 +1069,13 @@ export function getInternalRelationsFromStore(
|
|
|
965
1069
|
|
|
966
1070
|
export function getInternalRelations<
|
|
967
1071
|
ASide extends string,
|
|
1072
|
+
AType extends string,
|
|
968
1073
|
BSide extends string,
|
|
1074
|
+
BType extends string,
|
|
969
1075
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
970
1076
|
Content extends Json.Object | null,
|
|
971
1077
|
>(
|
|
972
|
-
token: JoinToken<ASide, BSide, Cardinality, Content>,
|
|
1078
|
+
token: JoinToken<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
973
1079
|
): MutableAtomFamilyToken<SetRTX<string>, SetRTXJson<string>, string> {
|
|
974
1080
|
return getInternalRelationsFromStore(token, IMPLICIT.STORE)
|
|
975
1081
|
}
|