cojson 0.2.2 → 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 (85) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/dist/account.d.ts +8 -8
  3. package/dist/account.js +2 -2
  4. package/dist/account.js.map +1 -1
  5. package/dist/coValue.d.ts +22 -27
  6. package/dist/coValue.js +21 -0
  7. package/dist/coValue.js.map +1 -1
  8. package/dist/coValueCore.d.ts +7 -7
  9. package/dist/coValueCore.js +11 -14
  10. package/dist/coValueCore.js.map +1 -1
  11. package/dist/coValues/coList.d.ts +107 -42
  12. package/dist/coValues/coList.js +163 -72
  13. package/dist/coValues/coList.js.map +1 -1
  14. package/dist/coValues/coMap.d.ts +109 -50
  15. package/dist/coValues/coMap.js +161 -109
  16. package/dist/coValues/coMap.js.map +1 -1
  17. package/dist/coValues/coStream.d.ts +78 -33
  18. package/dist/coValues/coStream.js +134 -53
  19. package/dist/coValues/coStream.js.map +1 -1
  20. package/dist/crypto.d.ts +8 -3
  21. package/dist/crypto.js +6 -6
  22. package/dist/crypto.js.map +1 -1
  23. package/dist/group.d.ts +59 -23
  24. package/dist/group.js +83 -25
  25. package/dist/group.js.map +1 -1
  26. package/dist/index.d.ts +14 -11
  27. package/dist/index.js +8 -8
  28. package/dist/index.js.map +1 -1
  29. package/dist/{node.d.ts → localNode.d.ts} +23 -11
  30. package/dist/{node.js → localNode.js} +80 -42
  31. package/dist/localNode.js.map +1 -0
  32. package/dist/media.d.ts +1 -2
  33. package/dist/permissions.js +6 -3
  34. package/dist/permissions.js.map +1 -1
  35. package/dist/queriedCoValues/queriedCoList.d.ts +66 -0
  36. package/dist/queriedCoValues/queriedCoList.js +120 -0
  37. package/dist/queriedCoValues/queriedCoList.js.map +1 -0
  38. package/dist/queriedCoValues/queriedCoMap.d.ts +47 -0
  39. package/dist/queriedCoValues/queriedCoMap.js +83 -0
  40. package/dist/queriedCoValues/queriedCoMap.js.map +1 -0
  41. package/dist/queriedCoValues/queriedCoStream.d.ts +40 -0
  42. package/dist/queriedCoValues/queriedCoStream.js +72 -0
  43. package/dist/queriedCoValues/queriedCoStream.js.map +1 -0
  44. package/dist/queries.d.ts +31 -0
  45. package/dist/queries.js +77 -0
  46. package/dist/queries.js.map +1 -0
  47. package/dist/sync.d.ts +1 -1
  48. package/dist/sync.js +1 -1
  49. package/dist/sync.js.map +1 -1
  50. package/dist/{testUtils.d.ts → tests/testUtils.d.ts} +9 -9
  51. package/dist/{testUtils.js → tests/testUtils.js} +9 -7
  52. package/dist/tests/testUtils.js.map +1 -0
  53. package/package.json +2 -2
  54. package/src/account.ts +6 -6
  55. package/src/coValue.ts +65 -34
  56. package/src/coValueCore.ts +18 -22
  57. package/src/coValues/coList.ts +272 -122
  58. package/src/coValues/coMap.ts +349 -152
  59. package/src/coValues/coStream.ts +258 -94
  60. package/src/crypto.ts +37 -24
  61. package/src/group.ts +112 -46
  62. package/src/index.ts +42 -30
  63. package/src/{node.ts → localNode.ts} +117 -66
  64. package/src/media.ts +1 -2
  65. package/src/permissions.ts +15 -18
  66. package/src/queriedCoValues/queriedCoList.ts +248 -0
  67. package/src/queriedCoValues/queriedCoMap.ts +180 -0
  68. package/src/queriedCoValues/queriedCoStream.ts +125 -0
  69. package/src/queries.ts +142 -0
  70. package/src/sync.ts +2 -2
  71. package/src/{account.test.ts → tests/account.test.ts} +6 -9
  72. package/src/{coValue.test.ts → tests/coValue.test.ts} +120 -114
  73. package/src/{coValueCore.test.ts → tests/coValueCore.test.ts} +7 -7
  74. package/src/{crypto.test.ts → tests/crypto.test.ts} +19 -21
  75. package/src/{group.test.ts → tests/group.test.ts} +2 -2
  76. package/src/{permissions.test.ts → tests/permissions.test.ts} +260 -247
  77. package/src/tests/queries.test.ts +318 -0
  78. package/src/{sync.test.ts → tests/sync.test.ts} +39 -39
  79. package/src/{testUtils.ts → tests/testUtils.ts} +10 -8
  80. package/dist/coValues/static.d.ts +0 -14
  81. package/dist/coValues/static.js +0 -20
  82. package/dist/coValues/static.js.map +0 -1
  83. package/dist/node.js.map +0 -1
  84. package/dist/testUtils.js.map +0 -1
  85. package/src/coValues/static.ts +0 -31
