jazz-tools 0.7.0-alpha.9 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
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
  };