cojson 0.19.22 → 0.20.1

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 (223) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +66 -0
  3. package/dist/PeerState.d.ts +6 -1
  4. package/dist/PeerState.d.ts.map +1 -1
  5. package/dist/PeerState.js +18 -3
  6. package/dist/PeerState.js.map +1 -1
  7. package/dist/coValueContentMessage.d.ts +0 -2
  8. package/dist/coValueContentMessage.d.ts.map +1 -1
  9. package/dist/coValueContentMessage.js +0 -8
  10. package/dist/coValueContentMessage.js.map +1 -1
  11. package/dist/coValueCore/SessionMap.d.ts +4 -2
  12. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  13. package/dist/coValueCore/SessionMap.js +30 -0
  14. package/dist/coValueCore/SessionMap.js.map +1 -1
  15. package/dist/coValueCore/coValueCore.d.ts +70 -5
  16. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  17. package/dist/coValueCore/coValueCore.js +302 -31
  18. package/dist/coValueCore/coValueCore.js.map +1 -1
  19. package/dist/coValueCore/verifiedState.d.ts +6 -1
  20. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  21. package/dist/coValueCore/verifiedState.js +9 -0
  22. package/dist/coValueCore/verifiedState.js.map +1 -1
  23. package/dist/coValues/coList.d.ts +4 -2
  24. package/dist/coValues/coList.d.ts.map +1 -1
  25. package/dist/coValues/coList.js +3 -0
  26. package/dist/coValues/coList.js.map +1 -1
  27. package/dist/coValues/group.d.ts.map +1 -1
  28. package/dist/coValues/group.js +3 -6
  29. package/dist/coValues/group.js.map +1 -1
  30. package/dist/config.d.ts +2 -8
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +4 -12
  33. package/dist/config.js.map +1 -1
  34. package/dist/crypto/NapiCrypto.d.ts +1 -2
  35. package/dist/crypto/NapiCrypto.d.ts.map +1 -1
  36. package/dist/crypto/NapiCrypto.js +19 -4
  37. package/dist/crypto/NapiCrypto.js.map +1 -1
  38. package/dist/crypto/RNCrypto.d.ts.map +1 -1
  39. package/dist/crypto/RNCrypto.js +19 -4
  40. package/dist/crypto/RNCrypto.js.map +1 -1
  41. package/dist/crypto/WasmCrypto.d.ts +11 -4
  42. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  43. package/dist/crypto/WasmCrypto.js +52 -10
  44. package/dist/crypto/WasmCrypto.js.map +1 -1
  45. package/dist/crypto/WasmCryptoEdge.d.ts +1 -0
  46. package/dist/crypto/WasmCryptoEdge.d.ts.map +1 -1
  47. package/dist/crypto/WasmCryptoEdge.js +4 -1
  48. package/dist/crypto/WasmCryptoEdge.js.map +1 -1
  49. package/dist/crypto/crypto.d.ts +3 -3
  50. package/dist/crypto/crypto.d.ts.map +1 -1
  51. package/dist/crypto/crypto.js +6 -1
  52. package/dist/crypto/crypto.js.map +1 -1
  53. package/dist/exports.d.ts +5 -5
  54. package/dist/exports.d.ts.map +1 -1
  55. package/dist/exports.js +4 -3
  56. package/dist/exports.js.map +1 -1
  57. package/dist/ids.d.ts +4 -1
  58. package/dist/ids.d.ts.map +1 -1
  59. package/dist/ids.js +4 -0
  60. package/dist/ids.js.map +1 -1
  61. package/dist/knownState.d.ts +2 -0
  62. package/dist/knownState.d.ts.map +1 -1
  63. package/dist/localNode.d.ts +12 -0
  64. package/dist/localNode.d.ts.map +1 -1
  65. package/dist/localNode.js +14 -0
  66. package/dist/localNode.js.map +1 -1
  67. package/dist/platformUtils.d.ts +3 -0
  68. package/dist/platformUtils.d.ts.map +1 -0
  69. package/dist/platformUtils.js +24 -0
  70. package/dist/platformUtils.js.map +1 -0
  71. package/dist/queue/LinkedList.d.ts +9 -3
  72. package/dist/queue/LinkedList.d.ts.map +1 -1
  73. package/dist/queue/LinkedList.js +30 -1
  74. package/dist/queue/LinkedList.js.map +1 -1
  75. package/dist/queue/OutgoingLoadQueue.d.ts +95 -0
  76. package/dist/queue/OutgoingLoadQueue.d.ts.map +1 -0
  77. package/dist/queue/OutgoingLoadQueue.js +240 -0
  78. package/dist/queue/OutgoingLoadQueue.js.map +1 -0
  79. package/dist/storage/DeletedCoValuesEraserScheduler.d.ts +30 -0
  80. package/dist/storage/DeletedCoValuesEraserScheduler.d.ts.map +1 -0
  81. package/dist/storage/DeletedCoValuesEraserScheduler.js +84 -0
  82. package/dist/storage/DeletedCoValuesEraserScheduler.js.map +1 -0
  83. package/dist/storage/sqlite/client.d.ts +3 -0
  84. package/dist/storage/sqlite/client.d.ts.map +1 -1
  85. package/dist/storage/sqlite/client.js +44 -0
  86. package/dist/storage/sqlite/client.js.map +1 -1
  87. package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -1
  88. package/dist/storage/sqlite/sqliteMigrations.js +7 -0
  89. package/dist/storage/sqlite/sqliteMigrations.js.map +1 -1
  90. package/dist/storage/sqliteAsync/client.d.ts +3 -0
  91. package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
  92. package/dist/storage/sqliteAsync/client.js +42 -0
  93. package/dist/storage/sqliteAsync/client.js.map +1 -1
  94. package/dist/storage/storageAsync.d.ts +7 -0
  95. package/dist/storage/storageAsync.d.ts.map +1 -1
  96. package/dist/storage/storageAsync.js +48 -0
  97. package/dist/storage/storageAsync.js.map +1 -1
  98. package/dist/storage/storageSync.d.ts +6 -0
  99. package/dist/storage/storageSync.d.ts.map +1 -1
  100. package/dist/storage/storageSync.js +42 -0
  101. package/dist/storage/storageSync.js.map +1 -1
  102. package/dist/storage/types.d.ts +59 -0
  103. package/dist/storage/types.d.ts.map +1 -1
  104. package/dist/storage/types.js +12 -1
  105. package/dist/storage/types.js.map +1 -1
  106. package/dist/sync.d.ts.map +1 -1
  107. package/dist/sync.js +66 -43
  108. package/dist/sync.js.map +1 -1
  109. package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts +2 -0
  110. package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts.map +1 -0
  111. package/dist/tests/DeletedCoValuesEraserScheduler.test.js +149 -0
  112. package/dist/tests/DeletedCoValuesEraserScheduler.test.js.map +1 -0
  113. package/dist/tests/GarbageCollector.test.js +5 -6
  114. package/dist/tests/GarbageCollector.test.js.map +1 -1
  115. package/dist/tests/LinkedList.test.js +90 -0
  116. package/dist/tests/LinkedList.test.js.map +1 -1
  117. package/dist/tests/OutgoingLoadQueue.test.d.ts +2 -0
  118. package/dist/tests/OutgoingLoadQueue.test.d.ts.map +1 -0
  119. package/dist/tests/OutgoingLoadQueue.test.js +814 -0
  120. package/dist/tests/OutgoingLoadQueue.test.js.map +1 -0
  121. package/dist/tests/StorageApiAsync.test.js +484 -152
  122. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  123. package/dist/tests/StorageApiSync.test.js +505 -136
  124. package/dist/tests/StorageApiSync.test.js.map +1 -1
  125. package/dist/tests/WasmCrypto.test.js +6 -3
  126. package/dist/tests/WasmCrypto.test.js.map +1 -1
  127. package/dist/tests/coValueCore.loadFromStorage.test.js +3 -0
  128. package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -1
  129. package/dist/tests/coValueCore.test.js +34 -13
  130. package/dist/tests/coValueCore.test.js.map +1 -1
  131. package/dist/tests/coreWasm.test.js +127 -4
  132. package/dist/tests/coreWasm.test.js.map +1 -1
  133. package/dist/tests/crypto.test.js +89 -93
  134. package/dist/tests/crypto.test.js.map +1 -1
  135. package/dist/tests/deleteCoValue.test.d.ts +2 -0
  136. package/dist/tests/deleteCoValue.test.d.ts.map +1 -0
  137. package/dist/tests/deleteCoValue.test.js +313 -0
  138. package/dist/tests/deleteCoValue.test.js.map +1 -0
  139. package/dist/tests/group.removeMember.test.js +18 -30
  140. package/dist/tests/group.removeMember.test.js.map +1 -1
  141. package/dist/tests/knownState.lazyLoading.test.js +3 -0
  142. package/dist/tests/knownState.lazyLoading.test.js.map +1 -1
  143. package/dist/tests/sync.concurrentLoad.test.d.ts +2 -0
  144. package/dist/tests/sync.concurrentLoad.test.d.ts.map +1 -0
  145. package/dist/tests/sync.concurrentLoad.test.js +481 -0
  146. package/dist/tests/sync.concurrentLoad.test.js.map +1 -0
  147. package/dist/tests/sync.deleted.test.d.ts +2 -0
  148. package/dist/tests/sync.deleted.test.d.ts.map +1 -0
  149. package/dist/tests/sync.deleted.test.js +214 -0
  150. package/dist/tests/sync.deleted.test.js.map +1 -0
  151. package/dist/tests/sync.mesh.test.js +3 -2
  152. package/dist/tests/sync.mesh.test.js.map +1 -1
  153. package/dist/tests/sync.storage.test.js +4 -3
  154. package/dist/tests/sync.storage.test.js.map +1 -1
  155. package/dist/tests/sync.test.js +3 -2
  156. package/dist/tests/sync.test.js.map +1 -1
  157. package/dist/tests/testStorage.d.ts +3 -0
  158. package/dist/tests/testStorage.d.ts.map +1 -1
  159. package/dist/tests/testStorage.js +17 -1
  160. package/dist/tests/testStorage.js.map +1 -1
  161. package/dist/tests/testUtils.d.ts +7 -3
  162. package/dist/tests/testUtils.d.ts.map +1 -1
  163. package/dist/tests/testUtils.js +19 -4
  164. package/dist/tests/testUtils.js.map +1 -1
  165. package/package.json +6 -16
  166. package/src/PeerState.ts +26 -3
  167. package/src/coValueContentMessage.ts +0 -14
  168. package/src/coValueCore/SessionMap.ts +43 -1
  169. package/src/coValueCore/coValueCore.ts +415 -27
  170. package/src/coValueCore/verifiedState.ts +26 -3
  171. package/src/coValues/coList.ts +9 -3
  172. package/src/coValues/group.ts +5 -6
  173. package/src/config.ts +4 -13
  174. package/src/crypto/NapiCrypto.ts +29 -13
  175. package/src/crypto/RNCrypto.ts +29 -11
  176. package/src/crypto/WasmCrypto.ts +67 -20
  177. package/src/crypto/WasmCryptoEdge.ts +5 -1
  178. package/src/crypto/crypto.ts +16 -4
  179. package/src/exports.ts +4 -2
  180. package/src/ids.ts +11 -1
  181. package/src/localNode.ts +15 -0
  182. package/src/platformUtils.ts +26 -0
  183. package/src/queue/LinkedList.ts +34 -4
  184. package/src/queue/OutgoingLoadQueue.ts +307 -0
  185. package/src/storage/DeletedCoValuesEraserScheduler.ts +124 -0
  186. package/src/storage/sqlite/client.ts +77 -0
  187. package/src/storage/sqlite/sqliteMigrations.ts +7 -0
  188. package/src/storage/sqliteAsync/client.ts +75 -0
  189. package/src/storage/storageAsync.ts +62 -0
  190. package/src/storage/storageSync.ts +58 -0
  191. package/src/storage/types.ts +69 -0
  192. package/src/sync.ts +78 -46
  193. package/src/tests/DeletedCoValuesEraserScheduler.test.ts +185 -0
  194. package/src/tests/GarbageCollector.test.ts +6 -10
  195. package/src/tests/LinkedList.test.ts +111 -0
  196. package/src/tests/OutgoingLoadQueue.test.ts +1129 -0
  197. package/src/tests/StorageApiAsync.test.ts +572 -162
  198. package/src/tests/StorageApiSync.test.ts +580 -143
  199. package/src/tests/WasmCrypto.test.ts +8 -3
  200. package/src/tests/coValueCore.loadFromStorage.test.ts +6 -0
  201. package/src/tests/coValueCore.test.ts +49 -14
  202. package/src/tests/coreWasm.test.ts +319 -10
  203. package/src/tests/crypto.test.ts +141 -150
  204. package/src/tests/deleteCoValue.test.ts +528 -0
  205. package/src/tests/group.removeMember.test.ts +35 -35
  206. package/src/tests/knownState.lazyLoading.test.ts +6 -0
  207. package/src/tests/sync.concurrentLoad.test.ts +650 -0
  208. package/src/tests/sync.deleted.test.ts +294 -0
  209. package/src/tests/sync.mesh.test.ts +5 -2
  210. package/src/tests/sync.storage.test.ts +6 -3
  211. package/src/tests/sync.test.ts +5 -2
  212. package/src/tests/testStorage.ts +31 -2
  213. package/src/tests/testUtils.ts +31 -10
  214. package/dist/crypto/PureJSCrypto.d.ts +0 -77
  215. package/dist/crypto/PureJSCrypto.d.ts.map +0 -1
  216. package/dist/crypto/PureJSCrypto.js +0 -236
  217. package/dist/crypto/PureJSCrypto.js.map +0 -1
  218. package/dist/tests/PureJSCrypto.test.d.ts +0 -2
  219. package/dist/tests/PureJSCrypto.test.d.ts.map +0 -1
  220. package/dist/tests/PureJSCrypto.test.js +0 -145
  221. package/dist/tests/PureJSCrypto.test.js.map +0 -1
  222. package/src/crypto/PureJSCrypto.ts +0 -429
  223. package/src/tests/PureJSCrypto.test.ts +0 -217
