cojson 0.13.11 → 0.13.13

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 (72) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/CoValuesStore.d.ts +3 -1
  4. package/dist/CoValuesStore.d.ts.map +1 -1
  5. package/dist/CoValuesStore.js +7 -6
  6. package/dist/CoValuesStore.js.map +1 -1
  7. package/dist/PeerState.d.ts +0 -2
  8. package/dist/PeerState.d.ts.map +1 -1
  9. package/dist/PeerState.js +0 -1
  10. package/dist/PeerState.js.map +1 -1
  11. package/dist/SyncStateManager.js +2 -2
  12. package/dist/SyncStateManager.js.map +1 -1
  13. package/dist/coValueCore.js +2 -2
  14. package/dist/coValueCore.js.map +1 -1
  15. package/dist/coValueState.d.ts +21 -46
  16. package/dist/coValueState.d.ts.map +1 -1
  17. package/dist/coValueState.js +170 -246
  18. package/dist/coValueState.js.map +1 -1
  19. package/dist/coValues/group.js +2 -2
  20. package/dist/coValues/group.js.map +1 -1
  21. package/dist/exports.d.ts +2 -4
  22. package/dist/exports.d.ts.map +1 -1
  23. package/dist/exports.js +1 -2
  24. package/dist/exports.js.map +1 -1
  25. package/dist/localNode.d.ts.map +1 -1
  26. package/dist/localNode.js +20 -16
  27. package/dist/localNode.js.map +1 -1
  28. package/dist/sync.d.ts.map +1 -1
  29. package/dist/sync.js +32 -41
  30. package/dist/sync.js.map +1 -1
  31. package/dist/tests/coValueState.test.js +57 -104
  32. package/dist/tests/coValueState.test.js.map +1 -1
  33. package/dist/tests/group.test.js +1 -2
  34. package/dist/tests/group.test.js.map +1 -1
  35. package/dist/tests/messagesTestUtils.d.ts +4 -1
  36. package/dist/tests/messagesTestUtils.d.ts.map +1 -1
  37. package/dist/tests/messagesTestUtils.js +10 -0
  38. package/dist/tests/messagesTestUtils.js.map +1 -1
  39. package/dist/tests/sync.peerReconciliation.test.js +8 -8
  40. package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
  41. package/dist/tests/sync.test.js +6 -4
  42. package/dist/tests/sync.test.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/CoValuesStore.ts +9 -6
  45. package/src/PeerState.ts +0 -2
  46. package/src/SyncStateManager.ts +2 -2
  47. package/src/coValueCore.ts +2 -2
  48. package/src/coValueState.ts +194 -316
  49. package/src/coValues/group.ts +2 -2
  50. package/src/exports.ts +0 -6
  51. package/src/localNode.ts +30 -21
  52. package/src/sync.ts +35 -43
  53. package/src/tests/coValueState.test.ts +55 -106
  54. package/src/tests/group.test.ts +2 -2
  55. package/src/tests/messagesTestUtils.ts +12 -1
  56. package/src/tests/sync.peerReconciliation.test.ts +8 -8
  57. package/src/tests/sync.test.ts +8 -23
  58. package/dist/storage/FileSystem.d.ts +0 -37
  59. package/dist/storage/FileSystem.d.ts.map +0 -1
  60. package/dist/storage/FileSystem.js +0 -48
  61. package/dist/storage/FileSystem.js.map +0 -1
  62. package/dist/storage/chunksAndKnownStates.d.ts +0 -7
  63. package/dist/storage/chunksAndKnownStates.d.ts.map +0 -1
  64. package/dist/storage/chunksAndKnownStates.js +0 -98
  65. package/dist/storage/chunksAndKnownStates.js.map +0 -1
  66. package/dist/storage/index.d.ts +0 -52
  67. package/dist/storage/index.d.ts.map +0 -1
  68. package/dist/storage/index.js +0 -335
  69. package/dist/storage/index.js.map +0 -1
  70. package/src/storage/FileSystem.ts +0 -113
  71. package/src/storage/chunksAndKnownStates.ts +0 -137
  72. package/src/storage/index.ts +0 -531
