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
package/src/main/join.ts
CHANGED
|
@@ -13,39 +13,36 @@ import {
|
|
|
13
13
|
getInternalRelationsFromStore,
|
|
14
14
|
IMPLICIT,
|
|
15
15
|
} from "atom.io/internal"
|
|
16
|
-
import type {
|
|
17
|
-
import type { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
16
|
+
import type { UList } from "atom.io/transceivers/u-list"
|
|
18
17
|
|
|
19
18
|
// biome-ignore format: intersection
|
|
20
19
|
export type JoinOptions<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
AName extends string,
|
|
21
|
+
A extends string,
|
|
22
|
+
BName extends string,
|
|
23
|
+
B extends string,
|
|
25
24
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
26
|
-
Content extends Json.Object | null,
|
|
27
25
|
> =
|
|
28
26
|
Flat<
|
|
29
|
-
& JunctionSchemaBase<
|
|
27
|
+
& JunctionSchemaBase<AName, BName>
|
|
30
28
|
& {
|
|
31
29
|
/** Unique identifier of the join */
|
|
32
30
|
readonly key: string
|
|
33
31
|
/** How many relations are allowed in each direction? */
|
|
34
32
|
readonly cardinality: Cardinality
|
|
35
33
|
/** Type guard for the type of the left side */
|
|
36
|
-
readonly isAType: Refinement<string,
|
|
34
|
+
readonly isAType: Refinement<string, A>
|
|
37
35
|
/** Type guard for the type of the right side */
|
|
38
|
-
readonly isBType: Refinement<string,
|
|
36
|
+
readonly isBType: Refinement<string, B>
|
|
39
37
|
}
|
|
40
|
-
> & Partial<JunctionEntriesBase<
|
|
38
|
+
> & Partial<JunctionEntriesBase<A, B, null>>
|
|
41
39
|
|
|
42
40
|
export type JoinToken<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
AName extends string,
|
|
42
|
+
A extends string,
|
|
43
|
+
BName extends string,
|
|
44
|
+
B extends string,
|
|
47
45
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
48
|
-
Content extends Json.Object | null = null,
|
|
49
46
|
> = {
|
|
50
47
|
/** Unique identifier of the join */
|
|
51
48
|
key: string
|
|
@@ -54,15 +51,13 @@ export type JoinToken<
|
|
|
54
51
|
/** How many relations are allowed in each direction? */
|
|
55
52
|
cardinality: Cardinality
|
|
56
53
|
/** Name of the join's left side */
|
|
57
|
-
a:
|
|
54
|
+
a: AName
|
|
58
55
|
/** Name of the join's right side */
|
|
59
|
-
b:
|
|
56
|
+
b: BName
|
|
60
57
|
/** Never present. This is a marker that preserves the type of the left side's keys */
|
|
61
|
-
__aType?:
|
|
58
|
+
__aType?: A
|
|
62
59
|
/** Never present. This is a marker that preserves the type of the right side's keys */
|
|
63
|
-
__bType?:
|
|
64
|
-
/** Never present. This is a marker that preserves the type of the data present for each relation */
|
|
65
|
-
__content?: Content
|
|
60
|
+
__bType?: B
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
/**
|
|
@@ -73,136 +68,61 @@ export type JoinToken<
|
|
|
73
68
|
* Under the hood, joins coordinate changes of multiple atoms to support that the desired relationships stay consistent.
|
|
74
69
|
*
|
|
75
70
|
* @param options - {@link JoinOptions}
|
|
76
|
-
* @param defaultContent - (undefined)
|
|
77
71
|
* @returns
|
|
78
72
|
* A reference to the join created: a {@link JoinToken}
|
|
79
|
-
* @overload No Content
|
|
80
73
|
*/
|
|
81
74
|
export function join<
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
const
|
|
75
|
+
const AName extends string,
|
|
76
|
+
const A extends string,
|
|
77
|
+
const BName extends string,
|
|
78
|
+
const B extends string,
|
|
86
79
|
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
87
80
|
>(
|
|
88
|
-
options: JoinOptions<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Create a join, an interface for managing relations between two sets of keys.
|
|
93
|
-
*
|
|
94
|
-
* Use joins when it is important to view relationships from either side.
|
|
95
|
-
*
|
|
96
|
-
* Under the hood, joins coordinate changes of multiple atoms to support that the desired relationships stay consistent.
|
|
97
|
-
*
|
|
98
|
-
* @param options - {@link JoinOptions}
|
|
99
|
-
* @param defaultContent - The default value for the content of each relation
|
|
100
|
-
* @returns
|
|
101
|
-
* A reference to the join created: a {@link JoinToken}
|
|
102
|
-
* @overload With Content
|
|
103
|
-
*/
|
|
104
|
-
export function join<
|
|
105
|
-
const ASide extends string,
|
|
106
|
-
const AType extends string,
|
|
107
|
-
const BSide extends string,
|
|
108
|
-
const BType extends string,
|
|
109
|
-
const Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
110
|
-
const Content extends Json.Object,
|
|
111
|
-
>(
|
|
112
|
-
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
113
|
-
defaultContent: Content,
|
|
114
|
-
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content>
|
|
115
|
-
export function join<
|
|
116
|
-
ASide extends string,
|
|
117
|
-
AType extends string,
|
|
118
|
-
BSide extends string,
|
|
119
|
-
BType extends string,
|
|
120
|
-
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
121
|
-
Content extends Json.Object,
|
|
122
|
-
>(
|
|
123
|
-
options: JoinOptions<ASide, AType, BSide, BType, Cardinality, Content>,
|
|
124
|
-
defaultContent: Content | undefined,
|
|
125
|
-
): JoinToken<ASide, AType, BSide, BType, Cardinality, Content> {
|
|
126
|
-
return createJoin(IMPLICIT.STORE, options, defaultContent)
|
|
81
|
+
options: JoinOptions<AName, A, BName, B, Cardinality>,
|
|
82
|
+
): JoinToken<AName, A, BName, B, Cardinality> {
|
|
83
|
+
return createJoin(IMPLICIT.STORE, options)
|
|
127
84
|
}
|
|
128
85
|
|
|
129
86
|
export type JoinStates<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
87
|
+
AName extends string,
|
|
88
|
+
A extends string,
|
|
89
|
+
BName extends string,
|
|
90
|
+
B extends string,
|
|
134
91
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
135
|
-
Content extends Json.Object | null,
|
|
136
92
|
> = Cardinality extends `1:1`
|
|
137
|
-
?
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
BType
|
|
142
|
-
>
|
|
143
|
-
} & {
|
|
144
|
-
readonly [B in BSide as `${B}EntryOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
|
|
145
|
-
[BType, Content] | null,
|
|
146
|
-
AType
|
|
147
|
-
>
|
|
148
|
-
}
|
|
149
|
-
: {}) & {
|
|
150
|
-
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
|
|
151
|
-
AType | null,
|
|
152
|
-
BType
|
|
93
|
+
? {
|
|
94
|
+
readonly [N in AName as `${N}KeyOf${Capitalize<BName>}`]: ReadonlyPureSelectorToken<
|
|
95
|
+
A | null,
|
|
96
|
+
B
|
|
153
97
|
>
|
|
154
98
|
} & {
|
|
155
|
-
readonly [
|
|
156
|
-
|
|
157
|
-
|
|
99
|
+
readonly [N in BName as `${N}KeyOf${Capitalize<AName>}`]: ReadonlyPureSelectorToken<
|
|
100
|
+
B | null,
|
|
101
|
+
A
|
|
158
102
|
>
|
|
159
103
|
}
|
|
160
104
|
: Cardinality extends `1:n`
|
|
161
|
-
?
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
BType
|
|
166
|
-
>
|
|
167
|
-
} & {
|
|
168
|
-
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
|
|
169
|
-
[BType, Content][],
|
|
170
|
-
AType
|
|
171
|
-
>
|
|
172
|
-
}
|
|
173
|
-
: {}) & {
|
|
174
|
-
readonly [A in ASide as `${A}KeyOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
|
|
175
|
-
AType | null,
|
|
176
|
-
BType
|
|
105
|
+
? {
|
|
106
|
+
readonly [N in AName as `${N}KeyOf${Capitalize<BName>}`]: ReadonlyPureSelectorToken<
|
|
107
|
+
A | null,
|
|
108
|
+
B
|
|
177
109
|
>
|
|
178
110
|
} & {
|
|
179
|
-
readonly [
|
|
180
|
-
|
|
181
|
-
|
|
111
|
+
readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorToken<
|
|
112
|
+
B[],
|
|
113
|
+
A
|
|
182
114
|
>
|
|
183
115
|
}
|
|
184
116
|
: Cardinality extends `n:n`
|
|
185
|
-
?
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
BType
|
|
190
|
-
>
|
|
191
|
-
} & {
|
|
192
|
-
readonly [B in BSide as `${B}EntriesOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
|
|
193
|
-
[BType, Content][],
|
|
194
|
-
AType
|
|
195
|
-
>
|
|
196
|
-
}
|
|
197
|
-
: {}) & {
|
|
198
|
-
readonly [A in ASide as `${A}KeysOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
|
|
199
|
-
AType[],
|
|
200
|
-
BType
|
|
117
|
+
? {
|
|
118
|
+
readonly [N in AName as `${N}KeysOf${Capitalize<BName>}`]: ReadonlyPureSelectorToken<
|
|
119
|
+
A[],
|
|
120
|
+
B
|
|
201
121
|
>
|
|
202
122
|
} & {
|
|
203
|
-
readonly [
|
|
204
|
-
|
|
205
|
-
|
|
123
|
+
readonly [N in BName as `${N}KeysOf${Capitalize<AName>}`]: ReadonlyPureSelectorToken<
|
|
124
|
+
B[],
|
|
125
|
+
A
|
|
206
126
|
>
|
|
207
127
|
}
|
|
208
128
|
: never
|
|
@@ -216,16 +136,15 @@ export type JoinStates<
|
|
|
216
136
|
* @overload Default
|
|
217
137
|
*/
|
|
218
138
|
export function findRelations<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
139
|
+
AName extends string,
|
|
140
|
+
A extends string,
|
|
141
|
+
BName extends string,
|
|
142
|
+
B extends string,
|
|
223
143
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
224
|
-
Content extends Json.Object | null,
|
|
225
144
|
>(
|
|
226
|
-
token: JoinToken<
|
|
227
|
-
key:
|
|
228
|
-
): JoinStates<
|
|
145
|
+
token: JoinToken<AName, A, BName, B, Cardinality>,
|
|
146
|
+
key: A | B,
|
|
147
|
+
): JoinStates<AName, A, BName, B, Cardinality> {
|
|
229
148
|
return findRelationsInStore(token, key, IMPLICIT.STORE)
|
|
230
149
|
}
|
|
231
150
|
|
|
@@ -235,15 +154,14 @@ export function findRelations<
|
|
|
235
154
|
* @param change - A function that takes a {@link Junction} interface to edit the relations
|
|
236
155
|
*/
|
|
237
156
|
export function editRelations<
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
157
|
+
AName extends string,
|
|
158
|
+
A extends string,
|
|
159
|
+
BName extends string,
|
|
160
|
+
B extends string,
|
|
242
161
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
243
|
-
Content extends Json.Object | null,
|
|
244
162
|
>(
|
|
245
|
-
token: JoinToken<
|
|
246
|
-
change: (relations: Junction<
|
|
163
|
+
token: JoinToken<AName, A, BName, B, Cardinality>,
|
|
164
|
+
change: (relations: Junction<AName, A, BName, B>) => void,
|
|
247
165
|
): void {
|
|
248
166
|
editRelationsInStore(token, change, IMPLICIT.STORE)
|
|
249
167
|
}
|
|
@@ -254,14 +172,13 @@ export function editRelations<
|
|
|
254
172
|
* A {@link MutableAtomFamilyToken} to access the internal relations
|
|
255
173
|
*/
|
|
256
174
|
export function getInternalRelations<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
175
|
+
AName extends string,
|
|
176
|
+
A extends string,
|
|
177
|
+
BName extends string,
|
|
178
|
+
B extends string,
|
|
261
179
|
Cardinality extends `1:1` | `1:n` | `n:n`,
|
|
262
|
-
Content extends Json.Object | null,
|
|
263
180
|
>(
|
|
264
|
-
token: JoinToken<
|
|
265
|
-
): MutableAtomFamilyToken<
|
|
181
|
+
token: JoinToken<AName, A, BName, B, Cardinality>,
|
|
182
|
+
): MutableAtomFamilyToken<UList<A> | UList<B>, string> {
|
|
266
183
|
return getInternalRelationsFromStore(token, IMPLICIT.STORE)
|
|
267
184
|
}
|
package/src/main/realm.ts
CHANGED
|
@@ -14,16 +14,20 @@ import type { Canonical } from "atom.io/json"
|
|
|
14
14
|
|
|
15
15
|
import type { TransactionToken } from "./tokens"
|
|
16
16
|
|
|
17
|
-
export const $
|
|
18
|
-
export type
|
|
17
|
+
export const $validatedKey: unique symbol = Symbol.for(`claim`)
|
|
18
|
+
export type ValidKey<K extends Canonical> = K & { [$validatedKey]?: true }
|
|
19
|
+
|
|
20
|
+
export function simpleCompound(a: string, b: string): string {
|
|
21
|
+
return [a, b].sort().join(`\u001F`)
|
|
22
|
+
}
|
|
19
23
|
|
|
20
24
|
export class Realm<H extends Hierarchy> {
|
|
21
25
|
public store: RootStore
|
|
22
|
-
public deallocateTX: TransactionToken<(claim:
|
|
26
|
+
public deallocateTX: TransactionToken<(claim: ValidKey<Vassal<H>>) => void>
|
|
23
27
|
public claimTX: TransactionToken<
|
|
24
28
|
<V extends Exclude<Vassal<H>, CompoundTypedKey>, A extends Above<V, H>>(
|
|
25
29
|
newProvenance: A,
|
|
26
|
-
claim:
|
|
30
|
+
claim: ValidKey<V>,
|
|
27
31
|
exclusive?: `exclusive`,
|
|
28
32
|
) => void
|
|
29
33
|
>
|
|
@@ -42,13 +46,13 @@ export class Realm<H extends Hierarchy> {
|
|
|
42
46
|
* @param key - A unique identifier for the new subject
|
|
43
47
|
* @param attachmentStyle - The attachment style of new subject to its owner(s). `any` means that if any owners remain, the subject will be retained. `all` means that the subject be retained only if all owners remain .
|
|
44
48
|
* @returns
|
|
45
|
-
* The subject's key, given status as a true {@link
|
|
49
|
+
* The subject's key, given status as a true {@link ValidKey}
|
|
46
50
|
*/
|
|
47
51
|
public allocate<V extends Vassal<H>, A extends Above<V, H>>(
|
|
48
52
|
provenance: A,
|
|
49
53
|
key: V,
|
|
50
54
|
attachmentStyle?: `all` | `any`,
|
|
51
|
-
):
|
|
55
|
+
): ValidKey<V> {
|
|
52
56
|
return allocateIntoStore<H, V, A>(
|
|
53
57
|
this.store,
|
|
54
58
|
provenance,
|
|
@@ -62,7 +66,7 @@ export class Realm<H extends Hierarchy> {
|
|
|
62
66
|
* @param reagentA - the left reagent of the compound
|
|
63
67
|
* @param reagentB - the right reagent of the compound
|
|
64
68
|
* @returns
|
|
65
|
-
* The compound's key, given status as a
|
|
69
|
+
* The compound's key, given status as a {@link ValidKey}
|
|
66
70
|
*/
|
|
67
71
|
public fuse<
|
|
68
72
|
C extends CompoundFrom<H>,
|
|
@@ -73,14 +77,14 @@ export class Realm<H extends Hierarchy> {
|
|
|
73
77
|
type: T,
|
|
74
78
|
reagentA: SingularTypedKey<A>,
|
|
75
79
|
reagentB: SingularTypedKey<B>,
|
|
76
|
-
):
|
|
80
|
+
): ValidKey<CompoundTypedKey<T, A, B>> {
|
|
77
81
|
return fuseWithinStore<H, C, T, A, B>(this.store, type, reagentA, reagentB)
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
80
84
|
* Remove a subject from the realm
|
|
81
85
|
* @param claim - The subject to be deallocated
|
|
82
86
|
*/
|
|
83
|
-
public deallocate<V extends Vassal<H>>(claim:
|
|
87
|
+
public deallocate<V extends Vassal<H>>(claim: ValidKey<V>): void {
|
|
84
88
|
actUponStore(this.store, this.deallocateTX, arbitrary())(claim)
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
@@ -89,12 +93,12 @@ export class Realm<H extends Hierarchy> {
|
|
|
89
93
|
* @param claim - The subject to be claimed
|
|
90
94
|
* @param exclusive - Whether the subjects previous owners should be detached from it
|
|
91
95
|
* @returns
|
|
92
|
-
* The subject's key, given status as a true {@link
|
|
96
|
+
* The subject's key, given status as a true {@link ValidKey}
|
|
93
97
|
*/
|
|
94
98
|
public claim<
|
|
95
99
|
V extends Exclude<Vassal<H>, CompoundTypedKey>,
|
|
96
100
|
A extends Above<V, H>,
|
|
97
|
-
>(newProvenance: A, claim:
|
|
101
|
+
>(newProvenance: A, claim: ValidKey<V>, exclusive?: `exclusive`): void {
|
|
98
102
|
actUponStore(this.store, this.claimTX, arbitrary())(
|
|
99
103
|
newProvenance,
|
|
100
104
|
claim,
|
|
@@ -157,22 +161,59 @@ export class Anarchy {
|
|
|
157
161
|
): void {
|
|
158
162
|
claimWithinStore<any, any, any>(this.store, newProvenance, key, exclusive)
|
|
159
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Fuse two reagents into a compound
|
|
166
|
+
* @param type - the name of the compound that is being fused
|
|
167
|
+
* @param reagentA - the left reagent of the compound
|
|
168
|
+
* @param reagentB - the right reagent of the compound
|
|
169
|
+
* @returns
|
|
170
|
+
* The compound's key, given status as a {@link ValidKey}
|
|
171
|
+
*/
|
|
172
|
+
public fuse<T extends string, A extends string, B extends string>(
|
|
173
|
+
type: T,
|
|
174
|
+
reagentA: SingularTypedKey<A>,
|
|
175
|
+
reagentB: SingularTypedKey<B>,
|
|
176
|
+
): ValidKey<CompoundTypedKey<T, A, B>> {
|
|
177
|
+
return fuseWithinStore<any, any, T, A, B>(
|
|
178
|
+
this.store,
|
|
179
|
+
type,
|
|
180
|
+
reagentA,
|
|
181
|
+
reagentB,
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function decomposeCompound(
|
|
187
|
+
compound: Canonical,
|
|
188
|
+
): [type: string, a: string, b: string] | null {
|
|
189
|
+
if ((typeof compound === `string`) === false) {
|
|
190
|
+
return null
|
|
191
|
+
}
|
|
192
|
+
const [typeTag, components] = compound.split(`==`)
|
|
193
|
+
if (!components) {
|
|
194
|
+
return null
|
|
195
|
+
}
|
|
196
|
+
const type = typeTag.slice(4)
|
|
197
|
+
const [a, b] = components.split(`++`)
|
|
198
|
+
if (type && a && b) {
|
|
199
|
+
return [type, a, b]
|
|
200
|
+
}
|
|
201
|
+
return null
|
|
160
202
|
}
|
|
161
203
|
|
|
162
|
-
export
|
|
163
|
-
export type T$ = typeof T$
|
|
204
|
+
export type T$ = `T$`
|
|
164
205
|
export type TypeTag<T extends string> = `${T$}--${T}`
|
|
165
206
|
export type SingularTypedKey<T extends string = string> = `${T}::${string}`
|
|
166
207
|
export type CompoundTypedKey<
|
|
208
|
+
T extends string = string,
|
|
167
209
|
A extends string = string,
|
|
168
210
|
B extends string = string,
|
|
169
|
-
|
|
170
|
-
> = `${TypeTag<A>}==${SingularTypedKey<B>}++${SingularTypedKey<C>}`
|
|
211
|
+
> = `${TypeTag<T>}==${SingularTypedKey<A>}++${SingularTypedKey<B>}`
|
|
171
212
|
export type TypedKey<
|
|
213
|
+
T extends string = string,
|
|
172
214
|
A extends string = string,
|
|
173
215
|
B extends string = string,
|
|
174
|
-
|
|
175
|
-
> = CompoundTypedKey<A, B, C> | SingularTypedKey<A>
|
|
216
|
+
> = CompoundTypedKey<T, A, B> | SingularTypedKey<T>
|
|
176
217
|
type Scope = SingularTypedKey[]
|
|
177
218
|
type MutualFealty = {
|
|
178
219
|
above: Scope
|
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
ReadonlyPureSelectorFamilyToken,
|
|
5
5
|
} from "atom.io"
|
|
6
6
|
import { getInternalRelations, join, mutableAtom, selectorFamily } from "atom.io"
|
|
7
|
-
import type { SetRTX } from "atom.io/transceivers/set-rtx"
|
|
8
7
|
import { UList } from "atom.io/transceivers/u-list"
|
|
9
8
|
|
|
10
9
|
export const usersInThisRoomIndex: MutableAtomToken<UList<string>> = mutableAtom<
|
|
@@ -27,28 +26,19 @@ export type UserInRoomMeta = {
|
|
|
27
26
|
export const DEFAULT_USER_IN_ROOM_META: UserInRoomMeta = {
|
|
28
27
|
enteredAtEpoch: 0,
|
|
29
28
|
}
|
|
30
|
-
export const usersInRooms: JoinToken
|
|
31
|
-
|
|
32
|
-
string,
|
|
33
|
-
`user`,
|
|
34
|
-
string,
|
|
35
|
-
`1:n`,
|
|
36
|
-
UserInRoomMeta
|
|
37
|
-
> = join(
|
|
38
|
-
{
|
|
29
|
+
export const usersInRooms: JoinToken<`room`, string, `user`, string, `1:n`> =
|
|
30
|
+
join({
|
|
39
31
|
key: `usersInRooms`,
|
|
40
32
|
between: [`room`, `user`],
|
|
41
33
|
cardinality: `1:n`,
|
|
42
34
|
isAType: (input): input is string => typeof input === `string`,
|
|
43
35
|
isBType: (input): input is string => typeof input === `string`,
|
|
44
|
-
}
|
|
45
|
-
DEFAULT_USER_IN_ROOM_META,
|
|
46
|
-
)
|
|
36
|
+
})
|
|
47
37
|
|
|
48
38
|
export const usersInMyRoomView: ReadonlyPureSelectorFamilyToken<
|
|
49
|
-
MutableAtomToken<
|
|
39
|
+
MutableAtomToken<UList<string>>[],
|
|
50
40
|
string
|
|
51
|
-
> = selectorFamily<MutableAtomToken<
|
|
41
|
+
> = selectorFamily<MutableAtomToken<UList<string>>[], string>({
|
|
52
42
|
key: `usersInMyRoomView`,
|
|
53
43
|
get:
|
|
54
44
|
(myUsername) =>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./micro"
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
Fn,
|
|
4
|
-
Transceiver,
|
|
5
|
-
TransceiverMode,
|
|
6
|
-
} from "atom.io/internal"
|
|
7
|
-
import { enumeration, packValue, Subject, unpackValue } from "atom.io/internal"
|
|
1
|
+
import type { Fn, Transceiver, TransceiverMode } from "atom.io/internal"
|
|
2
|
+
import { Subject } from "atom.io/internal"
|
|
8
3
|
import type { primitive } from "atom.io/json"
|
|
4
|
+
import type { Enumeration } from "atom.io/struct"
|
|
5
|
+
import { enumeration, packValue, unpackValue } from "atom.io/struct"
|
|
9
6
|
|
|
10
7
|
export type ArrayMutations = Exclude<keyof Array<any>, keyof ReadonlyArray<any>>
|
|
11
8
|
export type ArrayUpdate<P extends primitive> =
|
|
@@ -99,16 +96,23 @@ export type ArrayMutationHandler = {
|
|
|
99
96
|
[K in Exclude<OListUpdateType, `extend` | `set` | `truncate`>]: Fn
|
|
100
97
|
}
|
|
101
98
|
|
|
99
|
+
export type OListView<P extends primitive> = ReadonlyArray<P> & {
|
|
100
|
+
subscribe: (
|
|
101
|
+
key: string,
|
|
102
|
+
fn: (update: PackedArrayUpdate<P>) => void,
|
|
103
|
+
) => () => void
|
|
104
|
+
}
|
|
105
|
+
|
|
102
106
|
export class OList<P extends primitive>
|
|
103
107
|
extends Array<P>
|
|
104
108
|
implements
|
|
105
|
-
Transceiver<
|
|
109
|
+
Transceiver<OListView<P>, PackedArrayUpdate<P>, ReadonlyArray<P>>,
|
|
106
110
|
ArrayMutationHandler
|
|
107
111
|
{
|
|
108
112
|
public mode: TransceiverMode = `record`
|
|
109
113
|
public readonly subject: Subject<PackedArrayUpdate<P>> = new Subject()
|
|
110
114
|
|
|
111
|
-
public readonly READONLY_VIEW:
|
|
115
|
+
public readonly READONLY_VIEW: OListView<P> = this
|
|
112
116
|
|
|
113
117
|
public constructor(arrayLength?: number)
|
|
114
118
|
public constructor(...items: P[])
|
|
@@ -12,6 +12,10 @@ export interface SetRTXView<P extends primitive> extends ReadonlySet<P> {
|
|
|
12
12
|
readonly cacheLimit: number
|
|
13
13
|
readonly cacheIdx: number
|
|
14
14
|
readonly cacheUpdateNumber: number
|
|
15
|
+
readonly subscribe: (
|
|
16
|
+
key: string,
|
|
17
|
+
fn: (update: NumberedSetUpdateString) => void,
|
|
18
|
+
) => () => void
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
export interface SetRTXJson<P extends primitive> extends Json.Object {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AtomEffect } from "atom.io"
|
|
2
|
+
import { getUpdateToken, subscribeInStore } from "atom.io/internal"
|
|
3
|
+
import { type primitive, stringifyJson } from "atom.io/json"
|
|
4
|
+
|
|
5
|
+
import { UList } from "./u-list"
|
|
6
|
+
|
|
7
|
+
export const uListDisposedKeyCleanupEffect: AtomEffect<UList<primitive>> = ({
|
|
8
|
+
token,
|
|
9
|
+
setSelf,
|
|
10
|
+
store,
|
|
11
|
+
}) => {
|
|
12
|
+
const disposalSubscriptions = new Map<primitive, () => void>()
|
|
13
|
+
const updateToken = getUpdateToken(token)
|
|
14
|
+
subscribeInStore(
|
|
15
|
+
store,
|
|
16
|
+
updateToken,
|
|
17
|
+
function setAutoDeletionTriggers({ newValue }) {
|
|
18
|
+
const unpacked = UList.unpackUpdate(newValue)
|
|
19
|
+
switch (unpacked.type) {
|
|
20
|
+
case `add`:
|
|
21
|
+
{
|
|
22
|
+
const molecule = store.molecules.get(stringifyJson(unpacked.value))
|
|
23
|
+
if (molecule) {
|
|
24
|
+
disposalSubscriptions.set(
|
|
25
|
+
unpacked.value,
|
|
26
|
+
molecule.subject.subscribe(token.key, () => {
|
|
27
|
+
setSelf((self) => {
|
|
28
|
+
self.delete(unpacked.value)
|
|
29
|
+
return self
|
|
30
|
+
})
|
|
31
|
+
}),
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
break
|
|
36
|
+
case `delete`:
|
|
37
|
+
disposalSubscriptions.get(unpacked.value)?.()
|
|
38
|
+
disposalSubscriptions.delete(unpacked.value)
|
|
39
|
+
break
|
|
40
|
+
case `clear`:
|
|
41
|
+
for (const unsub of disposalSubscriptions.values()) unsub()
|
|
42
|
+
disposalSubscriptions.clear()
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
`set-auto-deletion-triggers`,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
Fn,
|
|
4
|
-
Transceiver,
|
|
5
|
-
TransceiverMode,
|
|
6
|
-
} from "atom.io/internal"
|
|
7
|
-
import { enumeration, packValue, Subject, unpackValue } from "atom.io/internal"
|
|
1
|
+
import type { Fn, Transceiver, TransceiverMode } from "atom.io/internal"
|
|
2
|
+
import { Subject } from "atom.io/internal"
|
|
8
3
|
import type { primitive } from "atom.io/json"
|
|
4
|
+
import type { Enumeration } from "atom.io/struct"
|
|
5
|
+
import { enumeration, packValue, unpackValue } from "atom.io/struct"
|
|
9
6
|
|
|
10
7
|
export type SetMutations = Exclude<
|
|
11
8
|
keyof Set<any>,
|
|
@@ -34,10 +31,17 @@ export const SET_UPDATE_ENUM: Enumeration<[`add`, `delete`, `clear`]> =
|
|
|
34
31
|
|
|
35
32
|
export type SetMutationHandler = { [K in UListUpdateType]: Fn }
|
|
36
33
|
|
|
34
|
+
export type UListView<P extends primitive> = ReadonlySet<P> & {
|
|
35
|
+
subscribe: (
|
|
36
|
+
key: string,
|
|
37
|
+
fn: (update: PackedSetUpdate<P>) => void,
|
|
38
|
+
) => () => void
|
|
39
|
+
}
|
|
40
|
+
|
|
37
41
|
export class UList<P extends primitive>
|
|
38
42
|
extends Set<P>
|
|
39
43
|
implements
|
|
40
|
-
Transceiver<
|
|
44
|
+
Transceiver<UListView<P>, PackedSetUpdate<P>, ReadonlyArray<P>>,
|
|
41
45
|
SetMutationHandler
|
|
42
46
|
{
|
|
43
47
|
public mode: TransceiverMode = `record`
|
|
@@ -49,7 +53,7 @@ export class UList<P extends primitive>
|
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
public readonly READONLY_VIEW:
|
|
56
|
+
public readonly READONLY_VIEW: UListView<P> = this
|
|
53
57
|
|
|
54
58
|
public toJSON(): ReadonlyArray<P> {
|
|
55
59
|
return [...this]
|