jazz-tools 0.7.0-alpha.9 → 0.7.3

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 (73) hide show
  1. package/.eslintrc.cjs +3 -10
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +14 -15
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +140 -0
  6. package/CHANGELOG.md +331 -27
  7. package/LICENSE.txt +1 -1
  8. package/README.md +10 -2
  9. package/dist/coValues/account.js +86 -41
  10. package/dist/coValues/account.js.map +1 -1
  11. package/dist/coValues/coList.js +75 -48
  12. package/dist/coValues/coList.js.map +1 -1
  13. package/dist/coValues/coMap.js +167 -44
  14. package/dist/coValues/coMap.js.map +1 -1
  15. package/dist/coValues/coStream.js +192 -35
  16. package/dist/coValues/coStream.js.map +1 -1
  17. package/dist/coValues/deepLoading.js +60 -0
  18. package/dist/coValues/deepLoading.js.map +1 -0
  19. package/dist/coValues/extensions/imageDef.js +10 -7
  20. package/dist/coValues/extensions/imageDef.js.map +1 -1
  21. package/dist/coValues/group.js +73 -13
  22. package/dist/coValues/group.js.map +1 -1
  23. package/dist/coValues/interfaces.js +58 -35
  24. package/dist/coValues/interfaces.js.map +1 -1
  25. package/dist/implementation/devtoolsFormatters.js +114 -0
  26. package/dist/implementation/devtoolsFormatters.js.map +1 -0
  27. package/dist/implementation/refs.js +58 -18
  28. package/dist/implementation/refs.js.map +1 -1
  29. package/dist/implementation/schema.js +58 -0
  30. package/dist/implementation/schema.js.map +1 -0
  31. package/dist/implementation/subscriptionScope.js +19 -1
  32. package/dist/implementation/subscriptionScope.js.map +1 -1
  33. package/dist/implementation/symbols.js +5 -0
  34. package/dist/implementation/symbols.js.map +1 -0
  35. package/dist/index.js +4 -5
  36. package/dist/index.js.map +1 -1
  37. package/dist/internal.js +5 -2
  38. package/dist/internal.js.map +1 -1
  39. package/dist/tests/coList.test.js +51 -48
  40. package/dist/tests/coList.test.js.map +1 -1
  41. package/dist/tests/coMap.test.js +131 -74
  42. package/dist/tests/coMap.test.js.map +1 -1
  43. package/dist/tests/coStream.test.js +56 -41
  44. package/dist/tests/coStream.test.js.map +1 -1
  45. package/dist/tests/deepLoading.test.js +188 -0
  46. package/dist/tests/deepLoading.test.js.map +1 -0
  47. package/dist/tests/groupsAndAccounts.test.js +83 -0
  48. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  49. package/package.json +17 -9
  50. package/src/coValues/account.ts +186 -128
  51. package/src/coValues/coList.ts +156 -107
  52. package/src/coValues/coMap.ts +272 -148
  53. package/src/coValues/coStream.ts +388 -87
  54. package/src/coValues/deepLoading.ts +229 -0
  55. package/src/coValues/extensions/imageDef.ts +17 -13
  56. package/src/coValues/group.ts +166 -59
  57. package/src/coValues/interfaces.ts +189 -160
  58. package/src/implementation/devtoolsFormatters.ts +110 -0
  59. package/src/implementation/inspect.ts +1 -1
  60. package/src/implementation/refs.ts +80 -28
  61. package/src/implementation/schema.ts +141 -0
  62. package/src/implementation/subscriptionScope.ts +48 -12
  63. package/src/implementation/symbols.ts +11 -0
  64. package/src/index.ts +19 -8
  65. package/src/internal.ts +7 -3
  66. package/src/tests/coList.test.ts +77 -62
  67. package/src/tests/coMap.test.ts +201 -114
  68. package/src/tests/coStream.test.ts +113 -84
  69. package/src/tests/deepLoading.test.ts +304 -0
  70. package/src/tests/groupsAndAccounts.test.ts +91 -0
  71. package/dist/implementation/encoding.js +0 -26
  72. package/dist/implementation/encoding.js.map +0 -1
  73. package/src/implementation/encoding.ts +0 -105
