cojson 0.2.3 → 0.3.0-alpha.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 (78) hide show
  1. package/dist/account.d.ts +1 -1
  2. package/dist/coValue.d.ts +5 -13
  3. package/dist/coValue.js +14 -7
  4. package/dist/coValue.js.map +1 -1
  5. package/dist/coValueCore.d.ts +6 -6
  6. package/dist/coValueCore.js +11 -14
  7. package/dist/coValueCore.js.map +1 -1
  8. package/dist/coValues/coList.d.ts +99 -34
  9. package/dist/coValues/coList.js +162 -72
  10. package/dist/coValues/coList.js.map +1 -1
  11. package/dist/coValues/coMap.d.ts +96 -31
  12. package/dist/coValues/coMap.js +157 -114
  13. package/dist/coValues/coMap.js.map +1 -1
  14. package/dist/coValues/coStream.d.ts +67 -23
  15. package/dist/coValues/coStream.js +131 -59
  16. package/dist/coValues/coStream.js.map +1 -1
  17. package/dist/crypto.d.ts +8 -3
  18. package/dist/crypto.js +6 -6
  19. package/dist/crypto.js.map +1 -1
  20. package/dist/group.d.ts +57 -23
  21. package/dist/group.js +75 -33
  22. package/dist/group.js.map +1 -1
  23. package/dist/index.d.ts +8 -6
  24. package/dist/index.js +8 -8
  25. package/dist/index.js.map +1 -1
  26. package/dist/{node.d.ts → localNode.d.ts} +16 -8
  27. package/dist/{node.js → localNode.js} +48 -40
  28. package/dist/localNode.js.map +1 -0
  29. package/dist/permissions.js +6 -3
  30. package/dist/permissions.js.map +1 -1
  31. package/dist/queriedCoValues/queriedCoList.d.ts +66 -0
  32. package/dist/queriedCoValues/queriedCoList.js +120 -0
  33. package/dist/queriedCoValues/queriedCoList.js.map +1 -0
  34. package/dist/queriedCoValues/queriedCoMap.d.ts +47 -0
  35. package/dist/queriedCoValues/queriedCoMap.js +83 -0
  36. package/dist/queriedCoValues/queriedCoMap.js.map +1 -0
  37. package/dist/queriedCoValues/queriedCoStream.d.ts +40 -0
  38. package/dist/queriedCoValues/queriedCoStream.js +72 -0
  39. package/dist/queriedCoValues/queriedCoStream.js.map +1 -0
  40. package/dist/queries.d.ts +29 -112
  41. package/dist/queries.js +44 -227
  42. package/dist/queries.js.map +1 -1
  43. package/dist/sync.d.ts +1 -1
  44. package/dist/sync.js +1 -1
  45. package/dist/sync.js.map +1 -1
  46. package/dist/tests/testUtils.d.ts +1 -1
  47. package/dist/tests/testUtils.js +3 -3
  48. package/dist/tests/testUtils.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/account.ts +1 -1
  51. package/src/coValue.ts +25 -20
  52. package/src/coValueCore.ts +17 -21
  53. package/src/coValues/coList.ts +242 -128
  54. package/src/coValues/coMap.ts +293 -162
  55. package/src/coValues/coStream.ts +227 -94
  56. package/src/crypto.ts +37 -24
  57. package/src/group.ts +90 -63
  58. package/src/index.ts +35 -25
  59. package/src/{node.ts → localNode.ts} +64 -64
  60. package/src/permissions.ts +15 -18
  61. package/src/queriedCoValues/queriedCoList.ts +248 -0
  62. package/src/queriedCoValues/queriedCoMap.ts +180 -0
  63. package/src/queriedCoValues/queriedCoStream.ts +125 -0
  64. package/src/queries.ts +83 -460
  65. package/src/sync.ts +2 -2
  66. package/src/tests/account.test.ts +3 -6
  67. package/src/tests/coValue.test.ts +116 -110
  68. package/src/tests/coValueCore.test.ts +1 -1
  69. package/src/tests/crypto.test.ts +19 -21
  70. package/src/tests/permissions.test.ts +255 -242
  71. package/src/tests/queries.test.ts +57 -40
  72. package/src/tests/sync.test.ts +30 -30
  73. package/src/tests/testUtils.ts +3 -3
  74. package/dist/coValues/static.d.ts +0 -14
  75. package/dist/coValues/static.js +0 -20
  76. package/dist/coValues/static.js.map +0 -1
  77. package/dist/node.js.map +0 -1
  78. package/src/coValues/static.ts +0 -31
