cojson 0.20.17 → 0.20.18

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 (36) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +9 -0
  3. package/dist/ClockOffset.d.ts +21 -0
  4. package/dist/ClockOffset.d.ts.map +1 -0
  5. package/dist/ClockOffset.js +55 -0
  6. package/dist/ClockOffset.js.map +1 -0
  7. package/dist/coValueCore/coValueCore.js +2 -2
  8. package/dist/coValueCore/coValueCore.js.map +1 -1
  9. package/dist/localNode.d.ts +16 -3
  10. package/dist/localNode.d.ts.map +1 -1
  11. package/dist/localNode.js +36 -5
  12. package/dist/localNode.js.map +1 -1
  13. package/dist/tests/ClockOffset.test.d.ts +2 -0
  14. package/dist/tests/ClockOffset.test.d.ts.map +1 -0
  15. package/dist/tests/ClockOffset.test.js +146 -0
  16. package/dist/tests/ClockOffset.test.js.map +1 -0
  17. package/dist/tests/clockDrift.integration.test.d.ts +2 -0
  18. package/dist/tests/clockDrift.integration.test.d.ts.map +1 -0
  19. package/dist/tests/clockDrift.integration.test.js +177 -0
  20. package/dist/tests/clockDrift.integration.test.js.map +1 -0
  21. package/dist/tests/localNode.clockOffset.test.d.ts +2 -0
  22. package/dist/tests/localNode.clockOffset.test.d.ts.map +1 -0
  23. package/dist/tests/localNode.clockOffset.test.js +70 -0
  24. package/dist/tests/localNode.clockOffset.test.js.map +1 -0
  25. package/dist/tests/testUtils.d.ts +2 -0
  26. package/dist/tests/testUtils.d.ts.map +1 -1
  27. package/dist/tests/testUtils.js +9 -2
  28. package/dist/tests/testUtils.js.map +1 -1
  29. package/package.json +4 -4
  30. package/src/ClockOffset.ts +83 -0
  31. package/src/coValueCore/coValueCore.ts +2 -2
  32. package/src/localNode.ts +31 -0
  33. package/src/tests/ClockOffset.test.ts +177 -0
  34. package/src/tests/clockDrift.integration.test.ts +261 -0
  35. package/src/tests/localNode.clockOffset.test.ts +92 -0
  36. package/src/tests/testUtils.ts +16 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ClockOffset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClockOffset.test.d.ts","sourceRoot":"","sources":["../../src/tests/ClockOffset.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { ClockOffset } from "../ClockOffset.js";
