cojson 0.1.8 → 0.1.10

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 (76) hide show
  1. package/dist/account.d.ts +6 -3
  2. package/dist/account.js +4 -2
  3. package/dist/account.js.map +1 -1
  4. package/dist/coValue.d.ts +44 -80
  5. package/dist/coValue.js +4 -348
  6. package/dist/coValue.js.map +1 -1
  7. package/dist/coValueCore.d.ts +84 -0
  8. package/dist/coValueCore.js +356 -0
  9. package/dist/coValueCore.js.map +1 -0
  10. package/dist/coValues/coList.d.ts +114 -0
  11. package/dist/{contentTypes → coValues}/coList.js +59 -19
  12. package/dist/coValues/coList.js.map +1 -0
  13. package/dist/{contentTypes → coValues}/coMap.d.ts +25 -7
  14. package/dist/{contentTypes → coValues}/coMap.js +34 -15
  15. package/dist/coValues/coMap.js.map +1 -0
  16. package/dist/coValues/coStream.d.ts +69 -0
  17. package/dist/coValues/coStream.js +131 -0
  18. package/dist/coValues/coStream.js.map +1 -0
  19. package/dist/coValues/static.d.ts +14 -0
  20. package/dist/coValues/static.js +20 -0
  21. package/dist/coValues/static.js.map +1 -0
  22. package/dist/group.d.ts +57 -9
  23. package/dist/group.js +94 -28
  24. package/dist/group.js.map +1 -1
  25. package/dist/index.d.ts +19 -10
  26. package/dist/index.js +7 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/node.d.ts +59 -5
  29. package/dist/node.js +36 -15
  30. package/dist/node.js.map +1 -1
  31. package/dist/permissions.d.ts +2 -2
  32. package/dist/permissions.js +1 -1
  33. package/dist/permissions.js.map +1 -1
  34. package/dist/sync.d.ts +3 -3
  35. package/dist/sync.js +2 -2
  36. package/dist/sync.js.map +1 -1
  37. package/dist/testUtils.d.ts +2 -2
  38. package/dist/testUtils.js +1 -1
  39. package/dist/testUtils.js.map +1 -1
  40. package/package.json +2 -2
  41. package/src/account.test.ts +1 -1
  42. package/src/account.ts +8 -5
  43. package/src/coValue.test.ts +335 -129
  44. package/src/coValue.ts +52 -576
  45. package/src/coValueCore.test.ts +180 -0
  46. package/src/coValueCore.ts +592 -0
  47. package/src/{contentTypes → coValues}/coList.ts +91 -42
  48. package/src/{contentTypes → coValues}/coMap.ts +40 -20
  49. package/src/coValues/coStream.ts +249 -0
  50. package/src/coValues/static.ts +31 -0
  51. package/src/group.test.ts +47 -0
  52. package/src/group.ts +120 -50
  53. package/src/index.ts +43 -28
  54. package/src/node.ts +48 -27
  55. package/src/permissions.test.ts +32 -32
  56. package/src/permissions.ts +5 -5
  57. package/src/sync.test.ts +77 -77
  58. package/src/sync.ts +5 -5
  59. package/src/testUtils.ts +1 -1
  60. package/tsconfig.json +1 -2
  61. package/dist/contentType.d.ts +0 -15
  62. package/dist/contentType.js +0 -7
  63. package/dist/contentType.js.map +0 -1
  64. package/dist/contentTypes/coList.d.ts +0 -77
  65. package/dist/contentTypes/coList.js.map +0 -1
  66. package/dist/contentTypes/coMap.js.map +0 -1
  67. package/dist/contentTypes/coStream.d.ts +0 -11
  68. package/dist/contentTypes/coStream.js +0 -16
  69. package/dist/contentTypes/coStream.js.map +0 -1
  70. package/dist/contentTypes/static.d.ts +0 -11
  71. package/dist/contentTypes/static.js +0 -14
  72. package/dist/contentTypes/static.js.map +0 -1
  73. package/src/contentType.test.ts +0 -284
  74. package/src/contentType.ts +0 -26
  75. package/src/contentTypes/coStream.ts +0 -24
  76. package/src/contentTypes/static.ts +0 -22