@@ -1,22 +1,22 @@
1
1
  import { JsonObject, JsonValue } from "../jsonValue.js";
2
- import { CoID, ReadableCoValue, WriteableCoValue } from "../coValue.js";
2
+ import { CoID, CoValue, isCoValue } from "../coValue.js";
3
3
  import { CoValueCore, accountOrAgentIDfromSessionID } from "../coValueCore.js";
4
- import { SessionID, TransactionID } from "../ids.js";
4
+ import { AgentID, SessionID, TransactionID } from "../ids.js";
5
5
  import { Group } from "../group.js";
6
- import { AccountID, isAccountID } from "../account.js";
6
+ import { AccountID } from "../account.js";
7
7
  import { parseJSON } from "../jsonStringify.js";
8
8
 
9
9
  type OpID = TransactionID & { changeIdx: number };
10
10
 
11
- type InsertionOpPayload<T extends JsonValue> =
11
+ type InsertionOpPayload<T extends JsonValue | CoValue> =
12
12
  | {
13
13
  op: "pre";
14
- value: T;
14
+ value: T extends CoValue ? CoID<T> : Exclude<T, CoValue>;
15
15
  before: OpID | "end";
16
16
  }
17
17
  | {
18
18
  op: "app";
19
- value: T;
19
+ value: T extends CoValue ? CoID<T> : Exclude<T, CoValue>;
20
20
  after: OpID | "start";
21
21
  };
22
22
 
@@ -25,11 +25,11 @@ type DeletionOpPayload = {
25
25
  insertion: OpID;
26
26
  };
27
27
 
28
- export type ListOpPayload<T extends JsonValue> =
28
+ export type ListOpPayload<T extends JsonValue | CoValue> =
29
29
  | InsertionOpPayload<T>
30
30
  | DeletionOpPayload;
31
31
 
32
- type InsertionEntry<T extends JsonValue> = {
32
+ type InsertionEntry<T extends JsonValue | CoValue> = {
33
33
  madeAt: number;
34
34
  predecessors: OpID[];
35
35
  successors: OpID[];
@@ -40,11 +40,16 @@ type DeletionEntry = {
40
40
  deletionID: OpID;
41
41
  } & DeletionOpPayload;
42
42
 
43
- export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
44
- implements ReadableCoValue
43
+ export class CoListView<
44
+ Item extends JsonValue | CoValue,
45
+ Meta extends JsonObject | null = null
46
+ > implements CoValue
45
47
  {
46
- id: CoID<CoList<T, Meta>>;
48
+ /** @category 6. Meta */
49
+ id: CoID<this>;
50
+ /** @category 6. Meta */
47
51
  type = "colist" as const;
52
+ /** @category 6. Meta */
48
53
  core: CoValueCore;
49
54
  /** @internal */
50
55
  afterStart: OpID[];
@@ -54,7 +59,7 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
54
59
  insertions: {
55
60
  [sessionID: SessionID]: {
56
61
  [txIdx: number]: {
57
- [changeIdx: number]: InsertionEntry<T>;
62
+ [changeIdx: number]: InsertionEntry<Item>;
58
63
  };
59
64
  };
60
65
  };
@@ -66,29 +71,18 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
66
71
  };
67
72
  };
68
73
  };
74
+ /** @category 6. Meta */
75
+ readonly _item!: Item;
69
76
 
70
77
  /** @internal */
