atom.io 0.29.5 → 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-TCINPEYE.js → chunk-SMKF3ZNG.js} +221 -137
- package/dist/index.d.ts +75 -10
- package/dist/index.js +3 -17
- package/internal/dist/index.d.ts +76 -41
- package/internal/dist/index.js +2 -1
- package/internal/src/atom/dispose-atom.ts +4 -8
- package/internal/src/index.ts +1 -1
- package/internal/src/ingest-updates/ingest-creation-disposal.ts +71 -27
- package/internal/src/junction.ts +152 -84
- package/internal/src/molecule/create-molecule-family.ts +2 -2
- package/internal/src/molecule/dispose-molecule.ts +4 -2
- package/internal/src/molecule/make-molecule-in-store.ts +11 -9
- package/internal/src/molecule/molecule-internal.ts +12 -8
- 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 +10 -2
- package/internal/src/timeline/create-timeline.ts +99 -71
- package/internal/src/transaction/index.ts +1 -1
- package/internal/src/utility-types.ts +9 -2
- package/json/dist/index.d.ts +3 -3
- package/json/dist/index.js +2 -1
- package/json/src/entries.ts +3 -3
- package/package.json +15 -15
- package/react-devtools/dist/index.js +9 -5
- package/react-devtools/src/TimelineIndex.tsx +4 -1
- package/react-devtools/src/Updates.tsx +18 -3
- 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 +277 -0
- package/src/index.ts +1 -0
- package/src/molecule.ts +9 -5
- package/src/transaction.ts +22 -4
package/internal/src/junction.ts
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
import type { Refinement } from "atom.io/introspection"
|
|
2
2
|
import type { Json } from "atom.io/json"
|
|
3
|
+
import { B } from "vitest/dist/chunks/benchmark.JVlTzojj.js"
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
extends
|
|
6
|
-
|
|
5
|
+
export type JunctionEntriesBase<
|
|
6
|
+
AType extends string,
|
|
7
|
+
BType extends string,
|
|
8
|
+
Content extends Json.Object | null,
|
|
9
|
+
> = {
|
|
10
|
+
readonly relations: ([AType, BType[]] | [BType, AType[]])[]
|
|
7
11
|
readonly contents: [string, Content][]
|
|
8
12
|
}
|
|
9
|
-
export interface
|
|
10
|
-
extends
|
|
13
|
+
export interface JunctionEntries<
|
|
14
|
+
AType extends string,
|
|
15
|
+
BType extends string,
|
|
16
|
+
Content extends Json.Object | null,
|
|
17
|
+
> extends Json.Object,
|
|
18
|
+
JunctionEntriesBase<AType, BType, Content> {}
|
|
19
|
+
|
|
20
|
+
export type JunctionSchemaBase<ASide extends string, BSide extends string> = {
|
|
11
21
|
readonly between: [a: ASide, b: BSide]
|
|
12
22
|
readonly cardinality: `1:1` | `1:n` | `n:n`
|
|
13
23
|
}
|
|
24
|
+
export interface JunctionSchema<ASide extends string, BSide extends string>
|
|
25
|
+
extends Json.Object,
|
|
26
|
+
JunctionSchemaBase<ASide, BSide> {}
|
|
14
27
|
|
|
15
28
|
export type BaseExternalStoreConfiguration = {
|
|
16
29
|
addRelation: (a: string, b: string) => void
|
|
17
30
|
deleteRelation: (a: string, b: string) => void
|
|
18
31
|
replaceRelationsSafely: (a: string, bs: string[]) => void
|
|
19
32
|
replaceRelationsUnsafely: (a: string, bs: string[]) => void
|
|
20
|
-
getRelatedKeys
|
|
33
|
+
getRelatedKeys(key: string): Set<string> | undefined
|
|
21
34
|
has: (a: string, b?: string) => boolean
|
|
22
35
|
}
|
|
23
36
|
|
|
@@ -39,41 +52,56 @@ export type ExternalStoreConfiguration<Content extends Json.Object | null> =
|
|
|
39
52
|
: BaseExternalStoreConfiguration &
|
|
40
53
|
Empty<ExternalStoreWithContentConfiguration<Json.Object>>
|
|
41
54
|
|
|
42
|
-
export type JunctionAdvancedConfiguration<
|
|
55
|
+
export type JunctionAdvancedConfiguration<
|
|
56
|
+
AType extends string,
|
|
57
|
+
BType extends string,
|
|
58
|
+
Content extends Json.Object | null,
|
|
59
|
+
> = {
|
|
43
60
|
warn?: (...args: any[]) => void
|
|
44
61
|
externalStore?: ExternalStoreConfiguration<Content>
|
|
62
|
+
isAType?: Refinement<string, AType>
|
|
63
|
+
isBType?: Refinement<string, BType>
|
|
45
64
|
isContent?: Refinement<unknown, Content>
|
|
46
|
-
makeContentKey?: (a:
|
|
65
|
+
makeContentKey?: (a: AType, b: BType) => string
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
export type JunctionJSON<
|
|
50
69
|
ASide extends string,
|
|
70
|
+
AType extends string,
|
|
51
71
|
BSide extends string,
|
|
72
|
+
BType extends string,
|
|
52
73
|
Content extends Json.Object | null,
|
|
53
|
-
> = JunctionEntries<Content> & JunctionSchema<ASide, BSide>
|
|
74
|
+
> = JunctionEntries<AType, BType, Content> & JunctionSchema<ASide, BSide>
|
|
54
75
|
|
|
55
76
|
export class Junction<
|
|
56
77
|
const ASide extends string,
|
|
78
|
+
const AType extends string,
|
|
57
79
|
const BSide extends string,
|
|
80
|
+
const BType extends string,
|
|
58
81
|
const Content extends Json.Object | null = null,
|
|
59
82
|
> {
|
|
60
83
|
public readonly a: ASide
|
|
61
84
|
public readonly b: BSide
|
|
62
85
|
public readonly cardinality: `1:1` | `1:n` | `n:n`
|
|
63
|
-
public readonly relations = new Map<
|
|
86
|
+
public readonly relations = new Map<AType | BType, Set<AType> | Set<BType>>()
|
|
64
87
|
public readonly contents = new Map<string, Content>()
|
|
65
88
|
|
|
66
89
|
public isContent: Refinement<unknown, Content> | null
|
|
67
|
-
public makeContentKey = (a:
|
|
90
|
+
public makeContentKey = (a: AType, b: BType): string => `${a}:${b}`
|
|
68
91
|
|
|
69
92
|
public warn?: (...args: any[]) => void
|
|
70
93
|
|
|
71
|
-
public getRelatedKeys(key:
|
|
94
|
+
public getRelatedKeys(key: AType): Set<BType> | undefined
|
|
95
|
+
public getRelatedKeys(key: BType): Set<AType> | undefined
|
|
96
|
+
public getRelatedKeys(key: AType | BType): Set<AType> | Set<BType> | undefined
|
|
97
|
+
public getRelatedKeys(
|
|
98
|
+
key: AType | BType,
|
|
99
|
+
): Set<AType> | Set<BType> | undefined {
|
|
72
100
|
return this.relations.get(key)
|
|
73
101
|
}
|
|
74
|
-
protected addRelation(a:
|
|
75
|
-
let aRelations = this.relations.get(a)
|
|
76
|
-
let bRelations = this.relations.get(b)
|
|
102
|
+
protected addRelation(a: AType, b: BType): void {
|
|
103
|
+
let aRelations = this.relations.get(a) as Set<BType> | undefined
|
|
104
|
+
let bRelations = this.relations.get(b) as Set<AType> | undefined
|
|
77
105
|
if (aRelations) {
|
|
78
106
|
aRelations.add(b)
|
|
79
107
|
} else {
|
|
@@ -87,14 +115,14 @@ export class Junction<
|
|
|
87
115
|
this.relations.set(b, bRelations)
|
|
88
116
|
}
|
|
89
117
|
}
|
|
90
|
-
protected deleteRelation(a:
|
|
91
|
-
const aRelations = this.relations.get(a)
|
|
118
|
+
protected deleteRelation(a: AType, b: BType): void {
|
|
119
|
+
const aRelations = this.relations.get(a) as Set<BType> | undefined
|
|
92
120
|
if (aRelations) {
|
|
93
121
|
aRelations.delete(b)
|
|
94
122
|
if (aRelations.size === 0) {
|
|
95
123
|
this.relations.delete(a)
|
|
96
124
|
}
|
|
97
|
-
const bRelations = this.relations.get(b)
|
|
125
|
+
const bRelations = this.relations.get(b) as Set<AType> | undefined
|
|
98
126
|
if (bRelations) {
|
|
99
127
|
bRelations.delete(a)
|
|
100
128
|
if (bRelations.size === 0) {
|
|
@@ -104,36 +132,46 @@ export class Junction<
|
|
|
104
132
|
}
|
|
105
133
|
}
|
|
106
134
|
|
|
107
|
-
protected replaceRelationsUnsafely(a:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
protected replaceRelationsUnsafely(a: AType, bs: BType[]): void
|
|
136
|
+
protected replaceRelationsUnsafely(b: BType, as: AType[]): void
|
|
137
|
+
protected replaceRelationsUnsafely(
|
|
138
|
+
x: AType | BType,
|
|
139
|
+
ys: AType[] | BType[],
|
|
140
|
+
): void {
|
|
141
|
+
this.relations.set(x as AType, new Set(ys as BType[]))
|
|
142
|
+
for (const y of ys) {
|
|
143
|
+
const yRelations = new Set<AType>().add(x as AType)
|
|
144
|
+
this.relations.set(y, yRelations)
|
|
112
145
|
}
|
|
113
146
|
}
|
|
114
|
-
protected replaceRelationsSafely(a:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
protected replaceRelationsSafely(a: AType, bs: BType[]): void
|
|
148
|
+
protected replaceRelationsSafely(b: BType, as: AType[]): void
|
|
149
|
+
protected replaceRelationsSafely<
|
|
150
|
+
XType extends AType | BType,
|
|
151
|
+
YType extends XType extends AType ? BType : AType,
|
|
152
|
+
>(x: XType, ys: YType[]): void {
|
|
153
|
+
const xRelationsPrev = this.relations.get(x)
|
|
154
|
+
if (xRelationsPrev) {
|
|
155
|
+
for (const y of xRelationsPrev) {
|
|
156
|
+
const yRelations = this.relations.get(y) as Set<XType> | undefined
|
|
157
|
+
if (yRelations) {
|
|
158
|
+
if (yRelations.size === 1) {
|
|
159
|
+
this.relations.delete(y)
|
|
122
160
|
} else {
|
|
123
|
-
|
|
161
|
+
yRelations.delete(x)
|
|
124
162
|
}
|
|
125
|
-
this.contents.delete(this.makeContentKey(
|
|
163
|
+
this.contents.delete(this.makeContentKey(x as any, y as any)) // sort XY to AB ❗
|
|
126
164
|
}
|
|
127
165
|
}
|
|
128
166
|
}
|
|
129
|
-
this.relations.set(
|
|
130
|
-
for (const
|
|
131
|
-
let
|
|
132
|
-
if (
|
|
133
|
-
|
|
167
|
+
this.relations.set(x, new Set(ys) as any)
|
|
168
|
+
for (const y of ys) {
|
|
169
|
+
let yRelations = this.relations.get(y) as Set<XType> | undefined
|
|
170
|
+
if (yRelations) {
|
|
171
|
+
yRelations.add(x)
|
|
134
172
|
} else {
|
|
135
|
-
|
|
136
|
-
this.relations.set(
|
|
173
|
+
yRelations = new Set<XType>().add(x)
|
|
174
|
+
this.relations.set(y, yRelations as any)
|
|
137
175
|
}
|
|
138
176
|
}
|
|
139
177
|
}
|
|
@@ -149,15 +187,18 @@ export class Junction<
|
|
|
149
187
|
}
|
|
150
188
|
|
|
151
189
|
public constructor(
|
|
152
|
-
data: JunctionSchema<ASide, BSide> &
|
|
153
|
-
|
|
190
|
+
data: JunctionSchema<ASide, BSide> &
|
|
191
|
+
Partial<JunctionEntries<AType, BType, Content>>,
|
|
192
|
+
config?: JunctionAdvancedConfiguration<AType, BType, Content>,
|
|
154
193
|
) {
|
|
155
194
|
this.a = data.between[0]
|
|
156
195
|
this.b = data.between[1]
|
|
157
196
|
|
|
158
197
|
this.cardinality = data.cardinality
|
|
159
198
|
if (!config?.externalStore) {
|
|
160
|
-
this.relations = new Map(
|
|
199
|
+
this.relations = new Map(
|
|
200
|
+
data.relations?.map(([x, ys]) => [x, new Set(ys as AType[])]),
|
|
201
|
+
)
|
|
161
202
|
this.contents = new Map(data.contents)
|
|
162
203
|
}
|
|
163
204
|
this.isContent = config?.isContent ?? null
|
|
@@ -179,7 +220,10 @@ export class Junction<
|
|
|
179
220
|
this.replaceRelationsUnsafely = (a, bs) => {
|
|
180
221
|
externalStore.replaceRelationsUnsafely(a, bs)
|
|
181
222
|
}
|
|
182
|
-
this.getRelatedKeys = (key) =>
|
|
223
|
+
this.getRelatedKeys = ((key) =>
|
|
224
|
+
externalStore.getRelatedKeys(
|
|
225
|
+
key,
|
|
226
|
+
)) as typeof Junction.prototype.getRelatedKeys
|
|
183
227
|
if (externalStore.getContent) {
|
|
184
228
|
this.getContentInternal = (contentKey) => {
|
|
185
229
|
return externalStore.getContent(contentKey) as any
|
|
@@ -192,7 +236,7 @@ export class Junction<
|
|
|
192
236
|
}
|
|
193
237
|
}
|
|
194
238
|
for (const [x, ys] of data.relations ?? []) {
|
|
195
|
-
for (const y of ys) this.addRelation(x, y)
|
|
239
|
+
for (const y of ys) this.addRelation(x as AType, y as BType) // sort XY to AB ❗
|
|
196
240
|
}
|
|
197
241
|
for (const [contentKey, content] of data.contents ?? []) {
|
|
198
242
|
this.setContent(contentKey, content)
|
|
@@ -202,33 +246,35 @@ export class Junction<
|
|
|
202
246
|
this.warn = config.warn
|
|
203
247
|
}
|
|
204
248
|
}
|
|
205
|
-
public toJSON(): JunctionJSON<ASide, BSide, Content> {
|
|
249
|
+
public toJSON(): JunctionJSON<ASide, AType, BSide, BType, Content> {
|
|
206
250
|
return {
|
|
207
251
|
between: [this.a, this.b],
|
|
208
252
|
cardinality: this.cardinality,
|
|
209
|
-
relations: [...this.relations.entries()].map(
|
|
253
|
+
relations: [...this.relations.entries()].map(
|
|
254
|
+
([a, b]) => [a, [...b]] as [AType, BType[]],
|
|
255
|
+
),
|
|
210
256
|
contents: [...this.contents.entries()],
|
|
211
257
|
}
|
|
212
258
|
}
|
|
213
259
|
|
|
214
260
|
public set(
|
|
215
|
-
a:
|
|
216
|
-
...rest: Content extends null ? [b:
|
|
261
|
+
a: AType,
|
|
262
|
+
...rest: Content extends null ? [b: BType] : [b: BType, content: Content]
|
|
217
263
|
): this
|
|
218
264
|
public set(
|
|
219
|
-
relation: { [Key in ASide
|
|
220
|
-
...rest: Content extends null ? [] | [
|
|
265
|
+
relation: { [Key in ASide]: AType } & { [Key in BSide]: BType },
|
|
266
|
+
...rest: Content extends null ? [] | [void?: undefined] : [content: Content]
|
|
221
267
|
): this
|
|
222
268
|
public set(
|
|
223
|
-
a:
|
|
269
|
+
a: AType | ({ [Key in ASide]: AType } & { [Key in BSide]: BType }),
|
|
224
270
|
...rest: Content extends null
|
|
225
|
-
? [] | [b?:
|
|
226
|
-
: [b:
|
|
271
|
+
? [] | [b?: BType | undefined]
|
|
272
|
+
: [b: BType, content: Content] | [content: Content]
|
|
227
273
|
): this {
|
|
228
|
-
const b:
|
|
274
|
+
const b: BType =
|
|
229
275
|
typeof rest[0] === `string`
|
|
230
276
|
? rest[0]
|
|
231
|
-
: (a[this.b as keyof typeof a] as
|
|
277
|
+
: (a[this.b as keyof typeof a] as BType)
|
|
232
278
|
const content: Content | undefined =
|
|
233
279
|
(rest[1] ?? typeof rest[0] === `string`) ? undefined : (rest[0] as Content)
|
|
234
280
|
a = typeof a === `string` ? a : a[this.a]
|
|
@@ -236,7 +282,7 @@ export class Junction<
|
|
|
236
282
|
// biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
|
|
237
283
|
case `1:1`: {
|
|
238
284
|
const bPrev = this.getRelatedKey(a)
|
|
239
|
-
if (bPrev && bPrev !== b) this.delete(
|
|
285
|
+
if (bPrev && bPrev !== b) this.delete(a, bPrev)
|
|
240
286
|
}
|
|
241
287
|
case `1:n`: {
|
|
242
288
|
const aPrev = this.getRelatedKey(b)
|
|
@@ -251,29 +297,32 @@ export class Junction<
|
|
|
251
297
|
return this
|
|
252
298
|
}
|
|
253
299
|
|
|
254
|
-
public delete(a:
|
|
300
|
+
public delete(a: AType, b?: BType): this
|
|
301
|
+
public delete(b: BType, a?: AType): this
|
|
255
302
|
public delete(
|
|
256
303
|
relation:
|
|
257
|
-
|
|
|
258
|
-
|
|
|
259
|
-
|
|
|
304
|
+
| { [Key in ASide]: AType }
|
|
305
|
+
| { [Key in BSide]: BType }
|
|
306
|
+
| ({ [Key in ASide]: AType } & { [Key in BSide]: BType }),
|
|
260
307
|
b?: undefined,
|
|
261
308
|
): this
|
|
262
309
|
public delete(
|
|
263
310
|
x:
|
|
311
|
+
| AType
|
|
312
|
+
| BType
|
|
264
313
|
| Record<ASide | BSide, string>
|
|
265
314
|
| Record<ASide, string>
|
|
266
|
-
| Record<BSide, string
|
|
267
|
-
|
|
268
|
-
b?: string,
|
|
315
|
+
| Record<BSide, string>,
|
|
316
|
+
b?: AType | BType,
|
|
269
317
|
): this {
|
|
270
318
|
// @ts-expect-error we deduce that this.b may index x
|
|
271
|
-
b = typeof b === `string` ? b : (x[this.b] as
|
|
272
|
-
|
|
273
|
-
|
|
319
|
+
b = typeof b === `string` ? (b as BType) : (x[this.b] as BType | undefined)
|
|
320
|
+
const a =
|
|
321
|
+
// @ts-expect-error we deduce that this.a may index x
|
|
322
|
+
typeof x === `string` ? (x as AType) : (x[this.a] as AType | undefined)
|
|
274
323
|
|
|
275
324
|
if (a === undefined && typeof b === `string`) {
|
|
276
|
-
const bRelations = this.getRelatedKeys(b)
|
|
325
|
+
const bRelations = this.getRelatedKeys(b) as Set<AType>
|
|
277
326
|
if (bRelations) {
|
|
278
327
|
for (const bRelation of bRelations) {
|
|
279
328
|
this.delete(bRelation, b)
|
|
@@ -296,7 +345,9 @@ export class Junction<
|
|
|
296
345
|
return this
|
|
297
346
|
}
|
|
298
347
|
|
|
299
|
-
public getRelatedKey(key:
|
|
348
|
+
public getRelatedKey(key: AType): BType | undefined
|
|
349
|
+
public getRelatedKey(key: BType): AType | undefined
|
|
350
|
+
public getRelatedKey(key: AType | BType): AType | BType | undefined {
|
|
300
351
|
const relations = this.getRelatedKeys(key)
|
|
301
352
|
if (relations) {
|
|
302
353
|
if (relations.size > 1) {
|
|
@@ -315,37 +366,52 @@ export class Junction<
|
|
|
315
366
|
}
|
|
316
367
|
|
|
317
368
|
public replaceRelations(
|
|
318
|
-
a:
|
|
319
|
-
relations: Content extends null ?
|
|
369
|
+
a: AType,
|
|
370
|
+
relations: Content extends null ? BType[] : Record<BType, Content>,
|
|
371
|
+
config?: { reckless: boolean },
|
|
372
|
+
): this
|
|
373
|
+
public replaceRelations(
|
|
374
|
+
b: BType,
|
|
375
|
+
relations: Content extends null ? AType[] : Record<AType, Content>,
|
|
376
|
+
config?: { reckless: boolean },
|
|
377
|
+
): this
|
|
378
|
+
public replaceRelations<
|
|
379
|
+
XType extends AType | BType,
|
|
380
|
+
YType extends XType extends AType ? BType : AType,
|
|
381
|
+
>(
|
|
382
|
+
x: XType,
|
|
383
|
+
relations: Content extends null ? YType[] : Record<YType, Content>,
|
|
320
384
|
config?: { reckless: boolean },
|
|
321
385
|
): this {
|
|
322
386
|
const hasContent = !Array.isArray(relations)
|
|
323
|
-
const
|
|
387
|
+
const ys = (hasContent ? Object.keys(relations) : relations) as YType[]
|
|
324
388
|
if (config?.reckless) {
|
|
325
|
-
this.replaceRelationsUnsafely(
|
|
389
|
+
this.replaceRelationsUnsafely(x as any, ys as any)
|
|
326
390
|
} else {
|
|
327
|
-
this.replaceRelationsSafely(
|
|
391
|
+
this.replaceRelationsSafely(x as any, ys as any)
|
|
328
392
|
}
|
|
329
393
|
if (hasContent) {
|
|
330
|
-
for (const
|
|
331
|
-
const contentKey = this.makeContentKey(
|
|
332
|
-
const content = relations
|
|
394
|
+
for (const y of ys) {
|
|
395
|
+
const contentKey = this.makeContentKey(x as any, y as any) // sort XY to AB ❗
|
|
396
|
+
const content = (relations as Record<YType, Content>)[y]
|
|
333
397
|
this.setContent(contentKey, content)
|
|
334
398
|
}
|
|
335
399
|
}
|
|
336
400
|
return this
|
|
337
401
|
}
|
|
338
402
|
|
|
339
|
-
public getContent(a:
|
|
403
|
+
public getContent(a: AType, b: BType): Content | undefined {
|
|
340
404
|
const contentKey = this.makeContentKey(a, b)
|
|
341
405
|
return this.getContentInternal(contentKey)
|
|
342
406
|
}
|
|
343
407
|
|
|
408
|
+
public getRelationEntries(input: Record<ASide, AType>): [BType, Content][]
|
|
409
|
+
public getRelationEntries(input: Record<BSide, BType>): [AType, Content][]
|
|
344
410
|
public getRelationEntries(
|
|
345
|
-
input: Record<ASide,
|
|
346
|
-
): [
|
|
347
|
-
const a:
|
|
348
|
-
const b:
|
|
411
|
+
input: Record<ASide, AType> | Record<BSide, BType>,
|
|
412
|
+
): [AType | BType, Content][] {
|
|
413
|
+
const a: AType | undefined = (input as any)[this.a]
|
|
414
|
+
const b: BType | undefined = (input as any)[this.b]
|
|
349
415
|
if (a !== undefined && b === undefined) {
|
|
350
416
|
const aRelations = this.getRelatedKeys(a)
|
|
351
417
|
if (aRelations) {
|
|
@@ -365,10 +431,12 @@ export class Junction<
|
|
|
365
431
|
return []
|
|
366
432
|
}
|
|
367
433
|
|
|
368
|
-
public has(a:
|
|
434
|
+
public has(a: AType, b?: BType): boolean
|
|
435
|
+
public has(b: BType, a?: AType): boolean
|
|
436
|
+
public has(a: AType | BType, b?: AType | BType): boolean {
|
|
369
437
|
if (b) {
|
|
370
438
|
const setA = this.getRelatedKeys(a)
|
|
371
|
-
return setA?.has(b) ?? false
|
|
439
|
+
return setA?.has(b as any) ?? false
|
|
372
440
|
}
|
|
373
441
|
return this.relations.has(a)
|
|
374
442
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
MoleculeConstructor,
|
|
3
|
-
|
|
3
|
+
MoleculeCreationClassic,
|
|
4
4
|
MoleculeFamily,
|
|
5
5
|
MoleculeFamilyOptions,
|
|
6
6
|
MoleculeFamilyToken,
|
|
@@ -13,7 +13,7 @@ export function createMoleculeFamily<M extends MoleculeConstructor>(
|
|
|
13
13
|
store: Store,
|
|
14
14
|
options: MoleculeFamilyOptions<M>,
|
|
15
15
|
): MoleculeFamilyToken<M> {
|
|
16
|
-
const subject = new Subject<
|
|
16
|
+
const subject = new Subject<MoleculeCreationClassic<M>>()
|
|
17
17
|
|
|
18
18
|
const token = {
|
|
19
19
|
type: `molecule_family`,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
MoleculeConstructor,
|
|
3
3
|
MoleculeDisposal,
|
|
4
|
+
MoleculeDisposalClassic,
|
|
4
5
|
MoleculeToken,
|
|
5
6
|
} from "atom.io"
|
|
6
7
|
|
|
@@ -36,8 +37,9 @@ export function disposeMolecule<M extends MoleculeConstructor>(
|
|
|
36
37
|
|
|
37
38
|
if (family) {
|
|
38
39
|
const Formula = withdraw(family, store)
|
|
39
|
-
const disposalEvent:
|
|
40
|
+
const disposalEvent: MoleculeDisposalClassic = {
|
|
40
41
|
type: `molecule_disposal`,
|
|
42
|
+
subType: `classic`,
|
|
41
43
|
token,
|
|
42
44
|
family,
|
|
43
45
|
context,
|
|
@@ -50,7 +52,7 @@ export function disposeMolecule<M extends MoleculeConstructor>(
|
|
|
50
52
|
disposeFromStore(store, state)
|
|
51
53
|
}
|
|
52
54
|
for (const child of molecule.below.values()) {
|
|
53
|
-
if (child.
|
|
55
|
+
if (child.dependsOn === `all`) {
|
|
54
56
|
disposeMolecule(child, store)
|
|
55
57
|
} else {
|
|
56
58
|
child.above.delete(molecule.stringKey)
|
|
@@ -2,7 +2,7 @@ import type {
|
|
|
2
2
|
CtorToolkit,
|
|
3
3
|
getState,
|
|
4
4
|
MoleculeConstructor,
|
|
5
|
-
|
|
5
|
+
MoleculeCreationClassic,
|
|
6
6
|
MoleculeFamilyToken,
|
|
7
7
|
MoleculeKey,
|
|
8
8
|
MoleculeParams,
|
|
@@ -82,7 +82,9 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
|
|
|
82
82
|
},
|
|
83
83
|
env: () => getEnvironmentData(newest(rootStore)),
|
|
84
84
|
bond: ((
|
|
85
|
-
token:
|
|
85
|
+
token:
|
|
86
|
+
| JoinToken<any, any, any, any, any, any>
|
|
87
|
+
| ReadableFamilyToken<any, any>,
|
|
86
88
|
maybeRole,
|
|
87
89
|
) => {
|
|
88
90
|
if (token.type === `join`) {
|
|
@@ -93,12 +95,11 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
|
|
|
93
95
|
const unsubFromFamily = family.subject.subscribe(
|
|
94
96
|
`join:${token.key}-${stringKey}`,
|
|
95
97
|
(event) => {
|
|
96
|
-
if (
|
|
97
|
-
event.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
join.molecules.delete(stringKey)
|
|
98
|
+
if (event.type === `molecule_disposal`) {
|
|
99
|
+
if (stringifyJson(event.token.key) === stringKey) {
|
|
100
|
+
unsubFromFamily()
|
|
101
|
+
join.molecules.delete(stringKey)
|
|
102
|
+
}
|
|
102
103
|
}
|
|
103
104
|
},
|
|
104
105
|
)
|
|
@@ -168,11 +169,12 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
|
|
|
168
169
|
|
|
169
170
|
const update = {
|
|
170
171
|
type: `molecule_creation`,
|
|
172
|
+
subType: `classic`,
|
|
171
173
|
token,
|
|
172
174
|
family: familyToken,
|
|
173
175
|
context: contextArray,
|
|
174
176
|
params,
|
|
175
|
-
} satisfies
|
|
177
|
+
} satisfies MoleculeCreationClassic<M>
|
|
176
178
|
|
|
177
179
|
if (isRootStore(target)) {
|
|
178
180
|
family.subject.next(update)
|
|
@@ -18,30 +18,34 @@ export class Molecule<M extends MoleculeConstructor>
|
|
|
18
18
|
public readonly type = `molecule`
|
|
19
19
|
public stringKey: string
|
|
20
20
|
public family?: MoleculeFamilyToken<M>
|
|
21
|
+
public _dependsOn: `all` | `any`
|
|
22
|
+
public get dependsOn(): `all` | `any` {
|
|
23
|
+
if (this.family) {
|
|
24
|
+
return this.family.dependsOn
|
|
25
|
+
}
|
|
26
|
+
return this._dependsOn
|
|
27
|
+
}
|
|
21
28
|
public readonly subject = new Subject<
|
|
22
29
|
StateCreation<any> | StateDisposal<any>
|
|
23
30
|
>()
|
|
24
31
|
public tokens = new Map<string, ReadableToken<any>>()
|
|
25
32
|
public above = new Map<string, Molecule<any>>()
|
|
26
33
|
public below = new Map<string, Molecule<any>>()
|
|
27
|
-
public joins = new Map<string, Join<any, any, any, any>>()
|
|
34
|
+
public joins = new Map<string, Join<any, any, any, any, any, any>>()
|
|
28
35
|
public instance: InstanceType<M>
|
|
29
36
|
public constructor(
|
|
30
|
-
ctx: Molecule<any>
|
|
37
|
+
ctx: Molecule<any>[] | undefined,
|
|
31
38
|
public readonly key: MoleculeKey<M>,
|
|
32
39
|
family?: MoleculeFamilyToken<M>,
|
|
33
40
|
) {
|
|
34
41
|
this.stringKey = stringifyJson(key)
|
|
35
42
|
if (family) {
|
|
36
43
|
this.family = family
|
|
44
|
+
this._dependsOn = family.dependsOn
|
|
37
45
|
}
|
|
38
46
|
if (ctx) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.above.set(molecule.stringKey, molecule)
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
this.above.set(ctx.stringKey, ctx)
|
|
47
|
+
for (const molecule of ctx) {
|
|
48
|
+
this.above.set(molecule.stringKey, molecule)
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
}
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
StateCreation,
|
|
8
8
|
StateDisposal,
|
|
9
9
|
} from "atom.io"
|
|
10
|
-
import type { Json } from "atom.io/json"
|
|
10
|
+
import type { Canonical, Json } from "atom.io/json"
|
|
11
11
|
import { selectJsonFamily, stringifyJson } from "atom.io/json"
|
|
12
12
|
|
|
13
13
|
import { type MutableAtomFamily, prettyPrintTokenType } from ".."
|
|
@@ -21,7 +21,7 @@ import type { Transceiver } from "./transceiver"
|
|
|
21
21
|
export function createMutableAtomFamily<
|
|
22
22
|
T extends Transceiver<any>,
|
|
23
23
|
J extends Json.Serializable,
|
|
24
|
-
K extends
|
|
24
|
+
K extends Canonical,
|
|
25
25
|
>(
|
|
26
26
|
store: Store,
|
|
27
27
|
options: MutableAtomFamilyOptions<T, J, K>,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MutableAtomFamilyToken } from "atom.io"
|
|
2
|
-
import type { Json } from "atom.io/json"
|
|
2
|
+
import type { Canonical, Json } from "atom.io/json"
|
|
3
3
|
|
|
4
4
|
import type { WritableSelectorFamily } from ".."
|
|
5
5
|
import { newest } from "../lineage"
|
|
@@ -9,7 +9,7 @@ import type { Transceiver } from "./transceiver"
|
|
|
9
9
|
export const getJsonFamily = <
|
|
10
10
|
Core extends Transceiver<Json.Serializable>,
|
|
11
11
|
SerializableCore extends Json.Serializable,
|
|
12
|
-
Key extends
|
|
12
|
+
Key extends Canonical,
|
|
13
13
|
>(
|
|
14
14
|
mutableAtomFamily: MutableAtomFamilyToken<Core, SerializableCore, Key>,
|
|
15
15
|
store: Store,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AtomToken,
|
|
3
3
|
Logger,
|
|
4
|
+
MoleculeCreationModern,
|
|
5
|
+
MoleculeDisposalModern,
|
|
4
6
|
MoleculeFamily,
|
|
5
7
|
MoleculeToken,
|
|
6
8
|
ReadonlySelectorToken,
|
|
@@ -54,7 +56,9 @@ export class Store implements Lineage {
|
|
|
54
56
|
})
|
|
55
57
|
public selectorGraph = new Junction<
|
|
56
58
|
`upstreamSelectorKey`,
|
|
59
|
+
string,
|
|
57
60
|
`downstreamSelectorKey`,
|
|
61
|
+
string,
|
|
58
62
|
{ source: string }
|
|
59
63
|
>(
|
|
60
64
|
{
|
|
@@ -86,7 +90,9 @@ export class Store implements Lineage {
|
|
|
86
90
|
public timelines = new Map<string, Timeline<any>>()
|
|
87
91
|
public timelineTopics = new Junction<
|
|
88
92
|
`timelineKey`,
|
|
93
|
+
string,
|
|
89
94
|
`topicKey`,
|
|
95
|
+
string,
|
|
90
96
|
{ topicType: `atom_family` | `atom` | `molecule_family` | `molecule` }
|
|
91
97
|
>({
|
|
92
98
|
between: [`timelineKey`, `topicKey`],
|
|
@@ -115,9 +121,11 @@ export class Store implements Lineage {
|
|
|
115
121
|
null,
|
|
116
122
|
),
|
|
117
123
|
operationClose: new Subject<OperationProgress>(),
|
|
118
|
-
moleculeCreationStart: new Subject<
|
|
124
|
+
moleculeCreationStart: new Subject<
|
|
125
|
+
MoleculeCreationModern | MoleculeToken<any>
|
|
126
|
+
>(),
|
|
119
127
|
moleculeCreationDone: new Subject<MoleculeToken<any>>(),
|
|
120
|
-
moleculeDisposal: new Subject<MoleculeToken<any>>(),
|
|
128
|
+
moleculeDisposal: new Subject<MoleculeDisposalModern | MoleculeToken<any>>(),
|
|
121
129
|
}
|
|
122
130
|
public operation: OperationProgress = { open: false }
|
|
123
131
|
|