@@ -0,0 +1,356 @@
1
+ import { randomBytes } from "@noble/hashes/utils";
2
+ import { Static } from "./coValues/static.js";
3
+ import { BinaryCoStream, CoStream } from "./coValues/coStream.js";
4
+ import { CoMap } from "./coValues/coMap.js";
5
+ import { StreamingHash, unseal, shortHash, sign, verify, encryptForTransaction, decryptForTransaction, decryptKeySecret, getAgentSignerID, getAgentSealerID, } from "./crypto.js";
6
+ import { base58 } from "@scure/base";
7
+ import { determineValidTransactions, isKeyForKeyField, } from "./permissions.js";
8
+ import { Group, expectGroupContent } from "./group.js";
9
+ import { CoList } from "./coValues/coList.js";
10
+ export function idforHeader(header) {
11
+ const hash = shortHash(header);
12
+ return `co_z${hash.slice("shortHash_z".length)}`;
13
+ }
14
+ export function accountOrAgentIDfromSessionID(sessionID) {
15
+ return sessionID.split("_session")[0];
16
+ }
17
+ export function newRandomSessionID(accountID) {
18
+ return `${accountID}_session_z${base58.encode(randomBytes(8))}`;
19
+ }
20
+ const readKeyCache = new WeakMap();
21
+ export class CoValueCore {
22
+ constructor(header, node, internalInitSessions = {}) {
23
+ this.listeners = new Set();
24
+ this.id = idforHeader(header);
25
+ this.header = header;
26
+ this._sessions = internalInitSessions;
27
+ this.node = node;
28
+ if (header.ruleset.type == "ownedByGroup") {
29
+ this.node
30
+ .expectCoValueLoaded(header.ruleset.group)
31
+ .subscribe((_groupUpdate) => {
32
+ this._cachedContent = undefined;
33
+ const newContent = this.getCurrentContent();
34
+ for (const listener of this.listeners) {
35
+ listener(newContent);
36
+ }
37
+ });
38
+ }
39
+ }
40
+ get sessions() {
41
+ return this._sessions;
42
+ }
43
+ testWithDifferentAccount(account, currentSessionID) {
44
+ const newNode = this.node.testWithDifferentAccount(account, currentSessionID);
45
+ return newNode.expectCoValueLoaded(this.id);
46
+ }
47
+ knownState() {
48
+ return {
49
+ id: this.id,
50
+ header: true,
51
+ sessions: Object.fromEntries(Object.entries(this.sessions).map(([k, v]) => [
52
+ k,
53
+ v.transactions.length,
54
+ ])),
55
+ };
56
+ }
57
+ get meta() {
58
+ return this.header?.meta ?? null;
59
+ }
60
+ nextTransactionID() {
61
+ const sessionID = this.node.currentSessionID;
62
+ return {
63
+ sessionID,
64
+ txIndex: this.sessions[sessionID]?.transactions.length || 0,
65
+ };
66
+ }
67
+ tryAddTransactions(sessionID, newTransactions, givenExpectedNewHash, newSignature) {
68
+ const signerID = getAgentSignerID(this.node.resolveAccountAgent(accountOrAgentIDfromSessionID(sessionID), "Expected to know signer of transaction"));
69
+ if (!signerID) {
70
+ console.warn("Unknown agent", accountOrAgentIDfromSessionID(sessionID));
71
+ return false;
72
+ }
73
+ const { expectedNewHash, newStreamingHash } = this.expectedNewHashAfter(sessionID, newTransactions);
74
+ if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
75
+ console.warn("Invalid hash", {
76
+ expectedNewHash,
77
+ givenExpectedNewHash,
78
+ });
79
+ return false;
80
+ }
81
+ if (!verify(newSignature, expectedNewHash, signerID)) {
82
+ console.warn("Invalid signature", newSignature, expectedNewHash, signerID);
83
+ return false;
84
+ }
85
+ const transactions = this.sessions[sessionID]?.transactions ?? [];
86
+ transactions.push(...newTransactions);
87
+ this._sessions[sessionID] = {
88
+ transactions,
89
+ lastHash: expectedNewHash,
90
+ streamingHash: newStreamingHash,
91
+ lastSignature: newSignature,
92
+ };
93
+ this._cachedContent = undefined;
94
+ const content = this.getCurrentContent();
95
+ for (const listener of this.listeners) {
96
+ listener(content);
97
+ }
98
+ return true;
99
+ }
100
+ subscribe(listener) {
101
+ this.listeners.add(listener);
102
+ listener(this.getCurrentContent());
103
+ return () => {
104
+ this.listeners.delete(listener);
105
+ };
106
+ }
107
+ expectedNewHashAfter(sessionID, newTransactions) {
108
+ const streamingHash = this.sessions[sessionID]?.streamingHash.clone() ??
109
+ new StreamingHash();
110
+ for (const transaction of newTransactions) {
111
+ streamingHash.update(transaction);
112
+ }
113
+ const newStreamingHash = streamingHash.clone();
114
+ return {
115
+ expectedNewHash: streamingHash.digest(),
116
+ newStreamingHash,
117
+ };
118
+ }
119
+ makeTransaction(changes, privacy) {
120
+ const madeAt = Date.now();
121
+ let transaction;
122
+ if (privacy === "private") {
123
+ const { secret: keySecret, id: keyID } = this.getCurrentReadKey();
124
+ if (!keySecret) {
125
+ throw new Error("Can't make transaction without read key secret");
126
+ }
127
+ transaction = {
128
+ privacy: "private",
129
+ madeAt,
130
+ keyUsed: keyID,
131
+ encryptedChanges: encryptForTransaction(changes, keySecret, {
132
+ in: this.id,
133
+ tx: this.nextTransactionID(),
134
+ }),
135
+ };
136
+ }
137
+ else {
138
+ transaction = {
139
+ privacy: "trusting",
140
+ madeAt,
141
+ changes,
142
+ };
143
+ }
144
+ const sessionID = this.node.currentSessionID;
145
+ const { expectedNewHash } = this.expectedNewHashAfter(sessionID, [
146
+ transaction,
147
+ ]);
148
+ const signature = sign(this.node.account.currentSignerSecret(), expectedNewHash);
149
+ const success = this.tryAddTransactions(sessionID, [transaction], expectedNewHash, signature);
150
+ if (success) {
151
+ void this.node.sync.syncCoValue(this);
152
+ }
153
+ return success;
154
+ }
155
+ getCurrentContent() {
156
+ if (this._cachedContent) {
157
+ return this._cachedContent;
158
+ }
159
+ if (this.header.type === "comap") {
160
+ this._cachedContent = new CoMap(this);
161
+ }
162
+ else if (this.header.type === "colist") {
163
+ this._cachedContent = new CoList(this);
164
+ }
165
+ else if (this.header.type === "costream") {
166
+ if (this.header.meta && this.header.meta.type === "binary") {
167
+ this._cachedContent = new BinaryCoStream(this);
168
+ }
169
+ else {
170
+ this._cachedContent = new CoStream(this);
171
+ }
172
+ }
173
+ else if (this.header.type === "static") {
174
+ this._cachedContent = new Static(this);
175
+ }
176
+ else {
177
+ throw new Error(`Unknown coValue type ${this.header.type}`);
178
+ }
179
+ return this._cachedContent;
180
+ }
181
+ getValidSortedTransactions() {
182
+ const validTransactions = determineValidTransactions(this);
183
+ const allTransactions = validTransactions
184
+ .map(({ txID, tx }) => {
185
+ if (tx.privacy === "trusting") {
186
+ return {
187
+ txID,
188
+ madeAt: tx.madeAt,
189
+ changes: tx.changes,
190
+ };
191
+ }
192
+ else {
193
+ const readKey = this.getReadKey(tx.keyUsed);
194
+ if (!readKey) {
195
+ return undefined;
196
+ }
197
+ else {
198
+ const decrytedChanges = decryptForTransaction(tx.encryptedChanges, readKey, {
199
+ in: this.id,
200
+ tx: txID,
201
+ });
202
+ if (!decrytedChanges) {
203
+ console.error("Failed to decrypt transaction despite having key");
204
+ return undefined;
205
+ }
206
+ return {
207
+ txID,
208
+ madeAt: tx.madeAt,
209
+ changes: decrytedChanges,
210
+ };
211
+ }
212
+ }
213
+ })
214
+ .filter((x) => !!x);
215
+ allTransactions.sort((a, b) => a.madeAt - b.madeAt ||
216
+ (a.txID.sessionID < b.txID.sessionID ? -1 : 1) ||
217
+ a.txID.txIndex - b.txID.txIndex);
218
+ return allTransactions;
219
+ }
220
+ getCurrentReadKey() {
221
+ if (this.header.ruleset.type === "group") {
222
+ const content = expectGroupContent(this.getCurrentContent());
223
+ const currentKeyId = content.get("readKey");
224
+ if (!currentKeyId) {
225
+ throw new Error("No readKey set");
226
+ }
227
+ const secret = this.getReadKey(currentKeyId);
228
+ return {
229
+ secret: secret,
230
+ id: currentKeyId,
231
+ };
232
+ }
233
+ else if (this.header.ruleset.type === "ownedByGroup") {
234
+ return this.node
235
+ .expectCoValueLoaded(this.header.ruleset.group)
236
+ .getCurrentReadKey();
237
+ }
238
+ else {
239
+ throw new Error("Only groups or values owned by groups have read secrets");
240
+ }
241
+ }
242
+ getReadKey(keyID) {
243
+ if (readKeyCache.get(this)?.[keyID]) {
244
+ return readKeyCache.get(this)?.[keyID];
245
+ }
246
+ if (this.header.ruleset.type === "group") {
247
+ const content = expectGroupContent(this.getCurrentContent());
248
+ // Try to find key revelation for us
249
+ const readKeyEntry = content.getLastEntry(`${keyID}_for_${this.node.account.id}`);
250
+ if (readKeyEntry) {
251
+ const revealer = accountOrAgentIDfromSessionID(readKeyEntry.txID.sessionID);
252
+ const revealerAgent = this.node.resolveAccountAgent(revealer, "Expected to know revealer");
253
+ const secret = unseal(readKeyEntry.value, this.node.account.currentSealerSecret(), getAgentSealerID(revealerAgent), {
254
+ in: this.id,
255
+ tx: readKeyEntry.txID,
256
+ });
257
+ if (secret) {
258
+ let cache = readKeyCache.get(this);
259
+ if (!cache) {
260
+ cache = {};
261
+ readKeyCache.set(this, cache);
262
+ }
263
+ cache[keyID] = secret;
264
+ return secret;
265
+ }
266
+ }
267
+ // Try to find indirect revelation through previousKeys
268
+ for (const field of content.keys()) {
269
+ if (isKeyForKeyField(field) && field.startsWith(keyID)) {
270
+ const encryptingKeyID = field.split("_for_")[1];
271
+ const encryptingKeySecret = this.getReadKey(encryptingKeyID);
272
+ if (!encryptingKeySecret) {
273
+ continue;
274
+ }
275
+ const encryptedPreviousKey = content.get(field);
276
+ const secret = decryptKeySecret({
277
+ encryptedID: keyID,
278
+ encryptingID: encryptingKeyID,
279
+ encrypted: encryptedPreviousKey,
280
+ }, encryptingKeySecret);
281
+ if (secret) {
282
+ let cache = readKeyCache.get(this);
283
+ if (!cache) {
284
+ cache = {};
285
+ readKeyCache.set(this, cache);
286
+ }
287
+ cache[keyID] = secret;
288
+ return secret;
289
+ }
290
+ else {
291
+ console.error(`Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`);
292
+ }
293
+ }
294
+ }
295
+ return undefined;
296
+ }
297
+ else if (this.header.ruleset.type === "ownedByGroup") {
298
+ return this.node
299
+ .expectCoValueLoaded(this.header.ruleset.group)
300
+ .getReadKey(keyID);
301
+ }
302
+ else {
303
+ throw new Error("Only groups or values owned by groups have read secrets");
304
+ }
305
+ }
306
+ getGroup() {
307
+ if (this.header.ruleset.type !== "ownedByGroup") {
308
+ throw new Error("Only values owned by groups have groups");
309
+ }
310
+ return new Group(expectGroupContent(this.node
311
+ .expectCoValueLoaded(this.header.ruleset.group)
312
+ .getCurrentContent()), this.node);
313
+ }
314
+ getTx(txID) {
315
+ return this.sessions[txID.sessionID]?.transactions[txID.txIndex];
316
+ }
317
+ newContentSince(knownState) {
318
+ const newContent = {
319
+ action: "content",
320
+ id: this.id,
321
+ header: knownState?.header ? undefined : this.header,
322
+ new: Object.fromEntries(Object.entries(this.sessions)
323
+ .map(([sessionID, log]) => {
324
+ const newTransactions = log.transactions.slice(knownState?.sessions[sessionID] || 0);
325
+ if (newTransactions.length === 0 ||
326
+ !log.lastHash ||
327
+ !log.lastSignature) {
328
+ return undefined;
329
+ }
330
+ return [
331
+ sessionID,
332
+ {
333
+ after: knownState?.sessions[sessionID] || 0,
334
+ newTransactions,
335
+ lastSignature: log.lastSignature,
336
+ },
337
+ ];
338
+ })
339
+ .filter((x) => !!x)),
340
+ };
341
+ if (!newContent.header && Object.keys(newContent.new).length === 0) {
342
+ return undefined;
343
+ }
344
+ return newContent;
345
+ }
346
+ getDependedOnCoValues() {
347
+ return this.header.ruleset.type === "group"
348
+ ? expectGroupContent(this.getCurrentContent())
349
+ .keys()
350
+ .filter((k) => k.startsWith("co_"))
351
+ : this.header.ruleset.type === "ownedByGroup"
352
+ ? [this.header.ruleset.group]
353
+ : [];
354
+ }
355
+ }
356
+ //# sourceMappingURL=coValueCore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coValueCore.js","sourceRoot":"","sources":["../src/coValueCore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { JsonObject, JsonValue } from "../jsonValue.js";
2
+ import { CoID, ReadableCoValue, WriteableCoValue } from "../coValue.js";
3
+ import { CoValueCore } from "../coValueCore.js";
4
+ import { SessionID, TransactionID } from "../ids.js";
5
+ import { Group } from "../group.js";
6
+ import { AccountID } from "../account.js";
7
+ type OpID = TransactionID & {
8
+ changeIdx: number;
9
+ };
10
+ type InsertionOpPayload<T extends JsonValue> = {
11
+ op: "pre";
12
+ value: T;
13
+ before: OpID | "end";
14
+ } | {
15
+ op: "app";
16
+ value: T;
17
+ after: OpID | "start";
18
+ };
19
+ type DeletionOpPayload = {
20
+ op: "del";
21
+ insertion: OpID;
22
+ };
23
+ export type ListOpPayload<T extends JsonValue> = InsertionOpPayload<T> | DeletionOpPayload;
24
+ type InsertionEntry<T extends JsonValue> = {
25
+ madeAt: number;
26
+ predecessors: OpID[];
27
+ successors: OpID[];
28
+ } & InsertionOpPayload<T>;
29
+ type DeletionEntry = {
30
+ madeAt: number;
31
+ deletionID: OpID;
32
+ } & DeletionOpPayload;
33
+ export declare class CoList<T extends JsonValue, Meta extends JsonObject | null = null> implements ReadableCoValue {
34
+ id: CoID<CoList<T, Meta>>;
35
+ type: "colist";
36
+ core: CoValueCore;
37
+ /** @internal */
38
+ afterStart: OpID[];
39
+ /** @internal */
40
+ beforeEnd: OpID[];
41
+ /** @internal */
42
+ insertions: {
43
+ [sessionID: SessionID]: {
44
+ [txIdx: number]: {
45
+ [changeIdx: number]: InsertionEntry<T>;
46
+ };
47
+ };
48
+ };
49
+ /** @internal */
50
+ deletionsByInsertion: {
51
+ [deletedSessionID: SessionID]: {
52
+ [deletedTxIdx: number]: {
53
+ [deletedChangeIdx: number]: DeletionEntry[];
54
+ };
55
+ };
56
+ };
57
+ /** @internal */
58
+ constructor(core: CoValueCore);
59
+ get meta(): Meta;
60
+ get group(): Group;
61
+ /** @internal */
62
+ protected fillOpsFromCoValue(): void;
63
+ /** Get the item currently at `idx`. */
64
+ get(idx: number): T | undefined;
65
+ /** Returns the current items in the CoList as an array. */
66
+ asArray(): T[];
67
+ entries(): {
68
+ value: T;
69
+ madeAt: number;
70
+ opID: OpID;
71
+ }[];
72
+ /** @internal */
73
+ private fillArrayFromOpID;
74
+ /** Returns the accountID of the account that inserted value at the given index. */
75
+ whoInserted(idx: number): AccountID | undefined;
76
+ /** Returns the current items in the CoList as an array. (alias of `asArray`) */
77
+ toJSON(): T[];
78
+ map<U>(mapper: (value: T, idx: number) => U): U[];
79
+ filter<U extends T>(predicate: (value: T, idx: number) => value is U): U[];
80
+ reduce<U>(reducer: (accumulator: U, value: T, idx: number) => U, initialValue: U): U;
81
+ subscribe(listener: (coMap: CoList<T, Meta>) => void): () => void;
82
+ edit(changer: (editable: WriteableCoList<T, Meta>) => void): CoList<T, Meta>;
83
+ }
84
+ export declare class WriteableCoList<T extends JsonValue, Meta extends JsonObject | null = null> extends CoList<T, Meta> implements WriteableCoValue {
85
+ /** @internal */
86
+ edit(_changer: (editable: WriteableCoList<T, Meta>) => void): CoList<T, Meta>;
87
+ /** Appends a new item after index `after`.
88
+ *
89
+ * 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.
90
+ *
91
+ * 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. */
92
+ append(after: number, value: T, privacy?: "private" | "trusting"): void;
93
+ /** Pushes a new item to the end of the list.
94
+ *
95
+ * 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.
96
+ *
97
+ * 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. */
98
+ push(value: T, privacy?: "private" | "trusting"): void;
99
+ /**
100
+ * Prepends a new item before index `before`.
101
+ *
102
+ * 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.
103
+ *
104
+ * 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.
105
+ */
106
+ prepend(before: number, value: T, privacy?: "private" | "trusting"): void;
107
+ /** Deletes the item at index `at` from the list.
108
+ *
109
+ * 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.
110
+ *
111
+ * 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. */
112
+ delete(at: number, privacy?: "private" | "trusting"): void;
113
+ }
114
+ export {};
@@ -1,10 +1,11 @@
1
- import { accountOrAgentIDfromSessionID } from "../coValue.js";
1
+ import { accountOrAgentIDfromSessionID } from "../coValueCore.js";
2
2
  import { isAccountID } from "../account.js";
