cojson 0.17.12 → 0.17.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 (82) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +8 -0
  3. package/dist/coValueCore/SessionMap.d.ts +4 -3
  4. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  5. package/dist/coValueCore/SessionMap.js +15 -4
  6. package/dist/coValueCore/SessionMap.js.map +1 -1
  7. package/dist/coValueCore/coValueCore.d.ts +2 -2
  8. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  9. package/dist/coValueCore/coValueCore.js +33 -32
  10. package/dist/coValueCore/coValueCore.js.map +1 -1
  11. package/dist/coValueCore/utils.d.ts.map +1 -1
  12. package/dist/coValueCore/utils.js.map +1 -1
  13. package/dist/coValueCore/verifiedState.d.ts +8 -2
  14. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  15. package/dist/coValueCore/verifiedState.js +7 -4
  16. package/dist/coValueCore/verifiedState.js.map +1 -1
  17. package/dist/crypto/PureJSCrypto.d.ts +4 -3
  18. package/dist/crypto/PureJSCrypto.d.ts.map +1 -1
  19. package/dist/crypto/PureJSCrypto.js +34 -2
  20. package/dist/crypto/PureJSCrypto.js.map +1 -1
  21. package/dist/crypto/WasmCrypto.d.ts +4 -3
  22. package/dist/crypto/WasmCrypto.d.ts.map +1 -1
  23. package/dist/crypto/WasmCrypto.js +10 -4
  24. package/dist/crypto/WasmCrypto.js.map +1 -1
  25. package/dist/crypto/crypto.d.ts +4 -3
  26. package/dist/crypto/crypto.d.ts.map +1 -1
  27. package/dist/sync.d.ts +2 -2
  28. package/dist/sync.d.ts.map +1 -1
  29. package/dist/sync.js +9 -13
  30. package/dist/sync.js.map +1 -1
  31. package/dist/tests/PureJSCrypto.test.js +43 -0
  32. package/dist/tests/PureJSCrypto.test.js.map +1 -1
  33. package/dist/tests/WasmCrypto.test.js +55 -0
  34. package/dist/tests/WasmCrypto.test.js.map +1 -1
  35. package/dist/tests/coList.test.js +13 -0
  36. package/dist/tests/coList.test.js.map +1 -1
  37. package/dist/tests/coMap.test.js +14 -0
  38. package/dist/tests/coMap.test.js.map +1 -1
  39. package/dist/tests/coPlainText.test.js +13 -0
  40. package/dist/tests/coPlainText.test.js.map +1 -1
  41. package/dist/tests/coStream.test.js +25 -0
  42. package/dist/tests/coStream.test.js.map +1 -1
  43. package/dist/tests/coValueCore.test.js +28 -2
  44. package/dist/tests/coValueCore.test.js.map +1 -1
  45. package/dist/tests/coreWasm.test.js +1 -1
  46. package/dist/tests/coreWasm.test.js.map +1 -1
  47. package/dist/tests/sync.sharding.test.js +35 -1
  48. package/dist/tests/sync.sharding.test.js.map +1 -1
  49. package/dist/tests/sync.storage.test.js +31 -1
  50. package/dist/tests/sync.storage.test.js.map +1 -1
  51. package/dist/tests/sync.storageAsync.test.js +1 -1
  52. package/dist/tests/sync.storageAsync.test.js.map +1 -1
  53. package/dist/tests/sync.test.js +2 -2
  54. package/dist/tests/sync.test.js.map +1 -1
  55. package/dist/tests/sync.upload.test.js +26 -0
  56. package/dist/tests/sync.upload.test.js.map +1 -1
  57. package/dist/tests/testUtils.d.ts.map +1 -1
  58. package/dist/tests/testUtils.js +3 -1
  59. package/dist/tests/testUtils.js.map +1 -1
  60. package/package.json +2 -2
  61. package/src/coValueCore/SessionMap.ts +24 -1
  62. package/src/coValueCore/coValueCore.ts +46 -41
  63. package/src/coValueCore/utils.ts +0 -1
  64. package/src/coValueCore/verifiedState.ts +14 -3
  65. package/src/crypto/PureJSCrypto.ts +49 -1
  66. package/src/crypto/WasmCrypto.ts +15 -1
  67. package/src/crypto/crypto.ts +7 -1
  68. package/src/sync.ts +9 -14
  69. package/src/tests/PureJSCrypto.test.ts +66 -0
  70. package/src/tests/WasmCrypto.test.ts +88 -0
  71. package/src/tests/coList.test.ts +19 -0
  72. package/src/tests/coMap.test.ts +21 -0
  73. package/src/tests/coPlainText.test.ts +18 -0
  74. package/src/tests/coStream.test.ts +36 -0
  75. package/src/tests/coValueCore.test.ts +49 -0
  76. package/src/tests/coreWasm.test.ts +1 -0
  77. package/src/tests/sync.sharding.test.ts +44 -1
  78. package/src/tests/sync.storage.test.ts +43 -1
  79. package/src/tests/sync.storageAsync.test.ts +1 -1
  80. package/src/tests/sync.test.ts +6 -2
  81. package/src/tests/sync.upload.test.ts +35 -0
  82. package/src/tests/testUtils.ts +3 -1