@@ -1,8 +1,8 @@
1
1
  import { JsonObject, JsonValue } from "../jsonValue.js";
2
- import { TransactionID } from "../ids.js";
2
+ import { AgentID, TransactionID } from "../ids.js";
3
3
  import { CoID, CoValue, isCoValue } from "../coValue.js";
4
4
  import { CoValueCore, accountOrAgentIDfromSessionID } from "../coValueCore.js";
5
- import { AccountID, isAccountID } from "../account.js";
5
+ import { AccountID } from "../account.js";
6
6
  import { Group } from "../group.js";
7
7
  import { parseJSON } from "../jsonStringify.js";
8
8
 
@@ -27,19 +27,25 @@ export type MapOpPayload<
27
27
  key: K;
28
28
  };
29
29
 
30
- /** A collaborative map with precise shape `M` and optional static metadata `Meta` */
31
- export class CoMap<
32
- M extends { [key: string]: JsonValue | CoValue | undefined },
30
+ export class CoMapView<
31
+ Shape extends { [key: string]: JsonValue | CoValue | undefined },
33
32
  Meta extends JsonObject | null = null
34
33
  > implements CoValue
35
34
  {
35
+ /** @category 6. Meta */
36
36
  id: CoID<this>;
37
+ /** @category 6. Meta */
37
38
  type = "comap" as const;
39
+ /** @category 6. Meta */
38
40
  core: CoValueCore;
39
41
  /** @internal */
40
42
  ops: {
41
- [Key in keyof M & string]?: MapOp<Key, M[Key]>[];
43
+ [Key in keyof Shape & string]?: MapOp<Key, Shape[Key]>[];
42
44
  };
45
+ /** @internal */
46
+ atTimeFilter?: number = undefined;
47
+ /** @category 6. Meta */
48
+ readonly _shape!: Shape;
43
49
 
44
50
  /** @internal */
45
51
  constructor(core: CoValueCore) {
@@ -47,32 +53,17 @@ export class CoMap<
47
53
  this.core = core;
48
54
  this.ops = {};
49
55
 
50
- this.fillOpsFromCoValue();
51
- }
52
-
53
- get meta(): Meta {
54
- return this.core.header.meta as Meta;
55
- }
56
-
57
- get group(): Group {
58
- return this.core.getGroup();
59
- }
60
-
61
- /** @internal */
62
- protected fillOpsFromCoValue() {
63
- this.ops = {};
64
-
65
56
  for (const {
66
57
  txID,
67
58
  changes,
68
59
  madeAt,
69
- } of this.core.getValidSortedTransactions()) {
60
+ } of core.getValidSortedTransactions()) {
70
61
  for (const [changeIdx, changeUntyped] of parseJSON(
71
62
  changes
72
63
  ).entries()) {
73
64
  const change = changeUntyped as MapOpPayload<
74
- keyof M & string,
75
- M[keyof M & string]
65
+ keyof Shape & string,
66
+ Shape[keyof Shape & string]
76
67
  >;
77
68
  let entries = this.ops[change.key];
78
69
  if (!entries) {
@@ -84,222 +75,301 @@ export class CoMap<
84
75
  madeAt,
85
76
  changeIdx,
86
77
  ...(change as MapOpPayload<
87
- keyof M & string,
88
- M[keyof M & string]
78
+ keyof Shape & string,
79
+ Shape[keyof Shape & string]
89
80
  >),
90
81
  });
91
82
  }
92
83
  }
93
84
  }
94
85
 
