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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/coValues/coList.d.ts +10 -4
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +30 -4
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +2 -1
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +5 -2
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/storage/sqlite/client.d.ts +3 -3
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js +1 -1
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +3 -3
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +1 -1
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +7 -7
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +7 -7
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +18 -14
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/tests/coList.test.js +28 -1
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/sync.multipleServers.test.d.ts +2 -0
- package/dist/tests/sync.multipleServers.test.d.ts.map +1 -0
- package/dist/tests/sync.multipleServers.test.js +399 -0
- package/dist/tests/sync.multipleServers.test.js.map +1 -0
- package/package.json +3 -3
- package/src/coValues/coList.ts +41 -8
- package/src/coValues/coPlainText.ts +6 -2
- package/src/storage/sqlite/client.ts +6 -3
- package/src/storage/sqliteAsync/client.ts +8 -3
- package/src/storage/storageAsync.ts +8 -5
- package/src/storage/storageSync.ts +8 -5
- package/src/storage/types.ts +43 -37
- package/src/tests/coList.test.ts +36 -3
- 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
|
|
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
|
|
369
|
+
const sessionRowID: number = await tx.addSessionUpdate({
|
|
367
370
|
sessionUpdate,
|
|
368
371
|
sessionRow,
|
|
369
372
|
});
|
|
370
373
|
|
|
371
374
|
if (shouldWriteSignature) {
|
|
372
|
-
await
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
344
|
+
const sessionRowID: number = tx.addSessionUpdate({
|
|
342
345
|
sessionUpdate,
|
|
343
346
|
sessionRow,
|
|
344
347
|
});
|
|
345
348
|
|
|
346
349
|
if (shouldWriteSignature) {
|
|
347
|
-
|
|
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
|
-
|
|
358
|
+
tx.addTransaction(sessionRowID, nextIdx + i, newTransaction),
|
|
356
359
|
);
|
|
357
360
|
|
|
358
361
|
return newLastIdx;
|
package/src/storage/types.ts
CHANGED
|
@@ -61,34 +61,12 @@ export type SignatureAfterRow = {
|
|
|
61
61
|
signature: Signature;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
export interface
|
|
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
|
|
120
|
-
getCoValue(
|
|
121
|
-
|
|
122
|
-
|
|
95
|
+
export interface DBClientInterfaceAsync {
|
|
96
|
+
getCoValue(
|
|
97
|
+
coValueId: string,
|
|
98
|
+
): Promise<StoredCoValueRow | undefined> | undefined;
|
|
123
99
|
|
|
124
|
-
|
|
100
|
+
upsertCoValue(
|
|
101
|
+
id: string,
|
|
102
|
+
header?: CoValueHeader,
|
|
103
|
+
): Promise<number | undefined>;
|
|
125
104
|
|
|
126
|
-
|
|
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
|
-
):
|
|
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
|
}
|
package/src/tests/coList.test.ts
CHANGED
|
@@ -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({
|