jazz-tools 0.7.0-alpha.9 → 0.7.1

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