@@ -40,10 +40,10 @@ describe("CoValueState", () => {
40
40
  const mockCoValueId = "co_test123" as RawCoID;
41
41
 
42
42
  test("should create unknown state", async () => {
43
- const state = CoValueState.Unknown(mockCoValueId);
43
+ const state = new CoValueState(mockCoValueId);
44
44
 
45
45
  expect(state.id).toBe(mockCoValueId);
46
- expect(state.state.type).toBe("unknown");
46
+ expect(state.highLevelState).toBe("unknown");
47
47
  expect(
48
48
  await metricReader.getMetricValue("jazz.covalues.loaded", {
49
49
  state: "unknown",
@@ -52,11 +52,14 @@ describe("CoValueState", () => {
52
52
  });
53
53
 
54
54
  test("should create loading state", async () => {
55
- const peerIds = ["peer1", "peer2"];
56
- const state = CoValueState.Loading(mockCoValueId, peerIds);
55
+ const state = new CoValueState(mockCoValueId);
56
+ state.loadFromPeers([
57
+ createMockPeerState({ id: "peer1", role: "server" }),
58
+ createMockPeerState({ id: "peer2", role: "server" }),
59
+ ]);
57
60
 
58
61
  expect(state.id).toBe(mockCoValueId);
59
- expect(state.state.type).toBe("loading");
62
+ expect(state.highLevelState).toBe("loading");
60
63
  expect(
61
64
  await metricReader.getMetricValue("jazz.covalues.loaded", {
62
65
  state: "loading",
@@ -66,11 +69,12 @@ describe("CoValueState", () => {
66
69
 
67
70
  test("should create available state", async () => {
68
71
  const mockCoValue = createMockCoValueCore(mockCoValueId);
69
- const state = CoValueState.Available(mockCoValue);
72
+ const state = new CoValueState(mockCoValueId);
73
+ state.internalMarkMagicallyAvailable(mockCoValue);
70
74
 
71
75
  expect(state.id).toBe(mockCoValueId);
72
- assert(state.state.type === "available");
73
- expect(state.state.coValue).toBe(mockCoValue);
76
+ expect(state.highLevelState).toBe("available");
77
+ expect(state.core).toBe(mockCoValue);
74
78
  await expect(state.getCoValue()).resolves.toEqual(mockCoValue);
75
79
  expect(
76
80
  await metricReader.getMetricValue("jazz.covalues.loaded", {
@@ -81,7 +85,11 @@ describe("CoValueState", () => {
81
85
 
82
86
  test("should handle found action", async () => {
83
87
  const mockCoValue = createMockCoValueCore(mockCoValueId);
84
- const state = CoValueState.Loading(mockCoValueId, ["peer1", "peer2"]);
88
+ const state = new CoValueState(mockCoValueId);
89
+ state.loadFromPeers([
90
+ createMockPeerState({ id: "peer1", role: "server" }),
91
+ createMockPeerState({ id: "peer2", role: "server" }),
92
+ ]);
85
93
 
86
94
  expect(
87
95
  await metricReader.getMetricValue("jazz.covalues.loaded", {
@@ -96,10 +104,7 @@ describe("CoValueState", () => {
96
104
 
97
105
  const stateValuePromise = state.getCoValue();
98
106
 
99
- state.dispatch({
100
- type: "available",
101
- coValue: mockCoValue,
102
- });
107
+ state.internalMarkMagicallyAvailable(mockCoValue);
103
108
 
104
109
  const result = await state.getCoValue();
105
110
  expect(result).toBe(mockCoValue);
@@ -117,17 +122,6 @@ describe("CoValueState", () => {
117
122
  ).toBe(0);
118
123
  });
119
124
 
120
- test("should ignore actions when not in loading state", () => {
121
- const state = CoValueState.Unknown(mockCoValueId);
122
-
123
- state.dispatch({
124
- type: "not-found-in-peer",
125
- peerId: "peer1",
126
- });
127
-
128
- expect(state.state.type).toBe("unknown");
129
- });
130
-
131
125
  test("should retry loading from peers when unsuccessful", async () => {
132
126
  vi.useFakeTimers();
133
127
 
@@ -137,10 +131,7 @@ describe("CoValueState", () => {
137
131
  role: "server",
138
132
  },
139
133
  async () => {
140
- state.dispatch({
141
- type: "not-found-in-peer",
142
- peerId: "peer1",
143
- });
134
+ state.markNotFoundInPeer("peer1");
144
135
  },
145
136
  );
146
137
  const peer2 = createMockPeerState(
@@ -149,15 +140,12 @@ describe("CoValueState", () => {
149
140
  role: "server",
150
141
  },
151
142
  async () => {
152
- state.dispatch({
153
- type: "not-found-in-peer",
154
- peerId: "peer2",
155
- });
143
+ state.markNotFoundInPeer("peer2");
156
144
  },
157
145
  );
158
146
  const mockPeers = [peer1, peer2] as unknown as PeerState[];
159
147
 
160
- const state = CoValueState.Unknown(mockCoValueId);
148
+ const state = new CoValueState(mockCoValueId);
161
149
  const loadPromise = state.loadFromPeers(mockPeers);
162
150
 
163
151
  // Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
@@ -173,7 +161,7 @@ describe("CoValueState", () => {
173
161
  expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
174
162
  CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
175
163
  );
176
- expect(state.state.type).toBe("unavailable");
164
+ expect(state.highLevelState).toBe("unavailable");
177
165
  await expect(state.getCoValue()).resolves.toBe("unavailable");
178
166
 
179
167
  vi.useRealTimers();
@@ -188,11 +176,7 @@ describe("CoValueState", () => {
188
176
  role: "server",
189
177
  },
190
178
  async () => {
191
- peer1.erroredCoValues.set(mockCoValueId, new Error("test") as any);
192
- state.dispatch({
193
- type: "not-found-in-peer",
194
- peerId: "peer1",
195
- });
179
+ state.markErrored("peer1", {} as any);
196
180
  },
197
181
  );
198
182
  const peer2 = createMockPeerState(
@@ -201,16 +185,13 @@ describe("CoValueState", () => {
201
185
  role: "server",
202
186
  },
203
187
  async () => {
204
- state.dispatch({
205
- type: "not-found-in-peer",
206
- peerId: "peer2",
207
- });
188
+ state.markNotFoundInPeer("peer2");
208
189
  },
209
190
  );
210
191
 
211
192
  const mockPeers = [peer1, peer2] as unknown as PeerState[];
212
193
 
213
- const state = CoValueState.Unknown(mockCoValueId);
194
+ const state = new CoValueState(mockCoValueId);
214
195
  const loadPromise = state.loadFromPeers(mockPeers);
215
196
 
216
197
  // Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
@@ -224,7 +205,7 @@ describe("CoValueState", () => {
224
205
  expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
225
206
  CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
226
207
  );
227
- expect(state.state.type).toBe("unavailable");
208
+ expect(state.highLevelState).toBe("unavailable");
228
209
  await expect(state.getCoValue()).resolves.toBe("unavailable");
229
210
 
230
211
  vi.useRealTimers();
@@ -239,10 +220,7 @@ describe("CoValueState", () => {
239
220
  role: "storage",
240
221
  },
241
222
  async () => {
242
- state.dispatch({
243
- type: "not-found-in-peer",
244
- peerId: "peer1",
245
- });
223
+ state.markNotFoundInPeer("peer1");
246
224
  },
247
225
  );
248
226
  const peer2 = createMockPeerState(
@@ -251,15 +229,12 @@ describe("CoValueState", () => {
251
229
  role: "server",
252
230
  },
253
231
  async () => {
254
- state.dispatch({
255
- type: "not-found-in-peer",
256
- peerId: "peer2",
257
- });
232
+ state.markNotFoundInPeer("peer2");
258
233
  },
259
234
  );
260
235
  const mockPeers = [peer1, peer2] as unknown as PeerState[];
261
236
 
262
- const state = CoValueState.Unknown(mockCoValueId);
237
+ const state = new CoValueState(mockCoValueId);
263
238
  const loadPromise = state.loadFromPeers(mockPeers);
264
239
 
265
240
  // Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
@@ -273,7 +248,7 @@ describe("CoValueState", () => {
273
248
  expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
274
249
  CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
275
250
  );
276
- expect(state.state.type).toBe("unavailable");
251
+ expect(state.highLevelState).toBe("unavailable");
277
252
  await expect(state.getCoValue()).resolves.toEqual("unavailable");
278
253
 
279
254
  vi.useRealTimers();
@@ -293,17 +268,11 @@ describe("CoValueState", () => {
293
268
  },
294
269
  async () => {
295
270
  retries++;
296
- state.dispatch({
297
- type: "not-found-in-peer",
298
- peerId: "peer1",
299
- });
271
+ state.markNotFoundInPeer("peer1");
300
272
 
301
273
  if (retries === 2) {
302
274
  setTimeout(() => {
303
- state.dispatch({
304
- type: "available",
305
- coValue: createMockCoValueCore(mockCoValueId),
306
- });
275
+ state.markAvailable(createMockCoValueCore(mockCoValueId), "peer1");
307
276
  }, 100);
308
277
  }
309
278
  },
@@ -311,7 +280,7 @@ describe("CoValueState", () => {
311
280
 
312
281
  const mockPeers = [peer1] as unknown as PeerState[];
313
282
 
314
- const state = CoValueState.Unknown(mockCoValueId);
283
+ const state = new CoValueState(mockCoValueId);
315
284
  const loadPromise = state.loadFromPeers(mockPeers);
316
285
 
317
286
  // Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
@@ -322,7 +291,7 @@ describe("CoValueState", () => {
322
291
  await loadPromise;
323
292
 
324
293
  expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(2);
325
- expect(state.state.type).toBe("available");
294
+ expect(state.highLevelState).toBe("available");
326
295
  await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
327
296
  vi.useRealTimers();
328
297
  });
@@ -336,16 +305,13 @@ describe("CoValueState", () => {
336
305
  role: "server",
337
306
  },
338
307
  async () => {
339
- state.dispatch({
340
- type: "not-found-in-peer",
341
- peerId: "peer1",
342
- });
308
+ state.markNotFoundInPeer("peer1");
343
309
  },
344
310
  );
345
311
 
346
312
  const mockPeers = [peer1] as unknown as PeerState[];
347
313
 
348
- const state = CoValueState.Unknown(mockCoValueId);
314
+ const state = new CoValueState(mockCoValueId);
349
315
  const loadPromise = state.loadFromPeers(mockPeers);
350
316
 
351
317
  // Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
@@ -353,17 +319,14 @@ describe("CoValueState", () => {
353
319
  await vi.runAllTimersAsync();
354
320
  }
355
321
 
356
- state.dispatch({
357
- type: "available",
358
- coValue: createMockCoValueCore(mockCoValueId),
359
- });
322
+ state.internalMarkMagicallyAvailable(createMockCoValueCore(mockCoValueId));
360
323
 
361
324
  await loadPromise;
362
325
 
363
326
  expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(
364
327
  CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
365
328
  );
366
- expect(state.state.type).toBe("available");
329
+ expect(state.highLevelState).toBe("available");
367
330
  await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
368
331
 
369
332
  vi.useRealTimers();
@@ -383,22 +346,17 @@ describe("CoValueState", () => {
383
346
  },
384
347
  async () => {
385
348
  if (run > 2) {
386
- state.dispatch({
387
- type: "available",
388
- coValue: createMockCoValueCore(mockCoValueId),
389
- });
349
+ state.markAvailable(createMockCoValueCore(mockCoValueId), "peer1");
350
+ } else {
351
+ state.markNotFoundInPeer("peer1");
352
+ run++;
390
353
  }
391
- state.dispatch({
392
- type: "not-found-in-peer",
393
- peerId: "peer1",
394
- });
395
- run++;
396
354
  },
397
355
  );
398
356
 
399
357
  const mockPeers = [peer1] as unknown as PeerState[];
400
358
 
401
- const state = CoValueState.Unknown(mockCoValueId);
359
+ const state = new CoValueState(mockCoValueId);
402
360
  const loadPromise = state.loadFromPeers(mockPeers);
403
361
 
404
362
  for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
@@ -407,7 +365,7 @@ describe("CoValueState", () => {
407
365
  await loadPromise;
408
366
 
409
367
  expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(3);
410
- expect(state.state.type).toBe("available");
368
+ expect(state.highLevelState).toBe("available");
411
369
  await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
412
370
 
413
371
  vi.useRealTimers();
@@ -424,26 +382,20 @@ describe("CoValueState", () => {
424
382
  role: "storage",
425
383
  },
426
384
  async () => {
427
- state.dispatch({
428
- type: "available",
429
- coValue: mockCoValue,
430
- });
385
+ state.markAvailable(mockCoValue, "peer1");
431
386
  },
432
387
  );
433
388
  const peer2 = createMockPeerState(
434
389
  {
435
- id: "peer1",
390
+ id: "peer2",
436
391
  role: "server",
437
392
  },
438
393
  async () => {
439
- state.dispatch({
440
- type: "not-found-in-peer",
441
- peerId: "peer2",
442
- });
394
+ state.markNotFoundInPeer("peer2");
443
395
  },
444
396
  );
445
397
 
446
- const state = CoValueState.Unknown(mockCoValueId);
398
+ const state = new CoValueState(mockCoValueId);
447
399
  const loadPromise = state.loadFromPeers([peer1, peer2]);
448
400
 
449
401
  for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
@@ -457,7 +409,7 @@ describe("CoValueState", () => {
457
409
  action: "load",
458
410
  ...mockCoValue.knownState(),
459
411
  });
460
- expect(state.state.type).toBe("available");
412
+ expect(state.highLevelState).toBe("available");
461
413
  await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
462
414
 
463
415
  vi.useRealTimers();
@@ -479,20 +431,17 @@ describe("CoValueState", () => {
479
431
  );
480
432
  const peer2 = createMockPeerState(
481
433
  {
482
- id: "peer1",
434
+ id: "peer2",
483
435
  role: "server",
484
436
  },
485
437
  async () => {
486
- state.dispatch({
487
- type: "available",
488
- coValue: mockCoValue,
489
- });
438
+ state.markAvailable(mockCoValue, "peer2");
490
439
  },
491
440
  );
492
441
 
493
442
  peer1.closed = true;
494
443
 
495
- const state = CoValueState.Unknown(mockCoValueId);
444
+ const state = new CoValueState(mockCoValueId);
496
445
  const loadPromise = state.loadFromPeers([peer1, peer2]);
497
446
 
498
447
  for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
@@ -503,7 +452,7 @@ describe("CoValueState", () => {
503
452
  expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(0);
504
453
  expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(1);
505
454
 
506
- expect(state.state.type).toBe("available");
455
+ expect(state.highLevelState).toBe("available");
507
456
  await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
508
457
 
509
458
  vi.useRealTimers();
@@ -520,7 +469,7 @@ describe("CoValueState", () => {
520
469
  async () => {},
521
470
  );
522
471
 
523
- const state = CoValueState.Unknown(mockCoValueId);
472
+ const state = new CoValueState(mockCoValueId);
524
473
  const loadPromise = state.loadFromPeers([peer1]);
525
474
 
526
475
  for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES * 2; i++) {
@@ -532,7 +481,7 @@ describe("CoValueState", () => {
532
481
  CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
533
482
  );
534
483
 
535
- expect(state.state.type).toBe("unavailable");
484
+ expect(state.highLevelState).toBe("unavailable");
536
485
  await expect(state.getCoValue()).resolves.toEqual("unavailable");
537
486
 
538
487
  vi.useRealTimers();
@@ -492,8 +492,8 @@ describe("writeOnly", () => {
492
492
  );
493
493
 
494
494
  node2.node.coValuesStore.coValues.delete(map.id);
495
- expect(node2.node.coValuesStore.get(map.id)).toEqual(
496
- CoValueState.Unknown(map.id),
495
+ expect(node2.node.coValuesStore.get(map.id)?.highLevelState).toBe(
496
+ "unknown",
497
497
  );
498
498
 
499
499
  const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
@@ -1,4 +1,4 @@
1
- import { CoValueCore } from "../exports";
1
+ import { CoValueCore, LocalNode, RawControlledAccount } from "../exports";
2
2
  import {
3
3
  CoValueKnownState,
4
4
  NewContentMessage,
@@ -63,6 +63,17 @@ export function toSimplifiedMessages(
63
63
  return messages.map((m) => toDebugString(m.from, m.to, m.msg));
64
64
  }
65
65
 
66
+ export function nodeRelatedKnownCoValues(node: LocalNode, name: string) {
67
+ const account = node.account as RawControlledAccount;
68
+ const profileID = account.get("profile");
69
+ const profile = profileID && node.expectCoValueLoaded(profileID);
70
+ return {
71
+ [`${name}Account`]: account,
72
+ [`${name}Profile`]: profile,
73
+ [`${name}ProfileGroup`]: profile?.getGroup().core,
74
+ };
75
+ }
76
+
66
77
  export function debugMessages(
67
78
  coValues: Record<string, CoValueCore>,
68
79
  messages: {
@@ -79,10 +79,10 @@ describe("peer reconciliation", () => {
79
79
 
80
80
  const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
81
81
 
82
- assert(mapOnSyncServer.state.type === "available");
82
+ assert(mapOnSyncServer.isAvailable());
83
83
 
84
84
  expect(
85
- expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello"),
85
+ expectMap(mapOnSyncServer.core.getCurrentContent()).get("hello"),
86
86
  ).toEqual("updated");
87
87
 
88
88
  expect(
@@ -126,10 +126,10 @@ describe("peer reconciliation", () => {
126
126
 
127
127
  const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
128
128
 
129
- assert(mapOnSyncServer.state.type === "available");
129
+ assert(mapOnSyncServer.isAvailable());
130
130
 
131
131
  expect(
132
- expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello"),
132
+ expectMap(mapOnSyncServer.core.getCurrentContent()).get("hello"),
133
133
  ).toEqual("updated");
134
134
 
135
135
  expect(peer.outgoing).toMatchObject({
@@ -180,7 +180,7 @@ describe("peer reconciliation", () => {
180
180
  await waitFor(() => {
181
181
  const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
182
182
 
183
- expect(mapOnSyncServer.state.type).toBe("available");
183
+ expect(mapOnSyncServer.highLevelState).toBe("available");
184
184
  });
185
185
 
186
186
  expect(
@@ -225,10 +225,10 @@ describe("peer reconciliation", () => {
225
225
  const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
226
226
 
227
227
  await waitFor(() => {
228
- expect(mapOnSyncServer.state.type).toBe("available");
228
+ expect(mapOnSyncServer.isAvailable()).toBe(true);
229
229
  });
230
230
 
231
- assert(mapOnSyncServer.state.type === "available");
231
+ assert(mapOnSyncServer.isAvailable());
232
232
 
233
233
  expect(
234
234
  SyncMessagesLog.getMessages({
@@ -245,7 +245,7 @@ describe("peer reconciliation", () => {
245
245
  `);
246
246
 
247
247
  expect(
248
- expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello"),
248
+ expectMap(mapOnSyncServer.core.getCurrentContent()).get("hello"),
249
249
  ).toEqual("updated");
250
250
  });
251
251
  });
@@ -1,23 +1,11 @@
1
- import {
2
- assert,
3
- afterEach,
4
- beforeEach,
5
- describe,
6
- expect,
7
- test,
8
- vi,
9
- } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
10
2
  import { expectMap } from "../coValue.js";
11
- import type { CoValueHeader, TryAddTransactionsError } from "../coValueCore.js";
12
- import type { RawAccountID } from "../coValues/account.js";
13
- import { type MapOpPayload, RawCoMap } from "../coValues/coMap.js";
3
+ import { RawCoMap } from "../coValues/coMap.js";
14
4
  import type { RawGroup } from "../coValues/group.js";
15
5
  import { WasmCrypto } from "../crypto/WasmCrypto.js";
16
- import { stableStringify } from "../jsonStringify.js";
17
6
  import { LocalNode } from "../localNode.js";
18
- import { getPriorityFromHeader } from "../priority.js";
19
7
  import { connectedPeers, newQueuePair } from "../streamUtils.js";
20
- import type { LoadMessage, SyncMessage } from "../sync.js";
8
+ import type { LoadMessage } from "../sync.js";
21
9
  import {
22
10
  blockMessageTypeOnOutgoingPeer,
23
11
  connectTwoPeers,
@@ -759,9 +747,7 @@ describe("SyncManager.addPeer", () => {
759
747
 
760
748
  await map.core.waitForSync();
761
749
 
762
- expect(jazzCloud.node.coValuesStore.get(map.id).state.type).toBe(
763
- "available",
764
- );
750
+ expect(jazzCloud.node.coValuesStore.get(map.id).isAvailable()).toBe(true);
765
751
  });
766
752
  });
767
753
 
@@ -1083,14 +1069,13 @@ describe("SyncManager.handleSyncMessage", () => {
1083
1069
  test("should ignore messages for errored coValues", async () => {
1084
1070
  const client = await setupTestAccount();
1085
1071
 
1086
- const { peerState } = client.connectToSyncServer();
1072
+ const { peer, peerState } = client.connectToSyncServer();
1087
1073
 
1088
1074
  // Add a coValue to the errored set
1089
1075
  const erroredId = "co_z123" as const;
1090
- peerState.erroredCoValues.set(
1091
- erroredId,
1092
- new Error("Test error") as unknown as TryAddTransactionsError,
1093
- );
1076
+ client.node.coValuesStore.get(erroredId).markErrored(peer.id, {
1077
+ message: "Test error",
1078
+ } as any);
1094
1079
 
1095
1080
  const message = {
1096
1081
  action: "load" as const,
@@ -1,37 +0,0 @@
1
- import { CryptoProvider } from "../crypto/crypto.js";
2
- import { RawCoID } from "../ids.js";
3
- import { CoValueChunk } from "./index.js";
4
- export type BlockFilename = `L${number}-${string}-${string}-H${number}.jsonl`;
5
- export type BlockHeader = {
6
- id: RawCoID;
7
- start: number;
8
- length: number;
9
- }[];
10
- export type WalEntry = {
11
- id: RawCoID;
12
- } & CoValueChunk;
13
- export type WalFilename = `wal-${number}.jsonl`;
14
- export interface FileSystem<WriteHandle, ReadHandle> {
15
- crypto: CryptoProvider;
16
- createFile(filename: string): Promise<WriteHandle>;
17
- append(handle: WriteHandle, data: Uint8Array): Promise<void>;
18
- close(handle: ReadHandle | WriteHandle): Promise<void>;
19
- closeAndRename(handle: WriteHandle, filename: BlockFilename): Promise<void>;
20
- openToRead(filename: string): Promise<{
21
- handle: ReadHandle;
22
- size: number;
23
- }>;
24
- read(handle: ReadHandle, offset: number, length: number): Promise<Uint8Array>;
25
- listFiles(): Promise<string[]>;
26
- removeFile(filename: BlockFilename | WalFilename): Promise<void>;
27
- }
28
- export declare const textEncoder: import("util").TextEncoder;
29
- export declare const textDecoder: import("util").TextDecoder;
30
- export declare function readChunk<RH, FS extends FileSystem<unknown, RH>>(handle: RH, header: {
31
- start: number;
32
- length: number;
33
- }, fs: FS): Promise<CoValueChunk>;
34
- export declare function readHeader<RH, FS extends FileSystem<unknown, RH>>(filename: string, handle: RH, size: number, fs: FS): Promise<BlockHeader>;
35
- export declare function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(chunks: Map<RawCoID, CoValueChunk>, level: number, blockNumber: number, fs: FS): Promise<BlockFilename>;
36
- export declare function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(handle: WH, fs: FS, id: RawCoID, chunk: CoValueChunk): Promise<void>;
37
- //# sourceMappingURL=FileSystem.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../src/storage/FileSystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM,QAAQ,CAAC;AAE9E,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC;AAE3E,MAAM,MAAM,QAAQ,GAAG;IAAE,EAAE,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,OAAO,MAAM,QAAQ,CAAC;AAEhD,MAAM,WAAW,UAAU,CAAC,WAAW,EAAE,UAAU;IACjD,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9E,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/B,UAAU,CAAC,QAAQ,EAAE,aAAa,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,eAAO,MAAM,WAAW,4BAAoB,CAAC;AAC7C,eAAO,MAAM,WAAW,4BAAoB,CAAC;AAE7C,wBAAsB,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EACpE,MAAM,EAAE,EAAE,EACV,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzC,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,YAAY,CAAC,CAKvB;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,SAAS,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,EACrE,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,EAAE,EACV,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,WAAW,CAAC,CAOtB;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,EACpE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,EAClC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,aAAa,CAAC,CAyCxB;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,EACpE,MAAM,EAAE,EAAE,EACV,EAAE,EAAE,EAAE,EACN,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,YAAY,iBAQpB"}
@@ -1,48 +0,0 @@
1
- import { StreamingHash } from "../crypto/crypto.js";
2
- export const textEncoder = new TextEncoder();
3
- export const textDecoder = new TextDecoder();
4
- export async function readChunk(handle, header, fs) {
5
- const chunkBytes = await fs.read(handle, header.start, header.length);
6
- const chunk = JSON.parse(textDecoder.decode(chunkBytes));
7
- return chunk;
8
- }
9
- export async function readHeader(filename, handle, size, fs) {
10
- const headerLength = Number(filename.match(/-H(\d+)\.jsonl$/)[1]);
11
- const headerBytes = await fs.read(handle, size - headerLength, headerLength);
12
- const header = JSON.parse(textDecoder.decode(headerBytes));
13
- return header;
14
- }
15
- export async function writeBlock(chunks, level, blockNumber, fs) {
16
- if (chunks.size === 0) {
17
- throw new Error("No chunks to write");
18
- }
19
- const blockHeader = [];
20
- let offset = 0;
21
- const file = await fs.createFile("wipBlock" + Math.random().toString(36).substring(7) + ".tmp.jsonl");
22
- const hash = new StreamingHash(fs.crypto);
23
- const chunksSortedById = Array.from(chunks).sort(([id1], [id2]) => id1.localeCompare(id2));
24
- for (const [id, chunk] of chunksSortedById) {
25
- const encodedBytes = hash.update(chunk);
26
- const encodedBytesWithNewline = new Uint8Array(encodedBytes.length + 1);
27
- encodedBytesWithNewline.set(encodedBytes);
28
- encodedBytesWithNewline[encodedBytes.length] = 10;
29
- await fs.append(file, encodedBytesWithNewline);
30
- const length = encodedBytesWithNewline.length;
31
- blockHeader.push({ id, start: offset, length });
32
- offset += length;
33
- }
34
- const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
35
- await fs.append(file, headerBytes);
36
- const filename = `L${level}-${(blockNumber + "").padStart(3, "0")}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${headerBytes.length}.jsonl`;
37
- await fs.closeAndRename(file, filename);
38
- return filename;
39
- }
40
- export async function writeToWal(handle, fs, id, chunk) {
41
- const walEntry = {
42
- id,
43
- ...chunk,
44
- };
45
- const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
46
- return fs.append(handle, bytes);
47
- }
48
- //# sourceMappingURL=FileSystem.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileSystem.js","sourceRoot":"","sources":["../../src/storage/FileSystem.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- import { RawCoID } from "../ids.js";
2
- import { CoValueKnownState, NewContentMessage } from "../sync.js";
3
- import { CoValueChunk } from "./index.js";
4
- export declare function contentSinceChunk(id: RawCoID, chunk: CoValueChunk, known?: CoValueKnownState): NewContentMessage[];
5
- export declare function chunkToKnownState(id: RawCoID, chunk: CoValueChunk): CoValueKnownState;
6
- export declare function mergeChunks(chunkA: CoValueChunk, chunkB: CoValueChunk): "nonContigous" | CoValueChunk;
7
- //# sourceMappingURL=chunksAndKnownStates.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chunksAndKnownStates.d.ts","sourceRoot":"","sources":["../../src/storage/chunksAndKnownStates.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAa,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,iBAAiB,GACxB,iBAAiB,EAAE,CA8CrB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,qBAgBjE;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,cAAc,GAAG,YAAY,CAyD/B"}