3
+ function makeRng(seed) {
4
+ let state = seed >>> 0;
5
+ return () => {
6
+ state ^= state << 13;
7
+ state ^= state >>> 17;
8
+ state ^= state << 5;
9
+ return ((state >>> 0) / 0xffffffff) * 2 - 1;
10
+ };
11
+ }
12
+ describe("ClockOffset", () => {
13
+ test("currentOffset() returns 0 before any samples are ingested", () => {
14
+ const clockOffset = new ClockOffset();
15
+ expect(clockOffset.currentOffset()).toBe(0);
16
+ });
17
+ test("sampleCount() reports sliding window size capped at windowSize", () => {
18
+ const windowSize = 4;
19
+ const clockOffset = new ClockOffset({
20
+ windowSize,
21
+ // Keep the outlier gate wide enough to accept the spread of samples
22
+ // we feed below; the point of this test is the window count, not
23
+ // outlier rejection.
24
+ outlierThresholdMs: 10000,
25
+ });
26
+ expect(clockOffset.sampleCount()).toBe(0);
27
+ for (let i = 0; i < 3; i++) {
28
+ clockOffset.addSample({
29
+ serverTime: 1000 + i,
30
+ localReceiveTime: 1000,
31
+ });
32
+ }
33
+ expect(clockOffset.sampleCount()).toBe(3);
34
+ for (let i = 0; i < windowSize + 2; i++) {
35
+ clockOffset.addSample({
36
+ serverTime: 2000 + i,
37
+ localReceiveTime: 2000,
38
+ });
39
+ }
40
+ expect(clockOffset.sampleCount()).toBe(windowSize);
41
+ });
42
+ test("after a single sample, currentOffset() reflects serverTime - localReceiveTime", () => {
43
+ const clockOffset = new ClockOffset();
44
+ clockOffset.addSample({ serverTime: 10500, localReceiveTime: 10000 });
45
+ expect(clockOffset.currentOffset()).toBe(500);
46
+ });
47
+ test("converges to within a small tolerance of the true offset under bounded jitter", () => {
48
+ // True offset is 1000 ms; each sample has jitter of +/- 50 ms. The tolerance
49
+ // of 60 ms is chosen to be slightly larger than the jitter amplitude so the
50
+ // test does not assume a specific estimator (mean / median / trimmed mean
51
+ // would all satisfy it), but is tight enough to prove convergence is real.
52
+ const clockOffset = new ClockOffset();
53
+ const rng = makeRng(42);
54
+ const trueOffset = 1000;
55
+ for (let i = 0; i < 64; i++) {
56
+ const jitter = rng() * 50;
57
+ const localReceiveTime = 1000000 + i * 100;
58
+ const serverTime = localReceiveTime + trueOffset + jitter;
59
+ clockOffset.addSample({ serverTime, localReceiveTime });
60
+ }
61
+ expect(clockOffset.currentOffset()).toBeGreaterThan(trueOffset - 60);
62
+ expect(clockOffset.currentOffset()).toBeLessThan(trueOffset + 60);
63
+ });
64
+ test("a single huge outlier does not meaningfully move the estimate", () => {
65
+ const clockOffset = new ClockOffset();
66
+ const trueOffset = 1000;
67
+ // Fill the window with clean samples near offset=1000.
68
+ for (let i = 0; i < 32; i++) {
69
+ const localReceiveTime = 2000000 + i * 100;
70
+ clockOffset.addSample({
71
+ serverTime: localReceiveTime + trueOffset,
72
+ localReceiveTime,
73
+ });
74
+ }
75
+ const before = clockOffset.currentOffset();
76
+ // One extreme sample — offset would be ~100_000 if taken at face value.
77
+ clockOffset.addSample({
78
+ serverTime: 2000000 + 32 * 100 + 100000,
79
+ localReceiveTime: 2000000 + 32 * 100,
80
+ });
81
+ const after = clockOffset.currentOffset();
82
+ expect(Math.abs(after - trueOffset)).toBeLessThan(50);
83
+ expect(Math.abs(after - before)).toBeLessThan(50);
84
+ });
85
+ test("samples beyond maxAbsOffsetMs are ignored entirely", () => {
86
+ const clockOffset = new ClockOffset({ maxAbsOffsetMs: 5000 });
87
+ clockOffset.addSample({ serverTime: 10200, localReceiveTime: 10000 });
88
+ const before = clockOffset.currentOffset();
89
+ // Implied offset is 10_000_000 ms — well beyond the 5000 ms cap.
90
+ clockOffset.addSample({
91
+ serverTime: 20000000,
92
+ localReceiveTime: 10000000,
93
+ });
94
+ expect(clockOffset.currentOffset()).toBe(before);
95
+ });
96
+ test("sliding window drops old samples once newer ones fill it", () => {
97
+ const clockOffset = new ClockOffset({ windowSize: 10 });
98
+ // Ten samples establishing offset ~500.
99
+ for (let i = 0; i < 10; i++) {
100
+ const localReceiveTime = 3000000 + i * 100;
101
+ clockOffset.addSample({
102
+ serverTime: localReceiveTime + 500,
103
+ localReceiveTime,
104
+ });
105
+ }
106
+ // Twenty samples at offset ~2000 — more than the window, so the old
107
+ // offset=500 samples should be fully evicted.
108
+ for (let i = 0; i < 20; i++) {
109
+ const localReceiveTime = 3100000 + i * 100;
110
+ clockOffset.addSample({
111
+ serverTime: localReceiveTime + 2000,
112
+ localReceiveTime,
113
+ });
114
+ }
115
+ expect(clockOffset.currentOffset()).toBeGreaterThan(1950);
116
+ expect(clockOffset.currentOffset()).toBeLessThan(2050);
117
+ });
118
+ test("a hostile peer's single bad sample does not poison later estimates", () => {
119
+ const clockOffset = new ClockOffset();
120
+ const trueOffset = 1000;
121
+ // Warm-up with good samples.
122
+ for (let i = 0; i < 16; i++) {
123
+ const localReceiveTime = 4000000 + i * 100;
124
+ clockOffset.addSample({
125
+ serverTime: localReceiveTime + trueOffset,
126
+ localReceiveTime,
127
+ });
128
+ }
129
+ // Hostile sample — way off.
130
+ clockOffset.addSample({
131
+ serverTime: 4000000 + 16 * 100 + 500000,
132
+ localReceiveTime: 4000000 + 16 * 100,
133
+ });
134
+ // More good samples after the attack.
135
+ for (let i = 17; i < 48; i++) {
136
+ const localReceiveTime = 4000000 + i * 100;
137
+ clockOffset.addSample({
138
+ serverTime: localReceiveTime + trueOffset,
139
+ localReceiveTime,
140
+ });
141
+ }
142
+ expect(clockOffset.currentOffset()).toBeGreaterThan(trueOffset - 25);
143
+ expect(clockOffset.currentOffset()).toBeLessThan(trueOffset + 25);
144
+ });
145
+ });
146
+ //# sourceMappingURL=ClockOffset.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClockOffset.test.js","sourceRoot":"","sources":["../../src/tests/ClockOffset.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=clockDrift.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clockDrift.integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/clockDrift.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,177 @@
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ import { logger } from "../logger.js";
3
+ import { loadCoValueOrFail, setupTestAccount, setupTestNode, waitFor, } from "./testUtils.js";
4
+ const CLIENT_SKEW_MS = 20000;
5
+ afterEach(() => {
6
+ vi.restoreAllMocks();
7
+ });
8
+ describe("clock drift across peers with clock sync enabled", () => {
9
+ test("worker can publish and self-remove after a skewed client with clock sync creates group, grant and chat", async () => {
10
+ const errorSpy = vi.spyOn(logger, "error");
11
+ const realNow = Math.floor(performance.timeOrigin + performance.now());
12
+ vi.spyOn(Date, "now").mockImplementation(() => {
13
+ const real = performance.timeOrigin + performance.now();
14
+ return Math.floor(real) + CLIENT_SKEW_MS;
15
+ });
16
+ const worker = await setupTestAccount({
17
+ isSyncServer: true,
18
+ });
19
+ const client = await setupTestAccount({
20
+ connected: true,
21
+ experimental_clockSyncFromServerPings: true,
22
+ });
23
+ const skewedNow = Date.now();
24
+ client.node.clockOffset.addSample({
25
+ serverTime: skewedNow - CLIENT_SKEW_MS,
26
+ localReceiveTime: skewedNow,
27
+ });
28
+ const group = client.node.createGroup();
29
+ const workerAccountOnClient = await loadCoValueOrFail(client.node, worker.accountID);
30
+ group.addMember(workerAccountOnClient, "admin");
31
+ const oneToOneChat = group.createMap();
32
+ oneToOneChat.set("kind", "OneToOneChat", "trusting");
33
+ oneToOneChat.set("published", false, "trusting");
34
+ await oneToOneChat.core.waitForSync();
35
+ await group.core.waitForSync();
36
+ const clientGroupTxs = group.core.getValidSortedTransactions();
37
+ const maxClientGroupMadeAt = Math.max(...clientGroupTxs.map((tx) => tx.madeAt));
38
+ expect(maxClientGroupMadeAt).toBeLessThan(realNow + CLIENT_SKEW_MS - 5000);
39
+ vi.restoreAllMocks();
40
+ const errorSpyAfter = vi.spyOn(logger, "error");
41
+ const chatOnWorker = await loadCoValueOrFail(worker.node, oneToOneChat.id);
42
+ const groupOnWorker = await loadCoValueOrFail(worker.node, group.id);
43
+ const workerAccountOnWorker = await loadCoValueOrFail(worker.node, worker.accountID);
44
+ await waitFor(() => {
45
+ expect(chatOnWorker.get("kind")).toBe("OneToOneChat");
46
+ expect(groupOnWorker.roleOf(worker.accountID)).toBe("admin");
47
+ });
48
+ chatOnWorker.set("published", true, "trusting");
49
+ groupOnWorker.removeMember(workerAccountOnWorker);
50
+ await chatOnWorker.core.waitForSync();
51
+ await groupOnWorker.core.waitForSync();
52
+ await waitFor(() => {
53
+ expect(oneToOneChat.get("published")).toBe(true);
54
+ expect(group.roleOf(worker.accountID)).not.toBe("admin");
55
+ expect(chatOnWorker.get("published")).toBe(true);
56
+ expect(groupOnWorker.roleOf(worker.accountID)).not.toBe("admin");
57
+ });
58
+ expect(oneToOneChat.get("published")).toBe(true);
59
+ expect(chatOnWorker.get("published")).toBe(true);
60
+ expect(group.roleOf(worker.accountID)).not.toBe("admin");
61
+ expect(groupOnWorker.roleOf(worker.accountID)).not.toBe("admin");
62
+ const forbiddenFragments = [
63
+ "invalid transaction",
64
+ "permission",
65
+ "rejected",
66
+ "not authorized",
67
+ "not authorised",
68
+ ];
69
+ const offendingCalls = [...errorSpy.mock.calls, ...errorSpyAfter.mock.calls]
70
+ .map((call) => call.map((arg) => String(arg)).join(" "))
71
+ .filter((line) => forbiddenFragments.some((f) => line.toLowerCase().includes(f)));
72
+ expect(offendingCalls).toEqual([]);
73
+ });
74
+ });
75
+ describe("experimental_clockSyncFromServerPings flag wiring", () => {
76
+ function seedOffset(clockOffset, offsetMs) {
77
+ const localReceiveTime = Date.now();
78
+ clockOffset.addSample({
79
+ serverTime: localReceiveTime + offsetMs,
80
+ localReceiveTime,
81
+ });
82
+ }
83
+ test("with the flag on, a seeded +10_000 ms offset pulls locally-stamped madeAt forward", () => {
84
+ const { node } = setupTestNode({
85
+ experimental_clockSyncFromServerPings: true,
86
+ });
87
+ seedOffset(node.clockOffset, 10000);
88
+ const group = node.createGroup();
89
+ const map = group.createMap();
90
+ const before = Date.now();
91
+ map.set("k", "v", "trusting");
92
+ const after = Date.now();
93
+ const txs = map.core.getValidSortedTransactions();
94
+ const lastTx = txs.at(-1);
95
+ expect(lastTx).toBeDefined();
96
+ expect(lastTx.madeAt).toBeGreaterThanOrEqual(before + 9900);
97
+ expect(lastTx.madeAt).toBeLessThanOrEqual(after + 10100);
98
+ });
99
+ test("without the flag, a seeded +10_000 ms offset does NOT shift locally-stamped madeAt", () => {
100
+ const { node } = setupTestNode({
101
+ experimental_clockSyncFromServerPings: false,
102
+ });
103
+ seedOffset(node.clockOffset, 10000);
104
+ const group = node.createGroup();
105
+ const map = group.createMap();
106
+ const before = Date.now();
107
+ map.set("k", "v", "trusting");
108
+ const after = Date.now();
109
+ const txs = map.core.getValidSortedTransactions();
110
+ const lastTx = txs.at(-1);
111
+ expect(lastTx).toBeDefined();
112
+ expect(lastTx.madeAt).toBeGreaterThanOrEqual(before);
113
+ expect(lastTx.madeAt).toBeLessThanOrEqual(after + 100);
114
+ });
115
+ });
116
+ describe("clock sync pulls skewed client stamps toward server time", () => {
117
+ test("with both nodes flag-on, a client whose wall clock is 20s ahead authors transactions that land near real time on the worker", async () => {
118
+ const errorSpy = vi.spyOn(logger, "error");
119
+ const worker = await setupTestAccount({
120
+ isSyncServer: true,
121
+ experimental_clockSyncFromServerPings: true,
122
+ });
123
+ const realNowBeforeClient = Date.now();
124
+ const SKEW_MS = 20000;
125
+ vi.spyOn(Date, "now").mockImplementation(() => {
126
+ const real = Math.floor(performance.timeOrigin + performance.now());
127
+ return real + SKEW_MS;
128
+ });
129
+ const client = await setupTestAccount({
130
+ connected: true,
131
+ experimental_clockSyncFromServerPings: true,
132
+ });
133
+ const localReceiveTime = Date.now();
134
+ client.node.clockOffset.addSample({
135
+ serverTime: localReceiveTime - SKEW_MS,
136
+ localReceiveTime,
137
+ });
138
+ expect(client.node.clockOffset.currentOffset()).toBeLessThanOrEqual(-SKEW_MS + 100);
139
+ expect(client.node.clockOffset.currentOffset()).toBeGreaterThanOrEqual(-SKEW_MS - 100);
140
+ const group = client.node.createGroup();
141
+ group.addMember("everyone", "writer");
142
+ const map = group.createMap();
143
+ map.set("from", "skewed-client", "trusting");
144
+ await map.core.waitForSync();
145
+ await group.core.waitForSync();
146
+ vi.restoreAllMocks();
147
+ const errorSpyAfter = vi.spyOn(logger, "error");
148
+ const realNowAfter = Date.now();
149
+ const mapOnWorker = await loadCoValueOrFail(worker.node, map.id);
150
+ await waitFor(() => {
151
+ expect(mapOnWorker.get("from")).toBe("skewed-client");
152
+ });
153
+ const clientTxsOnWorker = mapOnWorker.core.getValidSortedTransactions();
154
+ const setTx = clientTxsOnWorker.find((tx) => {
155
+ const changes = tx.changes;
156
+ return (changes?.[0]?.key === "from" && changes[0]?.value === "skewed-client");
157
+ });
158
+ expect(setTx).toBeDefined();
159
+ const TOLERANCE_MS = 2000;
160
+ expect(setTx.madeAt).toBeGreaterThanOrEqual(realNowBeforeClient - TOLERANCE_MS);
161
+ expect(setTx.madeAt).toBeLessThanOrEqual(realNowAfter + TOLERANCE_MS);
162
+ expect(setTx.madeAt).toBeLessThan(realNowAfter + SKEW_MS - 5000);
163
+ const forbiddenFragments = [
164
+ "invalid transaction",
165
+ "permission",
166
+ "rejected",
167
+ "not authorized",
168
+ "not authorised",
169
+ "out of order",
170
+ ];
171
+ const offendingCalls = [...errorSpy.mock.calls, ...errorSpyAfter.mock.calls]
172
+ .map((call) => call.map((arg) => String(arg)).join(" "))
173
+ .filter((line) => forbiddenFragments.some((f) => line.toLowerCase().includes(f)));
174
+ expect(offendingCalls).toEqual([]);
175
+ });
176
+ });
177
+ //# sourceMappingURL=clockDrift.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clockDrift.integration.test.js","sourceRoot":"","sources":["../../src/tests/clockDrift.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=localNode.clockOffset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localNode.clockOffset.test.d.ts","sourceRoot":"","sources":["../../src/tests/localNode.clockOffset.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { ClockOffset } from "../ClockOffset.js";
3
+ import { LocalNode } from "../localNode.js";
4
+ import { randomAgentAndSessionID } from "./testUtils.js";
5
+ import { WasmCrypto } from "../crypto/WasmCrypto.js";
6
+ const Crypto = await WasmCrypto.create();
7
+ function makeNode(opts) {
8
+ const [admin, session] = randomAgentAndSessionID();
9
+ return new LocalNode(admin.agentSecret, session, Crypto, undefined, undefined, opts);
10
+ }
11
+ describe("LocalNode clock offset wiring", () => {
12
+ test("clockOffset is always present on the node, regardless of flag state", () => {
13
+ const withFlag = makeNode({ experimental_clockSyncFromServerPings: true });
14
+ const withoutFlag = makeNode({
15
+ experimental_clockSyncFromServerPings: false,
16
+ });
17
+ expect(withFlag.clockOffset).toBeInstanceOf(ClockOffset);
18
+ expect(withoutFlag.clockOffset).toBeInstanceOf(ClockOffset);
19
+ });
20
+ test("with the flag enabled, seeding clockOffset with a +10_000 ms sample pulls stampNow() forward by ~10_000 ms", () => {
21
+ const flagged = makeNode({ experimental_clockSyncFromServerPings: true });
22
+ const control = makeNode({
23
+ experimental_clockSyncFromServerPings: false,
24
+ });
25
+ const localReceiveTime = Date.now();
26
+ flagged.clockOffset.addSample({
27
+ serverTime: localReceiveTime + 10000,
28
+ localReceiveTime,
29
+ });
30
+ const controlStamp = control.stampNow();
31
+ const flaggedStamp = flagged.stampNow();
32
+ const delta = flaggedStamp - controlStamp;
33
+ expect(delta).toBeGreaterThanOrEqual(9900);
34
+ expect(delta).toBeLessThanOrEqual(10100);
35
+ });
36
+ test("getClockOffsetDiagnostics() reflects current offset and sample count", () => {
37
+ const node = makeNode({ experimental_clockSyncFromServerPings: true });
38
+ expect(node.getClockOffsetDiagnostics()).toEqual({
39
+ currentOffset: 0,
40
+ sampleCount: 0,
41
+ });
42
+ const base = Date.now();
43
+ node.clockOffset.addSample({
44
+ serverTime: base + 400,
45
+ localReceiveTime: base,
46
+ });
47
+ node.clockOffset.addSample({
48
+ serverTime: base + 600,
49
+ localReceiveTime: base,
50
+ });
51
+ expect(node.getClockOffsetDiagnostics()).toEqual({
52
+ currentOffset: 500,
53
+ sampleCount: 2,
54
+ });
55
+ });
56
+ test("without the flag, seeding clockOffset with a +10_000 ms sample does NOT affect stampNow()", () => {
57
+ const node = makeNode({ experimental_clockSyncFromServerPings: false });
58
+ const localReceiveTime = Date.now();
59
+ node.clockOffset.addSample({
60
+ serverTime: localReceiveTime + 10000,
61
+ localReceiveTime,
62
+ });
63
+ const before = Date.now();
64
+ const stamp = node.stampNow();
65
+ const after = Date.now();
66
+ expect(stamp).toBeGreaterThanOrEqual(before);
67
+ expect(stamp).toBeLessThanOrEqual(after + 100);
68
+ });
69
+ });
70
+ //# sourceMappingURL=localNode.clockOffset.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localNode.clockOffset.test.js","sourceRoot":"","sources":["../../src/tests/localNode.clockOffset.test.ts"],"names":[],"mappings":"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"}
@@ -139,6 +139,7 @@ export declare function setupTestNode(opts?: {
139
139
  secret?: AgentSecret;
140
140
  syncWhen?: SyncWhen;
141
141
  enableFullStorageReconciliation?: boolean;
142
+ experimental_clockSyncFromServerPings?: boolean;
142
143
  }): {
143
144
  node: LocalNode;
144
145
  connectToSyncServer: (opts?: {
@@ -176,6 +177,7 @@ export declare function setupTestAccount(opts?: {
176
177
  storage?: StorageAPI;
177
178
  accountID?: RawAccountID;
178
179
  accountSecret?: AgentSecret;
180
+ experimental_clockSyncFromServerPings?: boolean;
179
181
  }): Promise<{
180
182
  node: LocalNode;
181
183
  accountID: RawAccountID;
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../src/tests/testUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../../src/tests/testUtils.ts"],"names":[],"mappings":"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"}
@@ -289,7 +289,9 @@ export function setupTestNode(opts = {}) {
289
289
  const [admin, session] = opts.secret
290
290
  ? agentAndSessionIDFromSecret(opts.secret)
291
291
  : randomAgentAndSessionID();
292
- let node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation);
292
+ let node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation, {
293
+ experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
294
+ });
293
295
  if (opts.isSyncServer) {
294
296
  syncServer.current = node;
295
297
  }
@@ -340,7 +342,9 @@ export function setupTestNode(opts = {}) {
340
342
  addAsyncStorage,
341
343
  restart: async () => {
342
344
  await node.gracefulShutdown();
343
- ctx.node = node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation);
345
+ ctx.node = node = new LocalNode(admin.agentSecret, session, Crypto, opts.syncWhen, opts.enableFullStorageReconciliation, {
346
+ experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
347
+ });
344
348
  if (opts.isSyncServer) {
345
349
  syncServer.current = node;
346
350
  }
@@ -352,6 +356,7 @@ export function setupTestNode(opts = {}) {
352
356
  connected: opts.connected,
353
357
  isSyncServer: opts.isSyncServer,
354
358
  enableFullStorageReconciliation: opts.enableFullStorageReconciliation,
359
+ experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
355
360
  });
356
361
  },
357
362
  disconnect: () => {
@@ -378,6 +383,7 @@ export async function setupTestAccount(opts = {}) {
378
383
  accountID: opts.accountID,
379
384
  accountSecret: opts.accountSecret,
380
385
  sessionID: Crypto.newRandomSessionID(opts.accountID),
386
+ experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
381
387
  }),
382
388
  accountID: opts.accountID,
383
389
  accountSecret: opts.accountSecret,
@@ -387,6 +393,7 @@ export async function setupTestAccount(opts = {}) {
387
393
  crypto: Crypto,
388
394
  creationProps: { name: "Client" },
389
395
  storage: opts.storage,
396
+ experimental_clockSyncFromServerPings: opts.experimental_clockSyncFromServerPings,
390
397
  });
391
398
  if (opts.isSyncServer) {
392
399
  syncServer.current = ctx.node;