cojson 0.19.21 → 0.20.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +67 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.d.ts +42 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.js +261 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.js.map +1 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.d.ts +18 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.js +37 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.js.map +1 -0
- package/dist/CojsonMessageChannel/index.d.ts +3 -0
- package/dist/CojsonMessageChannel/index.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/index.js +2 -0
- package/dist/CojsonMessageChannel/index.js.map +1 -0
- package/dist/CojsonMessageChannel/types.d.ts +149 -0
- package/dist/CojsonMessageChannel/types.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/types.js +36 -0
- package/dist/CojsonMessageChannel/types.js.map +1 -0
- package/dist/GarbageCollector.d.ts +4 -2
- package/dist/GarbageCollector.d.ts.map +1 -1
- package/dist/GarbageCollector.js +5 -3
- package/dist/GarbageCollector.js.map +1 -1
- package/dist/SyncStateManager.d.ts +3 -3
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +4 -4
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueContentMessage.d.ts +0 -2
- package/dist/coValueContentMessage.d.ts.map +1 -1
- package/dist/coValueContentMessage.js +0 -8
- package/dist/coValueContentMessage.js.map +1 -1
- package/dist/coValueCore/SessionMap.d.ts +4 -2
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js +30 -0
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +86 -4
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +318 -17
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +6 -1
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +9 -0
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/coList.d.ts +3 -2
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +3 -6
- package/dist/coValues/group.js.map +1 -1
- package/dist/config.d.ts +0 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/crypto/NapiCrypto.d.ts +1 -2
- package/dist/crypto/NapiCrypto.d.ts.map +1 -1
- package/dist/crypto/NapiCrypto.js +19 -4
- package/dist/crypto/NapiCrypto.js.map +1 -1
- package/dist/crypto/RNCrypto.d.ts.map +1 -1
- package/dist/crypto/RNCrypto.js +19 -4
- package/dist/crypto/RNCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.d.ts +11 -4
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js +52 -10
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/WasmCryptoEdge.d.ts +1 -0
- package/dist/crypto/WasmCryptoEdge.d.ts.map +1 -1
- package/dist/crypto/WasmCryptoEdge.js +4 -1
- package/dist/crypto/WasmCryptoEdge.js.map +1 -1
- package/dist/crypto/crypto.d.ts +3 -3
- package/dist/crypto/crypto.d.ts.map +1 -1
- package/dist/crypto/crypto.js +6 -1
- package/dist/crypto/crypto.js.map +1 -1
- package/dist/exports.d.ts +3 -2
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +3 -1
- package/dist/exports.js.map +1 -1
- package/dist/ids.d.ts +4 -1
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +4 -0
- package/dist/ids.js.map +1 -1
- package/dist/knownState.d.ts +2 -0
- package/dist/knownState.d.ts.map +1 -1
- package/dist/localNode.d.ts +13 -3
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +17 -2
- package/dist/localNode.js.map +1 -1
- package/dist/platformUtils.d.ts +3 -0
- package/dist/platformUtils.d.ts.map +1 -0
- package/dist/platformUtils.js +24 -0
- package/dist/platformUtils.js.map +1 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.d.ts +30 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.d.ts.map +1 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.js +84 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.js.map +1 -0
- package/dist/storage/sqlite/client.d.ts +3 -0
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js +44 -0
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.js +7 -0
- package/dist/storage/sqlite/sqliteMigrations.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +3 -0
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +42 -0
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +15 -3
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +60 -3
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +14 -3
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +54 -3
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +64 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +12 -1
- package/dist/storage/types.js.map +1 -1
- package/dist/sync.d.ts +6 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +69 -15
- package/dist/sync.js.map +1 -1
- package/dist/tests/CojsonMessageChannel.test.d.ts +2 -0
- package/dist/tests/CojsonMessageChannel.test.d.ts.map +1 -0
- package/dist/tests/CojsonMessageChannel.test.js +236 -0
- package/dist/tests/CojsonMessageChannel.test.js.map +1 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts +2 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts.map +1 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.js +149 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.js.map +1 -0
- package/dist/tests/GarbageCollector.test.js +91 -18
- package/dist/tests/GarbageCollector.test.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.js +510 -146
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/StorageApiSync.test.js +531 -130
- package/dist/tests/StorageApiSync.test.js.map +1 -1
- package/dist/tests/SyncManager.processQueues.test.js +1 -1
- package/dist/tests/SyncManager.processQueues.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +1 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/WasmCrypto.test.js +6 -3
- package/dist/tests/WasmCrypto.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +1 -1
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coValueCore.loadFromStorage.test.js +4 -0
- package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +34 -13
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coreWasm.test.js +127 -4
- package/dist/tests/coreWasm.test.js.map +1 -1
- package/dist/tests/crypto.test.js +89 -93
- package/dist/tests/crypto.test.js.map +1 -1
- package/dist/tests/deleteCoValue.test.d.ts +2 -0
- package/dist/tests/deleteCoValue.test.d.ts.map +1 -0
- package/dist/tests/deleteCoValue.test.js +313 -0
- package/dist/tests/deleteCoValue.test.js.map +1 -0
- package/dist/tests/group.removeMember.test.js +18 -30
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/knownState.lazyLoading.test.js +4 -0
- package/dist/tests/knownState.lazyLoading.test.js.map +1 -1
- package/dist/tests/sync.deleted.test.d.ts +2 -0
- package/dist/tests/sync.deleted.test.d.ts.map +1 -0
- package/dist/tests/sync.deleted.test.js +214 -0
- package/dist/tests/sync.deleted.test.js.map +1 -0
- package/dist/tests/sync.garbageCollection.test.js +56 -32
- package/dist/tests/sync.garbageCollection.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +3 -5
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +4 -3
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +3 -3
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +12 -11
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +7 -7
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.test.js +3 -2
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.tracking.test.js +35 -4
- package/dist/tests/sync.tracking.test.js.map +1 -1
- package/dist/tests/testStorage.d.ts +3 -0
- package/dist/tests/testStorage.d.ts.map +1 -1
- package/dist/tests/testStorage.js +16 -2
- package/dist/tests/testStorage.js.map +1 -1
- package/dist/tests/testUtils.d.ts +29 -4
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +84 -9
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +6 -16
- package/src/CojsonMessageChannel/CojsonMessageChannel.ts +332 -0
- package/src/CojsonMessageChannel/MessagePortOutgoingChannel.ts +52 -0
- package/src/CojsonMessageChannel/index.ts +9 -0
- package/src/CojsonMessageChannel/types.ts +200 -0
- package/src/GarbageCollector.ts +5 -5
- package/src/SyncStateManager.ts +6 -6
- package/src/coValueContentMessage.ts +0 -14
- package/src/coValueCore/SessionMap.ts +43 -1
- package/src/coValueCore/coValueCore.ts +430 -15
- package/src/coValueCore/verifiedState.ts +26 -3
- package/src/coValues/coList.ts +5 -3
- package/src/coValues/group.ts +5 -6
- package/src/config.ts +0 -9
- package/src/crypto/NapiCrypto.ts +29 -13
- package/src/crypto/RNCrypto.ts +29 -11
- package/src/crypto/WasmCrypto.ts +67 -20
- package/src/crypto/WasmCryptoEdge.ts +5 -1
- package/src/crypto/crypto.ts +16 -4
- package/src/exports.ts +3 -0
- package/src/ids.ts +11 -1
- package/src/localNode.ts +18 -5
- package/src/platformUtils.ts +26 -0
- package/src/storage/DeletedCoValuesEraserScheduler.ts +124 -0
- package/src/storage/sqlite/client.ts +77 -0
- package/src/storage/sqlite/sqliteMigrations.ts +7 -0
- package/src/storage/sqliteAsync/client.ts +75 -0
- package/src/storage/storageAsync.ts +77 -4
- package/src/storage/storageSync.ts +73 -4
- package/src/storage/types.ts +75 -0
- package/src/sync.ts +84 -15
- package/src/tests/CojsonMessageChannel.test.ts +306 -0
- package/src/tests/DeletedCoValuesEraserScheduler.test.ts +185 -0
- package/src/tests/GarbageCollector.test.ts +119 -22
- package/src/tests/StorageApiAsync.test.ts +615 -156
- package/src/tests/StorageApiSync.test.ts +623 -137
- package/src/tests/SyncManager.processQueues.test.ts +1 -1
- package/src/tests/SyncStateManager.test.ts +1 -1
- package/src/tests/WasmCrypto.test.ts +8 -3
- package/src/tests/coPlainText.test.ts +1 -1
- package/src/tests/coValueCore.loadFromStorage.test.ts +8 -0
- package/src/tests/coValueCore.test.ts +49 -14
- package/src/tests/coreWasm.test.ts +319 -10
- package/src/tests/crypto.test.ts +141 -150
- package/src/tests/deleteCoValue.test.ts +528 -0
- package/src/tests/group.removeMember.test.ts +35 -35
- package/src/tests/knownState.lazyLoading.test.ts +8 -0
- package/src/tests/sync.deleted.test.ts +294 -0
- package/src/tests/sync.garbageCollection.test.ts +69 -36
- package/src/tests/sync.load.test.ts +3 -5
- package/src/tests/sync.mesh.test.ts +6 -3
- package/src/tests/sync.peerReconciliation.test.ts +3 -3
- package/src/tests/sync.storage.test.ts +14 -11
- package/src/tests/sync.storageAsync.test.ts +7 -7
- package/src/tests/sync.test.ts +5 -2
- package/src/tests/sync.tracking.test.ts +54 -4
- package/src/tests/testStorage.ts +30 -3
- package/src/tests/testUtils.ts +113 -15
- package/dist/crypto/PureJSCrypto.d.ts +0 -77
- package/dist/crypto/PureJSCrypto.d.ts.map +0 -1
- package/dist/crypto/PureJSCrypto.js +0 -236
- package/dist/crypto/PureJSCrypto.js.map +0 -1
- package/dist/tests/PureJSCrypto.test.d.ts +0 -2
- package/dist/tests/PureJSCrypto.test.d.ts.map +0 -1
- package/dist/tests/PureJSCrypto.test.js +0 -145
- package/dist/tests/PureJSCrypto.test.js.map +0 -1
- package/src/crypto/PureJSCrypto.ts +0 -429
- package/src/tests/PureJSCrypto.test.ts +0 -217
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { describe, expect, onTestFinished, test, vi } from "vitest";
|
|
6
|
-
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
7
|
-
import { CoID, LocalNode, RawCoID, RawCoMap, logger } from "../exports.js";
|
|
1
|
+
import { describe, expect, test, vi, afterEach } from "vitest";
|
|
2
|
+
import { CoID, RawCoID, RawCoMap, logger } from "../exports.js";
|
|
8
3
|
import { CoValueCore } from "../exports.js";
|
|
9
4
|
import { NewContentMessage } from "../sync.js";
|
|
10
5
|
import { CoValueKnownState, emptyKnownState } from "../knownState.js";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
import {
|
|
7
|
+
createSyncStorage,
|
|
8
|
+
getAllCoValuesWaitingForDelete,
|
|
9
|
+
getCoValueStoredSessions,
|
|
10
|
+
getDbPath,
|
|
11
|
+
} from "./testStorage.js";
|
|
12
|
+
import {
|
|
13
|
+
fillCoMapWithLargeData,
|
|
14
|
+
loadCoValueOrFail,
|
|
15
|
+
setupTestNode,
|
|
16
|
+
} from "./testUtils.js";
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Helper function that gets new content since a known state, throwing if:
|
|
@@ -35,55 +37,23 @@ function getNewContentSince(
|
|
|
35
37
|
return contentMessage;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Create a unique database file for each test
|
|
43
|
-
const dbPath = customDbPath ?? join(tmpdir(), `test-${randomUUID()}.db`);
|
|
44
|
-
const storage = createSyncStorage({
|
|
45
|
-
filename: dbPath,
|
|
46
|
-
nodeName: "test",
|
|
47
|
-
storageName: "test-storage",
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
onTestFinished(() => {
|
|
51
|
-
try {
|
|
52
|
-
unlinkSync(dbPath);
|
|
53
|
-
} catch {}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
node.setStorage(storage);
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
fixturesNode: node,
|
|
60
|
-
dbPath,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function createTestNode(dbPath?: string) {
|
|
65
|
-
const [admin, session] = randomAgentAndSessionID();
|
|
66
|
-
const node = new LocalNode(admin.agentSecret, session, crypto);
|
|
67
|
-
|
|
68
|
-
const storage = createSyncStorage({
|
|
69
|
-
filename: dbPath,
|
|
70
|
-
nodeName: "test",
|
|
71
|
-
storageName: "test-storage",
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
node,
|
|
76
|
-
storage,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
vi.useRealTimers();
|
|
42
|
+
});
|
|
79
43
|
|
|
80
44
|
describe("StorageApiSync", () => {
|
|
81
45
|
describe("getKnownState", () => {
|
|
82
46
|
test("should return empty known state for new coValue ID and cache the result", async () => {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
47
|
+
const fixtures = setupTestNode();
|
|
48
|
+
const client = setupTestNode();
|
|
49
|
+
const { storage } = client.addStorage({
|
|
50
|
+
storage: createSyncStorage({
|
|
51
|
+
nodeName: "test",
|
|
52
|
+
storageName: "test-storage",
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
85
55
|
|
|
86
|
-
const id =
|
|
56
|
+
const id = fixtures.node.createGroup().id;
|
|
87
57
|
const knownState = storage.getKnownState(id);
|
|
88
58
|
|
|
89
59
|
expect(knownState).toEqual(emptyKnownState(id));
|
|
@@ -91,7 +61,13 @@ describe("StorageApiSync", () => {
|
|
|
91
61
|
});
|
|
92
62
|
|
|
93
63
|
test("should return separate known state instances for different coValue IDs", async () => {
|
|
94
|
-
const
|
|
64
|
+
const client = setupTestNode();
|
|
65
|
+
const { storage } = client.addStorage({
|
|
66
|
+
storage: createSyncStorage({
|
|
67
|
+
nodeName: "test",
|
|
68
|
+
storageName: "test-storage",
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
95
71
|
const id1 = "test-id-1";
|
|
96
72
|
const id2 = "test-id-2";
|
|
97
73
|
|
|
@@ -104,7 +80,13 @@ describe("StorageApiSync", () => {
|
|
|
104
80
|
|
|
105
81
|
describe("load", () => {
|
|
106
82
|
test("should fail gracefully when loading non-existent coValue and preserve known state", async () => {
|
|
107
|
-
const
|
|
83
|
+
const client = setupTestNode();
|
|
84
|
+
const { storage } = client.addStorage({
|
|
85
|
+
storage: createSyncStorage({
|
|
86
|
+
nodeName: "test",
|
|
87
|
+
storageName: "test-storage",
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
108
90
|
const id = "non-existent-id";
|
|
109
91
|
const callback = vi.fn();
|
|
110
92
|
const done = vi.fn();
|
|
@@ -124,15 +106,31 @@ describe("StorageApiSync", () => {
|
|
|
124
106
|
});
|
|
125
107
|
|
|
126
108
|
test("should successfully load coValue with header and update known state", async () => {
|
|
127
|
-
const
|
|
128
|
-
const
|
|
109
|
+
const dbPath = getDbPath();
|
|
110
|
+
const fixtures = setupTestNode();
|
|
111
|
+
fixtures.addStorage({
|
|
112
|
+
storage: createSyncStorage({
|
|
113
|
+
filename: dbPath,
|
|
114
|
+
nodeName: "test",
|
|
115
|
+
storageName: "test-storage",
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const client = setupTestNode();
|
|
120
|
+
const { storage } = client.addStorage({
|
|
121
|
+
storage: createSyncStorage({
|
|
122
|
+
filename: dbPath,
|
|
123
|
+
nodeName: "test",
|
|
124
|
+
storageName: "test-storage",
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
129
127
|
const callback = vi.fn((content) =>
|
|
130
|
-
node.syncManager.handleNewContent(content, "storage"),
|
|
128
|
+
client.node.syncManager.handleNewContent(content, "storage"),
|
|
131
129
|
);
|
|
132
130
|
const done = vi.fn();
|
|
133
131
|
|
|
134
132
|
// Create a real group and get its content message
|
|
135
|
-
const group =
|
|
133
|
+
const group = fixtures.node.createGroup();
|
|
136
134
|
await group.core.waitForSync();
|
|
137
135
|
|
|
138
136
|
// Get initial known state
|
|
@@ -154,7 +152,7 @@ describe("StorageApiSync", () => {
|
|
|
154
152
|
const updatedKnownState = storage.getKnownState(group.id);
|
|
155
153
|
expect(updatedKnownState).toEqual(group.core.knownState());
|
|
156
154
|
|
|
157
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
155
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
158
156
|
|
|
159
157
|
expect(groupOnNode.core.verified.header).toEqual(
|
|
160
158
|
group.core.verified.header,
|
|
@@ -162,15 +160,31 @@ describe("StorageApiSync", () => {
|
|
|
162
160
|
});
|
|
163
161
|
|
|
164
162
|
test("should successfully load coValue with transactions and update known state", async () => {
|
|
165
|
-
const
|
|
166
|
-
const
|
|
163
|
+
const dbPath = getDbPath();
|
|
164
|
+
const fixtures = setupTestNode();
|
|
165
|
+
fixtures.addStorage({
|
|
166
|
+
storage: createSyncStorage({
|
|
167
|
+
filename: dbPath,
|
|
168
|
+
nodeName: "test",
|
|
169
|
+
storageName: "test-storage",
|
|
170
|
+
}),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const client = setupTestNode();
|
|
174
|
+
const { storage } = client.addStorage({
|
|
175
|
+
storage: createSyncStorage({
|
|
176
|
+
filename: dbPath,
|
|
177
|
+
nodeName: "test",
|
|
178
|
+
storageName: "test-storage",
|
|
179
|
+
}),
|
|
180
|
+
});
|
|
167
181
|
const callback = vi.fn((content) =>
|
|
168
|
-
node.syncManager.handleNewContent(content, "storage"),
|
|
182
|
+
client.node.syncManager.handleNewContent(content, "storage"),
|
|
169
183
|
);
|
|
170
184
|
const done = vi.fn();
|
|
171
185
|
|
|
172
186
|
// Create a real group and add a member to create transactions
|
|
173
|
-
const group =
|
|
187
|
+
const group = fixtures.node.createGroup();
|
|
174
188
|
group.addMember("everyone", "reader");
|
|
175
189
|
await group.core.waitForSync();
|
|
176
190
|
|
|
@@ -185,7 +199,7 @@ describe("StorageApiSync", () => {
|
|
|
185
199
|
id: group.id,
|
|
186
200
|
header: group.core.verified.header,
|
|
187
201
|
new: expect.objectContaining({
|
|
188
|
-
[
|
|
202
|
+
[fixtures.node.currentSessionID]: expect.any(Object),
|
|
189
203
|
}),
|
|
190
204
|
}),
|
|
191
205
|
);
|
|
@@ -195,17 +209,30 @@ describe("StorageApiSync", () => {
|
|
|
195
209
|
const updatedKnownState = storage.getKnownState(group.id);
|
|
196
210
|
expect(updatedKnownState).toEqual(group.core.knownState());
|
|
197
211
|
|
|
198
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
212
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
199
213
|
expect(groupOnNode.get("everyone")).toEqual("reader");
|
|
200
214
|
});
|
|
201
215
|
});
|
|
202
216
|
|
|
203
217
|
describe("store", () => {
|
|
204
218
|
test("should successfully store new coValue with header and update known state", async () => {
|
|
205
|
-
const
|
|
206
|
-
|
|
219
|
+
const fixtures = setupTestNode();
|
|
220
|
+
fixtures.addStorage({
|
|
221
|
+
storage: createSyncStorage({
|
|
222
|
+
nodeName: "test",
|
|
223
|
+
storageName: "test-storage",
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const client = setupTestNode();
|
|
228
|
+
const { storage } = client.addStorage({
|
|
229
|
+
storage: createSyncStorage({
|
|
230
|
+
nodeName: "test",
|
|
231
|
+
storageName: "test-storage",
|
|
232
|
+
}),
|
|
233
|
+
});
|
|
207
234
|
// Create a real group and get its content message
|
|
208
|
-
const group =
|
|
235
|
+
const group = fixtures.node.createGroup();
|
|
209
236
|
const contentMessage = getNewContentSince(
|
|
210
237
|
group.core,
|
|
211
238
|
emptyKnownState(group.id),
|
|
@@ -222,9 +249,9 @@ describe("StorageApiSync", () => {
|
|
|
222
249
|
const updatedKnownState = storage.getKnownState(group.id);
|
|
223
250
|
expect(updatedKnownState).toEqual(group.core.knownState());
|
|
224
251
|
|
|
225
|
-
|
|
252
|
+
client.addStorage({ storage });
|
|
226
253
|
|
|
227
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
254
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
228
255
|
|
|
229
256
|
expect(groupOnNode.core.verified.header).toEqual(
|
|
230
257
|
group.core.verified.header,
|
|
@@ -232,11 +259,24 @@ describe("StorageApiSync", () => {
|
|
|
232
259
|
});
|
|
233
260
|
|
|
234
261
|
test("should successfully store coValue with transactions and update known state", async () => {
|
|
235
|
-
const
|
|
236
|
-
|
|
262
|
+
const fixtures = setupTestNode();
|
|
263
|
+
fixtures.addStorage({
|
|
264
|
+
storage: createSyncStorage({
|
|
265
|
+
nodeName: "test",
|
|
266
|
+
storageName: "test-storage",
|
|
267
|
+
}),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const client = setupTestNode();
|
|
271
|
+
const { storage } = client.addStorage({
|
|
272
|
+
storage: createSyncStorage({
|
|
273
|
+
nodeName: "test",
|
|
274
|
+
storageName: "test-storage",
|
|
275
|
+
}),
|
|
276
|
+
});
|
|
237
277
|
|
|
238
278
|
// Create a real group and add a member to create transactions
|
|
239
|
-
const group =
|
|
279
|
+
const group = fixtures.node.createGroup();
|
|
240
280
|
|
|
241
281
|
group.addMember("everyone", "reader");
|
|
242
282
|
|
|
@@ -256,17 +296,30 @@ describe("StorageApiSync", () => {
|
|
|
256
296
|
const updatedKnownState = storage.getKnownState(group.id);
|
|
257
297
|
expect(updatedKnownState).toEqual(group.core.knownState());
|
|
258
298
|
|
|
259
|
-
|
|
299
|
+
client.addStorage({ storage });
|
|
260
300
|
|
|
261
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
301
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
262
302
|
expect(groupOnNode.get("everyone")).toEqual("reader");
|
|
263
303
|
});
|
|
264
304
|
|
|
265
305
|
test("should handle correction when header assumption is invalid", async () => {
|
|
266
|
-
const
|
|
267
|
-
|
|
306
|
+
const fixtures = setupTestNode();
|
|
307
|
+
fixtures.addStorage({
|
|
308
|
+
storage: createSyncStorage({
|
|
309
|
+
nodeName: "test",
|
|
310
|
+
storageName: "test-storage",
|
|
311
|
+
}),
|
|
312
|
+
});
|
|
268
313
|
|
|
269
|
-
const
|
|
314
|
+
const client = setupTestNode();
|
|
315
|
+
const { storage } = client.addStorage({
|
|
316
|
+
storage: createSyncStorage({
|
|
317
|
+
nodeName: "test",
|
|
318
|
+
storageName: "test-storage",
|
|
319
|
+
}),
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const group = fixtures.node.createGroup();
|
|
270
323
|
const knownState = group.core.knownState();
|
|
271
324
|
|
|
272
325
|
group.addMember("everyone", "reader");
|
|
@@ -290,17 +343,30 @@ describe("StorageApiSync", () => {
|
|
|
290
343
|
const updatedKnownState = storage.getKnownState(group.id);
|
|
291
344
|
expect(updatedKnownState).toEqual(group.core.knownState());
|
|
292
345
|
|
|
293
|
-
|
|
294
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
346
|
+
client.addStorage({ storage });
|
|
347
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
295
348
|
|
|
296
349
|
expect(groupOnNode.get("everyone")).toEqual("reader");
|
|
297
350
|
});
|
|
298
351
|
|
|
299
352
|
test("should handle correction when new content assumption is invalid", async () => {
|
|
300
|
-
const
|
|
301
|
-
|
|
353
|
+
const fixtures = setupTestNode();
|
|
354
|
+
fixtures.addStorage({
|
|
355
|
+
storage: createSyncStorage({
|
|
356
|
+
nodeName: "test",
|
|
357
|
+
storageName: "test-storage",
|
|
358
|
+
}),
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
const client = setupTestNode();
|
|
362
|
+
const { storage } = client.addStorage({
|
|
363
|
+
storage: createSyncStorage({
|
|
364
|
+
nodeName: "test",
|
|
365
|
+
storageName: "test-storage",
|
|
366
|
+
}),
|
|
367
|
+
});
|
|
302
368
|
|
|
303
|
-
const group =
|
|
369
|
+
const group = fixtures.node.createGroup();
|
|
304
370
|
|
|
305
371
|
const initialContent = getNewContentSince(
|
|
306
372
|
group.core,
|
|
@@ -340,17 +406,30 @@ describe("StorageApiSync", () => {
|
|
|
340
406
|
const finalKnownState = storage.getKnownState(group.id);
|
|
341
407
|
expect(finalKnownState).toEqual(group.core.knownState());
|
|
342
408
|
|
|
343
|
-
|
|
344
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
409
|
+
client.addStorage({ storage });
|
|
410
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
345
411
|
|
|
346
412
|
expect(groupOnNode.get("everyone")).toEqual("writer");
|
|
347
413
|
});
|
|
348
414
|
|
|
349
415
|
test("should log error and fail when correction callback returns undefined", async () => {
|
|
350
|
-
const
|
|
351
|
-
|
|
416
|
+
const fixtures = setupTestNode();
|
|
417
|
+
fixtures.addStorage({
|
|
418
|
+
storage: createSyncStorage({
|
|
419
|
+
nodeName: "test",
|
|
420
|
+
storageName: "test-storage",
|
|
421
|
+
}),
|
|
422
|
+
});
|
|
352
423
|
|
|
353
|
-
const
|
|
424
|
+
const client = setupTestNode();
|
|
425
|
+
const { storage } = client.addStorage({
|
|
426
|
+
storage: createSyncStorage({
|
|
427
|
+
nodeName: "test",
|
|
428
|
+
storageName: "test-storage",
|
|
429
|
+
}),
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const group = fixtures.node.createGroup();
|
|
354
433
|
|
|
355
434
|
const knownState = group.core.knownState();
|
|
356
435
|
group.addMember("everyone", "writer");
|
|
@@ -385,10 +464,23 @@ describe("StorageApiSync", () => {
|
|
|
385
464
|
});
|
|
386
465
|
|
|
387
466
|
test("should log error and fail when correction callback returns invalid content message", async () => {
|
|
388
|
-
const
|
|
389
|
-
|
|
467
|
+
const fixtures = setupTestNode();
|
|
468
|
+
fixtures.addStorage({
|
|
469
|
+
storage: createSyncStorage({
|
|
470
|
+
nodeName: "test",
|
|
471
|
+
storageName: "test-storage",
|
|
472
|
+
}),
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
const client = setupTestNode();
|
|
476
|
+
const { storage } = client.addStorage({
|
|
477
|
+
storage: createSyncStorage({
|
|
478
|
+
nodeName: "test",
|
|
479
|
+
storageName: "test-storage",
|
|
480
|
+
}),
|
|
481
|
+
});
|
|
390
482
|
|
|
391
|
-
const group =
|
|
483
|
+
const group = fixtures.node.createGroup();
|
|
392
484
|
|
|
393
485
|
const knownState = group.core.knownState();
|
|
394
486
|
group.addMember("everyone", "writer");
|
|
@@ -420,15 +512,39 @@ describe("StorageApiSync", () => {
|
|
|
420
512
|
});
|
|
421
513
|
|
|
422
514
|
test("should successfully store coValue with multiple sessions", async () => {
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
const
|
|
515
|
+
const dbPath = getDbPath();
|
|
516
|
+
|
|
517
|
+
const fixtures = setupTestNode();
|
|
518
|
+
fixtures.addStorage({
|
|
519
|
+
storage: createSyncStorage({
|
|
520
|
+
filename: dbPath,
|
|
521
|
+
nodeName: "test",
|
|
522
|
+
storageName: "test-storage",
|
|
523
|
+
}),
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
const fixture2 = setupTestNode();
|
|
527
|
+
fixture2.addStorage({
|
|
528
|
+
storage: createSyncStorage({
|
|
529
|
+
filename: dbPath,
|
|
530
|
+
nodeName: "test",
|
|
531
|
+
storageName: "test-storage",
|
|
532
|
+
}),
|
|
533
|
+
});
|
|
426
534
|
|
|
427
|
-
const
|
|
535
|
+
const client = setupTestNode();
|
|
536
|
+
const { storage } = client.addStorage({
|
|
537
|
+
storage: createSyncStorage({
|
|
538
|
+
nodeName: "test",
|
|
539
|
+
storageName: "test-storage",
|
|
540
|
+
}),
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
const coValue = fixtures.node.createCoValue({
|
|
428
544
|
type: "comap",
|
|
429
545
|
ruleset: { type: "unsafeAllowAll" },
|
|
430
546
|
meta: null,
|
|
431
|
-
...crypto.createdNowUnique(),
|
|
547
|
+
...fixtures.node.crypto.createdNowUnique(),
|
|
432
548
|
});
|
|
433
549
|
|
|
434
550
|
coValue.makeTransaction(
|
|
@@ -443,7 +559,7 @@ describe("StorageApiSync", () => {
|
|
|
443
559
|
await coValue.waitForSync();
|
|
444
560
|
|
|
445
561
|
const mapOnNode2 = await loadCoValueOrFail(
|
|
446
|
-
|
|
562
|
+
fixture2.node,
|
|
447
563
|
coValue.id as CoID<RawCoMap>,
|
|
448
564
|
);
|
|
449
565
|
|
|
@@ -466,27 +582,216 @@ describe("StorageApiSync", () => {
|
|
|
466
582
|
|
|
467
583
|
storage.store(contentMessage, correctionCallback);
|
|
468
584
|
|
|
469
|
-
|
|
585
|
+
client.addStorage({ storage });
|
|
470
586
|
|
|
471
|
-
const finalMap = await loadCoValueOrFail(node, mapOnNode2.id);
|
|
587
|
+
const finalMap = await loadCoValueOrFail(client.node, mapOnNode2.id);
|
|
472
588
|
expect(finalMap.core.knownState()).toEqual(knownState);
|
|
473
589
|
});
|
|
474
590
|
});
|
|
475
591
|
|
|
592
|
+
describe("delete flow", () => {
|
|
593
|
+
test("deleteCoValue enqueues the coValue for erasure", async () => {
|
|
594
|
+
const client = setupTestNode();
|
|
595
|
+
const { storage } = client.addStorage({
|
|
596
|
+
storage: createSyncStorage({
|
|
597
|
+
nodeName: "test",
|
|
598
|
+
storageName: "test-storage",
|
|
599
|
+
}),
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
const group = client.node.createGroup();
|
|
603
|
+
const map = group.createMap();
|
|
604
|
+
map.core.deleteCoValue();
|
|
605
|
+
await map.core.waitForSync();
|
|
606
|
+
|
|
607
|
+
const queued = await getAllCoValuesWaitingForDelete(storage);
|
|
608
|
+
expect(queued).toContain(map.id);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
test("background erasure doesn't run if not enabled", async () => {
|
|
612
|
+
const dbPath = getDbPath();
|
|
613
|
+
const node = setupTestNode();
|
|
614
|
+
const { storage } = node.addStorage({
|
|
615
|
+
storage: createSyncStorage({
|
|
616
|
+
filename: dbPath,
|
|
617
|
+
nodeName: "test",
|
|
618
|
+
storageName: "test-storage",
|
|
619
|
+
}),
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
const group = node.node.createGroup();
|
|
623
|
+
const map = group.createMap();
|
|
624
|
+
map.set("k", "v");
|
|
625
|
+
await map.core.waitForSync();
|
|
626
|
+
|
|
627
|
+
vi.useFakeTimers();
|
|
628
|
+
|
|
629
|
+
map.core.deleteCoValue();
|
|
630
|
+
await map.core.waitForSync();
|
|
631
|
+
|
|
632
|
+
await vi.advanceTimersByTimeAsync(70_000);
|
|
633
|
+
|
|
634
|
+
// Queue drained
|
|
635
|
+
expect(await getAllCoValuesWaitingForDelete(storage)).toContain(map.id);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test("background erasure run if enabled", async () => {
|
|
639
|
+
const dbPath = getDbPath();
|
|
640
|
+
const node = setupTestNode();
|
|
641
|
+
const { storage } = node.addStorage({
|
|
642
|
+
storage: createSyncStorage({
|
|
643
|
+
filename: dbPath,
|
|
644
|
+
nodeName: "test",
|
|
645
|
+
storageName: "test-storage",
|
|
646
|
+
}),
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
vi.useFakeTimers();
|
|
650
|
+
|
|
651
|
+
node.node.enableDeletedCoValuesErasure();
|
|
652
|
+
|
|
653
|
+
const group = node.node.createGroup();
|
|
654
|
+
const map = group.createMap();
|
|
655
|
+
map.set("k", "v");
|
|
656
|
+
await map.core.waitForSync();
|
|
657
|
+
|
|
658
|
+
map.core.deleteCoValue();
|
|
659
|
+
await map.core.waitForSync();
|
|
660
|
+
|
|
661
|
+
await vi.advanceTimersByTimeAsync(70_000);
|
|
662
|
+
|
|
663
|
+
// Queue drained
|
|
664
|
+
expect(await getAllCoValuesWaitingForDelete(storage)).not.toContain(
|
|
665
|
+
map.id,
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
const sessionIDs = await getCoValueStoredSessions(storage, map.id);
|
|
669
|
+
|
|
670
|
+
expect(sessionIDs).toHaveLength(1);
|
|
671
|
+
expect(sessionIDs[0]).toMatch(/_session_d[1-9A-HJ-NP-Za-km-z]+\$$/); // Delete session format
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
test("eraseAllDeletedCoValues deletes history but preserves tombstone", async () => {
|
|
675
|
+
const dbPath = getDbPath();
|
|
676
|
+
|
|
677
|
+
const node = setupTestNode();
|
|
678
|
+
const { storage } = node.addStorage({
|
|
679
|
+
storage: createSyncStorage({
|
|
680
|
+
filename: dbPath,
|
|
681
|
+
nodeName: "test",
|
|
682
|
+
storageName: "test-storage",
|
|
683
|
+
}),
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
const group = node.node.createGroup();
|
|
687
|
+
const map = group.createMap();
|
|
688
|
+
map.set("k", "v");
|
|
689
|
+
await map.core.waitForSync();
|
|
690
|
+
|
|
691
|
+
map.core.deleteCoValue();
|
|
692
|
+
await map.core.waitForSync();
|
|
693
|
+
|
|
694
|
+
expect(await getAllCoValuesWaitingForDelete(storage)).toContain(map.id);
|
|
695
|
+
|
|
696
|
+
await storage.eraseAllDeletedCoValues();
|
|
697
|
+
|
|
698
|
+
// Queue drained
|
|
699
|
+
expect(await getAllCoValuesWaitingForDelete(storage)).not.toContain(
|
|
700
|
+
map.id,
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
// Tombstone preserved + history erased when loaded from storage
|
|
704
|
+
const client = setupTestNode();
|
|
705
|
+
const { storage: clientStorage } = client.addStorage({
|
|
706
|
+
storage: createSyncStorage({
|
|
707
|
+
filename: dbPath,
|
|
708
|
+
nodeName: "test",
|
|
709
|
+
storageName: "test-storage",
|
|
710
|
+
}),
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
const loaded = await loadCoValueOrFail(
|
|
714
|
+
client.node,
|
|
715
|
+
map.id as CoID<RawCoMap>,
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
expect(loaded.core.isDeleted).toBe(true);
|
|
719
|
+
expect(loaded.get("k")).toBeUndefined();
|
|
720
|
+
|
|
721
|
+
const sessionIDs = await getCoValueStoredSessions(clientStorage, map.id);
|
|
722
|
+
|
|
723
|
+
expect(sessionIDs).toHaveLength(1);
|
|
724
|
+
expect(sessionIDs[0]).toMatch(/_session_d[1-9A-HJ-NP-Za-km-z]+\$$/); // Delete session format
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
test("eraseAllDeletedCoValues does not break when called while a coValue is streaming from storage", async () => {
|
|
728
|
+
const dbPath = getDbPath();
|
|
729
|
+
|
|
730
|
+
const node = setupTestNode();
|
|
731
|
+
|
|
732
|
+
const storage = createSyncStorage({
|
|
733
|
+
filename: dbPath,
|
|
734
|
+
nodeName: "test",
|
|
735
|
+
storageName: "test-storage",
|
|
736
|
+
});
|
|
737
|
+
node.addStorage({ storage });
|
|
738
|
+
|
|
739
|
+
const group = node.node.createGroup();
|
|
740
|
+
const map = group.createMap();
|
|
741
|
+
fillCoMapWithLargeData(map);
|
|
742
|
+
await map.core.waitForSync();
|
|
743
|
+
map.core.deleteCoValue();
|
|
744
|
+
await map.core.waitForSync();
|
|
745
|
+
|
|
746
|
+
storage.close();
|
|
747
|
+
|
|
748
|
+
const newStorage = createSyncStorage({
|
|
749
|
+
filename: dbPath,
|
|
750
|
+
nodeName: "test",
|
|
751
|
+
storageName: "test-storage",
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
const callback = vi.fn();
|
|
755
|
+
|
|
756
|
+
const loadPromise = new Promise((resolve) => {
|
|
757
|
+
newStorage.load(map.id, callback, resolve);
|
|
758
|
+
});
|
|
759
|
+
await newStorage.eraseAllDeletedCoValues();
|
|
760
|
+
|
|
761
|
+
expect(await loadPromise).toBe(true);
|
|
762
|
+
});
|
|
763
|
+
});
|
|
764
|
+
|
|
476
765
|
describe("dependencies", () => {
|
|
477
766
|
test("should load dependencies before dependent coValues and update all known states", async () => {
|
|
478
|
-
const
|
|
479
|
-
const
|
|
767
|
+
const dbPath = getDbPath();
|
|
768
|
+
const fixtures = setupTestNode();
|
|
769
|
+
fixtures.addStorage({
|
|
770
|
+
storage: createSyncStorage({
|
|
771
|
+
filename: dbPath,
|
|
772
|
+
nodeName: "test",
|
|
773
|
+
storageName: "test-storage",
|
|
774
|
+
}),
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
const client = setupTestNode();
|
|
778
|
+
const { storage } = client.addStorage({
|
|
779
|
+
storage: createSyncStorage({
|
|
780
|
+
filename: dbPath,
|
|
781
|
+
nodeName: "test",
|
|
782
|
+
storageName: "test-storage",
|
|
783
|
+
}),
|
|
784
|
+
});
|
|
480
785
|
|
|
481
786
|
// Create a group and a map owned by that group to create dependencies
|
|
482
|
-
const group =
|
|
787
|
+
const group = fixtures.node.createGroup();
|
|
483
788
|
group.addMember("everyone", "reader");
|
|
484
789
|
const map = group.createMap({ test: "value" });
|
|
485
790
|
await group.core.waitForSync();
|
|
486
791
|
await map.core.waitForSync();
|
|
487
792
|
|
|
488
793
|
const callback = vi.fn((content) =>
|
|
489
|
-
node.syncManager.handleNewContent(content, "storage"),
|
|
794
|
+
client.node.syncManager.handleNewContent(content, "storage"),
|
|
490
795
|
);
|
|
491
796
|
const done = vi.fn();
|
|
492
797
|
|
|
@@ -521,24 +826,40 @@ describe("StorageApiSync", () => {
|
|
|
521
826
|
expect(updatedGroupKnownState).toEqual(group.core.knownState());
|
|
522
827
|
expect(updatedMapKnownState).toEqual(map.core.knownState());
|
|
523
828
|
|
|
524
|
-
|
|
525
|
-
const mapOnNode = await loadCoValueOrFail(node, map.id);
|
|
829
|
+
client.addStorage({ storage });
|
|
830
|
+
const mapOnNode = await loadCoValueOrFail(client.node, map.id);
|
|
526
831
|
expect(mapOnNode.get("test")).toEqual("value");
|
|
527
832
|
});
|
|
528
833
|
|
|
529
834
|
test("should skip loading already loaded dependencies", async () => {
|
|
530
|
-
const
|
|
531
|
-
const
|
|
835
|
+
const dbPath = getDbPath();
|
|
836
|
+
const fixtures = setupTestNode();
|
|
837
|
+
fixtures.addStorage({
|
|
838
|
+
storage: createSyncStorage({
|
|
839
|
+
filename: dbPath,
|
|
840
|
+
nodeName: "test",
|
|
841
|
+
storageName: "test-storage",
|
|
842
|
+
}),
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
const client = setupTestNode();
|
|
846
|
+
const { storage } = client.addStorage({
|
|
847
|
+
storage: createSyncStorage({
|
|
848
|
+
filename: dbPath,
|
|
849
|
+
nodeName: "test",
|
|
850
|
+
storageName: "test-storage",
|
|
851
|
+
}),
|
|
852
|
+
});
|
|
532
853
|
|
|
533
854
|
// Create a group and a map owned by that group
|
|
534
|
-
const group =
|
|
855
|
+
const group = fixtures.node.createGroup();
|
|
535
856
|
group.addMember("everyone", "reader");
|
|
536
857
|
const map = group.createMap({ test: "value" });
|
|
537
858
|
await group.core.waitForSync();
|
|
538
859
|
await map.core.waitForSync();
|
|
539
860
|
|
|
540
861
|
const callback = vi.fn((content) =>
|
|
541
|
-
node.syncManager.handleNewContent(content, "storage"),
|
|
862
|
+
client.node.syncManager.handleNewContent(content, "storage"),
|
|
542
863
|
);
|
|
543
864
|
const done = vi.fn();
|
|
544
865
|
|
|
@@ -574,19 +895,100 @@ describe("StorageApiSync", () => {
|
|
|
574
895
|
const finalMapKnownState = storage.getKnownState(map.id);
|
|
575
896
|
expect(finalMapKnownState).toEqual(map.core.knownState());
|
|
576
897
|
|
|
577
|
-
|
|
578
|
-
const mapOnNode = await loadCoValueOrFail(node, map.id);
|
|
898
|
+
client.addStorage({ storage });
|
|
899
|
+
const mapOnNode = await loadCoValueOrFail(client.node, map.id);
|
|
900
|
+
expect(mapOnNode.get("test")).toEqual("value");
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
test("should load dependencies again if they were unmounted", async () => {
|
|
904
|
+
const dbPath = getDbPath();
|
|
905
|
+
const fixtures = setupTestNode();
|
|
906
|
+
fixtures.addStorage({
|
|
907
|
+
storage: createSyncStorage({
|
|
908
|
+
filename: dbPath,
|
|
909
|
+
nodeName: "test",
|
|
910
|
+
storageName: "test-storage",
|
|
911
|
+
}),
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
const client = setupTestNode();
|
|
915
|
+
const { storage } = client.addStorage({
|
|
916
|
+
storage: createSyncStorage({
|
|
917
|
+
filename: dbPath,
|
|
918
|
+
nodeName: "test",
|
|
919
|
+
storageName: "test-storage",
|
|
920
|
+
}),
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
// Create a group and a map owned by that group
|
|
924
|
+
const group = fixtures.node.createGroup();
|
|
925
|
+
group.addMember("everyone", "reader");
|
|
926
|
+
const map = group.createMap({ test: "value" });
|
|
927
|
+
await group.core.waitForSync();
|
|
928
|
+
await map.core.waitForSync();
|
|
929
|
+
|
|
930
|
+
const callback = vi.fn((content) =>
|
|
931
|
+
client.node.syncManager.handleNewContent(content, "storage"),
|
|
932
|
+
);
|
|
933
|
+
const done = vi.fn();
|
|
934
|
+
|
|
935
|
+
// Load the map (and its group)
|
|
936
|
+
await storage.load(map.id, callback, done);
|
|
937
|
+
callback.mockClear();
|
|
938
|
+
done.mockClear();
|
|
939
|
+
|
|
940
|
+
// Unmount the map and its group
|
|
941
|
+
storage.onCoValueUnmounted(map.id);
|
|
942
|
+
storage.onCoValueUnmounted(group.id);
|
|
943
|
+
|
|
944
|
+
// Load the map. The group dependency should be loaded again
|
|
945
|
+
await storage.load(map.id, callback, done);
|
|
946
|
+
|
|
947
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
948
|
+
expect(callback).toHaveBeenNthCalledWith(
|
|
949
|
+
1,
|
|
950
|
+
expect.objectContaining({
|
|
951
|
+
id: group.id,
|
|
952
|
+
}),
|
|
953
|
+
);
|
|
954
|
+
expect(callback).toHaveBeenNthCalledWith(
|
|
955
|
+
2,
|
|
956
|
+
expect.objectContaining({
|
|
957
|
+
id: map.id,
|
|
958
|
+
}),
|
|
959
|
+
);
|
|
960
|
+
|
|
961
|
+
expect(done).toHaveBeenCalledWith(true);
|
|
962
|
+
|
|
963
|
+
client.addStorage({ storage });
|
|
964
|
+
const mapOnNode = await loadCoValueOrFail(client.node, map.id);
|
|
579
965
|
expect(mapOnNode.get("test")).toEqual("value");
|
|
580
966
|
});
|
|
581
967
|
});
|
|
582
968
|
|
|
583
969
|
describe("waitForSync", () => {
|
|
584
970
|
test("should resolve immediately when coValue is already synced", async () => {
|
|
585
|
-
const
|
|
586
|
-
const
|
|
971
|
+
const dbPath = getDbPath();
|
|
972
|
+
const fixtures = setupTestNode();
|
|
973
|
+
fixtures.addStorage({
|
|
974
|
+
storage: createSyncStorage({
|
|
975
|
+
filename: dbPath,
|
|
976
|
+
nodeName: "test",
|
|
977
|
+
storageName: "test-storage",
|
|
978
|
+
}),
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
const client = setupTestNode();
|
|
982
|
+
const { storage } = client.addStorage({
|
|
983
|
+
storage: createSyncStorage({
|
|
984
|
+
filename: dbPath,
|
|
985
|
+
nodeName: "test",
|
|
986
|
+
storageName: "test-storage",
|
|
987
|
+
}),
|
|
988
|
+
});
|
|
587
989
|
|
|
588
990
|
// Create a group and add a member
|
|
589
|
-
const group =
|
|
991
|
+
const group = fixtures.node.createGroup();
|
|
590
992
|
group.addMember("everyone", "reader");
|
|
591
993
|
await group.core.waitForSync();
|
|
592
994
|
|
|
@@ -598,10 +1000,10 @@ describe("StorageApiSync", () => {
|
|
|
598
1000
|
const correctionCallback = vi.fn();
|
|
599
1001
|
storage.store(contentMessage, correctionCallback);
|
|
600
1002
|
|
|
601
|
-
|
|
1003
|
+
client.addStorage({ storage });
|
|
602
1004
|
|
|
603
1005
|
// Load the group on the new node
|
|
604
|
-
const groupOnNode = await loadCoValueOrFail(node, group.id);
|
|
1006
|
+
const groupOnNode = await loadCoValueOrFail(client.node, group.id);
|
|
605
1007
|
|
|
606
1008
|
// Wait for sync should resolve immediately since the coValue is already synced
|
|
607
1009
|
await expect(
|
|
@@ -614,7 +1016,13 @@ describe("StorageApiSync", () => {
|
|
|
614
1016
|
|
|
615
1017
|
describe("close", () => {
|
|
616
1018
|
test("should close storage without throwing errors", async () => {
|
|
617
|
-
const
|
|
1019
|
+
const client = setupTestNode();
|
|
1020
|
+
const { storage } = client.addStorage({
|
|
1021
|
+
storage: createSyncStorage({
|
|
1022
|
+
nodeName: "test",
|
|
1023
|
+
storageName: "test-storage",
|
|
1024
|
+
}),
|
|
1025
|
+
});
|
|
618
1026
|
|
|
619
1027
|
expect(() => storage.close()).not.toThrow();
|
|
620
1028
|
});
|
|
@@ -622,11 +1030,27 @@ describe("StorageApiSync", () => {
|
|
|
622
1030
|
|
|
623
1031
|
describe("loadKnownState", () => {
|
|
624
1032
|
test("should return correct knownState structure for existing CoValue", async () => {
|
|
625
|
-
const
|
|
626
|
-
const
|
|
1033
|
+
const dbPath = getDbPath();
|
|
1034
|
+
const fixtures = setupTestNode();
|
|
1035
|
+
fixtures.addStorage({
|
|
1036
|
+
storage: createSyncStorage({
|
|
1037
|
+
filename: dbPath,
|
|
1038
|
+
nodeName: "test",
|
|
1039
|
+
storageName: "test-storage",
|
|
1040
|
+
}),
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
const client = setupTestNode();
|
|
1044
|
+
const { storage } = client.addStorage({
|
|
1045
|
+
storage: createSyncStorage({
|
|
1046
|
+
filename: dbPath,
|
|
1047
|
+
nodeName: "test",
|
|
1048
|
+
storageName: "test-storage",
|
|
1049
|
+
}),
|
|
1050
|
+
});
|
|
627
1051
|
|
|
628
1052
|
// Create a group to have data in the database
|
|
629
|
-
const group =
|
|
1053
|
+
const group = fixtures.node.createGroup();
|
|
630
1054
|
group.addMember("everyone", "reader");
|
|
631
1055
|
await group.core.waitForSync();
|
|
632
1056
|
|
|
@@ -643,7 +1067,13 @@ describe("StorageApiSync", () => {
|
|
|
643
1067
|
});
|
|
644
1068
|
|
|
645
1069
|
test("should return undefined for non-existent CoValue", async () => {
|
|
646
|
-
const
|
|
1070
|
+
const client = setupTestNode();
|
|
1071
|
+
const { storage } = client.addStorage({
|
|
1072
|
+
storage: createSyncStorage({
|
|
1073
|
+
nodeName: "test",
|
|
1074
|
+
storageName: "test-storage",
|
|
1075
|
+
}),
|
|
1076
|
+
});
|
|
647
1077
|
|
|
648
1078
|
const result = await new Promise<CoValueKnownState | undefined>(
|
|
649
1079
|
(resolve) => {
|
|
@@ -655,15 +1085,31 @@ describe("StorageApiSync", () => {
|
|
|
655
1085
|
});
|
|
656
1086
|
|
|
657
1087
|
test("should handle CoValue with no sessions (header only)", async () => {
|
|
658
|
-
const
|
|
659
|
-
const
|
|
1088
|
+
const dbPath = getDbPath();
|
|
1089
|
+
const fixtures = setupTestNode();
|
|
1090
|
+
fixtures.addStorage({
|
|
1091
|
+
storage: createSyncStorage({
|
|
1092
|
+
filename: dbPath,
|
|
1093
|
+
nodeName: "test",
|
|
1094
|
+
storageName: "test-storage",
|
|
1095
|
+
}),
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
const client = setupTestNode();
|
|
1099
|
+
const { storage } = client.addStorage({
|
|
1100
|
+
storage: createSyncStorage({
|
|
1101
|
+
filename: dbPath,
|
|
1102
|
+
nodeName: "test",
|
|
1103
|
+
storageName: "test-storage",
|
|
1104
|
+
}),
|
|
1105
|
+
});
|
|
660
1106
|
|
|
661
1107
|
// Create a CoValue with just a header (no transactions yet)
|
|
662
|
-
const coValue =
|
|
1108
|
+
const coValue = fixtures.node.createCoValue({
|
|
663
1109
|
type: "comap",
|
|
664
1110
|
ruleset: { type: "unsafeAllowAll" },
|
|
665
1111
|
meta: null,
|
|
666
|
-
...crypto.createdNowUnique(),
|
|
1112
|
+
...fixtures.node.crypto.createdNowUnique(),
|
|
667
1113
|
});
|
|
668
1114
|
await coValue.waitForSync();
|
|
669
1115
|
|
|
@@ -681,23 +1127,47 @@ describe("StorageApiSync", () => {
|
|
|
681
1127
|
});
|
|
682
1128
|
|
|
683
1129
|
test("should handle CoValue with multiple sessions", async () => {
|
|
684
|
-
const
|
|
685
|
-
const
|
|
686
|
-
|
|
1130
|
+
const dbPath = getDbPath();
|
|
1131
|
+
const fixtures = setupTestNode();
|
|
1132
|
+
fixtures.addStorage({
|
|
1133
|
+
storage: createSyncStorage({
|
|
1134
|
+
filename: dbPath,
|
|
1135
|
+
nodeName: "test",
|
|
1136
|
+
storageName: "test-storage",
|
|
1137
|
+
}),
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
const fixtures2 = setupTestNode();
|
|
1141
|
+
fixtures2.addStorage({
|
|
1142
|
+
storage: createSyncStorage({
|
|
1143
|
+
filename: dbPath,
|
|
1144
|
+
nodeName: "test",
|
|
1145
|
+
storageName: "test-storage",
|
|
1146
|
+
}),
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
const client = setupTestNode();
|
|
1150
|
+
const { storage } = client.addStorage({
|
|
1151
|
+
storage: createSyncStorage({
|
|
1152
|
+
filename: dbPath,
|
|
1153
|
+
nodeName: "test",
|
|
1154
|
+
storageName: "test-storage",
|
|
1155
|
+
}),
|
|
1156
|
+
});
|
|
687
1157
|
|
|
688
1158
|
// Create a CoValue and have two nodes make transactions
|
|
689
|
-
const coValue =
|
|
1159
|
+
const coValue = fixtures.node.createCoValue({
|
|
690
1160
|
type: "comap",
|
|
691
1161
|
ruleset: { type: "unsafeAllowAll" },
|
|
692
1162
|
meta: null,
|
|
693
|
-
...crypto.createdNowUnique(),
|
|
1163
|
+
...fixtures.node.crypto.createdNowUnique(),
|
|
694
1164
|
});
|
|
695
1165
|
|
|
696
1166
|
coValue.makeTransaction([{ key1: "value1" }], "trusting");
|
|
697
1167
|
await coValue.waitForSync();
|
|
698
1168
|
|
|
699
1169
|
const coValueOnNode2 = await loadCoValueOrFail(
|
|
700
|
-
|
|
1170
|
+
fixtures2.node,
|
|
701
1171
|
coValue.id as CoID<RawCoMap>,
|
|
702
1172
|
);
|
|
703
1173
|
|
|
@@ -722,11 +1192,27 @@ describe("StorageApiSync", () => {
|
|
|
722
1192
|
});
|
|
723
1193
|
|
|
724
1194
|
test("should use cache when knownState is cached", async () => {
|
|
725
|
-
const
|
|
726
|
-
const
|
|
1195
|
+
const dbPath = getDbPath();
|
|
1196
|
+
const fixtures = setupTestNode();
|
|
1197
|
+
fixtures.addStorage({
|
|
1198
|
+
storage: createSyncStorage({
|
|
1199
|
+
filename: dbPath,
|
|
1200
|
+
nodeName: "test",
|
|
1201
|
+
storageName: "test-storage",
|
|
1202
|
+
}),
|
|
1203
|
+
});
|
|
1204
|
+
|
|
1205
|
+
const client = setupTestNode();
|
|
1206
|
+
const { storage } = client.addStorage({
|
|
1207
|
+
storage: createSyncStorage({
|
|
1208
|
+
filename: dbPath,
|
|
1209
|
+
nodeName: "test",
|
|
1210
|
+
storageName: "test-storage",
|
|
1211
|
+
}),
|
|
1212
|
+
});
|
|
727
1213
|
|
|
728
1214
|
// Create a group to have data in the database
|
|
729
|
-
const group =
|
|
1215
|
+
const group = fixtures.node.createGroup();
|
|
730
1216
|
group.addMember("everyone", "reader");
|
|
731
1217
|
await group.core.waitForSync();
|
|
732
1218
|
|