71
78
  constructor(core: CoValueCore) {
72
- this.id = core.id as CoID<CoList<T, Meta>>;
79
+ this.id = core.id as CoID<this>;
73
80
  this.core = core;
74
81
  this.afterStart = [];
75
82
  this.beforeEnd = [];
76
83
  this.insertions = {};
77
84
  this.deletionsByInsertion = {};
78
85
 
79
- this.fillOpsFromCoValue();
80
- }
81
-
82
- get meta(): Meta {
83
- return this.core.header.meta as Meta;
84
- }
85
-
86
- get group(): Group {
87
- return this.core.getGroup();
88
- }
89
-
90
- /** @internal */
91
- protected fillOpsFromCoValue() {
92
86
  this.insertions = {};
93
87
  this.deletionsByInsertion = {};
94
88
  this.afterStart = [];
@@ -99,8 +93,10 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
99
93
  changes,
100
94
  madeAt,
101
95
  } of this.core.getValidSortedTransactions()) {
102
- for (const [changeIdx, changeUntyped] of parseJSON(changes).entries()) {
103
- const change = changeUntyped as ListOpPayload<T>;
96
+ for (const [changeIdx, changeUntyped] of parseJSON(
97
+ changes
98
+ ).entries()) {
99
+ const change = changeUntyped as ListOpPayload<Item>;
104
100
 
105
101
  if (change.op === "pre" || change.op === "app") {
106
102
  let sessionEntry = this.insertions[txID.sessionID];
@@ -200,8 +196,35 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
200
196
  }
201
197
  }
202
198
 
203
- /** Get the item currently at `idx`. */
204
- get(idx: number): T | undefined {
199
+ /** @category 6. Meta */
200
+ get meta(): Meta {
201
+ return this.core.header.meta as Meta;
202
+ }
203
+
204
+ /** @category 6. Meta */
205
+ get group(): Group {
206
+ return this.core.getGroup();
207
+ }
208
+
209
+ /**
210
+ * Not yet implemented
211
+ *
212
+ * @category 4. Time travel
213
+ */
214
+ atTime(_time: number): this {
215
+ throw new Error("Not yet implemented");
216
+ }
217
+
218
+ /**
219
+ * Get the item currently at `idx`.
220
+ *
221
+ * @category 1. Reading
222
+ */
223
+ get(
224
+ idx: number
225
+ ):
226
+ | (Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>)
227
+ | undefined {
205
228
  const entry = this.entries()[idx];
206
229
  if (!entry) {
207
230
  return undefined;
@@ -209,13 +232,26 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
209
232
  return entry.value;
210
233
  }
211
234
 
212
- /** Returns the current items in the CoList as an array. */
213
- asArray(): T[] {
235
+ /**
236
+ * Returns the current items in the CoList as an array.
237
+ *
238
+ * @category 1. Reading
239
+ **/
240
+ asArray(): (Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>)[] {
214
241
  return this.entries().map((entry) => entry.value);
215
242
  }
216
243
 
217
- entries(): { value: T; madeAt: number; opID: OpID }[] {
218
- const arr: { value: T; madeAt: number; opID: OpID }[] = [];
244
+ /** @internal */
245
+ entries(): {
246
+ value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
247
+ madeAt: number;
248
+ opID: OpID;
249
+ }[] {
250
+ const arr: {
251
+ value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
252
+ madeAt: number;
253
+ opID: OpID;
254
+ }[] = [];
219
255
  for (const opID of this.afterStart) {
220
256
  this.fillArrayFromOpID(opID, arr);
221
257
  }
@@ -228,7 +264,11 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
228
264
  /** @internal */
229
265
  private fillArrayFromOpID(
230
266
  opID: OpID,
231
- arr: { value: T; madeAt: number; opID: OpID }[]
267
+ arr: {
268
+ value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
269
+ madeAt: number;
270
+ opID: OpID;
271
+ }[]
232
272
  ) {
233
273
  const entry =
234
274
  this.insertions[opID.sessionID]?.[opID.txIndex]?.[opID.changeIdx];
@@ -254,86 +294,115 @@ export class CoList<T extends JsonValue, Meta extends JsonObject | null = null>
254
294
  }
255
295
  }
256
296
 
257
- /** Returns the accountID of the account that inserted value at the given index. */
258
- whoInserted(idx: number): AccountID | undefined {
297
+ /**
298
+ * Returns the current items in the CoList as an array. (alias of `asArray`)
299
+ *
300
+ * @category 1. Reading
301
+ */
302
+ toJSON(): (Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>)[] {
303
+ return this.asArray();
304
+ }
305
+
306
+ /** @category 5. Edit history */
307
+ editAt(idx: number):
308
+ | {
309
+ by: AccountID | AgentID;
310
+ tx: TransactionID;
311
+ at: Date;
312
+ value: Item extends CoValue ? CoID<Item> : Exclude<Item, CoValue>;
313
+ }
314
+ | undefined {
259
315
  const entry = this.entries()[idx];
260
316
  if (!entry) {
261
317
  return undefined;
262
318
  }
263
- const accountID = accountOrAgentIDfromSessionID(entry.opID.sessionID);
264
- if (isAccountID(accountID)) {
265
- return accountID;
266
- } else {
267
- return undefined;
268
- }
269
- }
270
-
271
- /** Returns the current items in the CoList as an array. (alias of `asArray`) */
272
- toJSON(): T[] {
273
- return this.asArray();
274
- }
275
-
276
- map<U>(mapper: (value: T, idx: number) => U): U[] {
277
- return this.entries().map((entry, idx) => mapper(entry.value, idx));
319
+ const madeAt = new Date(entry.madeAt);
320
+ const by = accountOrAgentIDfromSessionID(entry.opID.sessionID);
321
+ const value = entry.value;
322
+ return {
323
+ by,
324
+ tx: {
325
+ sessionID: entry.opID.sessionID,
326
+ txIndex: entry.opID.txIndex,
327
+ },
328
+ at: madeAt,
329
+ value,
330
+ };
278
331
  }
279
332
 
280
- filter<U extends T>(predicate: (value: T, idx: number) => value is U): U[];
281
- filter(predicate: (value: T, idx: number) => boolean): T[] {
282
- return this.entries()
283
- .filter((entry, idx) => predicate(entry.value, idx))
284
- .map((entry) => entry.value);
285
- }
333
+ /** @category 5. Edit history */
334
+ deletionEdits(): {
335
+ by: AccountID | AgentID;
336
+ tx: TransactionID;
337
+ at: Date;
338
+ // TODO: add indices that are now before and after the deleted item
339
+ }[] {
340
+ const edits: {
341
+ by: AccountID | AgentID;
342
+ tx: TransactionID;
343
+ at: Date;
344
+ }[] = [];
345
+
346
+ for (const sessionID in this.deletionsByInsertion) {
347
+ const sessionEntry =
348
+ this.deletionsByInsertion[sessionID as SessionID];
349
+ for (const txIdx in sessionEntry) {
350
+ const txEntry = sessionEntry[Number(txIdx)];
351
+ for (const changeIdx in txEntry) {
352
+ const changeEntry = txEntry[Number(changeIdx)];
353
+ for (const deletion of changeEntry || []) {
354
+ const madeAt = new Date(deletion.madeAt);
355
+ const by = accountOrAgentIDfromSessionID(
356
+ deletion.deletionID.sessionID
357
+ );
358
+ edits.push({
359
+ by,
360
+ tx: deletion.deletionID,
361
+ at: madeAt,
362
+ });
363
+ }
364
+ }
365
+ }
366
+ }
286
367
 
287
- reduce<U>(
288
- reducer: (accumulator: U, value: T, idx: number) => U,
289
- initialValue: U
290
- ): U {
291
- return this.entries().reduce(
292
- (accumulator, entry, idx) => reducer(accumulator, entry.value, idx),
293
- initialValue
294
- );
368
+ return edits;
295
369
  }
296
370
 
297
- subscribe(listener: (coMap: CoList<T, Meta>) => void): () => void {
371
+ /** @category 3. Subscription */
372
+ subscribe(listener: (coList: this) => void): () => void {
298
373
  return this.core.subscribe((content) => {
299
- listener(content as CoList<T, Meta>);
374
+ listener(content as this);
300
375
  });
301
376
  }
302
-
303
- edit(
304
- changer: (editable: WriteableCoList<T, Meta>) => void
305
- ): CoList<T, Meta> {
306
- const editable = new WriteableCoList<T, Meta>(this.core);
307
- changer(editable);
308
- return new CoList(this.core);
309
- }
310
377
  }
311
378
 
312
- export class WriteableCoList<
313
- T extends JsonValue,
379
+ export class CoList<
380
+ Item extends JsonValue | CoValue,
314
381
  Meta extends JsonObject | null = null
315
382
  >
316
- extends CoList<T, Meta>
317
- implements WriteableCoValue
383
+ extends CoListView<Item, Meta>
384
+ implements CoValue
318
385
  {
319
- /** @internal */
320
- edit(
321
- _changer: (editable: WriteableCoList<T, Meta>) => void
322
- ): CoList<T, Meta> {
323
- throw new Error("Already editing.");
324
- }
325
-
326
- /** Appends a new item after index `after`.
386
+ /** Returns a new version of this CoList with `item` appended after the item currently at index `after`.
387
+ *
388
+ * If `privacy` is `"private"` **(default)**, `item` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
327
389
  *
328
- * If `privacy` is `"private"` **(default)**, both `value` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
390
+ * If `privacy` is `"trusting"`, `item` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
329
391
  *
330
- * If `privacy` is `"trusting"`, both `value` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
392
+ * @category 2. Editing
393
+ **/
331
394
  append(
332
- after: number,
333
- value: T,
395
+ item: Item extends CoValue ? Item | CoID<Item> : Item,
396
+ after?: number,
334
397
  privacy: "private" | "trusting" = "private"
335
- ): void {
398
+ ): this {
336
399
  const entries = this.entries();
400
+ after =
401
+ after === undefined
402
+ ? entries.length > 0
403
+ ? entries.length - 1
404
+ : 0
405
+ : 0;
337
406
  let opIDBefore;
338
407
  if (entries.length > 0) {
339
408
  const entryBefore = entries[after];
@@ -351,44 +420,32 @@ export class WriteableCoList<
351
420
  [
352
421
  {
353
422
  op: "app",
354
- value,
423
+ value: isCoValue(item) ? item.id : item,
355
424
  after: opIDBefore,
356
425
  },
357
426
  ],
358
427
  privacy
359
428
  );
360
429
 
361
- this.fillOpsFromCoValue();
362
- }
363
-
364
- /** Pushes a new item to the end of the list.
365
- *
366
- * If `privacy` is `"private"` **(default)**, both `value` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
367
- *
368
- * If `privacy` is `"trusting"`, both `value` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
369
- push(value: T, privacy: "private" | "trusting" = "private"): void {
370
- // TODO: optimize
371
- const entries = this.entries();
372
- this.append(
373
- entries.length > 0 ? entries.length - 1 : 0,
374
- value,
375
- privacy
376
- );
430
+ return new CoList(this.core) as this;
377
431
  }
378
432
 
379
433
  /**
380
- * Prepends a new item before index `before`.
434
+ * Returns a new version of this CoList with `item` prepended before the item currently at index `before`.
435
+ *
436
+ * If `privacy` is `"private"` **(default)**, `item` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
381
437
  *
382
- * If `privacy` is `"private"` **(default)**, both `value` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
438
+ * If `privacy` is `"trusting"`, `item` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
383
439
  *
384
- * If `privacy` is `"trusting"`, both `value` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
440
+ * @category 2. Editing
385
441
  */
386
442
  prepend(
387
- before: number,
388
- value: T,
443
+ item: Item extends CoValue ? Item | CoID<Item> : Item,
444
+ before?: number,
389
445
  privacy: "private" | "trusting" = "private"
390
- ): void {
446
+ ): this {
391
447
  const entries = this.entries();
448
+ before = before === undefined ? 0 : before;
392
449
  let opIDAfter;
393
450
  if (entries.length > 0) {
394
451
  const entryAfter = entries[before];
@@ -410,22 +467,25 @@ export class WriteableCoList<
410
467
  [
411
468
  {
412
469
  op: "pre",
413
- value,
470
+ value: isCoValue(item) ? item.id : item,
414
471
  before: opIDAfter,
415
472
  },
416
473
  ],
417
474
  privacy
418
475
  );
419
476
 
420
- this.fillOpsFromCoValue();
477
+ return new CoList(this.core) as this;
421
478
  }
422
479
 
423
- /** Deletes the item at index `at` from the list.
480
+ /** Returns a new version of this CoList with the item at index `at` deleted from the list.
424
481
  *
425
482
  * If `privacy` is `"private"` **(default)**, the fact of this deletion is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
426
483
  *
427
- * If `privacy` is `"trusting"`, the fact of this deletion is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers. */
428
- delete(at: number, privacy: "private" | "trusting" = "private"): void {
484
+ * If `privacy` is `"trusting"`, the fact of this deletion is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
485
+ *
486
+ * @category 2. Editing
487
+ **/
488
+ delete(at: number, privacy: "private" | "trusting" = "private"): this {
429
489
  const entries = this.entries();
430
490
  const entry = entries[at];
431
491
  if (!entry) {
@@ -441,6 +501,96 @@ export class WriteableCoList<
441
501
  privacy
442
502
  );
443
503
 
444
- this.fillOpsFromCoValue();
504
+ return new CoList(this.core) as this;
505
+ }
506
+
507
+ /** @category 2. Editing */
508
+ mutate(mutator: (mutable: MutableCoList<Item, Meta>) => void): this {
509
+ const mutable = new MutableCoList<Item, Meta>(this.core);
510
+ mutator(mutable);
511
+ return new CoList(this.core) as this;
512
+ }
513
+
514
+ /** @deprecated Use `mutate` instead. */
515
+ edit(mutator: (mutable: MutableCoList<Item, Meta>) => void): this {
516
+ return this.mutate(mutator);
517
+ }
518
+ }
519
+
520
+ export class MutableCoList<
521
+ Item extends JsonValue | CoValue,
522
+ Meta extends JsonObject | null = null
523
+ >
524
+ extends CoListView<Item, Meta>
525
+ implements CoValue
526
+ {
527
+ /** Appends `item` after the item currently at index `after`.
528
+ *
529
+ * If `privacy` is `"private"` **(default)**, `item` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
530
+ *
531
+ * If `privacy` is `"trusting"`, `item` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
532
+ *
533
+ * @category 2. Mutating
534
+ **/
535
+ append(
536
+ item: Item extends CoValue ? Item | CoID<Item> : Item,
537
+ after?: number,
538
+ privacy: "private" | "trusting" = "private"
539
+ ): void {
540
+ const listAfter = CoList.prototype.append.call(
541
+ this,
542
+ item,
543
+ after,
544
+ privacy
545
+ ) as CoList<Item, Meta>;
546
+ this.afterStart = listAfter.afterStart;
547
+ this.beforeEnd = listAfter.beforeEnd;
548
+ this.insertions = listAfter.insertions;
549
+ this.deletionsByInsertion = listAfter.deletionsByInsertion;
550
+ }
551
+
552
+ /** Prepends `item` before the item currently at index `before`.
553
+ *
554
+ * If `privacy` is `"private"` **(default)**, `item` is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
555
+ *
556
+ * If `privacy` is `"trusting"`, `item` is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
557
+ *
558
+ * * @category 2. Mutating
559
+ **/
560
+ prepend(
561
+ item: Item extends CoValue ? Item | CoID<Item> : Item,
562
+ before?: number,
563
+ privacy: "private" | "trusting" = "private"
564
+ ): void {
565
+ const listAfter = CoList.prototype.prepend.call(
566
+ this,
567
+ item,
568
+ before,
569
+ privacy
570
+ ) as CoList<Item, Meta>;
571
+ this.afterStart = listAfter.afterStart;
572
+ this.beforeEnd = listAfter.beforeEnd;
573
+ this.insertions = listAfter.insertions;
574
+ this.deletionsByInsertion = listAfter.deletionsByInsertion;
575
+ }
576
+
577
+ /** Deletes the item at index `at` from the list.
578
+ *
579
+ * If `privacy` is `"private"` **(default)**, the fact of this deletion is encrypted in the transaction, only readable by other members of the group this `CoList` belongs to. Not even sync servers can see the content in plaintext.
580
+ *
581
+ * If `privacy` is `"trusting"`, the fact of this deletion is stored in plaintext in the transaction, visible to everyone who gets a hold of it, including sync servers.
582
+ *
583
+ * * @category 2. Mutating
584
+ **/
585
+ delete(at: number, privacy: "private" | "trusting" = "private"): void {
586
+ const listAfter = CoList.prototype.delete.call(
587
+ this,
588
+ at,
589
+ privacy
590
+ ) as CoList<Item, Meta>;
591
+ this.afterStart = listAfter.afterStart;
592
+ this.beforeEnd = listAfter.beforeEnd;
593
+ this.insertions = listAfter.insertions;
594
+ this.deletionsByInsertion = listAfter.deletionsByInsertion;
445
595
  }
446
596
  }