atom.io 0.41.1 → 0.42.0

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.
Files changed (52) hide show
  1. package/dist/internal/index.d.ts +21 -38
  2. package/dist/internal/index.d.ts.map +1 -1
  3. package/dist/internal/index.js +82 -263
  4. package/dist/internal/index.js.map +1 -1
  5. package/dist/main/index.d.ts +18 -36
  6. package/dist/main/index.d.ts.map +1 -1
  7. package/dist/main/index.js +13 -2
  8. package/dist/main/index.js.map +1 -1
  9. package/dist/realtime/index.d.ts +2 -3
  10. package/dist/realtime/index.d.ts.map +1 -1
  11. package/dist/realtime/index.js +1 -1
  12. package/dist/realtime/index.js.map +1 -1
  13. package/dist/realtime-server/index.js +1 -1
  14. package/dist/realtime-server/index.js.map +1 -1
  15. package/dist/realtime-testing/index.js +1 -1
  16. package/dist/struct/index.d.ts +14 -0
  17. package/dist/struct/index.d.ts.map +1 -0
  18. package/dist/struct/index.js +35 -0
  19. package/dist/struct/index.js.map +1 -0
  20. package/dist/transceivers/o-list/index.d.ts +8 -4
  21. package/dist/transceivers/o-list/index.d.ts.map +1 -1
  22. package/dist/transceivers/o-list/index.js +2 -1
  23. package/dist/transceivers/o-list/index.js.map +1 -1
  24. package/dist/transceivers/set-rtx/index.d.ts +1 -0
  25. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  26. package/dist/transceivers/set-rtx/index.js.map +1 -1
  27. package/dist/transceivers/u-list/index.d.ts +8 -4
  28. package/dist/transceivers/u-list/index.d.ts.map +1 -1
  29. package/dist/transceivers/u-list/index.js +2 -1
  30. package/dist/transceivers/u-list/index.js.map +1 -1
  31. package/dist/utility-types-aZkJVERa.d.ts +10 -0
  32. package/dist/utility-types-aZkJVERa.d.ts.map +1 -0
  33. package/package.json +13 -9
  34. package/src/internal/index.ts +0 -1
  35. package/src/internal/join/create-join.ts +8 -11
  36. package/src/internal/join/edit-relations-in-store.ts +6 -8
  37. package/src/internal/join/find-relations-in-store.ts +11 -67
  38. package/src/internal/join/get-internal-relations-from-store.ts +11 -5
  39. package/src/internal/join/get-join.ts +7 -9
  40. package/src/internal/join/join-internal.ts +154 -394
  41. package/src/internal/mutable/transceiver.ts +1 -5
  42. package/src/internal/set-state/dispatch-state-update.ts +1 -1
  43. package/src/internal/store/store.ts +1 -1
  44. package/src/main/join.ts +68 -151
  45. package/src/main/realm.ts +4 -4
  46. package/src/realtime/shared-room-store.ts +5 -15
  47. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +1 -1
  48. package/src/struct/index.ts +1 -0
  49. package/src/{internal → struct}/micro.ts +1 -1
  50. package/src/transceivers/o-list/o-list.ts +13 -9
  51. package/src/transceivers/set-rtx/set-rtx.ts +4 -0
  52. package/src/transceivers/u-list/u-list.ts +13 -9
@@ -1,7 +1,7 @@
1
1
  import type { Json } from "atom.io/json"
2
2
 
3
3
  export interface Transceiver<
4
- V,
4
+ V extends { subscribe: (key: string, fn: (update: S) => void) => () => void },
5
5
  S extends Json.Serializable,
6
6
  J extends Json.Serializable,
7
7
  > {
@@ -9,8 +9,6 @@ export interface Transceiver<
9
9
  do: (update: S) => number | `OUT_OF_RANGE` | null
10
10
  undo: (update: S) => void
11
11
  subscribe: (key: string, fn: (update: S) => void) => () => void
12
- // cacheUpdateNumber: number
13
- // getUpdateNumber: (update: S) => number
14
12
  toJSON: () => J
15
13
  }
16
14
 
@@ -31,8 +29,6 @@ export function isTransceiver(
31
29
  `do` in value &&
32
30
  `undo` in value &&
33
31
  `subscribe` in value &&
34
- // `cacheUpdateNumber` in value &&
35
- // `getUpdateNumber` in value &&
36
32
  `READONLY_VIEW` in value &&
37
33
  `toJSON` in value
38
34
  )