3
3
  export class CoList {
4
- constructor(coValue) {
4
+ /** @internal */
5
+ constructor(core) {
5
6
  this.type = "colist";
6
- this.id = coValue.id;
7
- this.coValue = coValue;
7
+ this.id = core.id;
8
+ this.core = core;
8
9
  this.afterStart = [];
9
10
  this.beforeEnd = [];
10
11
  this.insertions = {};
@@ -12,17 +13,18 @@ export class CoList {
12
13
  this.fillOpsFromCoValue();
13
14
  }
14
15
  get meta() {
15
- return this.coValue.header.meta;
16
+ return this.core.header.meta;
16
17
  }
17
18
  get group() {
18
- return this.coValue.getGroup();
19
+ return this.core.getGroup();
19
20
  }
21
+ /** @internal */
20
22
  fillOpsFromCoValue() {
21
23
  this.insertions = {};
22
24
  this.deletionsByInsertion = {};
23
25
  this.afterStart = [];
24
26
  this.beforeEnd = [];
25
- for (const { txID, changes, madeAt, } of this.coValue.getValidSortedTransactions()) {
27
+ for (const { txID, changes, madeAt, } of this.core.getValidSortedTransactions()) {
26
28
  for (const [changeIdx, changeUntyped] of changes.entries()) {
27
29
  const change = changeUntyped;
28
30
  if (change.op === "pre" || change.op === "app") {
@@ -114,6 +116,18 @@ export class CoList {
114
116
  }
115
117
  }
116
118
  }
119
+ /** Get the item currently at `idx`. */
120
+ get(idx) {
121
+ const entry = this.entries()[idx];
122
+ if (!entry) {
123
+ return undefined;
124
+ }
125
+ return entry.value;
126
+ }
127
+ /** Returns the current items in the CoList as an array. */
128
+ asArray() {
129
+ return this.entries().map((entry) => entry.value);
130
+ }
117
131
  entries() {
118
132
  const arr = [];
119
133
  for (const opID of this.afterStart) {
@@ -124,6 +138,7 @@ export class CoList {
124
138
  }
125
139
  return arr;
126
140
  }
141
+ /** @internal */
127
142
  fillArrayFromOpID(opID, arr) {
128
143
  const entry = this.insertions[opID.sessionID]?.[opID.txIndex]?.[opID.changeIdx];
129
144
  if (!entry) {
@@ -144,6 +159,7 @@ export class CoList {
144
159
  this.fillArrayFromOpID(successor, arr);
145
160
  }
146
161
  }
162
+ /** Returns the accountID of the account that inserted value at the given index. */
147
163
  whoInserted(idx) {
148
164
  const entry = this.entries()[idx];
149
165
  if (!entry) {
@@ -157,12 +173,10 @@ export class CoList {
157
173
  return undefined;
158
174
  }
159
175
  }
176
+ /** Returns the current items in the CoList as an array. (alias of `asArray`) */
160
177
  toJSON() {
161
178
  return this.asArray();
162
179
  }
163
- asArray() {
164
- return this.entries().map((entry) => entry.value);
165
- }
166
180
  map(mapper) {
167
181
  return this.entries().map((entry, idx) => mapper(entry.value, idx));
168
182
  }
@@ -174,18 +188,27 @@ export class CoList {
174
188
  reduce(reducer, initialValue) {
175
189
  return this.entries().reduce((accumulator, entry, idx) => reducer(accumulator, entry.value, idx), initialValue);
176
190
  }
177
- edit(changer) {
178
- const editable = new WriteableCoList(this.coValue);
179
- changer(editable);
180
- return new CoList(this.coValue);
181
- }
182
191
  subscribe(listener) {
183
- return this.coValue.subscribe((content) => {
192
+ return this.core.subscribe((content) => {
184
193
  listener(content);
185
194
  });
186
195
  }
196
+ edit(changer) {
197
+ const editable = new WriteableCoList(this.core);
198
+ changer(editable);
199
+ return new CoList(this.core);
200
+ }
187
201
  }
188
202
  export class WriteableCoList extends CoList {
203
+ /** @internal */
204
+ edit(_changer) {
205
+ throw new Error("Already editing.");
206
+ }
207
+ /** Appends a new item after index `after`.
208
+ *
209
+ * 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.
210
+ *
211
+ * 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. */
189
212
  append(after, value, privacy = "private") {
190
213
  const entries = this.entries();
191
214
  let opIDBefore;
@@ -202,7 +225,7 @@ export class WriteableCoList extends CoList {
202
225
  }
203
226
  opIDBefore = "start";
204
227
  }
205
- this.coValue.makeTransaction([
228
+ this.core.makeTransaction([
206
229
  {
207
230
  op: "app",
208
231
  value,
@@ -211,11 +234,23 @@ export class WriteableCoList extends CoList {
211
234
  ], privacy);
212
235
  this.fillOpsFromCoValue();
213
236
  }
237
+ /** Pushes a new item to the end of the list.
238
+ *
239
+ * 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.
240
+ *
241
+ * 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. */
214
242
  push(value, privacy = "private") {
215
243
  // TODO: optimize
216
244
  const entries = this.entries();
217
245
  this.append(entries.length > 0 ? entries.length - 1 : 0, value, privacy);
218
246
  }
247
+ /**
248
+ * Prepends a new item before index `before`.
249
+ *
250
+ * 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.
251
+ *
252
+ * 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.
253
+ */
219
254
  prepend(before, value, privacy = "private") {
220
255
  const entries = this.entries();
221
256
  let opIDAfter;
@@ -237,7 +272,7 @@ export class WriteableCoList extends CoList {
237
272
  }
238
273
  opIDAfter = "end";
239
274
  }
240
- this.coValue.makeTransaction([
275
+ this.core.makeTransaction([
241
276
  {
242
277
  op: "pre",
243
278
  value,
@@ -246,13 +281,18 @@ export class WriteableCoList extends CoList {
246
281
  ], privacy);
247
282
  this.fillOpsFromCoValue();
248
283
  }
284
+ /** Deletes the item at index `at` from the list.
285
+ *
286
+ * 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.
287
+ *
288
+ * 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. */
249
289
  delete(at, privacy = "private") {
250
290
  const entries = this.entries();
251
291
  const entry = entries[at];
252
292
  if (!entry) {
253
293
  throw new Error("Invalid index " + at);
254
294
  }
255
- this.coValue.makeTransaction([
295
+ this.core.makeTransaction([
256
296
  {
257
297
  op: "del",
258
298
  insertion: entry.opID,