cojson 0.19.2 → 0.19.4

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 (42) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/dist/coValues/coList.d.ts +10 -4
  4. package/dist/coValues/coList.d.ts.map +1 -1
  5. package/dist/coValues/coList.js +30 -4
  6. package/dist/coValues/coList.js.map +1 -1
  7. package/dist/coValues/coPlainText.d.ts +2 -1
  8. package/dist/coValues/coPlainText.d.ts.map +1 -1
  9. package/dist/coValues/coPlainText.js +5 -2
  10. package/dist/coValues/coPlainText.js.map +1 -1
  11. package/dist/storage/sqlite/client.d.ts +3 -3
  12. package/dist/storage/sqlite/client.d.ts.map +1 -1
  13. package/dist/storage/sqlite/client.js +1 -1
  14. package/dist/storage/sqlite/client.js.map +1 -1
  15. package/dist/storage/sqliteAsync/client.d.ts +3 -3
  16. package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
  17. package/dist/storage/sqliteAsync/client.js +1 -1
  18. package/dist/storage/sqliteAsync/client.js.map +1 -1
  19. package/dist/storage/storageAsync.d.ts.map +1 -1
  20. package/dist/storage/storageAsync.js +7 -7
  21. package/dist/storage/storageAsync.js.map +1 -1
  22. package/dist/storage/storageSync.d.ts.map +1 -1
  23. package/dist/storage/storageSync.js +7 -7
  24. package/dist/storage/storageSync.js.map +1 -1
  25. package/dist/storage/types.d.ts +18 -14
  26. package/dist/storage/types.d.ts.map +1 -1
  27. package/dist/tests/coList.test.js +28 -1
  28. package/dist/tests/coList.test.js.map +1 -1
  29. package/dist/tests/sync.multipleServers.test.d.ts +2 -0
  30. package/dist/tests/sync.multipleServers.test.d.ts.map +1 -0
  31. package/dist/tests/sync.multipleServers.test.js +399 -0
  32. package/dist/tests/sync.multipleServers.test.js.map +1 -0
  33. package/package.json +3 -3
  34. package/src/coValues/coList.ts +41 -8
  35. package/src/coValues/coPlainText.ts +6 -2
  36. package/src/storage/sqlite/client.ts +6 -3
  37. package/src/storage/sqliteAsync/client.ts +8 -3
  38. package/src/storage/storageAsync.ts +8 -5
  39. package/src/storage/storageSync.ts +8 -5
  40. package/src/storage/types.ts +43 -37
  41. package/src/tests/coList.test.ts +36 -3
  42. package/src/tests/sync.multipleServers.test.ts +491 -0