@@ -127,7 +127,7 @@ export function dispatchOrDeferStateUpdate<T, E>(
127
127
  if (hasRole(state, `tracker:signal`)) {
128
128
  const keyOfMutable = key.slice(1)
129
129
  const mutable = target.atoms.get(keyOfMutable) as MutableAtom<
130
- Transceiver<unknown, any, any>
130
+ Transceiver<any, any, any>
131
131
  >
132
132
  const transceiver = readOrComputeValue<Transceiver<any, any, any>, never>(
133
133
  target,
@@ -80,7 +80,7 @@ export class Store implements Lineage {
80
80
  | PureSelectorFamily<any, any, any>
81
81
  | RegularAtomFamily<any, any, any>
82
82
  > = new Map()
83
- public joins: Map<string, Join<any, any, any, any, any, any>> = new Map()
83
+ public joins: Map<string, Join<any, any, any, any, any>> = new Map()
84
84
 
85
85
  public transactions: Map<string, Transaction<Fn>> = new Map()
86
86
  public transactionMeta: TransactionEpoch | TransactionProgress<Fn> = {
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 { Json } from "atom.io/json"
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
- ASide extends string,
22
- AType extends string,
23
- BSide extends string,
24
- BType extends string,
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<ASide, BSide>
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, AType>
34
+ readonly isAType: Refinement<string, A>
37
35
  /** Type guard for the type of the right side */
38
- readonly isBType: Refinement<string, BType>
36
+ readonly isBType: Refinement<string, B>
39
37
  }
40
- > & Partial<JunctionEntriesBase<AType, BType, Content>>
38
+ > & Partial<JunctionEntriesBase<A, B, null>>
41
39
 
42
40
  export type JoinToken<
43
- ASide extends string,
44
- AType extends string,
45
- BSide extends string,
46
- BType extends string,
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: ASide
54
+ a: AName
58
55
  /** Name of the join's right side */
59
- b: BSide
56
+ b: BName
60
57
  /** Never present. This is a marker that preserves the type of the left side's keys */
61
- __aType?: AType
58
+ __aType?: A
62
59
  /** Never present. This is a marker that preserves the type of the right side's keys */
63
- __bType?: 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 ASide extends string,
83
- const AType extends string,
84
- const BSide extends string,
85
- const BType extends string,
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<ASide, AType, BSide, BType, Cardinality, null>,
89
- defaultContent?: undefined,
90
- ): JoinToken<ASide, AType, BSide, BType, Cardinality, null>
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
- ASide extends string,
131
- AType extends string,
132
- BSide extends string,
133
- BType extends string,
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
- ? (Content extends Json.Object
138
- ? {
139
- readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
140
- [AType, Content] | null,
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 [B in BSide as `${B}KeyOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
156
- BType | null,
157
- AType
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
- ? (Content extends Json.Object
162
- ? {
163
- readonly [A in ASide as `${A}EntryOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
164
- [AType, Content] | null,
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 [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
180
- BType[],
181
- AType
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
- ? (Content extends Json.Object
186
- ? {
187
- readonly [A in ASide as `${A}EntriesOf${Capitalize<BSide>}`]: ReadonlyPureSelectorToken<
188
- [AType, Content][],
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 [B in BSide as `${B}KeysOf${Capitalize<ASide>}`]: ReadonlyPureSelectorToken<
204
- BType[],
205
- AType
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
- ASide extends string,
220
- AType extends string,
221
- BSide extends string,
222
- BType extends string,
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<ASide, AType, BSide, BType, Cardinality, Content>,
227
- key: AType | BType,
228
- ): JoinStates<ASide, AType, BSide, BType, Cardinality, Content> {
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
- ASide extends string,
239
- AType extends string,
240
- BSide extends string,
241
- BType extends string,
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<ASide, AType, BSide, BType, Cardinality, Content>,
246
- change: (relations: Junction<ASide, AType, BSide, BType, Content>) => void,
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
- ASide extends string,
258
- AType extends string,
259
- BSide extends string,
260
- BType extends string,
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<ASide, AType, BSide, BType, Cardinality, Content>,
265
- ): MutableAtomFamilyToken<SetRTX<string>, string> {
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
@@ -164,15 +164,15 @@ export type T$ = typeof T$
164
164
  export type TypeTag<T extends string> = `${T$}--${T}`
165
165
  export type SingularTypedKey<T extends string = string> = `${T}::${string}`
166
166
  export type CompoundTypedKey<
167
+ T extends string = string,
167
168
  A extends string = string,
168
169
  B extends string = string,
169
- C extends string = string,
170
- > = `${TypeTag<A>}==${SingularTypedKey<B>}++${SingularTypedKey<C>}`
170
+ > = `${TypeTag<T>}==${SingularTypedKey<A>}++${SingularTypedKey<B>}`
171
171
  export type TypedKey<
172
+ T extends string = string,
172
173
  A extends string = string,
173
174
  B extends string = string,
174
- C extends string = string,
175
- > = CompoundTypedKey<A, B, C> | SingularTypedKey<A>
175
+ > = CompoundTypedKey<T, A, B> | SingularTypedKey<T>
176
176
  type Scope = SingularTypedKey[]
177
177
  type MutualFealty = {
178
178
  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
- `room`,
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<SetRTX<string>>[],
39
+ MutableAtomToken<UList<string>>[],
50
40
  string
51
- > = selectorFamily<MutableAtomToken<SetRTX<string>>[], string>({
41
+ > = selectorFamily<MutableAtomToken<UList<string>>[], string>({
52
42
  key: `usersInMyRoomView`,
53
43
  get:
54
44
  (myUsername) =>
@@ -43,7 +43,7 @@ export const joinRoomTX: TransactionToken<
43
43
  editRelationsInStore(
44
44
  usersInRooms,
45
45
  (relations) => {
46
- relations.set({ room: roomId, user: userId }, meta)
46
+ relations.set({ room: roomId, user: userId })
47
47
  },
48
48
  tools.env().store,
49
49
  )
@@ -0,0 +1 @@
1
+ export * from "./micro"
@@ -1,6 +1,6 @@
1
1
  import type { primitive } from "atom.io/json"
2
2
 
3
- import type { Flat } from "./utility-types"
3
+ import type { Flat } from "../internal/utility-types"
4
4
 
5
5
  export type IndexOf<
6
6
  T extends readonly unknown[],
@@ -1,11 +1,8 @@
1
- import type {
2
- Enumeration,
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<ReadonlyArray<P>, PackedArrayUpdate<P>, ReadonlyArray<P>>,
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: ReadonlyArray<P> = this
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 {
@@ -1,11 +1,8 @@
1
- import type {
2
- Enumeration,
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<ReadonlySet<P>, PackedSetUpdate<P>, ReadonlyArray<P>>,
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: ReadonlySet<P> = this
56
+ public readonly READONLY_VIEW: UListView<P> = this
53
57
 
54
58
  public toJSON(): ReadonlyArray<P> {
55
59
  return [...this]