@@ -1,14 +1,8 @@
1
- import { randomUUID } from "node:crypto";
2
- import { unlinkSync } from "node:fs";
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 { LocalNode, logger } from "../exports.js";
1
+ import { describe, expect, test, vi, afterEach } from "vitest";
2
+ import { logger } from "../exports.js";
8
3
  import { emptyKnownState } from "../knownState.js";
9
- import { createSyncStorage } from "./testStorage.js";
10
- import { loadCoValueOrFail, randomAgentAndSessionID } from "./testUtils.js";
11
- const crypto = await WasmCrypto.create();
4
+ import { createSyncStorage, getAllCoValuesWaitingForDelete, getCoValueStoredSessions, getDbPath, } from "./testStorage.js";
5
+ import { fillCoMapWithLargeData, loadCoValueOrFail, setupTestNode, } from "./testUtils.js";
12
6
  /**
13
7
  * Helper function that gets new content since a known state, throwing if:
14
8
  * - The coValue is not verified
@@ -24,53 +18,33 @@ function getNewContentSince(coValue, knownState) {
24
18
  }
25
19
  return contentMessage;
26
20
  }
27
- async function createFixturesNode(customDbPath) {
28
- const [admin, session] = randomAgentAndSessionID();
29
- const node = new LocalNode(admin.agentSecret, session, crypto);
30
- // Create a unique database file for each test
31
- const dbPath = customDbPath ?? join(tmpdir(), `test-${randomUUID()}.db`);
32
- const storage = createSyncStorage({
33
- filename: dbPath,
34
- nodeName: "test",
35
- storageName: "test-storage",
36
- });
37
- onTestFinished(() => {
38
- try {
39
- unlinkSync(dbPath);
40
- }
41
- catch { }
42
- });
43
- node.setStorage(storage);
44
- return {
45
- fixturesNode: node,
46
- dbPath,
47
- };
48
- }
49
- async function createTestNode(dbPath) {
50
- const [admin, session] = randomAgentAndSessionID();
51
- const node = new LocalNode(admin.agentSecret, session, crypto);
52
- const storage = createSyncStorage({
53
- filename: dbPath,
54
- nodeName: "test",
55
- storageName: "test-storage",
56
- });
57
- return {
58
- node,
59
- storage,
60
- };
61
- }
21
+ afterEach(() => {
22
+ vi.useRealTimers();
23
+ });
62
24
  describe("StorageApiSync", () => {
63
25
  describe("getKnownState", () => {
64
26
  test("should return empty known state for new coValue ID and cache the result", async () => {
65
- const { fixturesNode } = await createFixturesNode();
66
- const { storage } = await createTestNode();
67
- const id = fixturesNode.createGroup().id;
27
+ const fixtures = setupTestNode();
28
+ const client = setupTestNode();
29
+ const { storage } = client.addStorage({
30
+ storage: createSyncStorage({
31
+ nodeName: "test",
32
+ storageName: "test-storage",
33
+ }),
34
+ });
35
+ const id = fixtures.node.createGroup().id;
68
36
  const knownState = storage.getKnownState(id);
69
37
  expect(knownState).toEqual(emptyKnownState(id));
70
38
  expect(storage.getKnownState(id)).toBe(knownState); // Should return same instance
71
39
  });
72
40
  test("should return separate known state instances for different coValue IDs", async () => {
73
- const { storage } = await createTestNode();
41
+ const client = setupTestNode();
42
+ const { storage } = client.addStorage({
43
+ storage: createSyncStorage({
44
+ nodeName: "test",
45
+ storageName: "test-storage",
46
+ }),
47
+ });
74
48
  const id1 = "test-id-1";
75
49
  const id2 = "test-id-2";
76
50
  const knownState1 = storage.getKnownState(id1);
@@ -80,7 +54,13 @@ describe("StorageApiSync", () => {
80
54
  });
81
55
  describe("load", () => {
82
56
  test("should fail gracefully when loading non-existent coValue and preserve known state", async () => {
83
- const { storage } = await createTestNode();
57
+ const client = setupTestNode();
58
+ const { storage } = client.addStorage({
59
+ storage: createSyncStorage({
60
+ nodeName: "test",
61
+ storageName: "test-storage",
62
+ }),
63
+ });
84
64
  const id = "non-existent-id";
85
65
  const callback = vi.fn();
86
66
  const done = vi.fn();
@@ -95,12 +75,27 @@ describe("StorageApiSync", () => {
95
75
  expect(afterLoadKnownState).toEqual(initialKnownState);
96
76
  });
97
77
  test("should successfully load coValue with header and update known state", async () => {
98
- const { fixturesNode, dbPath } = await createFixturesNode();
99
- const { node, storage } = await createTestNode(dbPath);
100
- const callback = vi.fn((content) => node.syncManager.handleNewContent(content, "storage"));
78
+ const dbPath = getDbPath();
79
+ const fixtures = setupTestNode();
80
+ fixtures.addStorage({
81
+ storage: createSyncStorage({
82
+ filename: dbPath,
83
+ nodeName: "test",
84
+ storageName: "test-storage",
85
+ }),
86
+ });
87
+ const client = setupTestNode();
88
+ const { storage } = client.addStorage({
89
+ storage: createSyncStorage({
90
+ filename: dbPath,
91
+ nodeName: "test",
92
+ storageName: "test-storage",
93
+ }),
94
+ });
95
+ const callback = vi.fn((content) => client.node.syncManager.handleNewContent(content, "storage"));
101
96
  const done = vi.fn();
102
97
  // Create a real group and get its content message
103
- const group = fixturesNode.createGroup();
98
+ const group = fixtures.node.createGroup();
104
99
  await group.core.waitForSync();
105
100
  // Get initial known state
106
101
  const initialKnownState = storage.getKnownState(group.id);
@@ -115,16 +110,31 @@ describe("StorageApiSync", () => {
115
110
  // Verify that storage known state is updated after load
116
111
  const updatedKnownState = storage.getKnownState(group.id);
117
112
  expect(updatedKnownState).toEqual(group.core.knownState());
118
- const groupOnNode = await loadCoValueOrFail(node, group.id);
113
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
119
114
  expect(groupOnNode.core.verified.header).toEqual(group.core.verified.header);
120
115
  });
121
116
  test("should successfully load coValue with transactions and update known state", async () => {
122
- const { fixturesNode, dbPath } = await createFixturesNode();
123
- const { node, storage } = await createTestNode(dbPath);
124
- const callback = vi.fn((content) => node.syncManager.handleNewContent(content, "storage"));
117
+ const dbPath = getDbPath();
118
+ const fixtures = setupTestNode();
119
+ fixtures.addStorage({
120
+ storage: createSyncStorage({
121
+ filename: dbPath,
122
+ nodeName: "test",
123
+ storageName: "test-storage",
124
+ }),
125
+ });
126
+ const client = setupTestNode();
127
+ const { storage } = client.addStorage({
128
+ storage: createSyncStorage({
129
+ filename: dbPath,
130
+ nodeName: "test",
131
+ storageName: "test-storage",
132
+ }),
133
+ });
134
+ const callback = vi.fn((content) => client.node.syncManager.handleNewContent(content, "storage"));
125
135
  const done = vi.fn();
126
136
  // Create a real group and add a member to create transactions
127
- const group = fixturesNode.createGroup();
137
+ const group = fixtures.node.createGroup();
128
138
  group.addMember("everyone", "reader");
129
139
  await group.core.waitForSync();
130
140
  // Get initial known state
@@ -135,23 +145,35 @@ describe("StorageApiSync", () => {
135
145
  id: group.id,
136
146
  header: group.core.verified.header,
137
147
  new: expect.objectContaining({
138
- [fixturesNode.currentSessionID]: expect.any(Object),
148
+ [fixtures.node.currentSessionID]: expect.any(Object),
139
149
  }),
140
150
  }));
141
151
  expect(done).toHaveBeenCalledWith(true);
142
152
  // Verify that storage known state is updated after load
143
153
  const updatedKnownState = storage.getKnownState(group.id);
144
154
  expect(updatedKnownState).toEqual(group.core.knownState());
145
- const groupOnNode = await loadCoValueOrFail(node, group.id);
155
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
146
156
  expect(groupOnNode.get("everyone")).toEqual("reader");
147
157
  });
148
158
  });
149
159
  describe("store", () => {
150
160
  test("should successfully store new coValue with header and update known state", async () => {
151
- const { fixturesNode } = await createFixturesNode();
152
- const { node, storage } = await createTestNode();
161
+ const fixtures = setupTestNode();
162
+ fixtures.addStorage({
163
+ storage: createSyncStorage({
164
+ nodeName: "test",
165
+ storageName: "test-storage",
166
+ }),
167
+ });
168
+ const client = setupTestNode();
169
+ const { storage } = client.addStorage({
170
+ storage: createSyncStorage({
171
+ nodeName: "test",
172
+ storageName: "test-storage",
173
+ }),
174
+ });
153
175
  // Create a real group and get its content message
154
- const group = fixturesNode.createGroup();
176
+ const group = fixtures.node.createGroup();
155
177
  const contentMessage = getNewContentSince(group.core, emptyKnownState(group.id));
156
178
  const correctionCallback = vi.fn();
157
179
  // Get initial known state
@@ -161,15 +183,27 @@ describe("StorageApiSync", () => {
161
183
  // Verify that storage known state is updated after store
162
184
  const updatedKnownState = storage.getKnownState(group.id);
163
185
  expect(updatedKnownState).toEqual(group.core.knownState());
164
- node.setStorage(storage);
165
- const groupOnNode = await loadCoValueOrFail(node, group.id);
186
+ client.addStorage({ storage });
187
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
166
188
  expect(groupOnNode.core.verified.header).toEqual(group.core.verified.header);
167
189
  });
168
190
  test("should successfully store coValue with transactions and update known state", async () => {
169
- const { fixturesNode } = await createFixturesNode();
170
- const { node, storage } = await createTestNode();
191
+ const fixtures = setupTestNode();
192
+ fixtures.addStorage({
193
+ storage: createSyncStorage({
194
+ nodeName: "test",
195
+ storageName: "test-storage",
196
+ }),
197
+ });
198
+ const client = setupTestNode();
199
+ const { storage } = client.addStorage({
200
+ storage: createSyncStorage({
201
+ nodeName: "test",
202
+ storageName: "test-storage",
203
+ }),
204
+ });
171
205
  // Create a real group and add a member to create transactions
172
- const group = fixturesNode.createGroup();
206
+ const group = fixtures.node.createGroup();
173
207
  group.addMember("everyone", "reader");
174
208
  const contentMessage = getNewContentSince(group.core, emptyKnownState(group.id));
175
209
  const correctionCallback = vi.fn();
@@ -180,14 +214,26 @@ describe("StorageApiSync", () => {
180
214
  // Verify that storage known state is updated after store
181
215
  const updatedKnownState = storage.getKnownState(group.id);
182
216
  expect(updatedKnownState).toEqual(group.core.knownState());
183
- node.setStorage(storage);
184
- const groupOnNode = await loadCoValueOrFail(node, group.id);
217
+ client.addStorage({ storage });
218
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
185
219
  expect(groupOnNode.get("everyone")).toEqual("reader");
186
220
  });
187
221
  test("should handle correction when header assumption is invalid", async () => {
188
- const { fixturesNode } = await createFixturesNode();
189
- const { node, storage } = await createTestNode();
190
- const group = fixturesNode.createGroup();
222
+ const fixtures = setupTestNode();
223
+ fixtures.addStorage({
224
+ storage: createSyncStorage({
225
+ nodeName: "test",
226
+ storageName: "test-storage",
227
+ }),
228
+ });
229
+ const client = setupTestNode();
230
+ const { storage } = client.addStorage({
231
+ storage: createSyncStorage({
232
+ nodeName: "test",
233
+ storageName: "test-storage",
234
+ }),
235
+ });
236
+ const group = fixtures.node.createGroup();
191
237
  const knownState = group.core.knownState();
192
238
  group.addMember("everyone", "reader");
193
239
  const contentMessage = getNewContentSince(group.core, knownState);
@@ -204,14 +250,26 @@ describe("StorageApiSync", () => {
204
250
  // Verify that storage known state is updated after store with correction
205
251
  const updatedKnownState = storage.getKnownState(group.id);
206
252
  expect(updatedKnownState).toEqual(group.core.knownState());
207
- node.setStorage(storage);
208
- const groupOnNode = await loadCoValueOrFail(node, group.id);
253
+ client.addStorage({ storage });
254
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
209
255
  expect(groupOnNode.get("everyone")).toEqual("reader");
210
256
  });
211
257
  test("should handle correction when new content assumption is invalid", async () => {
212
- const { fixturesNode } = await createFixturesNode();
213
- const { node, storage } = await createTestNode();
214
- const group = fixturesNode.createGroup();
258
+ const fixtures = setupTestNode();
259
+ fixtures.addStorage({
260
+ storage: createSyncStorage({
261
+ nodeName: "test",
262
+ storageName: "test-storage",
263
+ }),
264
+ });
265
+ const client = setupTestNode();
266
+ const { storage } = client.addStorage({
267
+ storage: createSyncStorage({
268
+ nodeName: "test",
269
+ storageName: "test-storage",
270
+ }),
271
+ });
272
+ const group = fixtures.node.createGroup();
215
273
  const initialContent = getNewContentSince(group.core, emptyKnownState(group.id));
216
274
  const initialKnownState = group.core.knownState();
217
275
  group.addMember("everyone", "reader");
@@ -235,14 +293,26 @@ describe("StorageApiSync", () => {
235
293
  // Verify that storage known state is updated after store with correction
236
294
  const finalKnownState = storage.getKnownState(group.id);
237
295
  expect(finalKnownState).toEqual(group.core.knownState());
238
- node.setStorage(storage);
239
- const groupOnNode = await loadCoValueOrFail(node, group.id);
296
+ client.addStorage({ storage });
297
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
240
298
  expect(groupOnNode.get("everyone")).toEqual("writer");
241
299
  });
242
300
  test("should log error and fail when correction callback returns undefined", async () => {
243
- const { fixturesNode } = await createFixturesNode();
244
- const { storage } = await createTestNode();
245
- const group = fixturesNode.createGroup();
301
+ const fixtures = setupTestNode();
302
+ fixtures.addStorage({
303
+ storage: createSyncStorage({
304
+ nodeName: "test",
305
+ storageName: "test-storage",
306
+ }),
307
+ });
308
+ const client = setupTestNode();
309
+ const { storage } = client.addStorage({
310
+ storage: createSyncStorage({
311
+ nodeName: "test",
312
+ storageName: "test-storage",
313
+ }),
314
+ });
315
+ const group = fixtures.node.createGroup();
246
316
  const knownState = group.core.knownState();
247
317
  group.addMember("everyone", "writer");
248
318
  const contentMessage = getNewContentSince(group.core, knownState);
@@ -265,9 +335,21 @@ describe("StorageApiSync", () => {
265
335
  errorSpy.mockClear();
266
336
  });
267
337
  test("should log error and fail when correction callback returns invalid content message", async () => {
268
- const { fixturesNode } = await createFixturesNode();
269
- const { storage } = await createTestNode();
270
- const group = fixturesNode.createGroup();
338
+ const fixtures = setupTestNode();
339
+ fixtures.addStorage({
340
+ storage: createSyncStorage({
341
+ nodeName: "test",
342
+ storageName: "test-storage",
343
+ }),
344
+ });
345
+ const client = setupTestNode();
346
+ const { storage } = client.addStorage({
347
+ storage: createSyncStorage({
348
+ nodeName: "test",
349
+ storageName: "test-storage",
350
+ }),
351
+ });
352
+ const group = fixtures.node.createGroup();
271
353
  const knownState = group.core.knownState();
272
354
  group.addMember("everyone", "writer");
273
355
  const contentMessage = getNewContentSince(group.core, knownState);
@@ -288,14 +370,35 @@ describe("StorageApiSync", () => {
288
370
  errorSpy.mockClear();
289
371
  });
290
372
  test("should successfully store coValue with multiple sessions", async () => {
291
- const { fixturesNode, dbPath } = await createFixturesNode();
292
- const { fixturesNode: fixtureNode2 } = await createFixturesNode(dbPath);
293
- const { node, storage } = await createTestNode();
294
- const coValue = fixturesNode.createCoValue({
373
+ const dbPath = getDbPath();
374
+ const fixtures = setupTestNode();
375
+ fixtures.addStorage({
376
+ storage: createSyncStorage({
377
+ filename: dbPath,
378
+ nodeName: "test",
379
+ storageName: "test-storage",
380
+ }),
381
+ });
382
+ const fixture2 = setupTestNode();
383
+ fixture2.addStorage({
384
+ storage: createSyncStorage({
385
+ filename: dbPath,
386
+ nodeName: "test",
387
+ storageName: "test-storage",
388
+ }),
389
+ });
390
+ const client = setupTestNode();
391
+ const { storage } = client.addStorage({
392
+ storage: createSyncStorage({
393
+ nodeName: "test",
394
+ storageName: "test-storage",
395
+ }),
396
+ });
397
+ const coValue = fixtures.node.createCoValue({
295
398
  type: "comap",
296
399
  ruleset: { type: "unsafeAllowAll" },
297
400
  meta: null,
298
- ...crypto.createdNowUnique(),
401
+ ...fixtures.node.crypto.createdNowUnique(),
299
402
  });
300
403
  coValue.makeTransaction([
301
404
  {
@@ -303,7 +406,7 @@ describe("StorageApiSync", () => {
303
406
  },
304
407
  ], "trusting");
305
408
  await coValue.waitForSync();
306
- const mapOnNode2 = await loadCoValueOrFail(fixtureNode2, coValue.id);
409
+ const mapOnNode2 = await loadCoValueOrFail(fixture2.node, coValue.id);
307
410
  coValue.makeTransaction([
308
411
  {
309
412
  count: 2,
@@ -313,22 +416,164 @@ describe("StorageApiSync", () => {
313
416
  const contentMessage = getNewContentSince(mapOnNode2.core, emptyKnownState(mapOnNode2.id));
314
417
  const correctionCallback = vi.fn();
315
418
  storage.store(contentMessage, correctionCallback);
316
- node.setStorage(storage);
317
- const finalMap = await loadCoValueOrFail(node, mapOnNode2.id);
419
+ client.addStorage({ storage });
420
+ const finalMap = await loadCoValueOrFail(client.node, mapOnNode2.id);
318
421
  expect(finalMap.core.knownState()).toEqual(knownState);
319
422
  });
320
423
  });
424
+ describe("delete flow", () => {
425
+ test("deleteCoValue enqueues the coValue for erasure", async () => {
426
+ const client = setupTestNode();
427
+ const { storage } = client.addStorage({
428
+ storage: createSyncStorage({
429
+ nodeName: "test",
430
+ storageName: "test-storage",
431
+ }),
432
+ });
433
+ const group = client.node.createGroup();
434
+ const map = group.createMap();
435
+ map.core.deleteCoValue();
436
+ await map.core.waitForSync();
437
+ const queued = await getAllCoValuesWaitingForDelete(storage);
438
+ expect(queued).toContain(map.id);
439
+ });
440
+ test("background erasure doesn't run if not enabled", async () => {
441
+ const dbPath = getDbPath();
442
+ const node = setupTestNode();
443
+ const { storage } = node.addStorage({
444
+ storage: createSyncStorage({
445
+ filename: dbPath,
446
+ nodeName: "test",
447
+ storageName: "test-storage",
448
+ }),
449
+ });
450
+ const group = node.node.createGroup();
451
+ const map = group.createMap();
452
+ map.set("k", "v");
453
+ await map.core.waitForSync();
454
+ vi.useFakeTimers();
455
+ map.core.deleteCoValue();
456
+ await map.core.waitForSync();
457
+ await vi.advanceTimersByTimeAsync(70000);
458
+ // Queue drained
459
+ expect(await getAllCoValuesWaitingForDelete(storage)).toContain(map.id);
460
+ });
461
+ test("background erasure run if enabled", async () => {
462
+ const dbPath = getDbPath();
463
+ const node = setupTestNode();
464
+ const { storage } = node.addStorage({
465
+ storage: createSyncStorage({
466
+ filename: dbPath,
467
+ nodeName: "test",
468
+ storageName: "test-storage",
469
+ }),
470
+ });
471
+ vi.useFakeTimers();
472
+ node.node.enableDeletedCoValuesErasure();
473
+ const group = node.node.createGroup();
474
+ const map = group.createMap();
475
+ map.set("k", "v");
476
+ await map.core.waitForSync();
477
+ map.core.deleteCoValue();
478
+ await map.core.waitForSync();
479
+ await vi.advanceTimersByTimeAsync(70000);
480
+ // Queue drained
481
+ expect(await getAllCoValuesWaitingForDelete(storage)).not.toContain(map.id);
482
+ const sessionIDs = await getCoValueStoredSessions(storage, map.id);
483
+ expect(sessionIDs).toHaveLength(1);
484
+ expect(sessionIDs[0]).toMatch(/_session_d[1-9A-HJ-NP-Za-km-z]+\$$/); // Delete session format
485
+ });
486
+ test("eraseAllDeletedCoValues deletes history but preserves tombstone", async () => {
487
+ const dbPath = getDbPath();
488
+ const node = setupTestNode();
489
+ const { storage } = node.addStorage({
490
+ storage: createSyncStorage({
491
+ filename: dbPath,
492
+ nodeName: "test",
493
+ storageName: "test-storage",
494
+ }),
495
+ });
496
+ const group = node.node.createGroup();
497
+ const map = group.createMap();
498
+ map.set("k", "v");
499
+ await map.core.waitForSync();
500
+ map.core.deleteCoValue();
501
+ await map.core.waitForSync();
502
+ expect(await getAllCoValuesWaitingForDelete(storage)).toContain(map.id);
503
+ await storage.eraseAllDeletedCoValues();
504
+ // Queue drained
505
+ expect(await getAllCoValuesWaitingForDelete(storage)).not.toContain(map.id);
506
+ // Tombstone preserved + history erased when loaded from storage
507
+ const client = setupTestNode();
508
+ const { storage: clientStorage } = client.addStorage({
509
+ storage: createSyncStorage({
510
+ filename: dbPath,
511
+ nodeName: "test",
512
+ storageName: "test-storage",
513
+ }),
514
+ });
515
+ const loaded = await loadCoValueOrFail(client.node, map.id);
516
+ expect(loaded.core.isDeleted).toBe(true);
517
+ expect(loaded.get("k")).toBeUndefined();
518
+ const sessionIDs = await getCoValueStoredSessions(clientStorage, map.id);
519
+ expect(sessionIDs).toHaveLength(1);
520
+ expect(sessionIDs[0]).toMatch(/_session_d[1-9A-HJ-NP-Za-km-z]+\$$/); // Delete session format
521
+ });
522
+ test("eraseAllDeletedCoValues does not break when called while a coValue is streaming from storage", async () => {
523
+ const dbPath = getDbPath();
524
+ const node = setupTestNode();
525
+ const storage = createSyncStorage({
526
+ filename: dbPath,
527
+ nodeName: "test",
528
+ storageName: "test-storage",
529
+ });
530
+ node.addStorage({ storage });
531
+ const group = node.node.createGroup();
532
+ const map = group.createMap();
533
+ fillCoMapWithLargeData(map);
534
+ await map.core.waitForSync();
535
+ map.core.deleteCoValue();
536
+ await map.core.waitForSync();
537
+ storage.close();
538
+ const newStorage = createSyncStorage({
539
+ filename: dbPath,
540
+ nodeName: "test",
541
+ storageName: "test-storage",
542
+ });
543
+ const callback = vi.fn();
544
+ const loadPromise = new Promise((resolve) => {
545
+ newStorage.load(map.id, callback, resolve);
546
+ });
547
+ await newStorage.eraseAllDeletedCoValues();
548
+ expect(await loadPromise).toBe(true);
549
+ });
550
+ });
321
551
  describe("dependencies", () => {
322
552
  test("should load dependencies before dependent coValues and update all known states", async () => {
323
- const { fixturesNode, dbPath } = await createFixturesNode();
324
- const { node, storage } = await createTestNode(dbPath);
553
+ const dbPath = getDbPath();
554
+ const fixtures = setupTestNode();
555
+ fixtures.addStorage({
556
+ storage: createSyncStorage({
557
+ filename: dbPath,
558
+ nodeName: "test",
559
+ storageName: "test-storage",
560
+ }),
561
+ });
562
+ const client = setupTestNode();
563
+ const { storage } = client.addStorage({
564
+ storage: createSyncStorage({
565
+ filename: dbPath,
566
+ nodeName: "test",
567
+ storageName: "test-storage",
568
+ }),
569
+ });
325
570
  // Create a group and a map owned by that group to create dependencies
326
- const group = fixturesNode.createGroup();
571
+ const group = fixtures.node.createGroup();
327
572
  group.addMember("everyone", "reader");
328
573
  const map = group.createMap({ test: "value" });
329
574
  await group.core.waitForSync();
330
575
  await map.core.waitForSync();
331
- const callback = vi.fn((content) => node.syncManager.handleNewContent(content, "storage"));
576
+ const callback = vi.fn((content) => client.node.syncManager.handleNewContent(content, "storage"));
332
577
  const done = vi.fn();
333
578
  // Get initial known states
334
579
  const initialGroupKnownState = storage.getKnownState(group.id);
@@ -350,20 +595,35 @@ describe("StorageApiSync", () => {
350
595
  const updatedMapKnownState = storage.getKnownState(map.id);
351
596
  expect(updatedGroupKnownState).toEqual(group.core.knownState());
352
597
  expect(updatedMapKnownState).toEqual(map.core.knownState());
353
- node.setStorage(storage);
354
- const mapOnNode = await loadCoValueOrFail(node, map.id);
598
+ client.addStorage({ storage });
599
+ const mapOnNode = await loadCoValueOrFail(client.node, map.id);
355
600
  expect(mapOnNode.get("test")).toEqual("value");
356
601
  });
357
602
  test("should skip loading already loaded dependencies", async () => {
358
- const { fixturesNode, dbPath } = await createFixturesNode();
359
- const { node, storage } = await createTestNode(dbPath);
603
+ const dbPath = getDbPath();
604
+ const fixtures = setupTestNode();
605
+ fixtures.addStorage({
606
+ storage: createSyncStorage({
607
+ filename: dbPath,
608
+ nodeName: "test",
609
+ storageName: "test-storage",
610
+ }),
611
+ });
612
+ const client = setupTestNode();
613
+ const { storage } = client.addStorage({
614
+ storage: createSyncStorage({
615
+ filename: dbPath,
616
+ nodeName: "test",
617
+ storageName: "test-storage",
618
+ }),
619
+ });
360
620
  // Create a group and a map owned by that group
361
- const group = fixturesNode.createGroup();
621
+ const group = fixtures.node.createGroup();
362
622
  group.addMember("everyone", "reader");
363
623
  const map = group.createMap({ test: "value" });
364
624
  await group.core.waitForSync();
365
625
  await map.core.waitForSync();
366
- const callback = vi.fn((content) => node.syncManager.handleNewContent(content, "storage"));
626
+ const callback = vi.fn((content) => client.node.syncManager.handleNewContent(content, "storage"));
367
627
  const done = vi.fn();
368
628
  // Get initial known states
369
629
  const initialGroupKnownState = storage.getKnownState(group.id);
@@ -388,20 +648,35 @@ describe("StorageApiSync", () => {
388
648
  // Verify map known state is updated after second load
389
649
  const finalMapKnownState = storage.getKnownState(map.id);
390
650
  expect(finalMapKnownState).toEqual(map.core.knownState());
391
- node.setStorage(storage);
392
- const mapOnNode = await loadCoValueOrFail(node, map.id);
651
+ client.addStorage({ storage });
652
+ const mapOnNode = await loadCoValueOrFail(client.node, map.id);
393
653
  expect(mapOnNode.get("test")).toEqual("value");
394
654
  });
395
655
  test("should load dependencies again if they were unmounted", async () => {
396
- const { fixturesNode, dbPath } = await createFixturesNode();
397
- const { node, storage } = await createTestNode(dbPath);
656
+ const dbPath = getDbPath();
657
+ const fixtures = setupTestNode();
658
+ fixtures.addStorage({
659
+ storage: createSyncStorage({
660
+ filename: dbPath,
661
+ nodeName: "test",
662
+ storageName: "test-storage",
663
+ }),
664
+ });
665
+ const client = setupTestNode();
666
+ const { storage } = client.addStorage({
667
+ storage: createSyncStorage({
668
+ filename: dbPath,
669
+ nodeName: "test",
670
+ storageName: "test-storage",
671
+ }),
672
+ });
398
673
  // Create a group and a map owned by that group
399
- const group = fixturesNode.createGroup();
674
+ const group = fixtures.node.createGroup();
400
675
  group.addMember("everyone", "reader");
401
676
  const map = group.createMap({ test: "value" });
402
677
  await group.core.waitForSync();
403
678
  await map.core.waitForSync();
404
- const callback = vi.fn((content) => node.syncManager.handleNewContent(content, "storage"));
679
+ const callback = vi.fn((content) => client.node.syncManager.handleNewContent(content, "storage"));
405
680
  const done = vi.fn();
406
681
  // Load the map (and its group)
407
682
  await storage.load(map.id, callback, done);
@@ -420,26 +695,41 @@ describe("StorageApiSync", () => {
420
695
  id: map.id,
421
696
  }));
422
697
  expect(done).toHaveBeenCalledWith(true);
423
- node.setStorage(storage);
424
- const mapOnNode = await loadCoValueOrFail(node, map.id);
698
+ client.addStorage({ storage });
699
+ const mapOnNode = await loadCoValueOrFail(client.node, map.id);
425
700
  expect(mapOnNode.get("test")).toEqual("value");
426
701
  });
427
702
  });
428
703
  describe("waitForSync", () => {
429
704
  test("should resolve immediately when coValue is already synced", async () => {
430
- const { fixturesNode, dbPath } = await createFixturesNode();
431
- const { node, storage } = await createTestNode(dbPath);
705
+ const dbPath = getDbPath();
706
+ const fixtures = setupTestNode();
707
+ fixtures.addStorage({
708
+ storage: createSyncStorage({
709
+ filename: dbPath,
710
+ nodeName: "test",
711
+ storageName: "test-storage",
712
+ }),
713
+ });
714
+ const client = setupTestNode();
715
+ const { storage } = client.addStorage({
716
+ storage: createSyncStorage({
717
+ filename: dbPath,
718
+ nodeName: "test",
719
+ storageName: "test-storage",
720
+ }),
721
+ });
432
722
  // Create a group and add a member
433
- const group = fixturesNode.createGroup();
723
+ const group = fixtures.node.createGroup();
434
724
  group.addMember("everyone", "reader");
435
725
  await group.core.waitForSync();
436
726
  // Store the group in storage
437
727
  const contentMessage = getNewContentSince(group.core, emptyKnownState(group.id));
438
728
  const correctionCallback = vi.fn();
439
729
  storage.store(contentMessage, correctionCallback);
440
- node.setStorage(storage);
730
+ client.addStorage({ storage });
441
731
  // Load the group on the new node
442
- const groupOnNode = await loadCoValueOrFail(node, group.id);
732
+ const groupOnNode = await loadCoValueOrFail(client.node, group.id);
443
733
  // Wait for sync should resolve immediately since the coValue is already synced
444
734
  await expect(storage.waitForSync(group.id, groupOnNode.core)).resolves.toBeUndefined();
445
735
  expect(groupOnNode.get("everyone")).toEqual("reader");
@@ -447,16 +737,37 @@ describe("StorageApiSync", () => {
447
737
  });
448
738
  describe("close", () => {
449
739
  test("should close storage without throwing errors", async () => {
450
- const { storage } = await createTestNode();
740
+ const client = setupTestNode();
741
+ const { storage } = client.addStorage({
742
+ storage: createSyncStorage({
743
+ nodeName: "test",
744
+ storageName: "test-storage",
745
+ }),
746
+ });
451
747
  expect(() => storage.close()).not.toThrow();
452
748
  });
453
749
  });
454
750
  describe("loadKnownState", () => {
455
751
  test("should return correct knownState structure for existing CoValue", async () => {
456
- const { fixturesNode, dbPath } = await createFixturesNode();
457
- const { storage } = await createTestNode(dbPath);
752
+ const dbPath = getDbPath();
753
+ const fixtures = setupTestNode();
754
+ fixtures.addStorage({
755
+ storage: createSyncStorage({
756
+ filename: dbPath,
757
+ nodeName: "test",
758
+ storageName: "test-storage",
759
+ }),
760
+ });
761
+ const client = setupTestNode();
762
+ const { storage } = client.addStorage({
763
+ storage: createSyncStorage({
764
+ filename: dbPath,
765
+ nodeName: "test",
766
+ storageName: "test-storage",
767
+ }),
768
+ });
458
769
  // Create a group to have data in the database
459
- const group = fixturesNode.createGroup();
770
+ const group = fixtures.node.createGroup();
460
771
  group.addMember("everyone", "reader");
461
772
  await group.core.waitForSync();
462
773
  const result = await new Promise((resolve) => {
@@ -468,21 +779,42 @@ describe("StorageApiSync", () => {
468
779
  expect(result?.sessions).toEqual(group.core.knownState().sessions);
469
780
  });
470
781
  test("should return undefined for non-existent CoValue", async () => {
471
- const { storage } = await createTestNode();
782
+ const client = setupTestNode();
783
+ const { storage } = client.addStorage({
784
+ storage: createSyncStorage({
785
+ nodeName: "test",
786
+ storageName: "test-storage",
787
+ }),
788
+ });
472
789
  const result = await new Promise((resolve) => {
473
790
  storage.loadKnownState("co_nonexistent", resolve);
474
791
  });
475
792
  expect(result).toBeUndefined();
476
793
  });
477
794
  test("should handle CoValue with no sessions (header only)", async () => {
478
- const { fixturesNode, dbPath } = await createFixturesNode();
479
- const { storage } = await createTestNode(dbPath);
795
+ const dbPath = getDbPath();
796
+ const fixtures = setupTestNode();
797
+ fixtures.addStorage({
798
+ storage: createSyncStorage({
799
+ filename: dbPath,
800
+ nodeName: "test",
801
+ storageName: "test-storage",
802
+ }),
803
+ });
804
+ const client = setupTestNode();
805
+ const { storage } = client.addStorage({
806
+ storage: createSyncStorage({
807
+ filename: dbPath,
808
+ nodeName: "test",
809
+ storageName: "test-storage",
810
+ }),
811
+ });
480
812
  // Create a CoValue with just a header (no transactions yet)
481
- const coValue = fixturesNode.createCoValue({
813
+ const coValue = fixtures.node.createCoValue({
482
814
  type: "comap",
483
815
  ruleset: { type: "unsafeAllowAll" },
484
816
  meta: null,
485
- ...crypto.createdNowUnique(),
817
+ ...fixtures.node.crypto.createdNowUnique(),
486
818
  });
487
819
  await coValue.waitForSync();
488
820
  const result = await new Promise((resolve) => {
@@ -495,19 +827,41 @@ describe("StorageApiSync", () => {
495
827
  expect(Object.keys(result?.sessions || {}).length).toBe(0);
496
828
  });
497
829
  test("should handle CoValue with multiple sessions", async () => {
498
- const { fixturesNode, dbPath } = await createFixturesNode();
499
- const { fixturesNode: fixturesNode2 } = await createFixturesNode(dbPath);
500
- const { storage } = await createTestNode(dbPath);
830
+ const dbPath = getDbPath();
831
+ const fixtures = setupTestNode();
832
+ fixtures.addStorage({
833
+ storage: createSyncStorage({
834
+ filename: dbPath,
835
+ nodeName: "test",
836
+ storageName: "test-storage",
837
+ }),
838
+ });
839
+ const fixtures2 = setupTestNode();
840
+ fixtures2.addStorage({
841
+ storage: createSyncStorage({
842
+ filename: dbPath,
843
+ nodeName: "test",
844
+ storageName: "test-storage",
845
+ }),
846
+ });
847
+ const client = setupTestNode();
848
+ const { storage } = client.addStorage({
849
+ storage: createSyncStorage({
850
+ filename: dbPath,
851
+ nodeName: "test",
852
+ storageName: "test-storage",
853
+ }),
854
+ });
501
855
  // Create a CoValue and have two nodes make transactions
502
- const coValue = fixturesNode.createCoValue({
856
+ const coValue = fixtures.node.createCoValue({
503
857
  type: "comap",
504
858
  ruleset: { type: "unsafeAllowAll" },
505
859
  meta: null,
506
- ...crypto.createdNowUnique(),
860
+ ...fixtures.node.crypto.createdNowUnique(),
507
861
  });
508
862
  coValue.makeTransaction([{ key1: "value1" }], "trusting");
509
863
  await coValue.waitForSync();
510
- const coValueOnNode2 = await loadCoValueOrFail(fixturesNode2, coValue.id);
864
+ const coValueOnNode2 = await loadCoValueOrFail(fixtures2.node, coValue.id);
511
865
  coValueOnNode2.set("key2", "value2", "trusting");
512
866
  await coValueOnNode2.core.waitForSync();
513
867
  const result = await new Promise((resolve) => {
@@ -522,10 +876,25 @@ describe("StorageApiSync", () => {
522
876
  expect(result?.sessions).toEqual(coValueOnNode2.core.knownState().sessions);
523
877
  });
524
878
  test("should use cache when knownState is cached", async () => {
525
- const { fixturesNode, dbPath } = await createFixturesNode();
526
- const { storage } = await createTestNode(dbPath);
879
+ const dbPath = getDbPath();
880
+ const fixtures = setupTestNode();
881
+ fixtures.addStorage({
882
+ storage: createSyncStorage({
883
+ filename: dbPath,
884
+ nodeName: "test",
885
+ storageName: "test-storage",
886
+ }),
887
+ });
888
+ const client = setupTestNode();
889
+ const { storage } = client.addStorage({
890
+ storage: createSyncStorage({
891
+ filename: dbPath,
892
+ nodeName: "test",
893
+ storageName: "test-storage",
894
+ }),
895
+ });
527
896
  // Create a group to have data in the database
528
- const group = fixturesNode.createGroup();
897
+ const group = fixtures.node.createGroup();
529
898
  group.addMember("everyone", "reader");
530
899
  await group.core.waitForSync();
531
900
  // First call should hit the database and cache the result