@@ -1,15 +1,19 @@
1
1
  import type { JsonValue, RawCoMap } from "cojson";
2
2
  import type { Simplify } from "effect/Types";
3
- import { Schema } from "@effect/schema";
3
+ import { encodeSync, decodeSync } from "@effect/schema/Schema";
4
4
  import type {
5
5
  CoValue,
6
- Encoding,
7
- EncodingFor,
6
+ Schema,
8
7
  Group,
9
8
  ID,
10
9
  RefEncoded,
11
- EnsureCoValueNullable,
12
- IsVal,
10
+ IfCo,
11
+ RefIfCoValue,
12
+ DepthsIn,
13
+ DeeplyLoaded,
14
+ UnavailableError,
15
+ AccountCtx,
16
+ CoValueClass,
13
17
  } from "../internal.js";
14
18
  import {
15
19
  Account,
@@ -21,161 +25,193 @@ import {
21
25
  subscriptionsScopes,
22
26
  ItemsSym,
23
27
  InitValues,
28
+ isRefEncoded,
29
+ loadCoValue,
30
+ loadCoValueEf,
31
+ subscribeToCoValue,
32
+ subscribeToCoValueEf,
33
+ ensureCoValueLoaded,
34
+ subscribeToExistingCoValue,
24
35
  } from "../internal.js";
25
-
26
- type ValidFields<Fields extends { [key: string]: any; [ItemsSym]?: any }> = {
27
- [Key in keyof Fields & string as IsVal<
28
- Fields[Key],
29
- IfOptionalKey<Key, Fields>
30
- >]?: EnsureCoValueNullable<Fields[Key], Key>;
31
- } & {
32
- [Key in keyof Fields & string as IsVal<
33
- Fields[Key],
34
- IfRequiredKey<Key, Fields>
35
- >]: EnsureCoValueNullable<Fields[Key], Key>;
36
- } & {
37
- [Key in ItemsSym]?: EnsureCoValueNullable<Fields[ItemsSym], Key>;
38
- };
39
-
40
- type IfOptionalKey<Key extends keyof Obj, Obj> = Pick<
41
- Partial<Obj>,
42
- Key
43
- > extends Pick<Obj, Key>
44
- ? Key
45
- : never;
46
- type IfRequiredKey<Key extends keyof Obj, Obj> = Pick<
47
- Partial<Obj>,
48
- Key
49
- > extends Pick<Obj, Key>
50
- ? never
51
- : Key;
52
-
53
- type DefaultFields = {
54
- [key: string]: any;
55
- [ItemsSym]?: any;
56
- };
57
-
58
- type CoMapEncoding<Fields extends object> = {
59
- [Key in OwnKeys<Fields> as IsVal<Fields[Key], Key>]: EncodingFor<
60
- Fields[Key]
61
- >;
62
- } &
63
- {
64
- [ItemsSym]: ItemsSym extends keyof Fields ? EncodingFor<Fields[ItemsSym]> : never;
65
- }
36
+ import { Effect, Stream } from "effect";
66
37
 
67
38
  type CoMapEdit<V> = {
68
39
  value?: V;
69
- ref?: V extends CoValue ? Ref<V> : never;
40
+ ref?: RefIfCoValue<V>;
70
41
  by?: Account;
71
42
  madeAt: Date;
72
- }
43
+ };
73
44
 
74
45
  type InitValuesFor<C extends CoMap> = {
75
46
  init: Simplify<CoMapInit<C>>;
76
47
  owner: Account | Group;
77
- }
48
+ };
78
49
 