@@ -126,6 +126,72 @@ describe("PureJSCrypto", () => {
126
126
 
127
127
  expect(map.get("count")).toEqual(0);
128
128
  });
129
+
130
+ it("can add a meta to a private transaction", async () => {
131
+ const client = setupTestNode({
132
+ connected: true,
133
+ });
134
+
135
+ const group = client.node.createGroup();
136
+ const map = group.createMap();
137
+
138
+ map.core.makeTransaction([], "private", {
139
+ meta: {
140
+ count: 1,
141
+ },
142
+ });
143
+
144
+ await map.core.waitForSync();
145
+
146
+ const session2 = client.spawnNewSession();
147
+
148
+ const mapInOtherSession = await loadCoValueOrFail(session2.node, map.id);
149
+
150
+ const decryptedMeta =
151
+ mapInOtherSession.core.verified.decryptTransactionMeta(
152
+ client.node.currentSessionID,
153
+ 0,
154
+ map.core.getCurrentReadKey().secret!,
155
+ );
156
+
157
+ expect(decryptedMeta).toEqual({
158
+ meta: {
159
+ count: 1,
160
+ },
161
+ });
162
+ });
163
+
164
+ it("can add a meta to a trusting transaction", async () => {
165
+ const client = setupTestNode({
166
+ connected: true,
167
+ });
168
+
169
+ const group = client.node.createGroup();
170
+ const map = group.createMap();
171
+
172
+ map.core.makeTransaction([], "trusting", {
173
+ meta: {
174
+ count: 1,
175
+ },
176
+ });
177
+
178
+ await map.core.waitForSync();
179
+
180
+ const session2 = client.spawnNewSession();
181
+
182
+ const mapInOtherSession = await loadCoValueOrFail(session2.node, map.id);
183
+
184
+ const transferredMeta = JSON.parse(
185
+ mapInOtherSession.core.verified.sessions.get(client.node.currentSessionID)
186
+ ?.transactions[0]?.meta!,
187
+ );
188
+
189
+ expect(transferredMeta).toEqual({
190
+ meta: {
191
+ count: 1,
192
+ },
193
+ });
194
+ });
129
195
  });
130
196
 
