atom.io 0.14.8 → 0.15.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/README.md +5 -0
- package/data/dist/index.cjs +216 -218
- package/data/dist/index.cjs.map +1 -1
- package/data/dist/index.d.ts +30 -11
- package/data/dist/index.js +218 -221
- package/data/dist/index.js.map +1 -1
- package/data/src/join.ts +337 -296
- package/data/src/struct-family.ts +2 -2
- package/data/src/struct.ts +2 -2
- package/dist/chunk-S7R5MU6A.js +137 -0
- package/dist/chunk-S7R5MU6A.js.map +1 -0
- package/dist/index.cjs +3 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1 -151
- package/dist/index.js.map +1 -1
- package/internal/dist/index.cjs +278 -201
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.ts +43 -36
- package/internal/dist/index.js +224 -194
- package/internal/dist/index.js.map +1 -1
- package/internal/src/atom/create-atom.ts +5 -86
- package/internal/src/atom/create-regular-atom.ts +92 -0
- package/internal/src/atom/index.ts +16 -0
- package/internal/src/atom/is-default.ts +0 -5
- package/internal/src/caching.ts +14 -16
- package/internal/src/families/create-atom-family.ts +20 -46
- package/internal/src/families/create-readonly-selector-family.ts +4 -1
- package/internal/src/families/create-regular-atom-family.ts +72 -0
- package/internal/src/families/create-selector-family.ts +2 -0
- package/internal/src/families/index.ts +1 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +2 -2
- package/internal/src/mutable/create-mutable-atom.ts +8 -3
- package/internal/src/mutable/get-update-family.ts +1 -1
- package/internal/src/mutable/is-mutable.ts +3 -30
- package/internal/src/mutable/tracker-family.ts +2 -2
- package/internal/src/mutable/tracker.ts +5 -5
- package/internal/src/operation.ts +14 -18
- package/internal/src/selector/create-read-write-selector.ts +2 -3
- package/internal/src/selector/create-selector.ts +1 -1
- package/internal/src/selector/register-selector.ts +9 -14
- package/internal/src/set-state/evict-downstream.ts +3 -5
- package/internal/src/set-state/set-atom.ts +14 -17
- package/internal/src/store/store.ts +23 -19
- package/internal/src/store/withdraw.ts +32 -70
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +5 -3
- package/internal/src/subscribe/subscribe-to-state.ts +5 -3
- package/internal/src/transaction/apply-transaction.ts +20 -2
- package/internal/src/transaction/build-transaction.ts +19 -11
- package/internal/src/transaction/create-transaction.ts +6 -11
- package/internal/src/transaction/index.ts +2 -3
- package/introspection/dist/index.cjs +6 -6
- package/introspection/dist/index.cjs.map +1 -1
- package/introspection/dist/index.d.ts +3 -3
- package/introspection/dist/index.js +7 -7
- package/introspection/dist/index.js.map +1 -1
- package/introspection/src/attach-atom-index.ts +7 -2
- package/introspection/src/attach-selector-index.ts +7 -2
- package/introspection/src/attach-timeline-family.ts +5 -2
- package/introspection/src/attach-timeline-index.ts +2 -2
- package/introspection/src/attach-transaction-index.ts +2 -2
- package/introspection/src/attach-transaction-logs.ts +2 -2
- package/package.json +10 -8
- package/react-devtools/dist/index.d.ts +17 -11
- package/realtime-client/dist/index.cjs +3 -0
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.ts +3 -3
- package/realtime-client/dist/index.js +3 -0
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/src/index.ts +6 -6
- package/realtime-client/src/{use-pull-family-member.ts → pull-family-member.ts} +1 -1
- package/realtime-client/src/{use-pull-mutable-family-member.ts → pull-mutable-family-member.ts} +1 -1
- package/realtime-client/src/{use-pull-mutable.ts → pull-mutable.ts} +1 -1
- package/realtime-client/src/{use-server-action.ts → server-action.ts} +3 -0
- package/realtime-react/dist/index.cjs +31 -17
- package/realtime-react/dist/index.cjs.map +1 -1
- package/realtime-react/dist/index.d.ts +3 -3
- package/realtime-react/dist/index.js +31 -17
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/src/realtime-context.tsx +2 -3
- package/realtime-react/src/use-pull-family-member.ts +6 -2
- package/realtime-react/src/use-pull-mutable-family-member.ts +5 -4
- package/realtime-react/src/use-pull-mutable.ts +6 -2
- package/realtime-react/src/use-pull.ts +5 -1
- package/realtime-react/src/use-push.ts +5 -4
- package/realtime-react/src/use-server-action.ts +5 -4
- package/src/atom.ts +8 -17
- package/src/selector.ts +3 -1
- package/src/set-state.ts +1 -3
- package/src/silo.ts +2 -14
- package/src/transaction.ts +17 -6
- package/transceivers/set-rtx/dist/index.cjs +2 -1
- package/transceivers/set-rtx/dist/index.cjs.map +1 -1
- package/transceivers/set-rtx/dist/index.js +2 -1
- package/transceivers/set-rtx/dist/index.js.map +1 -1
- package/transceivers/set-rtx/src/set-rtx.ts +2 -1
- package/internal/src/transaction/redo-transaction.ts +0 -27
- package/internal/src/transaction/undo-transaction.ts +0 -27
- /package/realtime-client/src/{use-pull.ts → pull.ts} +0 -0
- /package/realtime-client/src/{use-push.ts → push.ts} +0 -0
package/data/src/join.ts
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
2
|
import type {
|
|
3
3
|
AtomFamily,
|
|
4
|
+
MutableAtomFamily,
|
|
4
5
|
Read,
|
|
5
6
|
SelectorFamily,
|
|
6
7
|
Transactors,
|
|
7
8
|
Write,
|
|
8
9
|
} from "atom.io"
|
|
9
|
-
import { getState, setState } from "atom.io"
|
|
10
|
+
import { dispose, getState, setState } from "atom.io"
|
|
10
11
|
import type { Store } from "atom.io/internal"
|
|
11
12
|
import {
|
|
12
13
|
IMPLICIT,
|
|
13
|
-
createAtomFamily,
|
|
14
14
|
createMutableAtomFamily,
|
|
15
|
+
createRegularAtomFamily,
|
|
15
16
|
createSelectorFamily,
|
|
16
17
|
getJsonFamily,
|
|
17
18
|
} from "atom.io/internal"
|
|
18
19
|
import type { Json } from "atom.io/json"
|
|
20
|
+
import type { SetRTXJson } from "atom.io/transceivers/set-rtx"
|
|
19
21
|
import { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
20
22
|
|
|
21
23
|
import type {
|
|
22
24
|
BaseExternalStoreConfiguration,
|
|
23
25
|
ExternalStoreConfiguration,
|
|
24
|
-
ExternalStoreWithContentConfiguration,
|
|
25
26
|
JunctionEntries,
|
|
26
27
|
JunctionSchema,
|
|
27
28
|
} from "~/packages/rel8/junction/src"
|
|
@@ -57,7 +58,7 @@ export type JoinState<
|
|
|
57
58
|
readonly [AB in ASide | BSide as AB extends ASide
|
|
58
59
|
? `${AB}EntryOf${Capitalize<BSide>}`
|
|
59
60
|
: `${AB}EntryOf${Capitalize<ASide>}`]: SelectorFamily<
|
|
60
|
-
[string, Content] |
|
|
61
|
+
[string, Content] | null,
|
|
61
62
|
string
|
|
62
63
|
>
|
|
63
64
|
}
|
|
@@ -65,7 +66,7 @@ export type JoinState<
|
|
|
65
66
|
readonly [AB in ASide | BSide as AB extends ASide
|
|
66
67
|
? `${AB}KeyOf${Capitalize<BSide>}`
|
|
67
68
|
: `${AB}KeyOf${Capitalize<ASide>}`]: SelectorFamily<
|
|
68
|
-
string |
|
|
69
|
+
string | null,
|
|
69
70
|
string
|
|
70
71
|
>
|
|
71
72
|
}
|
|
@@ -73,7 +74,7 @@ export type JoinState<
|
|
|
73
74
|
? (Content extends Json.Object
|
|
74
75
|
? {
|
|
75
76
|
readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: SelectorFamily<
|
|
76
|
-
[string, Content] |
|
|
77
|
+
[string, Content] | null,
|
|
77
78
|
string
|
|
78
79
|
>
|
|
79
80
|
} & {
|
|
@@ -84,7 +85,7 @@ export type JoinState<
|
|
|
84
85
|
}
|
|
85
86
|
: {}) & {
|
|
86
87
|
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: SelectorFamily<
|
|
87
|
-
string |
|
|
88
|
+
string | null,
|
|
88
89
|
string
|
|
89
90
|
>
|
|
90
91
|
} & {
|
|
@@ -113,338 +114,378 @@ export type JoinState<
|
|
|
113
114
|
}
|
|
114
115
|
: never
|
|
115
116
|
|
|
116
|
-
export
|
|
117
|
+
export class Join<
|
|
117
118
|
const ASide extends string,
|
|
118
119
|
const BSide extends string,
|
|
119
|
-
const Cardinality extends Rel8.Cardinality,
|
|
120
|
-
>(
|
|
121
|
-
options: JoinOptions<ASide, BSide, Cardinality, null>,
|
|
122
|
-
defaultContent?: undefined,
|
|
123
|
-
store?: Store,
|
|
124
|
-
): {
|
|
125
|
-
relations: Junction<ASide, BSide>
|
|
126
|
-
findState: JoinState<ASide, BSide, Cardinality, null>
|
|
127
|
-
}
|
|
128
|
-
export function join<
|
|
129
|
-
const ASide extends string,
|
|
130
120
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
b
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
121
|
+
const Content extends Json.Object | null = null,
|
|
122
|
+
> {
|
|
123
|
+
private transactors: Transactors = TRANSACTORS
|
|
124
|
+
public relations: Junction<ASide, BSide, Content>
|
|
125
|
+
public findState: JoinState<ASide, BSide, Cardinality, Content>
|
|
126
|
+
public core: {
|
|
127
|
+
findRelatedKeysState: MutableAtomFamily<
|
|
128
|
+
SetRTX<string>,
|
|
129
|
+
SetRTXJson<string>,
|
|
130
|
+
string
|
|
131
|
+
>
|
|
132
|
+
}
|
|
133
|
+
public transact(
|
|
134
|
+
transactors: Transactors,
|
|
135
|
+
run: (join: Join<ASide, BSide, Cardinality, Content>) => void,
|
|
136
|
+
): void {
|
|
137
|
+
this.transactors = transactors
|
|
138
|
+
run(this)
|
|
139
|
+
this.transactors = TRANSACTORS
|
|
140
|
+
}
|
|
141
|
+
public constructor(
|
|
142
|
+
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
143
|
+
defaultContent: Content | undefined,
|
|
144
|
+
store: Store = IMPLICIT.STORE,
|
|
145
|
+
) {
|
|
146
|
+
const a: ASide = options.between[0]
|
|
147
|
+
const b: BSide = options.between[1]
|
|
148
|
+
const findRelatedKeysState = createMutableAtomFamily<
|
|
149
|
+
SetRTX<string>,
|
|
150
|
+
SetRTXJson<string>,
|
|
151
|
+
string
|
|
152
|
+
>(
|
|
153
|
+
{
|
|
154
|
+
key: `${options.key}/relatedKeys`,
|
|
155
|
+
default: () => new SetRTX(),
|
|
156
|
+
mutable: true,
|
|
157
|
+
fromJson: (json) => SetRTX.fromJSON(json),
|
|
158
|
+
toJson: (set) => set.toJSON(),
|
|
159
|
+
},
|
|
160
|
+
store,
|
|
161
|
+
)
|
|
162
|
+
this.core = { findRelatedKeysState }
|
|
163
|
+
const getRelatedKeys: Read<(key: string) => SetRTX<string>> = (
|
|
164
|
+
{ get },
|
|
165
|
+
key,
|
|
166
|
+
) => get(findRelatedKeysState(key))
|
|
167
|
+
const addRelation: Write<(a: string, b: string) => void> = (
|
|
168
|
+
transactors,
|
|
169
|
+
a,
|
|
170
|
+
b,
|
|
171
|
+
) => {
|
|
172
|
+
const aKeys = getRelatedKeys(transactors, a)
|
|
173
|
+
const bKeys = getRelatedKeys(transactors, b)
|
|
182
174
|
transactors.set(findRelatedKeysState(a), aKeys.add(b))
|
|
183
|
-
} else {
|
|
184
|
-
transactors.set(findRelatedKeysState(a), new SetRTX([b]))
|
|
185
|
-
}
|
|
186
|
-
if (bKeys) {
|
|
187
175
|
transactors.set(findRelatedKeysState(b), bKeys.add(a))
|
|
188
|
-
} else {
|
|
189
|
-
transactors.set(findRelatedKeysState(b), new SetRTX([a]))
|
|
190
176
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const aKeys = getRelatedKeys(transactors, a)
|
|
198
|
-
if (aKeys) {
|
|
177
|
+
const deleteRelation: Write<(a: string, b: string) => void> = (
|
|
178
|
+
transactors,
|
|
179
|
+
a,
|
|
180
|
+
b,
|
|
181
|
+
) => {
|
|
182
|
+
const aKeys = getRelatedKeys(transactors, a)
|
|
199
183
|
aKeys.delete(b)
|
|
200
184
|
if (aKeys.size === 0) {
|
|
201
|
-
|
|
185
|
+
dispose(findRelatedKeysState(a))
|
|
202
186
|
}
|
|
203
187
|
const bKeys = getRelatedKeys(transactors, b)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
transactors.set(findRelatedKeysState(b), undefined)
|
|
208
|
-
}
|
|
188
|
+
bKeys.delete(a)
|
|
189
|
+
if (bKeys.size === 0) {
|
|
190
|
+
dispose(findRelatedKeysState(b))
|
|
209
191
|
}
|
|
210
192
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const aRelations = getRelatedKeys(transactors, a)
|
|
218
|
-
if (aRelations) {
|
|
193
|
+
const replaceRelationsSafely: Write<(a: string, bs: string[]) => void> = (
|
|
194
|
+
transactors,
|
|
195
|
+
a,
|
|
196
|
+
bs,
|
|
197
|
+
) => {
|
|
198
|
+
const aRelations = getRelatedKeys(transactors, a)
|
|
219
199
|
for (const b of aRelations) {
|
|
220
200
|
const bKeys = getRelatedKeys(transactors, b)
|
|
221
201
|
if (bKeys) {
|
|
222
202
|
bKeys.delete(a)
|
|
223
203
|
if (bKeys.size === 0) {
|
|
224
|
-
|
|
204
|
+
dispose(findRelatedKeysState(b))
|
|
225
205
|
}
|
|
226
206
|
}
|
|
227
207
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const bKeys = getRelatedKeys(transactors, b)
|
|
232
|
-
if (bKeys) {
|
|
208
|
+
transactors.set(findRelatedKeysState(a), new SetRTX(bs))
|
|
209
|
+
for (const b of bs) {
|
|
210
|
+
const bKeys = getRelatedKeys(transactors, b)
|
|
233
211
|
bKeys.add(a)
|
|
234
|
-
} else {
|
|
235
|
-
transactors.set(findRelatedKeysState(b), new SetRTX([a]))
|
|
236
212
|
}
|
|
237
213
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
let bKeys = getRelatedKeys(transactors, b)
|
|
247
|
-
if (bKeys) {
|
|
214
|
+
const replaceRelationsUnsafely: Write<(a: string, bs: string[]) => void> = (
|
|
215
|
+
transactors,
|
|
216
|
+
a,
|
|
217
|
+
bs,
|
|
218
|
+
) => {
|
|
219
|
+
transactors.set(findRelatedKeysState(a), new SetRTX(bs))
|
|
220
|
+
for (const b of bs) {
|
|
221
|
+
const bKeys = getRelatedKeys(transactors, b)
|
|
248
222
|
bKeys.add(a)
|
|
249
|
-
} else {
|
|
250
|
-
bKeys = new SetRTX([a])
|
|
251
|
-
transactors.set(findRelatedKeysState(b), bKeys)
|
|
252
223
|
}
|
|
253
224
|
}
|
|
254
|
-
|
|
255
|
-
const has: Read<(a: string, b?: string) => boolean> = (transactors, a, b) => {
|
|
256
|
-
const aKeys = getRelatedKeys(transactors, a)
|
|
257
|
-
return b ? aKeys?.has(b) ?? false : (aKeys?.size ?? 0) > 0 ?? false
|
|
258
|
-
}
|
|
259
|
-
const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
|
|
260
|
-
getRelatedKeys: (key) => getRelatedKeys(TRANSACTORS, key),
|
|
261
|
-
addRelation: (a, b) => addRelation(TRANSACTORS, a, b),
|
|
262
|
-
deleteRelation: (a, b) => deleteRelation(TRANSACTORS, a, b),
|
|
263
|
-
replaceRelationsSafely: (a, bs) =>
|
|
264
|
-
replaceRelationsSafely(TRANSACTORS, a, bs),
|
|
265
|
-
replaceRelationsUnsafely: (a, bs) =>
|
|
266
|
-
replaceRelationsUnsafely(TRANSACTORS, a, bs),
|
|
267
|
-
has: (a, b) => has(TRANSACTORS, a, b),
|
|
268
|
-
}
|
|
269
|
-
let externalStore: ExternalStoreConfiguration<Content>
|
|
270
|
-
let findContentState: AtomFamily<Content, string>
|
|
271
|
-
if (defaultContent) {
|
|
272
|
-
findContentState = createAtomFamily<Content, string>(
|
|
273
|
-
{
|
|
274
|
-
key: `${options.key}/content`,
|
|
275
|
-
default: defaultContent,
|
|
276
|
-
},
|
|
277
|
-
store,
|
|
278
|
-
)
|
|
279
|
-
const getContent: Read<(key: string) => Content | undefined> = (
|
|
280
|
-
{ get },
|
|
281
|
-
key,
|
|
282
|
-
) => get(findContentState(key))
|
|
283
|
-
const setContent: Write<(key: string, content: Content) => void> = (
|
|
225
|
+
const has: Read<(a: string, b?: string) => boolean> = (
|
|
284
226
|
transactors,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
) =>
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
227
|
+
a,
|
|
228
|
+
b,
|
|
229
|
+
) => {
|
|
230
|
+
const aKeys = getRelatedKeys(transactors, a)
|
|
231
|
+
return b ? aKeys.has(b) : aKeys.size > 0
|
|
232
|
+
}
|
|
233
|
+
const baseExternalStoreConfiguration: BaseExternalStoreConfiguration = {
|
|
234
|
+
getRelatedKeys: (key) => getRelatedKeys(this.transactors, key),
|
|
235
|
+
addRelation: (a, b) => addRelation(this.transactors, a, b),
|
|
236
|
+
deleteRelation: (a, b) => deleteRelation(this.transactors, a, b),
|
|
237
|
+
replaceRelationsSafely: (a, bs) =>
|
|
238
|
+
replaceRelationsSafely(this.transactors, a, bs),
|
|
239
|
+
replaceRelationsUnsafely: (a, bs) =>
|
|
240
|
+
replaceRelationsUnsafely(this.transactors, a, bs),
|
|
241
|
+
has: (a, b) => has(this.transactors, a, b),
|
|
242
|
+
}
|
|
243
|
+
let externalStore: ExternalStoreConfiguration<Content>
|
|
244
|
+
let findContentState: AtomFamily<Content, string>
|
|
245
|
+
if (defaultContent) {
|
|
246
|
+
findContentState = createRegularAtomFamily<Content, string>(
|
|
247
|
+
{
|
|
248
|
+
key: `${options.key}/content`,
|
|
249
|
+
default: defaultContent,
|
|
250
|
+
},
|
|
251
|
+
store,
|
|
252
|
+
)
|
|
253
|
+
const getContent: Read<(key: string) => Content | null> = ({ get }, key) =>
|
|
254
|
+
get(findContentState(key))
|
|
255
|
+
const setContent: Write<(key: string, content: Content) => void> = (
|
|
256
|
+
transactors,
|
|
257
|
+
key,
|
|
258
|
+
content,
|
|
259
|
+
) => transactors.set(findContentState(key), content)
|
|
260
|
+
const deleteContent: Write<(key: string) => void> = (_, key) =>
|
|
261
|
+
dispose(findContentState(key))
|
|
262
|
+
const externalStoreWithContentConfiguration = {
|
|
292
263
|
getContent: (contentKey: string) => {
|
|
293
|
-
const content = getContent(
|
|
264
|
+
const content = getContent(this.transactors, contentKey)
|
|
294
265
|
return content
|
|
295
266
|
},
|
|
296
267
|
setContent: (contentKey: string, content: Content) => {
|
|
297
|
-
setContent(
|
|
268
|
+
setContent(this.transactors, contentKey, content)
|
|
298
269
|
},
|
|
299
270
|
deleteContent: (contentKey: string) => {
|
|
300
|
-
deleteContent(
|
|
271
|
+
deleteContent(this.transactors, contentKey)
|
|
301
272
|
},
|
|
302
273
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
274
|
+
externalStore = Object.assign(
|
|
275
|
+
baseExternalStoreConfiguration,
|
|
276
|
+
externalStoreWithContentConfiguration,
|
|
277
|
+
) as ExternalStoreConfiguration<Content>
|
|
278
|
+
} else {
|
|
279
|
+
externalStore =
|
|
280
|
+
baseExternalStoreConfiguration as ExternalStoreConfiguration<Content>
|
|
281
|
+
}
|
|
282
|
+
const relations = new Junction<ASide, BSide, Content>(options, {
|
|
283
|
+
externalStore,
|
|
284
|
+
makeContentKey: (...args) => args.sort().join(`:`),
|
|
285
|
+
})
|
|
315
286
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
)
|
|
287
|
+
const createSingleKeyStateFamily = () =>
|
|
288
|
+
createSelectorFamily<string | null, string>(
|
|
289
|
+
{
|
|
290
|
+
key: `${options.key}/singleRelatedKey`,
|
|
291
|
+
get:
|
|
292
|
+
(key) =>
|
|
293
|
+
({ get }) => {
|
|
294
|
+
const relatedKeys = get(findRelatedKeysState(key))
|
|
295
|
+
for (const relatedKey of relatedKeys) {
|
|
296
|
+
return relatedKey
|
|
297
|
+
}
|
|
298
|
+
return null
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
store,
|
|
302
|
+
)
|
|
303
|
+
const getMultipleKeyStateFamily = () => {
|
|
304
|
+
return createSelectorFamily<string[], string>(
|
|
305
|
+
{
|
|
306
|
+
key: `${options.key}/multipleRelatedKeys`,
|
|
307
|
+
get:
|
|
308
|
+
(key) =>
|
|
309
|
+
({ get }) => {
|
|
310
|
+
const jsonFamily = getJsonFamily(findRelatedKeysState, store)
|
|
311
|
+
const json = get(jsonFamily(key))
|
|
312
|
+
return json.members
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
store,
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
const createSingleEntryStateFamily = () =>
|
|
319
|
+
createSelectorFamily<[string, Content] | null, string>(
|
|
320
|
+
{
|
|
321
|
+
key: `${options.key}/singleRelatedEntry`,
|
|
322
|
+
get:
|
|
323
|
+
(key) =>
|
|
324
|
+
({ get }) => {
|
|
325
|
+
const relatedKeys = get(findRelatedKeysState(key))
|
|
326
|
+
for (const relatedKey of relatedKeys) {
|
|
327
|
+
const contentKey = relations.makeContentKey(key, relatedKey)
|
|
328
|
+
return [relatedKey, get(findContentState(contentKey))]
|
|
329
|
+
}
|
|
330
|
+
return null
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
store,
|
|
334
|
+
)
|
|
335
|
+
const getMultipleEntryStateFamily = () =>
|
|
336
|
+
createSelectorFamily<[string, Content][], string>(
|
|
337
|
+
{
|
|
338
|
+
key: `${options.key}/multipleRelatedEntries`,
|
|
339
|
+
get:
|
|
340
|
+
(key) =>
|
|
341
|
+
({ get }) => {
|
|
342
|
+
const jsonFamily = getJsonFamily(findRelatedKeysState, store)
|
|
343
|
+
const json = get(jsonFamily(key))
|
|
344
|
+
return json.members.map((relatedKey) => {
|
|
345
|
+
const contentKey = relations.makeContentKey(key, relatedKey)
|
|
346
|
+
return [relatedKey, get(findContentState(contentKey))]
|
|
347
|
+
})
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
store,
|
|
351
|
+
)
|
|
365
352
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
353
|
+
switch (options.cardinality) {
|
|
354
|
+
case `1:1`: {
|
|
355
|
+
const findSingleRelatedKeyState = createSingleKeyStateFamily()
|
|
356
|
+
const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
|
|
357
|
+
const stateKeyB = `${b}KeyOf${capitalize(a)}` as const
|
|
358
|
+
const findStateBase = {
|
|
359
|
+
[stateKeyA]: findSingleRelatedKeyState,
|
|
360
|
+
[stateKeyB]: findSingleRelatedKeyState,
|
|
361
|
+
} as JoinState<ASide, BSide, Cardinality, Content>
|
|
362
|
+
let findState: JoinState<ASide, BSide, Cardinality, Content>
|
|
363
|
+
if (defaultContent) {
|
|
364
|
+
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
365
|
+
const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
|
|
366
|
+
const entriesStateKeyB = `${b}EntryOf${capitalize(a)}` as const
|
|
367
|
+
const findStateWithContent = {
|
|
368
|
+
[entriesStateKeyA]: findSingleRelatedEntryState,
|
|
369
|
+
[entriesStateKeyB]: findSingleRelatedEntryState,
|
|
370
|
+
}
|
|
371
|
+
findState = Object.assign(findStateBase, findStateWithContent)
|
|
372
|
+
} else {
|
|
373
|
+
findState = findStateBase
|
|
383
374
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
return {
|
|
389
|
-
relations,
|
|
390
|
-
findState,
|
|
375
|
+
this.relations = relations
|
|
376
|
+
this.findState = findState
|
|
377
|
+
break
|
|
391
378
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
379
|
+
case `1:n`: {
|
|
380
|
+
const findSingleRelatedKeyState = createSingleKeyStateFamily()
|
|
381
|
+
const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
|
|
382
|
+
const stateKeyA = `${a}KeyOf${capitalize(b)}` as const
|
|
383
|
+
const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
|
|
384
|
+
const findStateBase = {
|
|
385
|
+
[stateKeyA]: findSingleRelatedKeyState,
|
|
386
|
+
[stateKeyB]: findMultipleRelatedKeysState,
|
|
387
|
+
} as JoinState<ASide, BSide, Cardinality, Content>
|
|
388
|
+
let findState: JoinState<ASide, BSide, Cardinality, Content>
|
|
389
|
+
if (defaultContent) {
|
|
390
|
+
const findSingleRelatedEntryState = createSingleEntryStateFamily()
|
|
391
|
+
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
392
|
+
const entriesStateKeyA = `${a}EntryOf${capitalize(b)}` as const
|
|
393
|
+
const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
|
|
394
|
+
const findStateWithContent = {
|
|
395
|
+
[entriesStateKeyA]: findSingleRelatedEntryState,
|
|
396
|
+
[entriesStateKeyB]: findMultipleRelatedEntriesState,
|
|
397
|
+
}
|
|
398
|
+
findState = Object.assign(findStateBase, findStateWithContent)
|
|
399
|
+
} else {
|
|
400
|
+
findState = findStateBase
|
|
411
401
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
402
|
+
this.relations = relations
|
|
403
|
+
this.findState = findState
|
|
404
|
+
break
|
|
415
405
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
[entriesStateKeyB]: findMultipleRelatedEntriesState,
|
|
406
|
+
default: {
|
|
407
|
+
const findMultipleRelatedKeysState = getMultipleKeyStateFamily()
|
|
408
|
+
const stateKeyA = `${a}KeysOf${capitalize(b)}` as const
|
|
409
|
+
const stateKeyB = `${b}KeysOf${capitalize(a)}` as const
|
|
410
|
+
const findStateBase = {
|
|
411
|
+
[stateKeyA]: findMultipleRelatedKeysState,
|
|
412
|
+
[stateKeyB]: findMultipleRelatedKeysState,
|
|
413
|
+
} as JoinState<ASide, BSide, Cardinality, Content>
|
|
414
|
+
let findState: JoinState<ASide, BSide, Cardinality, Content>
|
|
415
|
+
if (defaultContent) {
|
|
416
|
+
const findMultipleRelatedEntriesState = getMultipleEntryStateFamily()
|
|
417
|
+
const entriesStateKeyA = `${a}EntriesOf${capitalize(b)}` as const
|
|
418
|
+
const entriesStateKeyB = `${b}EntriesOf${capitalize(a)}` as const
|
|
419
|
+
const findStateWithContent = {
|
|
420
|
+
[entriesStateKeyA]: findMultipleRelatedEntriesState,
|
|
421
|
+
[entriesStateKeyB]: findMultipleRelatedEntriesState,
|
|
422
|
+
}
|
|
423
|
+
findState = Object.assign(findStateBase, findStateWithContent)
|
|
424
|
+
} else {
|
|
425
|
+
findState = findStateBase
|
|
437
426
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
findState = findStateBase
|
|
441
|
-
}
|
|
442
|
-
return {
|
|
443
|
-
relations,
|
|
444
|
-
findState,
|
|
427
|
+
this.relations = relations
|
|
428
|
+
this.findState = findState
|
|
445
429
|
}
|
|
446
430
|
}
|
|
447
|
-
default:
|
|
448
|
-
throw new Error(`Invalid cardinality: ${options.cardinality}`)
|
|
449
431
|
}
|
|
450
432
|
}
|
|
433
|
+
export function join<
|
|
434
|
+
const ASide extends string,
|
|
435
|
+
const BSide extends string,
|
|
436
|
+
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
437
|
+
>(
|
|
438
|
+
options: JoinOptions<ASide, BSide, Cardinality, null>,
|
|
439
|
+
defaultContent?: undefined,
|
|
440
|
+
store?: Store,
|
|
441
|
+
): {
|
|
442
|
+
readonly relations: Junction<ASide, BSide, null>
|
|
443
|
+
readonly findState: JoinState<ASide, BSide, Cardinality, null>
|
|
444
|
+
readonly transact: (
|
|
445
|
+
transactors: Transactors,
|
|
446
|
+
run: (join: Join<ASide, BSide, Cardinality, null>) => void,
|
|
447
|
+
) => void
|
|
448
|
+
readonly core: {
|
|
449
|
+
readonly findRelatedKeysState: MutableAtomFamily<
|
|
450
|
+
SetRTX<string>,
|
|
451
|
+
SetRTXJson<string>,
|
|
452
|
+
string
|
|
453
|
+
>
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
export function join<
|
|
457
|
+
const ASide extends string,
|
|
458
|
+
const BSide extends string,
|
|
459
|
+
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
460
|
+
const Content extends Json.Object,
|
|
461
|
+
>(
|
|
462
|
+
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
463
|
+
defaultContent: Content,
|
|
464
|
+
store?: Store,
|
|
465
|
+
): {
|
|
466
|
+
readonly relations: Junction<ASide, BSide, Content>
|
|
467
|
+
readonly findState: JoinState<ASide, BSide, Cardinality, Content>
|
|
468
|
+
readonly transact: (
|
|
469
|
+
transactors: Transactors,
|
|
470
|
+
run: (join: Join<ASide, BSide, Cardinality, Content>) => void,
|
|
471
|
+
) => void
|
|
472
|
+
readonly core: {
|
|
473
|
+
readonly findRelatedKeysState: MutableAtomFamily<
|
|
474
|
+
SetRTX<string>,
|
|
475
|
+
SetRTXJson<string>,
|
|
476
|
+
string
|
|
477
|
+
>
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
export function join<
|
|
481
|
+
ASide extends string,
|
|
482
|
+
BSide extends string,
|
|
483
|
+
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
484
|
+
Content extends Json.Object,
|
|
485
|
+
>(
|
|
486
|
+
options: JoinOptions<ASide, BSide, Cardinality, Content>,
|
|
487
|
+
defaultContent: Content | undefined,
|
|
488
|
+
store: Store = IMPLICIT.STORE,
|
|
489
|
+
): Join<ASide, BSide, Cardinality, Content> {
|
|
490
|
+
return new Join(options, defaultContent, store)
|
|
491
|
+
}
|