95
- keys(): (keyof M & string)[] {
96
- return Object.keys(this.ops) as (keyof M & string)[];
86
+ /** @category 6. Meta */
87
+ get meta(): Meta {
88
+ return this.core.header.meta as Meta;
97
89
  }
98
90
 
99
- /** Returns the current value for the given key. */
100
- get<K extends keyof M & string>(
91
+ /** @category 6. Meta */
92
+ get group(): Group {
93
+ return this.core.getGroup();
94
+ }
95
+
96
+ /** @category 4. Time travel */
97
+ atTime(time: number): this {
98
+ const clone = Object.create(this) as this;
99
+ clone.id = this.id;
100
+ clone.type = this.type;
101
+ clone.core = this.core;
102
+ clone.ops = this.ops;
103
+ clone.atTimeFilter = time;
104
+ return clone;
105
+ }
106
+
107
+ /** @internal */
108
+ timeFilteredOps<K extends keyof Shape & string>(
101
109
  key: K
102
- ):
103
- | (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
104
- | undefined {
105
- const ops = this.ops[key];
106
- if (!ops) {
107
- return undefined;
110
+ ): MapOp<K, Shape[K]>[] | undefined {
111
+ if (this.atTimeFilter) {
112
+ return this.ops[key]?.filter(
113
+ (op) => op.madeAt <= this.atTimeFilter!
114
+ );
115
+ } else {
116
+ return this.ops[key];
108
117
  }
118
+ }
109
119
 
110
- const lastEntry = ops[ops.length - 1]!;
111
-
112
- if (lastEntry.op === "del") {
113
- return undefined;
120
+ /**
121
+ * Get all keys currently in the map.
122
+ *
123
+ * @category 1. Reading */
124
+ keys(): (keyof Shape & string)[] {
125
+ const keys = Object.keys(this.ops) as (keyof Shape & string)[];
126
+
127
+ if (this.atTimeFilter) {
128
+ return keys.filter((key) => {
129
+ this.timeFilteredOps(key)?.length;
130
+ });
114
131
  } else {
115
- return lastEntry.value;
132
+ return keys;
116
133
  }
117
134
  }
118
135
 
119
- getAtTime<K extends keyof M & string>(
120
- key: K,
121
- time: number
136
+ /**
137
+ * Returns the current value for the given key.
138
+ *
139
+ * @category 1. Reading
140
+ **/
141
+ get<K extends keyof Shape & string>(
142
+ key: K
122
143
  ):
123
- | (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
144
+ | (Shape[K] extends CoValue
145
+ ? CoID<Shape[K]>
146
+ : Exclude<Shape[K], CoValue>)
124
147
  | undefined {
125
- const ops = this.ops[key];
148
+ const ops = this.timeFilteredOps(key);
126
149
  if (!ops) {
127
150
  return undefined;
128
151
  }
129
152
 
130
- const lastOpBeforeOrAtTime = ops.findLast((op) => op.madeAt <= time);
131
-
132
- if (!lastOpBeforeOrAtTime) {
133
- return undefined;
134
- }
153
+ const includeUntil = this.atTimeFilter;
154
+ const lastEntry = includeUntil
155
+ ? ops.findLast((entry) => entry.madeAt <= includeUntil)
156
+ : ops[ops.length - 1]!;
135
157
 
136
- if (lastOpBeforeOrAtTime.op === "del") {
158
+ if (lastEntry?.op === "del") {
137
159
  return undefined;
138
160
  } else {
139
- return lastOpBeforeOrAtTime.value;
161
+ return lastEntry?.value;
140
162
  }
141
163
  }
142
164
 
143
- /** Returns the accountID of the last account to modify the value for the given key. */
144
- whoEdited<K extends keyof M & string>(key: K): AccountID | undefined {
145
- const tx = this.getLastTxID(key);
146
- if (!tx) {
147
- return undefined;
148
- }
149
- const accountID = accountOrAgentIDfromSessionID(tx.sessionID);
150
- if (isAccountID(accountID)) {
151
- return accountID;
152
- } else {
153
- return undefined;
154
- }
155
- }
165
+ /** @category 1. Reading */
166
+ asObject(): {
167
+ [K in keyof Shape & string]: Shape[K] extends CoValue
168
+ ? CoID<Shape[K]>
169
+ : Exclude<Shape[K], CoValue>;
170
+ } {
171
+ const object: Partial<{
172
+ [K in keyof Shape & string]: Shape[K] extends CoValue
173
+ ? CoID<Shape[K]>
174
+ : Exclude<Shape[K], CoValue>;
175
+ }> = {};
156
176
 
157
- getLastTxID<K extends keyof M & string>(key: K): TransactionID | undefined {
158
- const ops = this.ops[key];
159
- if (!ops) {
160
- return undefined;
177
+ for (const key of this.keys()) {
178
+ const value = this.get(key);
179
+ if (value !== undefined) {
180
+ object[key] = value;
181
+ }
161
182
  }
162
183
 
163
- const lastEntry = ops[ops.length - 1]!;
184
+ return object as {
185
+ [K in keyof Shape & string]: Shape[K] extends CoValue
186
+ ? CoID<Shape[K]>
187
+ : Exclude<Shape[K], CoValue>;
188
+ };
189
+ }
164
190
 
165
- return lastEntry.txID;
191
+ /** @category 1. Reading */
192
+ toJSON(): {
193
+ [K in keyof Shape & string]: Shape[K] extends CoValue
194
+ ? CoID<Shape[K]>
195
+ : Exclude<Shape[K], CoValue>;
196
+ } {
197
+ return this.asObject();
166
198
  }
167
199
 
168
- getLastEntry<K extends keyof M & string>(
169
- key: K
200
+ /** @category 5. Edit history */
201
+ nthEditAt<K extends keyof Shape & string>(
202
+ key: K,
203
+ n: number
170
204
  ):
171
205
  | {
172
- at: number;
173
- txID: TransactionID;
174
- value: M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>;
206
+ by: AccountID | AgentID;
207
+ tx: TransactionID;
208
+ at: Date;
209
+ value?: Shape[K] extends CoValue
210
+ ? CoID<Shape[K]>
211
+ : Exclude<Shape[K], CoValue>;
175
212
  }
176
213
  | undefined {
177
- const ops = this.ops[key];
178
- if (!ops) {
214
+ const ops = this.timeFilteredOps(key);
215
+ if (!ops || ops.length <= n) {
179
216
  return undefined;
180
217
  }
181
218
 
182
- const lastEntry = ops[ops.length - 1]!;
219
+ const entry = ops[n]!;
183
220
 
184
- if (lastEntry.op === "del") {
221
+ if (this.atTimeFilter && entry.madeAt > this.atTimeFilter) {
185
222
  return undefined;
186
- } else {
187
- return {
188
- at: lastEntry.madeAt,
189
- txID: lastEntry.txID,
190
- value: lastEntry.value,
191
- };
192
223
  }
224
+
225
+ return {
226
+ by: accountOrAgentIDfromSessionID(entry.txID.sessionID),
227
+ tx: entry.txID,
228
+ at: new Date(entry.madeAt),
229
+ value: entry.op === "del" ? undefined : entry.value,
230
+ };
193
231
  }
194
232
 
195
- getHistory<K extends keyof M & string>(
233
+ /** @category 5. Edit history */
234
+ lastEditAt<K extends keyof Shape & string>(
196
235
  key: K
197
- ): {
198
- at: number;
199
- txID: TransactionID;
200
- value:
201
- | (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
202
- | undefined;
203
- }[] {
204
- const ops = this.ops[key];
205
- if (!ops) {
206
- return [];
207
- }
208
-
209
- const history: {
210
- at: number;
211
- txID: TransactionID;
212
- value:
213
- | (M[K] extends CoValue ? CoID<M[K]> : Exclude<M[K], CoValue>)
214
- | undefined;
215
- }[] = [];
216
-
217
- for (const op of ops) {
218
- if (op.op === "del") {
219
- history.push({
220
- at: op.madeAt,
221
- txID: op.txID,
222
- value: undefined,
223
- });
224
- } else {
225
- history.push({ at: op.madeAt, txID: op.txID, value: op.value });
226
- }
236
+ ):
237
+ | {
238
+ by: AccountID | AgentID;
239
+ tx: TransactionID;
240
+ at: Date;
241
+ value?: Shape[K] extends CoValue
242
+ ? CoID<Shape[K]>
243
+ : Exclude<Shape[K], CoValue>;
244
+ }
245
+ | undefined {
246
+ const ops = this.timeFilteredOps(key);
247
+ if (!ops || ops.length === 0) {
248
+ return undefined;
227
249
  }
228
-
229
- return history;
250
+ return this.nthEditAt(key, ops.length - 1);
230
251
  }
231
252
 
232
- toJSON(): JsonObject {
233
- const json: JsonObject = {};
234
-
235
- for (const key of this.keys()) {
236
- const value = this.get(key);
237
- if (value !== undefined) {
238
- json[key] = value;
239
- }
253
+ /** @category 5. Edit history */
254
+ *editsAt<K extends keyof Shape & string>(key: K) {
255
+ const ops = this.timeFilteredOps(key);
256
+ if (!ops) {
257
+ return;
240
258
  }
241
259
 
242
- return json;
260
+ for (let i = 0; i < ops.length; i++) {
261
+ yield this.nthEditAt(key, i)!;
262
+ }
243
263
  }
244
264
 
265
+ /** @category 3. Subscription */
245
266
  subscribe(listener: (coMap: this) => void): () => void {
246
267
  return this.core.subscribe((content) => {
247
268
  listener(content as this);
248
269
  });
249
270
  }
250
-
251
- edit(changer: (editable: WriteableCoMap<M, Meta>) => void): this {
252
- const editable = new WriteableCoMap<M, Meta>(this.core);
253
- changer(editable);
254
- return new CoMap(this.core) as this;
255
- }
256
271
  }
257
272
 
258
- export class WriteableCoMap<
259
- M extends { [key: string]: JsonValue | CoValue | undefined },
273
+ /** A collaborative map with precise shape `Shape` and optional static metadata `Meta` */
274
+ export class CoMap<
275
+ Shape extends { [key: string]: JsonValue | CoValue | undefined },
260
276
  Meta extends JsonObject | null = null
261
277
  >
262
- extends CoMap<M, Meta>
278
+ extends CoMapView<Shape, Meta>
263
279
  implements CoValue
264
280
  {
265
- /** @internal */
266
- edit(_changer: (editable: WriteableCoMap<M, Meta>) => void): this {
267
- throw new Error("Already editing.");
268
- }
269
281
 
270
- /** Sets a new value for the given key.
282
+
283
+ /** Returns a new version of this CoMap with a new value for the given key.
271
284
  *
272
285
  * If `privacy` is `"private"` **(default)**, both `key` and `value` are encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
273
286
  *
274
- * If `privacy` is `"trusting"`, both `key` and `value` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
275
- set<K extends keyof M & string>(
287
+ * If `privacy` is `"trusting"`, both `key` and `value` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
288
+ *
289
+ * @category 2. Editing
290
+ **/
291
+ set<K extends keyof Shape & string>(
276
292
  key: K,
277
- value: M[K] extends CoValue ? M[K] | CoID<M[K]> : M[K],
278
- privacy: "private" | "trusting" = "private"
279
- ): void {
280
- this.core.makeTransaction(
281
- [
293
+ value: Shape[K] extends CoValue ? Shape[K] | CoID<Shape[K]> : Shape[K],
294
+ privacy?: "private" | "trusting"
295
+ ): this;
296
+ set(
297
+ kv: {
298
+ [K in keyof Shape & string]?: Shape[K] extends CoValue
299
+ ? Shape[K] | CoID<Shape[K]>
300
+ : Shape[K];
301
+ },
302
+ privacy?: "private" | "trusting"
303
+ ): this;
304
+ set<K extends keyof Shape & string>(
305
+ ...args:
306
+ | [
307
+ {
308
+ [K in keyof Shape & string]?: Shape[K] extends CoValue
309
+ ? Shape[K] | CoID<Shape[K]>
310
+ : Shape[K];
311
+ },
312
+ ("private" | "trusting")?
313
+ ]
314
+ | [
315
+ K,
316
+ Shape[K] extends CoValue
317
+ ? Shape[K] | CoID<Shape[K]>
318
+ : Shape[K],
319
+ ("private" | "trusting")?
320
+ ]
321
+ ): this {
322
+ if (typeof args[0] === "string") {
323
+ const [key, value, privacy = "private"] = args;
324
+ this.core.makeTransaction(
325
+ [
326
+ {
327
+ op: "set",
328
+ key,
329
+ value: isCoValue(value) ? value.id : value,
330
+ },
331
+ ],
332
+ privacy
333
+ );
334
+ } else {
335
+ const [kv, privacy = "private"] = args as [
282
336
  {
283
- op: "set",
284
- key,
285
- value: isCoValue(value) ? value.id : value,
337
+ [K in keyof Shape & string]: Shape[K] extends CoValue
338
+ ? Shape[K] | CoID<Shape[K]>
339
+ : Shape[K];
286
340
  },
287
- ],
288
- privacy
289
- );
341
+ "private" | "trusting" | undefined
342
+ ];
343
+
344
+ for (const [key, value] of Object.entries(kv)) {
345
+ this.core.makeTransaction(
346
+ [
347
+ {
348
+ op: "set",
349
+ key,
350
+ value: isCoValue(value) ? value.id : value,
351
+ },
352
+ ],
353
+ privacy
354
+ );
355
+ }
356
+ }
290
357
 
291
- this.fillOpsFromCoValue();
358
+ return new CoMap(this.core) as this;
292
359
  }
293
360
 
294
- /** Deletes the value for the given key (setting it to undefined).
361
+ /** Returns a new version of this CoMap with the given key deleted (setting it to undefined).
295
362
  *
296
363
  * If `privacy` is `"private"` **(default)**, `key` is encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
297
364
  *
298
- * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
365
+ * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
366
+ *
367
+ * @category 2. Editing
368
+ **/
299
369
  delete(
300
- key: keyof M & string,
370
+ key: keyof Shape & string,
301
371
  privacy: "private" | "trusting" = "private"
302
- ): void {
372
+ ): this {
303
373
  this.core.makeTransaction(
304
374
  [
305
375
  {
@@ -310,6 +380,67 @@ export class WriteableCoMap<
310
380
  privacy
311
381
  );
312
382
 
313
- this.fillOpsFromCoValue();
383
+ return new CoMap(this.core) as this;
384
+ }
385
+
386
+ /** @category 2. Editing */
387
+ mutate(mutator: (mutable: MutableCoMap<Shape, Meta>) => void): this {
388
+ const mutable = new MutableCoMap<Shape, Meta>(this.core);
389
+ mutator(mutable);
390
+ return new CoMap(this.core) as this;
391
+ }
392
+
393
+ /** @deprecated Use `mutate` instead. */
394
+ edit(mutator: (mutable: MutableCoMap<Shape, Meta>) => void): this {
395
+ return this.mutate(mutator);
396
+ }
397
+ }
398
+
399
+ export class MutableCoMap<
400
+ Shape extends { [key: string]: JsonValue | CoValue | undefined },
401
+ Meta extends JsonObject | null = null
402
+ >
403
+ extends CoMapView<Shape, Meta>
404
+ implements CoValue
405
+ {
406
+ /** Sets a new value for the given key.
407
+ *
408
+ * If `privacy` is `"private"` **(default)**, both `key` and `value` are encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
409
+ *
410
+ * If `privacy` is `"trusting"`, both `key` and `value` are stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
411
+ *
412
+ * @category 2. Mutation
413
+ */
414
+ set<K extends keyof Shape & string>(
415
+ key: K,
416
+ value: Shape[K] extends CoValue ? Shape[K] | CoID<Shape[K]> : Shape[K],
417
+ privacy: "private" | "trusting" = "private"
418
+ ): void {
419
+ // eslint-disable-next-line @typescript-eslint/ban-types
420
+ const after = (CoMap.prototype.set as Function).call(
421
+ this,
422
+ key,
423
+ value,
424
+ privacy
425
+ ) as CoMap<Shape, Meta>;
426
+ this.ops = after.ops;
427
+ }
428
+
429
+ /** Deletes the value for the given key (setting it to undefined).
430
+ *
431
+ * If `privacy` is `"private"` **(default)**, `key` is encrypted in the transaction, only readable by other members of the group this `CoMap` belongs to. Not even sync servers can see the content in plaintext.
432
+ *
433
+ * If `privacy` is `"trusting"`, `key` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
434
+ * @category 2. Mutation
435
+ */
436
+ delete(
437
+ key: keyof Shape & string,
438
+ privacy: "private" | "trusting" = "private"
439
+ ): void {
440
+ const after = CoMap.prototype.delete.call(this, key, privacy) as CoMap<
441
+ Shape,
442
+ Meta
443
+ >;
444
+ this.ops = after.ops;
314
445
  }
315
446
  }