@@ -25,6 +25,7 @@ import {
25
25
  import type {
26
26
  CorrectionCallback,
27
27
  DBClientInterfaceAsync,
28
+ DBTransactionInterfaceAsync,
28
29
  SignatureAfterRow,
29
30
  StoredCoValueRow,
30
31
  StoredSessionRow,
@@ -280,8 +281,8 @@ export class StorageApiAsync implements StorageAPI {
280
281
  let invalidAssumptions = false;
281
282
 
282
283
  for (const sessionID of Object.keys(msg.new) as SessionID[]) {
283
- await this.dbClient.transaction(async () => {
284
- const sessionRow = await this.dbClient.getSingleCoValueSession(
284
+ await this.dbClient.transaction(async (tx) => {
285
+ const sessionRow = await tx.getSingleCoValueSession(
285
286
  storedCoValueRowID,
286
287
  sessionID,
287
288
  );
@@ -301,6 +302,7 @@ export class StorageApiAsync implements StorageAPI {
301
302
  invalidAssumptions = true;
302
303
  } else {
303
304
  const newLastIdx = await this.putNewTxs(
305
+ tx,
304
306
  msg,
305
307
  sessionID,
306
308
  sessionRow,
@@ -321,6 +323,7 @@ export class StorageApiAsync implements StorageAPI {
321
323
  }
322
324
 
323
325
  private async putNewTxs(
326
+ tx: DBTransactionInterfaceAsync,
324
327
  msg: NewContentMessage,
325
328
  sessionID: SessionID,
326
329
  sessionRow: StoredSessionRow | undefined,
@@ -363,13 +366,13 @@ export class StorageApiAsync implements StorageAPI {
363
366
  bytesSinceLastSignature,
364
367
  };
365
368
 
366
- const sessionRowID: number = await this.dbClient.addSessionUpdate({
369
+ const sessionRowID: number = await tx.addSessionUpdate({
367
370
  sessionUpdate,
368
371
  sessionRow,
369
372
  });
370
373
 
371
374
  if (shouldWriteSignature) {
372
- await this.dbClient.addSignatureAfter({
375
+ await tx.addSignatureAfter({
373
376
  sessionRowID,
374
377
  idx: newLastIdx - 1,
375
378
  signature: msg.new[sessionID].lastSignature,
@@ -378,7 +381,7 @@ export class StorageApiAsync implements StorageAPI {
378
381
 
379
382
  await Promise.all(
380
383
  actuallyNewTransactions.map((newTransaction, i) =>
381
- this.dbClient.addTransaction(sessionRowID, nextIdx + i, newTransaction),
384
+ tx.addTransaction(sessionRowID, nextIdx + i, newTransaction),
382
385
  ),
383
386
  );
384
387
 
@@ -25,6 +25,7 @@ import {
25
25
  import type {
26
26
  CorrectionCallback,
27
27
  DBClientInterfaceSync,
28
+ DBTransactionInterfaceSync,
28
29
  SignatureAfterRow,
29
30
  StoredCoValueRow,
30
31
  StoredSessionRow,
@@ -257,8 +258,8 @@ export class StorageApiSync implements StorageAPI {
257
258
  let invalidAssumptions = false;
258
259
 
259
260
  for (const sessionID of Object.keys(msg.new) as SessionID[]) {
260
- this.dbClient.transaction(() => {
261
- const sessionRow = this.dbClient.getSingleCoValueSession(
261
+ this.dbClient.transaction((tx) => {
262
+ const sessionRow = tx.getSingleCoValueSession(
262
263
  storedCoValueRowID,
263
264
  sessionID,
264
265
  );
@@ -275,6 +276,7 @@ export class StorageApiSync implements StorageAPI {
275
276
  invalidAssumptions = true;
276
277
  } else {
277
278
  const newLastIdx = this.putNewTxs(
279
+ tx,
278
280
  msg,
279
281
  sessionID,
280
282
  sessionRow,
@@ -295,6 +297,7 @@ export class StorageApiSync implements StorageAPI {
295
297
  }
296
298
 
297
299
  private putNewTxs(
300
+ tx: DBTransactionInterfaceSync,
298
301
  msg: NewContentMessage,
299
302
  sessionID: SessionID,
300
303
  sessionRow: StoredSessionRow | undefined,
@@ -338,13 +341,13 @@ export class StorageApiSync implements StorageAPI {
338
341
  bytesSinceLastSignature,
339
342
  };
340
343
 
341
- const sessionRowID: number = this.dbClient.addSessionUpdate({
344
+ const sessionRowID: number = tx.addSessionUpdate({
342
345
  sessionUpdate,
343
346
  sessionRow,
344
347
  });
345
348
 
346
349
  if (shouldWriteSignature) {
347
- this.dbClient.addSignatureAfter({
350
+ tx.addSignatureAfter({
348
351
  sessionRowID,
349
352
  idx: newLastIdx - 1,
350
353
  signature: msg.new[sessionID].lastSignature,
@@ -352,7 +355,7 @@ export class StorageApiSync implements StorageAPI {
352
355
  }
353
356
 
354
357
  actuallyNewTransactions.map((newTransaction, i) =>
355
- this.dbClient.addTransaction(sessionRowID, nextIdx + i, newTransaction),
358
+ tx.addTransaction(sessionRowID, nextIdx + i, newTransaction),
356
359
  );
357
360
 
358
361
  return newLastIdx;
@@ -61,34 +61,12 @@ export type SignatureAfterRow = {
61
61
  signature: Signature;
62
62
  };
63
63
 
64
- export interface DBClientInterfaceAsync {
65
- getCoValue(
66
- coValueId: string,
67
- ): Promise<StoredCoValueRow | undefined> | undefined;
68
-
69
- upsertCoValue(
70
- id: string,
71
- header?: CoValueHeader,
72
- ): Promise<number | undefined>;
73
-
74
- getCoValueSessions(coValueRowId: number): Promise<StoredSessionRow[]>;
75
-
64
+ export interface DBTransactionInterfaceAsync {
76
65
  getSingleCoValueSession(
77
66
  coValueRowId: number,
78
67
  sessionID: SessionID,
79
68
  ): Promise<StoredSessionRow | undefined>;
80
69
 
81
- getNewTransactionInSession(
82
- sessionRowId: number,
83
- fromIdx: number,
84
- toIdx: number,
85
- ): Promise<TransactionRow[]>;
86
-
87
- getSignatures(
88
- sessionRowId: number,
89
- firstNewTxIdx: number,
90
- ): Promise<SignatureAfterRow[]>;
91
-
92
70
  addSessionUpdate({
93
71
  sessionUpdate,
94
72
  sessionRow,
@@ -112,32 +90,41 @@ export interface DBClientInterfaceAsync {
112
90
  idx: number;
113
91
  signature: Signature;
114
92
  }): Promise<unknown>;
115
-
116
- transaction(callback: () => unknown): Promise<unknown>;
117
93
  }
118
94
 
119
- export interface DBClientInterfaceSync {
120
- getCoValue(coValueId: string): StoredCoValueRow | undefined;
121
-
122
- upsertCoValue(id: string, header?: CoValueHeader): number | undefined;
95
+ export interface DBClientInterfaceAsync {
96
+ getCoValue(
97
+ coValueId: string,
98
+ ): Promise<StoredCoValueRow | undefined> | undefined;
123
99
 
124
- getCoValueSessions(coValueRowId: number): StoredSessionRow[];
100
+ upsertCoValue(
101
+ id: string,
102
+ header?: CoValueHeader,
103
+ ): Promise<number | undefined>;
125
104
 
126
- getSingleCoValueSession(
127
- coValueRowId: number,
128
- sessionID: SessionID,
129
- ): StoredSessionRow | undefined;
105
+ getCoValueSessions(coValueRowId: number): Promise<StoredSessionRow[]>;
130
106
 
131
107
  getNewTransactionInSession(
132
108
  sessionRowId: number,
133
109
  fromIdx: number,
134
110
  toIdx: number,
135
- ): TransactionRow[];
111
+ ): Promise<TransactionRow[]>;
136
112
 
137
113
  getSignatures(
138
114
  sessionRowId: number,
139
115
  firstNewTxIdx: number,
140
- ): Pick<SignatureAfterRow, "idx" | "signature">[];
116
+ ): Promise<SignatureAfterRow[]>;
117
+
118
+ transaction(
119
+ callback: (tx: DBTransactionInterfaceAsync) => Promise<unknown>,
120
+ ): Promise<unknown>;
121
+ }
122
+
123
+ export interface DBTransactionInterfaceSync {
124
+ getSingleCoValueSession(
125
+ coValueRowId: number,
126
+ sessionID: SessionID,
127
+ ): StoredSessionRow | undefined;
141
128
 
142
129
  addSessionUpdate({
143
130
  sessionUpdate,
@@ -162,6 +149,25 @@ export interface DBClientInterfaceSync {
162
149
  idx: number;
163
150
  signature: Signature;
164
151
  }): number | undefined | unknown;
152
+ }
153
+
154
+ export interface DBClientInterfaceSync {
155
+ getCoValue(coValueId: string): StoredCoValueRow | undefined;
156
+
157
+ upsertCoValue(id: string, header?: CoValueHeader): number | undefined;
158
+
159
+ getCoValueSessions(coValueRowId: number): StoredSessionRow[];
160
+
161
+ getNewTransactionInSession(
162
+ sessionRowId: number,
163
+ fromIdx: number,
164
+ toIdx: number,
165
+ ): TransactionRow[];
166
+
167
+ getSignatures(
168
+ sessionRowId: number,
169
+ firstNewTxIdx: number,
170
+ ): Pick<SignatureAfterRow, "idx" | "signature">[];
165
171
 
166
- transaction(callback: () => unknown): unknown;
172
+ transaction(callback: (tx: DBTransactionInterfaceSync) => unknown): unknown;
167
173
  }
@@ -1,12 +1,10 @@
1
1
  import { beforeEach, describe, expect, test } from "vitest";
2
2
  import { expectList } from "../coValue.js";
3
3
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
4
- import { LocalNode } from "../localNode.js";
5
- import { expectGroup } from "../typeUtils/expectGroup.js";
6
4
  import {
5
+ hotSleep,
7
6
  loadCoValueOrFail,
8
7
  nodeWithRandomAgentAndSessionID,
9
- randomAgentAndSessionID,
10
8
  setupTestNode,
11
9
  waitFor,
12
10
  } from "./testUtils.js";
@@ -429,6 +427,41 @@ test("Should ignore unknown meta transactions", () => {
429
427
  expect(content.toJSON()).toEqual(["first"]);
430
428
  });
431
429
 
430
+ describe("CoList Time Travel", () => {
431
+ test("atTime should return a time travel entity", () => {
432
+ const node = nodeWithRandomAgentAndSessionID();
433
+ const coValue = node.createCoValue({
434
+ type: "colist",
435
+ ruleset: { type: "unsafeAllowAll" },
436
+ meta: null,
437
+ ...Crypto.createdNowUnique(),
438
+ });
439
+
440
+ const content = expectList(coValue.getCurrentContent());
441
+
442
+ const beforeA = hotSleep(10);
443
+ content.append("first", 0, "trusting");
444
+
445
+ const beforeB = hotSleep(10);
446
+ content.append("second", 0, "trusting");
447
+
448
+ const beforeC = hotSleep(10);
449
+ content.delete(0, "trusting");
450
+
451
+ const beforeD = hotSleep(10);
452
+ content.prepend("third", 0, "trusting");
453
+
454
+ expect(content.toJSON()).toEqual(["third", "second"]);
455
+
456
+ expect(content.atTime(0).toJSON()).toEqual([]);
457
+ expect(content.atTime(beforeA).toJSON()).toEqual([]);
458
+ expect(content.atTime(beforeB).toJSON()).toEqual(["first"]);
459
+ expect(content.atTime(beforeC).toJSON()).toEqual(["first", "second"]);
460
+ expect(content.atTime(beforeD).toJSON()).toEqual(["second"]);
461
+ expect(content.atTime(Date.now()).toJSON()).toEqual(["third", "second"]);
462
+ });
463
+ });
464
+
432
465
  describe("CoList Branching", () => {
433
466
  test("should handle concurrent appends from multiple branches", async () => {
434
467
  const client1 = setupTestNode({