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.
- package/dist/internal/index.d.ts +30 -47
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +116 -287
- package/dist/internal/index.js.map +1 -1
- package/dist/main/index.d.ts +52 -56
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +45 -8
- package/dist/main/index.js.map +1 -1
- package/dist/realtime/index.d.ts +2 -3
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +1 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime-server/index.js +1 -1
- package/dist/realtime-server/index.js.map +1 -1
- package/dist/realtime-testing/index.js +1 -1
- package/dist/struct/index.d.ts +14 -0
- package/dist/struct/index.d.ts.map +1 -0
- package/dist/struct/index.js +35 -0
- package/dist/struct/index.js.map +1 -0
- package/dist/transceivers/o-list/index.d.ts +8 -4
- package/dist/transceivers/o-list/index.d.ts.map +1 -1
- package/dist/transceivers/o-list/index.js +2 -1
- package/dist/transceivers/o-list/index.js.map +1 -1
- package/dist/transceivers/set-rtx/index.d.ts +1 -0
- package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
- package/dist/transceivers/set-rtx/index.js.map +1 -1
- package/dist/transceivers/u-list/index.d.ts +12 -4
- package/dist/transceivers/u-list/index.d.ts.map +1 -1
- package/dist/transceivers/u-list/index.js +34 -2
- package/dist/transceivers/u-list/index.js.map +1 -1
- package/dist/utility-types-aZkJVERa.d.ts +10 -0
- package/dist/utility-types-aZkJVERa.d.ts.map +1 -0
- package/package.json +20 -16
- package/src/internal/atom/create-regular-atom.ts +3 -1
- package/src/internal/index.ts +0 -1
- package/src/internal/join/create-join.ts +8 -11
- package/src/internal/join/edit-relations-in-store.ts +6 -8
- package/src/internal/join/find-relations-in-store.ts +11 -67
- package/src/internal/join/get-internal-relations-from-store.ts +11 -5
- package/src/internal/join/get-join.ts +7 -9
- package/src/internal/join/join-internal.ts +143 -412
- package/src/internal/molecule.ts +44 -25
- package/src/internal/mutable/create-mutable-atom.ts +15 -11
- package/src/internal/mutable/transceiver.ts +1 -5
- package/src/internal/set-state/dispatch-state-update.ts +1 -1
- package/src/internal/store/store.ts +16 -15
- package/src/internal/transaction/build-transaction.ts +1 -1
- package/src/main/atom.ts +15 -6
- package/src/main/join.ts +68 -151
- package/src/main/realm.ts +58 -17
- package/src/realtime/shared-room-store.ts +5 -15
- package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +1 -1
- package/src/struct/index.ts +1 -0
- package/src/{internal → struct}/micro.ts +1 -1
- package/src/transceivers/o-list/o-list.ts +13 -9
- package/src/transceivers/set-rtx/set-rtx.ts +4 -0
- package/src/transceivers/u-list/index.ts +1 -0
- package/src/transceivers/u-list/u-list-disposed-key-cleanup-effect.ts +47 -0
- package/src/transceivers/u-list/u-list.ts +13 -9
|
@@ -1,152 +1,82 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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 {
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
?
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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 [
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
?
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
?
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 [
|
|
113
|
-
|
|
114
|
-
|
|
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
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const
|
|
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<
|
|
134
|
-
public
|
|
135
|
-
public
|
|
136
|
-
public
|
|
137
|
-
|
|
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<
|
|
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<
|
|
164
|
-
defaultContent: Content | undefined,
|
|
92
|
+
options: JoinOptions<AName, A, BName, B, Cardinality>,
|
|
165
93
|
store: RootStore = IMPLICIT.STORE,
|
|
166
94
|
) {
|
|
167
|
-
type
|
|
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:
|
|
190
|
-
const bSide:
|
|
191
|
-
const relatedKeysAtoms = createMutableAtomFamily<
|
|
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:
|
|
119
|
+
class: UList,
|
|
196
120
|
},
|
|
197
121
|
[`join`, `relations`],
|
|
198
122
|
)
|
|
199
|
-
this.
|
|
200
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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) =>
|
|
217
|
+
getRelatedKeys: (key) =>
|
|
218
|
+
this.toolkit.get(relatedKeysAtoms, key) as UList<A> | UList<B>,
|
|
315
219
|
addRelation: (a, b) => {
|
|
316
|
-
this.store.
|
|
317
|
-
this.store.
|
|
318
|
-
|
|
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
|
-
|
|
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) =>
|
|
330
|
-
|
|
331
|
-
|
|
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
|
|
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
|
-
|
|
295
|
+
this.relations = relations
|
|
296
|
+
this.states = {
|
|
495
297
|
[stateKeyA]: singleRelatedKeySelectors,
|
|
496
298
|
[stateKeyB]: singleRelatedKeySelectors,
|
|
497
|
-
} as JoinStateFamilies<
|
|
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<
|
|
531
|
-
|
|
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 =
|
|
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
|
-
|
|
320
|
+
this.relations = relations
|
|
321
|
+
this.states = {
|
|
564
322
|
[stateKeyA]: multipleRelatedKeysSelectors,
|
|
565
323
|
[stateKeyB]: multipleRelatedKeysSelectors,
|
|
566
|
-
} as JoinStateFamilies<
|
|
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
|
}
|