131
197
  describe("PureJSSessionLog", () => {
@@ -125,4 +125,92 @@ describe("WasmCrypto", () => {
125
125
 
126
126
  expect(map.get("count")).toEqual(0);
127
127
  });
128
+
129
+ it("can add a meta to a private transaction", async () => {
130
+ const client = setupTestNode({
131
+ connected: true,
132
+ });
133
+
134
+ const group = client.node.createGroup();
135
+ const map = group.createMap();
136
+
137
+ map.core.makeTransaction([], "private", {
138
+ meta: {
139
+ count: 1,
140
+ },
141
+ });
142
+
143
+ await map.core.waitForSync();
144
+
145
+ const session2 = client.spawnNewSession();
146
+
147
+ const mapInOtherSession = await loadCoValueOrFail(session2.node, map.id);
148
+
149
+ const decryptedMeta =
150
+ mapInOtherSession.core.verified.decryptTransactionMeta(
151
+ client.node.currentSessionID,
152
+ 0,
153
+ mapInOtherSession.core.getCurrentReadKey().secret!,
154
+ );
155
+
156
+ expect(decryptedMeta).toEqual({
157
+ meta: {
158
+ count: 1,
159
+ },
160
+ });
161
+ });
162
+
163
+ it("can add a meta to a trusting transaction", async () => {
164
+ const client = setupTestNode({
165
+ connected: true,
166
+ });
167
+
168
+ const group = client.node.createGroup();
169
+ const map = group.createMap();
170
+
171
+ map.core.makeTransaction([], "trusting", {
172
+ meta: {
173
+ count: 1,
174
+ },
175
+ });
176
+
177
+ await map.core.waitForSync();
178
+
179
+ const session2 = client.spawnNewSession();
180
+
181
+ const mapInOtherSession = await loadCoValueOrFail(session2.node, map.id);
182
+
183
+ const transferredMeta = JSON.parse(
184
+ mapInOtherSession.core.verified.sessions.get(client.node.currentSessionID)
185
+ ?.transactions[0]?.meta!,
186
+ );
187
+
188
+ expect(transferredMeta).toEqual({
189
+ meta: {
190
+ count: 1,
191
+ },
192
+ });
193
+ });
194
+
195
+ it("fails to verify signatures without a signer ID", async () => {
196
+ const agentSecret = wasmCrypto.newRandomAgentSecret();
197
+ const sessionID = wasmCrypto.newRandomSessionID(
198
+ wasmCrypto.getAgentID(agentSecret),
199
+ );
200
+
201
+ const sessionLog = wasmCrypto.createSessionLog("co_z12345678", sessionID);
202
+ expect(() =>
203
+ sessionLog.tryAdd(
204
+ [
205
+ {
206
+ privacy: "trusting",
207
+ changes: stableStringify([{ op: "set", key: "count", value: 1 }]),
208
+ madeAt: Date.now(),
209
+ },
210
+ ],
211
+ "signature_z12345678",
212
+ false,
213
+ ),
214
+ ).toThrow(expect.stringContaining("Signature verification failed"));
215
+ });
128
216
  });
@@ -409,3 +409,22 @@ test("totalValidTransactions should return the number of valid transactions proc
409
409
  listOnOtherClient.core.getCurrentContent().totalValidTransactions,
410
410
  ).toEqual(2);
411
411
  });
412
+
413
+ test("Should ignore unknown meta transactions", () => {
414
+ const node = nodeWithRandomAgentAndSessionID();
415
+
416
+ const coValue = node.createCoValue({
417
+ type: "colist",
418
+ ruleset: { type: "unsafeAllowAll" },
419
+ meta: null,
420
+ ...Crypto.createdNowUnique(),
421
+ });
422
+
423
+ coValue.makeTransaction([], "trusting", { unknownMeta: 1 });
424
+
425
+ const content = expectList(coValue.getCurrentContent());
426
+
427
+ content.append("first", 0, "trusting");
428
+
429
+ expect(content.toJSON()).toEqual(["first"]);
430
+ });
@@ -217,6 +217,27 @@ test("Can set items in bulk with assign", () => {
217
217
  });
218
218
  });
219
219
 