79
- export class CoMap<Fields extends ValidFields<Fields> = DefaultFields>
80
- extends CoValueBase
81
- implements CoValue<"CoMap", RawCoMap>
82
- {
83
- id!: ID<this>;
84
- _type!: "CoMap";
50
+ /**
51
+ * CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
52
+ *
53
+ * @categoryDescription Declaration
54
+ * Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`.
55
+ *
56
+ * ```ts
57
+ * import { co, CoMap } from "jazz-tools";
58
+ *
59
+ * class Person extends CoMap {
60
+ * name = co.string;
61
+ * age = co.number;
62
+ * pet = co.ref(Animal);
63
+ * }
64
+ * ```
65
+ *
66
+ * @categoryDescription Content
67
+ * You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc.
68
+ *
69
+ * ```ts
70
+ * person.name;
71
+ * person["age"];
72
+ * person.age = 42;
73
+ * person.pet?.name;
74
+ * Object.keys(person);
75
+ * // => ["name", "age", "pet"]
76
+ * ```
77
+ *
78
+ * @category CoValues
79
+ * */
80
+ export class CoMap extends CoValueBase implements CoValue {
81
+ /**
82
+ * The ID of this `CoMap`
83
+ * @category Content */
84
+ declare id: ID<this>;
85
+ /** @category Type Helpers */
86
+ declare _type: "CoMap";
85
87
  static {
86
88
  this.prototype._type = "CoMap";
87
89
  }
88
- _raw!: RawCoMap;
89
-
90
- static _encoding: any;
91
- get _encoding() {
92
- return (this.constructor as typeof CoMap)._encoding as CoMapEncoding<this>
90
+ /** @category Internals */
91
+ declare _raw: RawCoMap;
92
+
93
+ /** @internal */
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ static _schema: any;
96
+ /** @internal */
97
+ get _schema() {
98
+ return (this.constructor as typeof CoMap)._schema as {
99
+ [key: string]: Schema;
100
+ } & { [ItemsSym]?: Schema };
93
101
  }
94
102
 
103
+ /**
104
+ * If property `prop` is a `co.ref(...)`, you can use `coMaps._refs.prop` to access
105
+ * the `Ref` instead of the potentially loaded/null value.
106
+ * This allows you to always get the ID or load the value manually.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * person._refs.pet.id; // => ID<Animal>
111
+ * person._refs.pet.value;
112
+ * // => Animal | undefined
113
+ * const pet = await person._refs.pet.load();
114
+ * ```
115
+ *
116
+ * @category Content */
95
117
  get _refs(): {
96
- [Key in OwnKeys<this> as NonNullable<this[Key]> extends CoValue
97
- ? Key
98
- : never]: NonNullable<this[Key]> extends CoValue
99
- ? Ref<NonNullable<this[Key]>>
100
- : never;
118
+ [Key in CoKeys<this>]: IfCo<this[Key], RefIfCoValue<this[Key]>>;
101
119
  } {
102
- return makeRefs<OwnKeys<Fields>>(
120
+ return makeRefs<CoKeys<this>>(
103
121
  (key) => this._raw.get(key as string) as unknown as ID<CoValue>,
104
- () =>
105
- Object.keys(this._encoding).filter((key) => {
106
- const schema = this._encoding[
107
- key as keyof typeof this._encoding
108
- ] as Encoding;
109
- schema !== "json" && "ref" in schema;
110
- }) as OwnKeys<Fields>[],
122
+ () => {
123
+ const keys = this._raw.keys().filter((key) => {
124
+ const schema =
125
+ this._schema[key as keyof typeof this._schema] ||
126
+ (this._schema[ItemsSym] as Schema | undefined);
127
+ return schema && schema !== "json" && isRefEncoded(schema);
128
+ }) as CoKeys<this>[];
129
+
130
+ return keys;
131
+ },
111
132
  this._loadedAs,
112
- (key) => this._encoding[key] as RefEncoded<CoValue>
133
+ (key) =>
134
+ (this._schema[key] ||
135
+ this._schema[ItemsSym]) as RefEncoded<CoValue>,
136
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
137
  ) as any;
114
138
  }
115
139
 
140
+ /** @category Collaboration */
116
141
  get _edits() {
117
142
  return new Proxy(this, {
118
143
  get(target, key) {
119
144
  const rawEdit = target._raw.lastEditAt(key as string);
120
145
  if (!rawEdit) return undefined;
121
146
 
122
- const descriptor = target._encoding[
123
- key as keyof typeof target._encoding
124
- ] as Encoding;
147
+ const descriptor = target._schema[
148
+ key as keyof typeof target._schema
149
+ ] as Schema;
125
150
 
126
151
  return {
127
152
  value:
128
153
  descriptor === "json"
129
154
  ? rawEdit.value
130
155
  : "encoded" in descriptor
131
- ? Schema.decodeSync(descriptor.encoded)(
132
- rawEdit.value
133
- )
156
+ ? decodeSync(descriptor.encoded)(rawEdit.value)
134
157
  : new Ref(
135
158
  rawEdit.value as ID<CoValue>,
136
159
  target._loadedAs,
137
- descriptor
138
- ).accessFrom(target),
160
+ descriptor,
161
+ ).accessFrom(
162
+ target,
163
+ "_edits." + key.toString() + ".value",
164
+ ),
139
165
  ref:
140
- descriptor !== "json" && "ref" in descriptor
166
+ descriptor !== "json" && isRefEncoded(descriptor)
141
167
  ? new Ref(
142
168
  rawEdit.value as ID<CoValue>,
143
169
  target._loadedAs,
144
- descriptor
170
+ descriptor,
145
171
  )
146
172
  : undefined,
147
173
  by:
148
174
  rawEdit.by &&
149
- new Ref(rawEdit.by as ID<Account>, target._loadedAs, {
150
- ref: () => Account,
151
- }).accessFrom(target),
175
+ new Ref<Account>(
176
+ rawEdit.by as ID<Account>,
177
+ target._loadedAs,
178
+ {
179
+ ref: Account,
180
+ optional: false,
181
+ },
182
+ ).accessFrom(
183
+ target,
184
+ "_edits." + key.toString() + ".by",
185
+ ),
152
186
  madeAt: rawEdit.at,
153
187
  };
154
188
  },
155
189
  }) as {
156
- [Key in OwnKeys<this> as IsVal<this[Key], Key>]: CoMapEdit<this[Key]>
190
+ [Key in CoKeys<this>]: IfCo<this[Key], CoMapEdit<this[Key]>>;
157
191
  };
158
192
  }
159
193
 
194
+ /** @internal */
160
195
  get _loadedAs() {
161
196
  return Account.fromNode(this._raw.core.node);
162
197
  }
163
198
 
164
- [InitValues]?: InitValuesFor<this>;
199
+ /** @internal */
200
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
201
+ [InitValues]?: any;
165
202
 
166
- constructor(_init: undefined, options: { fromRaw: RawCoMap });
167
- constructor(
168
- init: Simplify<CoMapInit<Fields>>,
169
- options: { owner: Account | Group }
170
- );
203
+ /** @internal */
171
204
  constructor(
172
- init: Simplify<CoMapInit<Fields>> | undefined,
173
- options: { owner: Account | Group } | { fromRaw: RawCoMap }
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ options: { fromRaw: RawCoMap } | { init: any; owner: Account | Group },
174
207
  ) {
175
208
  super();
176
209
 
177
- if (init && "owner" in options) {
178
- this[InitValues] = { init, owner: options.owner } as InitValuesFor<this>;
210
+ if ("owner" in options) {
211
+ this[InitValues] = {
212
+ init: options.init,
213
+ owner: options.owner,
214
+ } as InitValuesFor<this>;
179
215
  } else if ("fromRaw" in options) {
180
216
  Object.defineProperties(this, {
181
217
  id: {
@@ -191,14 +227,25 @@ export class CoMap<Fields extends ValidFields<Fields> = DefaultFields>
191
227
  return new Proxy(this, CoMapProxyHandler as ProxyHandler<this>);
192
228
  }
193
229
 
230
+ /** @category Creation */
231
+ static create<M extends CoMap>(
232
+ this: CoValueClass<M>,
233
+ init: Simplify<CoMapInit<M>>,
234
+ options: { owner: Account | Group },
235
+ ) {
236
+ return new this({ init, owner: options.owner });
237
+ }
238
+
194
239
  toJSON() {
195
240
  const jsonedFields = this._raw.keys().map((key) => {
196
- const tKey = key as OwnKeys<Fields>;
197
- const descriptor = this._encoding[tKey] as Encoding;
241
+ const tKey = key as CoKeys<this>;
242
+ const descriptor = (this._schema[tKey] ||
243
+ this._schema[ItemsSym]) as Schema;
198
244
 
199
245
  if (descriptor == "json" || "encode" in descriptor) {
200
246
  return [key, this._raw.get(key)];
201
- } else if ("ref" in descriptor) {
247
+ } else if (isRefEncoded(descriptor)) {
248
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
202
249
  const jsonedRef = (this as any)[tKey]?.toJSON();
203
250
  return [key, jsonedRef];
204
251
  } else {
@@ -217,9 +264,11 @@ export class CoMap<Fields extends ValidFields<Fields> = DefaultFields>
217
264
  return this.toJSON();
218
265
  }
219
266
 
267
+ /** @internal */
268
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
269
  rawFromInit<Fields extends object = Record<string, any>>(
221
270
  init: Simplify<CoMapInit<Fields>> | undefined,
222
- owner: Account | Group
271
+ owner: Account | Group,
223
272
  ) {
224
273
  const rawOwner = owner._raw;
225
274
 
@@ -231,51 +280,119 @@ export class CoMap<Fields extends ValidFields<Fields> = DefaultFields>
231
280
  for (const key of Object.keys(init) as (keyof Fields)[]) {
232
281
  const initValue = init[key as keyof typeof init];
233
282
 
234
- const descriptor = (this._encoding[
235
- key as keyof typeof this._encoding
236
- ] || this._encoding[ItemsSym]) as Encoding;
283
+ const descriptor = (this._schema[
284
+ key as keyof typeof this._schema
285
+ ] || this._schema[ItemsSym]) as Schema;
237
286
 
238
287
  if (descriptor === "json") {
239
288
  rawInit[key] = initValue as JsonValue;
240
- } else if ("ref" in descriptor) {
289
+ } else if (isRefEncoded(descriptor)) {
241
290
  if (initValue) {
242
291
  rawInit[key] = (initValue as unknown as CoValue).id;
243
292
  }
244
293
  } else if ("encoded" in descriptor) {
245
- rawInit[key] = Schema.encodeSync(descriptor.encoded)(
246
- initValue as any
294
+ rawInit[key] = encodeSync(descriptor.encoded)(
295
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
296
+ initValue as any,
247
297
  );
248
298
  }
249
299
  }
250
300
 
251
301
  return rawOwner.createMap(rawInit);
252
302
  }
303
+
304
+ /** @category Declaration */
305
+ static Record<Value>(value: IfCo<Value, Value>) {
306
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
307
+ class RecordLikeCoMap extends CoMap {
308
+ [ItemsSym] = value;
309
+ }
310
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
311
+ interface RecordLikeCoMap extends Record<string, Value> {}
312
+
313
+ return RecordLikeCoMap;
314
+ }
315
+
316
+ /** @category Subscription & Loading */
317
+ static load<M extends CoMap, Depth>(
318
+ this: CoValueClass<M>,
319
+ id: ID<M>,
320
+ as: Account,
321
+ depth: Depth & DepthsIn<M>,
322
+ ): Promise<DeeplyLoaded<M, Depth> | undefined> {
323
+ return loadCoValue(this, id, as, depth);
324
+ }
325
+
326
+ /** @category Subscription & Loading */
327
+ static loadEf<M extends CoMap, Depth>(
328
+ this: CoValueClass<M>,
329
+ id: ID<M>,
330
+ depth: Depth & DepthsIn<M>,
331
+ ): Effect.Effect<DeeplyLoaded<M, Depth>, UnavailableError, AccountCtx> {
332
+ return loadCoValueEf<M, Depth>(this, id, depth);
333
+ }
334
+
335
+ /** @category Subscription & Loading */
336
+ static subscribe<M extends CoMap, Depth>(
337
+ this: CoValueClass<M>,
338
+ id: ID<M>,
339
+ as: Account,
340
+ depth: Depth & DepthsIn<M>,
341
+ listener: (value: DeeplyLoaded<M, Depth>) => void,
342
+ ): () => void {
343
+ return subscribeToCoValue<M, Depth>(this, id, as, depth, listener);
344
+ }
345
+
346
+ /** @category Subscription & Loading */
347
+ static subscribeEf<M extends CoMap, Depth>(
348
+ this: CoValueClass<M>,
349
+ id: ID<M>,
350
+ depth: Depth & DepthsIn<M>,
351
+ ): Stream.Stream<DeeplyLoaded<M, Depth>, UnavailableError, AccountCtx> {
352
+ return subscribeToCoValueEf<M, Depth>(this, id, depth);
353
+ }
354
+
355
+ /** @category Subscription & Loading */
356
+ ensureLoaded<M extends CoMap, Depth>(
357
+ this: M,
358
+ depth: Depth & DepthsIn<M>,
359
+ ): Promise<DeeplyLoaded<M, Depth> | undefined> {
360
+ return ensureCoValueLoaded(this, depth);
361
+ }
362
+
363
+ /** @category Subscription & Loading */
364
+ subscribe<M extends CoMap, Depth>(
365
+ this: M,
366
+ depth: Depth & DepthsIn<M>,
367
+ listener: (value: DeeplyLoaded<M, Depth>) => void,
368
+ ): () => void {
369
+ return subscribeToExistingCoValue(this, depth, listener);
370
+ }
253
371
  }
254
372
 
255
- export type OwnKeys<Fields extends object> = Exclude<
256
- keyof Fields & string,
257
- keyof CoMap<Record<string, never>>
373
+ export type CoKeys<Map extends object> = Exclude<
374
+ keyof Map & string,
375
+ keyof CoMap
258
376
  >;
259
377
 
260
- export type CoMapInit<Fields extends object> = {
261
- [Key in OwnKeys<Fields> as undefined extends Fields[Key]
378
+ export type CoMapInit<Map extends object> = {
379
+ [Key in CoKeys<Map> as undefined extends Map[Key]
262
380
  ? never
263
- : null extends Fields[Key]
264
- ? never
265
- : IsVal<Fields[Key], Key>]: Fields[Key];
266
- } & { [Key in OwnKeys<Fields> as IsVal<Fields[Key], Key>]?: Fields[Key] };
381
+ : IfCo<Map[Key], Key>]: Map[Key];
382
+ } & { [Key in CoKeys<Map> as IfCo<Map[Key], Key>]?: Map[Key] };
267
383
 
268
384
  function tryInit(map: CoMap) {
269
385
  if (
270
386
  map[InitValues] &&
271
- (map._encoding[ItemsSym] ||
387
+ (map._schema[ItemsSym] ||
272
388
  Object.keys(map[InitValues].init).every(
273
- (key) => (map._encoding as any)[key]
389
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
390
+ (key) => (map._schema as any)[key],
274
391
  ))
275
392
  ) {
276
393
  const raw = map.rawFromInit(
277
394
  map[InitValues].init,
278
- map[InitValues].owner
395
+ map[InitValues].owner,
279
396
  );
280
397
  Object.defineProperties(map, {
281
398
  id: {
@@ -291,14 +408,13 @@ function tryInit(map: CoMap) {
291
408
  // TODO: cache handlers per descriptor for performance?
292
409
  const CoMapProxyHandler: ProxyHandler<CoMap> = {
293
410
  get(target, key, receiver) {
294
- if (key === "_encoding") {
411
+ if (key === "_schema") {
295
412
  return Reflect.get(target, key);
296
413
  } else if (key in target) {
297
414
  return Reflect.get(target, key, receiver);
298
415
  } else {
299
- const descriptor = (target._encoding[
300
- key as keyof CoMap["_encoding"]
301
- ] || target._encoding[ItemsSym]) as Encoding;
416
+ const descriptor = (target._schema[key as keyof CoMap["_schema"]] ||
417
+ target._schema[ItemsSym]) as Schema;
302
418
  if (descriptor && typeof key === "string") {
303
419
  const raw = target._raw.get(key);
304
420
 
@@ -307,15 +423,15 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
307
423
  } else if ("encoded" in descriptor) {
308
424
  return raw === undefined
309
425
  ? undefined
310
- : Schema.decodeSync(descriptor.encoded)(raw);
311
- } else if ("ref" in descriptor) {
426
+ : decodeSync(descriptor.encoded)(raw);
427
+ } else if (isRefEncoded(descriptor)) {
312
428
  return raw === undefined
313
429
  ? undefined
314
430
  : new Ref(
315
431
  raw as unknown as ID<CoValue>,
316
432
  target._loadedAs,
317
- descriptor
318
- ).accessFrom(receiver);
433
+ descriptor,
434
+ ).accessFrom(receiver, key);
319
435
  }
320
436
  } else {
321
437
  return undefined;
@@ -328,26 +444,25 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
328
444
  typeof value === "object" &&
329
445
  SchemaInit in value
330
446
  ) {
331
- (target.constructor as typeof CoMap)._encoding ||= {};
332
- (target.constructor as typeof CoMap)._encoding[key] =
447
+ (target.constructor as typeof CoMap)._schema ||= {};
448
+ (target.constructor as typeof CoMap)._schema[key] =
333
449
  value[SchemaInit];
334
450
  tryInit(target);
335
451
  return true;
336
452
  }
337
453
 
338
- const descriptor = (target._encoding[key as keyof CoMap["_encoding"]] ||
339
- target._encoding[ItemsSym]) as Encoding;
454
+ const descriptor = (target._schema[key as keyof CoMap["_schema"]] ||
455
+ target._schema[ItemsSym]) as Schema;
340
456
  if (descriptor && typeof key === "string") {
341
457
  if (descriptor === "json") {
342
458
  target._raw.set(key, value);
343
459
  } else if ("encoded" in descriptor) {
344
- target._raw.set(
345
- key,
346
- Schema.encodeSync(descriptor.encoded)(value)
347
- );
348
- } else if ("ref" in descriptor) {
460
+ target._raw.set(key, encodeSync(descriptor.encoded)(value));
461
+ } else if (isRefEncoded(descriptor)) {
349
462
  target._raw.set(key, value.id);
350
- subscriptionsScopes.get(target)?.onRefAccessedOrSet(value.id);
463
+ subscriptionsScopes
464
+ .get(target)
465
+ ?.onRefAccessedOrSet(target.id, value.id);
351
466
  }
352
467
  return true;
353
468
  } else {
@@ -360,8 +475,8 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
360
475
  typeof attributes.value === "object" &&
361
476
  SchemaInit in attributes.value
362
477
  ) {
363
- (target.constructor as typeof CoMap)._encoding ||= {};
364
- (target.constructor as typeof CoMap)._encoding[key as string] =
478
+ (target.constructor as typeof CoMap)._schema ||= {};
479
+ (target.constructor as typeof CoMap)._schema[key as string] =
365
480
  attributes.value[SchemaInit];
366
481
  tryInit(target);
367
482
  return true;
@@ -371,11 +486,11 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
371
486
  },
372
487
  ownKeys(target) {
373
488
  const keys = Reflect.ownKeys(target).filter((k) => k !== ItemsSym);
374
- for (const key of Reflect.ownKeys(target._encoding)) {
375
- if (key !== ItemsSym && !keys.includes(key)) {
376
- keys.push(key);
377
- }
378
- }
489
+ // for (const key of Reflect.ownKeys(target._schema)) {
490
+ // if (key !== ItemsSym && !keys.includes(key)) {
491
+ // keys.push(key);
492
+ // }
493
+ // }
379
494
  for (const key of target._raw.keys()) {
380
495
  if (!keys.includes(key)) {
381
496
  keys.push(key);
@@ -388,9 +503,8 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
388
503
  if (key in target) {
389
504
  return Reflect.getOwnPropertyDescriptor(target, key);
390
505
  } else {
391
- const descriptor = (target._encoding[
392
- key as keyof CoMap["_encoding"]
393
- ] || target._encoding[ItemsSym]) as Encoding;
506
+ const descriptor = (target._schema[key as keyof CoMap["_schema"]] ||
507
+ target._schema[ItemsSym]) as Schema;
394
508
  if (descriptor || key in target._raw.ops) {
395
509
  return {
396
510
  enumerable: true,
@@ -400,4 +514,14 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
400
514
  }
401
515
  }
402
516
  },
517
+ deleteProperty(target, key) {
518
+ const descriptor = (target._schema[key as keyof CoMap["_schema"]] ||
519
+ target._schema[ItemsSym]) as Schema;
520
+ if (typeof key === "string" && descriptor) {
521
+ target._raw.delete(key);
522
+ return true;
523
+ } else {
524
+ return Reflect.deleteProperty(target, key);
525
+ }
526
+ },
403
527
  };