220
+ test("Should ignore unknown meta transactions", () => {
221
+ const node = nodeWithRandomAgentAndSessionID();
222
+
223
+ const coValue = node.createCoValue({
224
+ type: "comap",
225
+ ruleset: { type: "unsafeAllowAll" },
226
+ meta: null,
227
+ ...Crypto.createdNowUnique(),
228
+ });
229
+
230
+ coValue.makeTransaction([], "trusting", { unknownMeta: 1 });
231
+
232
+ const content = expectMap(coValue.getCurrentContent());
233
+
234
+ expect(content.type).toEqual("comap");
235
+
236
+ content.set("key1", "set1", "trusting");
237
+
238
+ expect(content.get("key1")).toEqual("set1");
239
+ });
240
+
220
241
  test("totalValidTransactions should return the number of valid transactions processed", async () => {
221
242
  const client = setupTestNode({
222
243
  connected: true,
@@ -298,6 +298,24 @@ test("Splits into and from grapheme string arrays", () => {
298
298
  expect(text).toEqual("👋 안녕!");
299
299
  });
300
300
 
301
+ test("Should ignore unknown meta transactions", () => {
302
+ const node = nodeWithRandomAgentAndSessionID();
303
+
304
+ const coValue = node.createCoValue({
305
+ type: "coplaintext",
306
+ ruleset: { type: "unsafeAllowAll" },
307
+ meta: null,
308
+ ...Crypto.createdNowUnique(),
309
+ });
310
+
311
+ coValue.makeTransaction([], "trusting", { unknownMeta: 1 });
312
+
313
+ const content = expectPlainText(coValue.getCurrentContent());
314
+
315
+ content.insertAfter(0, "hello", "trusting");
316
+ expect(content.toString()).toEqual("hello");
317
+ });
318
+
301
319
  test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX_SIZE", async () => {
302
320
  setMaxRecommendedTxSize(5);
303
321
 
@@ -127,6 +127,42 @@ test("Can push into RawBinaryCoStream", () => {
127
127
  });
128
128
  });
129
129
 
130
+ test("Should ignore meta transactions on RawBinaryCoStream", () => {
131
+ const node = nodeWithRandomAgentAndSessionID();
132
+
133
+ const coValue = node.createCoValue({
134
+ type: "costream",
135
+ ruleset: { type: "unsafeAllowAll" },
136
+ meta: { type: "binary" },
137
+ ...Crypto.createdNowUnique(),
138
+ });
139
+
140
+ coValue.makeTransaction([], "trusting", { unknownMeta: 1 });
141
+
142
+ const content = coValue.getCurrentContent();
143
+
144
+ if (
145
+ content.type !== "costream" ||
146
+ content.headerMeta?.type !== "binary" ||
147
+ !(content instanceof RawBinaryCoStream)
148
+ ) {
149
+ throw new Error("Expected binary stream");
150
+ }
151
+
152
+ content.startBinaryStream(
153
+ { mimeType: "text/plain", fileName: "test.txt" },
154
+ "trusting",
155
+ );
156
+ content.pushBinaryStreamChunk(new Uint8Array([1, 2, 3]), "trusting");
157
+ content.endBinaryStream("trusting");
158
+ expect(content.getBinaryChunks()).toEqual({
159
+ mimeType: "text/plain",
160
+ fileName: "test.txt",
161
+ chunks: [new Uint8Array([1, 2, 3])],
162
+ finished: true,
163
+ });
164
+ });
165
+
130
166
  test("When adding large transactions (small fraction of MAX_RECOMMENDED_TX_SIZE), we store an inbetween signature every time we reach MAX_RECOMMENDED_TX_SIZE and split up newContentSince accordingly", () => {
131
167
  const node = nodeWithRandomAgentAndSessionID();
132
168
 
@@ -20,9 +20,11 @@ import {
20
20
  loadCoValueOrFail,
21
21
  nodeWithRandomAgentAndSessionID,
22
22
  randomAgentAndSessionID,
23
+ setupTestNode,
23
24
  tearDownTestMetricReader,
24
25
  } from "./testUtils.js";
25
26
  import { CO_VALUE_PRIORITY } from "../priority.js";
27
+ import { determineValidTransactions } from "../permissions.js";
26
28
 
27
29
  const Crypto = await WasmCrypto.create();
28
30
 
@@ -32,6 +34,7 @@ const agentSecret =
32
34
 
33
35
  beforeEach(() => {
34
36
  metricReader = createTestMetricReader();
37
+ setupTestNode({ isSyncServer: true });
35
38
  });
36
39
 
37
40
  afterEach(() => {
@@ -53,6 +56,7 @@ test("transactions with wrong signature are rejected", () => {
53
56
  node.currentSessionID,
54
57
  node.getCurrentAgent(),
55
58
  [{ hello: "world" }],
59
+ undefined,
56
60
  );
57
61
 
58
62
  transaction.madeAt = Date.now() + 1000;
@@ -264,6 +268,51 @@ test("listeners are notified even if the previous listener threw an error", asyn
264
268
  errorLog.mockRestore();
265
269
  });
266
270
 
271
+ test("creates a transaction with trusting meta information", async () => {
272
+ const client = setupTestNode();
273
+
274
+ const group = client.node.createGroup();
275
+ const map = group.createMap();
276
+ map.core.makeTransaction([], "trusting", {
277
+ meta: true,
278
+ });
279
+
280
+ const validTransactions = determineValidTransactions(map.core);
281
+
282
+ expect(validTransactions[0]?.tx.meta).toBe(`{"meta":true}`);
283
+ });
284
+
285
+ test("creates a transaction with private meta information", async () => {
286
+ const client = setupTestNode({ connected: true });
287
+
288
+ const group = client.node.createGroup();
289
+ const map = group.createMap();
290
+ map.core.makeTransaction([], "private", {
291
+ meta: true,
292
+ });
293
+
294
+ const localTransactionMeta = map.core.verified.decryptTransactionMeta(
295
+ client.node.currentSessionID,
296
+ 0,
297
+ map.core.getCurrentReadKey().secret!,
298
+ );
299
+
300
+ expect(localTransactionMeta).toEqual({ meta: true });
301
+
302
+ const newSession = client.spawnNewSession();
303
+
304
+ const mapOnNewSession = await loadCoValueOrFail(newSession.node, map.id);
305
+
306
+ const syncedTransactionMeta =
307
+ mapOnNewSession.core.verified.decryptTransactionMeta(
308
+ client.node.currentSessionID,
309
+ 0,
310
+ mapOnNewSession.core.getCurrentReadKey().secret!,
311
+ );
312
+
313
+ expect(syncedTransactionMeta).toEqual({ meta: true });
314
+ });
315
+
267
316
  test("getValidTransactions should skip private transactions with invalid JSON", () => {
268
317
  const [agent, sessionID] = agentAndSessionIDFromSecret(agentSecret);
269
318
  const node = new LocalNode(agent.agentSecret, sessionID, Crypto);
@@ -85,6 +85,7 @@ describe("SessionLog WASM", () => {
85
85
  key.id,
86
86
  key.secret,
87
87
  0,
88
+ undefined,
88
89
  );
89
90
 
90
91
  expect(signature).toMatch(/^signature_z[a-zA-Z0-9]+$/);
@@ -4,6 +4,7 @@ import {
4
4
  SyncMessagesLog,
5
5
  TEST_NODE_CONFIG,
6
6
  blockMessageTypeOnOutgoingPeer,
7
+ connectedPeersWithMessagesTracking,
7
8
  getSyncServerConnectedPeer,
8
9
  loadCoValueOrFail,
9
10
  setupTestAccount,
@@ -47,7 +48,6 @@ describe("sharding", () => {
47
48
  const firstAlphabetical: ServerPeerSelector = (id, serverPeers) => {
48
49
  return serverPeers.sort((a, b) => a.id.localeCompare(b.id)).slice(0, 1);
49
50
  };
50
-
51
51
  const { node: client } = setupTestNode({
52
52
  connected: false,
53
53
  });
@@ -73,4 +73,47 @@ describe("sharding", () => {
73
73
  allPeers.sort((a, b) => a.id.localeCompare(b.id))[0]!.id,
74
74
  );
75
75
  });
76
+
77
+ test("getPeers respects the serverPeerSelector", async () => {
78
+ const firstPeer: ServerPeerSelector = (id, serverPeers) => {
79
+ return serverPeers.slice(0, 1);
80
+ };
81
+ const { node: edge } = setupTestNode({
82
+ connected: false,
83
+ });
84
+ edge.syncManager.serverPeerSelector = firstPeer;
85
+
86
+ // Connect 2 clients to edge
87
+ for (let i = 0; i < 2; i++) {
88
+ const client = await setupTestAccount({});
89
+ const { peer1, peer2 } = connectedPeersWithMessagesTracking({
90
+ peer1: {
91
+ id: client.node.getCurrentAgent().id,
92
+ role: "client",
93
+ },
94
+ peer2: {
95
+ id: edge.getCurrentAgent().id,
96
+ role: "server",
97
+ },
98
+ });
99
+
100
+ edge.syncManager.addPeer(peer1);
101
+ }
102
+
103
+ // Connect edge to 3 core nodes
104
+ for (let i = 0; i < 3; i++) {
105
+ const syncServer = await setupTestAccount({ isSyncServer: true });
106
+
107
+ const { peer } = getSyncServerConnectedPeer({
108
+ peerId: edge.getCurrentAgent().id,
109
+ syncServer: syncServer.node,
110
+ });
111
+
112
+ edge.syncManager.addPeer(peer);
113
+ }
114
+
115
+ expect(edge.syncManager.getPeers("co_z12345").length).toBe(
116
+ 2 + 1, // 2 clients + 1 selected core
117
+ );
118
+ });
76
119
  });
@@ -20,6 +20,7 @@ import {
20
20
  waitFor,
21
21
  } from "./testUtils";
22
22
  import { stableStringify } from "../jsonStringify";
23
+ import { determineValidTransactions } from "../permissions";
23
24
 
24
25
  // We want to simulate a real world communication that happens asynchronously
25
26
  TEST_NODE_CONFIG.withAsyncPeers = true;
@@ -151,6 +152,47 @@ describe("client with storage syncs with server", () => {
151
152
  `);
152
153
  });
153
154
 
155
+ test("persists meta information", async () => {
156
+ const client = setupTestNode();
157
+
158
+ const { storage } = client.addStorage();
159
+
160
+ const group = client.node.createGroup();
161
+ const map = group.createMap();
162
+ map.core.makeTransaction([], "trusting", {
163
+ meta: true,
164
+ });
165
+
166
+ await map.core.waitForSync();
167
+
168
+ client.restart();
169
+
170
+ client.addStorage({
171
+ storage,
172
+ });
173
+
174
+ const loadedValue = await loadCoValueOrFail(client.node, map.id);
175
+
176
+ const validTransactions = determineValidTransactions(loadedValue.core);
177
+
178
+ expect(validTransactions[0]?.tx.meta).toBe(`{"meta":true}`);
179
+
180
+ expect(
181
+ SyncMessagesLog.getMessages({
182
+ Group: group.core,
183
+ Map: map.core,
184
+ }),
185
+ ).toMatchInlineSnapshot(`
186
+ [
187
+ "client -> storage | CONTENT Group header: true new: After: 0 New: 3",
188
+ "client -> storage | CONTENT Map header: true new: After: 0 New: 1",
189
+ "client -> storage | LOAD Map sessions: empty",
190
+ "storage -> client | CONTENT Group header: true new: After: 0 New: 3",
191
+ "storage -> client | CONTENT Map header: true new: After: 0 New: 1",
192
+ ]
193
+ `);
194
+ });
195
+
154
196
  test("updating a coValue while offline", async () => {
155
197
  const client = setupTestNode();
156
198
 
@@ -164,7 +206,7 @@ describe("client with storage syncs with server", () => {
164
206
  const mapOnClient = await loadCoValueOrFail(client.node, map.id);
165
207
  expect(mapOnClient.get("hello")).toEqual("world");
166
208
 
167
- client.node.syncManager.getPeers()[0]?.gracefulShutdown();
209
+ client.node.syncManager.getPeers(map.id)[0]?.gracefulShutdown();
168
210
 
169
211
  SyncMessagesLog.clear();
170
212
  map.set("hello", "updated", "trusting");
@@ -156,7 +156,7 @@ describe("client with storage syncs with server", () => {
156
156
  const mapOnClient = await loadCoValueOrFail(client.node, map.id);
157
157
  expect(mapOnClient.get("hello")).toEqual("world");
158
158
 
159
- client.node.syncManager.getPeers()[0]?.gracefulShutdown();
159
+ client.node.syncManager.getPeers(map.id)[0]?.gracefulShutdown();
160
160
 
161
161
  SyncMessagesLog.clear();
162
162
  map.set("hello", "updated", "trusting");
@@ -599,8 +599,12 @@ describe("SyncManager - knownStates vs optimisticKnownStates", () => {
599
599
  // Wait for the full sync to complete
600
600
  await mapOnClient.core.waitForSync();
601
601
 
602
- const peerStateClient = client.syncManager.getPeers()[0]!;
603
- const peerStateJazzCloud = jazzCloud.node.syncManager.getPeers()[0]!;
602
+ const peerStateClient = client.syncManager.getPeers(
603
+ mapOnClient.core.id,
604
+ )[0]!;
605
+ const peerStateJazzCloud = jazzCloud.node.syncManager.getPeers(
606
+ mapOnClient.core.id,
607
+ )[0]!;
604
608
 
605
609
  // The optimisticKnownStates should be the same as the knownStates after the full sync is complete
606
610
  expect(
@@ -9,6 +9,7 @@ import {
9
9
  setupTestNode,
10
10
  waitFor,
11
11
  } from "./testUtils";
12
+ import { determineValidTransactions } from "../permissions";
12
13
 
13
14
  // We want to simulate a real world communication that happens asynchronously
14
15
  TEST_NODE_CONFIG.withAsyncPeers = true;
@@ -51,6 +52,40 @@ describe("client to server upload", () => {
51
52
  `);
52
53
  });
53
54
 
55
+ test("syncs meta information", async () => {
56
+ const client = setupTestNode({
57
+ connected: true,
58
+ });
59
+
60
+ const group = client.node.createGroup();
61
+ const map = group.createMap();
62
+ map.core.makeTransaction([], "trusting", {
63
+ meta: true,
64
+ });
65
+
66
+ await map.core.waitForSync();
67
+
68
+ const loadedValue = await loadCoValueOrFail(jazzCloud.node, map.id);
69
+
70
+ const validTransactions = determineValidTransactions(loadedValue.core);
71
+
72
+ expect(validTransactions[0]?.tx.meta).toBe(`{"meta":true}`);
73
+
74
+ expect(
75
+ SyncMessagesLog.getMessages({
76
+ Group: group.core,
77
+ Map: map.core,
78
+ }),
79
+ ).toMatchInlineSnapshot(`
80
+ [
81
+ "client -> server | CONTENT Group header: true new: After: 0 New: 3",
82
+ "client -> server | CONTENT Map header: true new: After: 0 New: 1",
83
+ "server -> client | KNOWN Group sessions: header/3",
84
+ "server -> client | KNOWN Map sessions: header/1",
85
+ ]
86
+ `);
87
+ });
88
+
54
89
  test("coValue with parent groups uploading", async () => {
55
90
  const client = setupTestNode({
56
91
  connected: true,
@@ -669,9 +669,11 @@ export async function setupTestAccount(
669
669
  addStorage,
670
670
  addAsyncStorage,
671
671
  disconnect: () => {
672
- ctx.node.syncManager.getPeers().forEach((peer) => {
672
+ const allPeers = ctx.node.syncManager.getPeers(ctx.accountID);
673
+ allPeers.forEach((peer) => {
673
674
  peer.gracefulShutdown();
674
675
  });
676
+ ctx.node.syncManager.peers = {};
675
677
  },
676
678
  };
677
679
  }