@peers-app/peers-device 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-download-manager.d.ts +2 -2
- package/dist/chunk-download-manager.js +1 -1
- package/dist/chunk-download-manager.js.map +1 -1
- package/dist/chunk-download-manager.test.js +57 -57
- package/dist/chunk-download-manager.test.js.map +1 -1
- package/dist/chunk-download.types.d.ts +1 -1
- package/dist/connection-manager/connection-manager-priorities.d.ts +1 -1
- package/dist/connection-manager/connection-manager-priorities.js +10 -6
- package/dist/connection-manager/connection-manager-priorities.js.map +1 -1
- package/dist/connection-manager/connection-manager-priorities.test.js +192 -194
- package/dist/connection-manager/connection-manager-priorities.test.js.map +1 -1
- package/dist/connection-manager/connection-manager.d.ts +2 -2
- package/dist/connection-manager/connection-manager.js +71 -55
- package/dist/connection-manager/connection-manager.js.map +1 -1
- package/dist/connection-manager/connection-manager.test.js +165 -147
- package/dist/connection-manager/connection-manager.test.js.map +1 -1
- package/dist/connection-manager/connection-state.type.d.ts +1 -1
- package/dist/connection-manager/device-message-handler.types.d.ts +6 -6
- package/dist/connection-manager/device-messages.d.ts +4 -4
- package/dist/connection-manager/device-messages.js +56 -40
- package/dist/connection-manager/device-messages.js.map +1 -1
- package/dist/connection-manager/group-invite-messages.d.ts +2 -2
- package/dist/connection-manager/group-invite-messages.js +36 -47
- package/dist/connection-manager/group-invite-messages.js.map +1 -1
- package/dist/connection-manager/hops-map.js +4 -4
- package/dist/connection-manager/hops-map.js.map +1 -1
- package/dist/connection-manager/hops-map.test.js +3 -3
- package/dist/connection-manager/hops-map.test.js.map +1 -1
- package/dist/connection-manager/network-manager.d.ts +2 -2
- package/dist/connection-manager/network-manager.js +81 -75
- package/dist/connection-manager/network-manager.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/json-diff.d.ts +2 -2
- package/dist/json-diff.js +30 -27
- package/dist/json-diff.js.map +1 -1
- package/dist/local.data-source.d.ts +1 -1
- package/dist/local.data-source.js +23 -23
- package/dist/local.data-source.js.map +1 -1
- package/dist/local.data-source.test.js +17 -17
- package/dist/local.data-source.test.js.map +1 -1
- package/dist/machine-stats.js +57 -51
- package/dist/machine-stats.js.map +1 -1
- package/dist/machine-stats.test.js +42 -42
- package/dist/machine-stats.test.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.js +10 -8
- package/dist/main.js.map +1 -1
- package/dist/packages.tracked-data-source.d.ts +1 -1
- package/dist/packages.tracked-data-source.js.map +1 -1
- package/dist/persistent-vars.test.js +148 -148
- package/dist/persistent-vars.test.js.map +1 -1
- package/dist/pvars.tracked-data-source.d.ts +1 -1
- package/dist/pvars.tracked-data-source.js +12 -10
- package/dist/pvars.tracked-data-source.js.map +1 -1
- package/dist/sync-group.d.ts +2 -2
- package/dist/sync-group.js +110 -88
- package/dist/sync-group.js.map +1 -1
- package/dist/sync-group.test.js +157 -120
- package/dist/sync-group.test.js.map +1 -1
- package/dist/tracked-data-source.d.ts +1 -1
- package/dist/tracked-data-source.js +61 -62
- package/dist/tracked-data-source.js.map +1 -1
- package/dist/tracked-data-source.test.js +507 -299
- package/dist/tracked-data-source.test.js.map +1 -1
- package/dist/websocket-client.d.ts +1 -1
- package/dist/websocket-client.js +50 -41
- package/dist/websocket-client.js.map +1 -1
- package/package.json +3 -3
|
@@ -32,7 +32,7 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
32
32
|
async function createTestUserContext() {
|
|
33
33
|
const userId = (0, peers_sdk_1.newid)();
|
|
34
34
|
const deviceId = (0, peers_sdk_1.newid)();
|
|
35
|
-
const db = new local_data_source_1.DBLocal(
|
|
35
|
+
const db = new local_data_source_1.DBLocal(":memory:");
|
|
36
36
|
const dataSourceFactory = (metaData, schema, groupId) => {
|
|
37
37
|
const sqlDataSource = new peers_sdk_1.SQLDataSource(db, metaData, schema);
|
|
38
38
|
return sqlDataSource;
|
|
@@ -45,47 +45,47 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
45
45
|
describe("pvar basic functionality", () => {
|
|
46
46
|
it("should create and persist a pvar value", async () => {
|
|
47
47
|
const userContext = await createTestUserContext();
|
|
48
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
49
|
-
defaultValue:
|
|
50
|
-
userContext
|
|
48
|
+
const pvar = (0, peers_sdk_1.deviceVar)("basicTestVar", {
|
|
49
|
+
defaultValue: "initial",
|
|
50
|
+
userContext,
|
|
51
51
|
});
|
|
52
52
|
await pvar.loadingPromise;
|
|
53
|
-
expect(pvar()).toBe(
|
|
54
|
-
pvar(
|
|
53
|
+
expect(pvar()).toBe("initial");
|
|
54
|
+
pvar("updated");
|
|
55
55
|
await (0, peers_sdk_1.sleep)(100);
|
|
56
|
-
expect(pvar()).toBe(
|
|
56
|
+
expect(pvar()).toBe("updated");
|
|
57
57
|
});
|
|
58
58
|
it("should sync value between two pvar instances (without rapid updates)", async () => {
|
|
59
59
|
const userContext = await createTestUserContext();
|
|
60
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
61
|
-
defaultValue:
|
|
62
|
-
userContext
|
|
60
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("syncTestVar", {
|
|
61
|
+
defaultValue: "initial",
|
|
62
|
+
userContext,
|
|
63
63
|
});
|
|
64
64
|
await pvar1.loadingPromise;
|
|
65
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
66
|
-
defaultValue:
|
|
67
|
-
userContext
|
|
65
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("syncTestVar", {
|
|
66
|
+
defaultValue: "initial",
|
|
67
|
+
userContext,
|
|
68
68
|
});
|
|
69
69
|
await pvar2.loadingPromise;
|
|
70
70
|
// Single update with enough time to settle
|
|
71
|
-
pvar1(
|
|
71
|
+
pvar1("updated-value");
|
|
72
72
|
await (0, peers_sdk_1.sleep)(200);
|
|
73
73
|
// Both should have the same value
|
|
74
|
-
expect(pvar1()).toBe(
|
|
75
|
-
expect(pvar2()).toBe(
|
|
74
|
+
expect(pvar1()).toBe("updated-value");
|
|
75
|
+
expect(pvar2()).toBe("updated-value");
|
|
76
76
|
});
|
|
77
77
|
});
|
|
78
78
|
describe("bug documentation", () => {
|
|
79
79
|
it("confirms same pvar instance is returned for same name (singleton pattern)", async () => {
|
|
80
80
|
const userContext = await createTestUserContext();
|
|
81
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
82
|
-
defaultValue:
|
|
83
|
-
userContext
|
|
81
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("instanceTestVar", {
|
|
82
|
+
defaultValue: "default",
|
|
83
|
+
userContext,
|
|
84
84
|
});
|
|
85
85
|
await pvar1.loadingPromise;
|
|
86
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
87
|
-
defaultValue:
|
|
88
|
-
userContext
|
|
86
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("instanceTestVar", {
|
|
87
|
+
defaultValue: "default",
|
|
88
|
+
userContext,
|
|
89
89
|
});
|
|
90
90
|
await pvar2.loadingPromise;
|
|
91
91
|
// Singleton pattern: these ARE the same instance
|
|
@@ -99,20 +99,20 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
99
99
|
let localEventCount = 0;
|
|
100
100
|
let remoteEventCount = 0;
|
|
101
101
|
// Subscribe to events before creating the pvar
|
|
102
|
-
userContext.subscribeToDataChangedAcrossAllGroups(
|
|
103
|
-
if (evt.data.source ===
|
|
102
|
+
userContext.subscribeToDataChangedAcrossAllGroups("PersistentVars", (evt) => {
|
|
103
|
+
if (evt.data.source === "local") {
|
|
104
104
|
localEventCount++;
|
|
105
105
|
}
|
|
106
106
|
else {
|
|
107
107
|
remoteEventCount++;
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
111
|
-
defaultValue:
|
|
112
|
-
userContext
|
|
110
|
+
const pvar = (0, peers_sdk_1.deviceVar)("eventTestVar", {
|
|
111
|
+
defaultValue: "initial",
|
|
112
|
+
userContext,
|
|
113
113
|
});
|
|
114
114
|
await pvar.loadingPromise;
|
|
115
|
-
pvar(
|
|
115
|
+
pvar("test-value");
|
|
116
116
|
await (0, peers_sdk_1.sleep)(200);
|
|
117
117
|
// Document that local events ARE received (this contributes to the bug)
|
|
118
118
|
// WHEN FIXED: Local events should either be filtered out OR the pvar
|
|
@@ -125,14 +125,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
125
125
|
const userContext = await createTestUserContext();
|
|
126
126
|
let updateCount = 0;
|
|
127
127
|
const maxUpdates = 20;
|
|
128
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
128
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("debugBugVar", {
|
|
129
129
|
defaultValue: 0,
|
|
130
|
-
userContext
|
|
130
|
+
userContext,
|
|
131
131
|
});
|
|
132
132
|
await pvar1.loadingPromise;
|
|
133
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
133
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("debugBugVar", {
|
|
134
134
|
defaultValue: 0,
|
|
135
|
-
userContext
|
|
135
|
+
userContext,
|
|
136
136
|
});
|
|
137
137
|
await pvar2.loadingPromise;
|
|
138
138
|
pvar1.subscribe(() => {
|
|
@@ -158,14 +158,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
158
158
|
});
|
|
159
159
|
it("singleton pattern returns same instance for same name/scope", async () => {
|
|
160
160
|
const userContext = await createTestUserContext();
|
|
161
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
162
|
-
defaultValue:
|
|
163
|
-
userContext
|
|
161
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("singletonVerifyVar", {
|
|
162
|
+
defaultValue: "default",
|
|
163
|
+
userContext,
|
|
164
164
|
});
|
|
165
165
|
await pvar1.loadingPromise;
|
|
166
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
167
|
-
defaultValue:
|
|
168
|
-
userContext
|
|
166
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("singletonVerifyVar", {
|
|
167
|
+
defaultValue: "default",
|
|
168
|
+
userContext,
|
|
169
169
|
});
|
|
170
170
|
await pvar2.loadingPromise;
|
|
171
171
|
// Singleton pattern is now implemented - same instance should be returned
|
|
@@ -173,14 +173,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
173
173
|
});
|
|
174
174
|
it("different pvar names return different instances", async () => {
|
|
175
175
|
const userContext = await createTestUserContext();
|
|
176
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
177
|
-
defaultValue:
|
|
178
|
-
userContext
|
|
176
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("singletonVarA", {
|
|
177
|
+
defaultValue: "default",
|
|
178
|
+
userContext,
|
|
179
179
|
});
|
|
180
180
|
await pvar1.loadingPromise;
|
|
181
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
182
|
-
defaultValue:
|
|
183
|
-
userContext
|
|
181
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("singletonVarB", {
|
|
182
|
+
defaultValue: "default",
|
|
183
|
+
userContext,
|
|
184
184
|
});
|
|
185
185
|
await pvar2.loadingPromise;
|
|
186
186
|
// Different names should be different instances
|
|
@@ -189,24 +189,24 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
189
189
|
it("different userContexts return different instances (test isolation)", async () => {
|
|
190
190
|
const userContext1 = await createTestUserContext();
|
|
191
191
|
const userContext2 = await createTestUserContext();
|
|
192
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
193
|
-
defaultValue:
|
|
194
|
-
userContext: userContext1
|
|
192
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("isolationTestVar", {
|
|
193
|
+
defaultValue: "default",
|
|
194
|
+
userContext: userContext1,
|
|
195
195
|
});
|
|
196
196
|
await pvar1.loadingPromise;
|
|
197
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
198
|
-
defaultValue:
|
|
199
|
-
userContext: userContext2
|
|
197
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("isolationTestVar", {
|
|
198
|
+
defaultValue: "default",
|
|
199
|
+
userContext: userContext2,
|
|
200
200
|
});
|
|
201
201
|
await pvar2.loadingPromise;
|
|
202
202
|
// Different userContexts should have different instances (important for test isolation)
|
|
203
203
|
expect(pvar1).not.toBe(pvar2);
|
|
204
204
|
// They should work independently
|
|
205
|
-
pvar1(
|
|
206
|
-
pvar2(
|
|
205
|
+
pvar1("value1");
|
|
206
|
+
pvar2("value2");
|
|
207
207
|
await (0, peers_sdk_1.sleep)(100);
|
|
208
|
-
expect(pvar1()).toBe(
|
|
209
|
-
expect(pvar2()).toBe(
|
|
208
|
+
expect(pvar1()).toBe("value1");
|
|
209
|
+
expect(pvar2()).toBe("value2");
|
|
210
210
|
});
|
|
211
211
|
});
|
|
212
212
|
/**
|
|
@@ -218,14 +218,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
218
218
|
it("rapid sequential updates should not cause infinite loop", async () => {
|
|
219
219
|
const userContext = await createTestUserContext();
|
|
220
220
|
let updateCount = 0;
|
|
221
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
221
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("rapidBugVar", {
|
|
222
222
|
defaultValue: 0,
|
|
223
|
-
userContext
|
|
223
|
+
userContext,
|
|
224
224
|
});
|
|
225
225
|
await pvar1.loadingPromise;
|
|
226
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
226
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("rapidBugVar", {
|
|
227
227
|
defaultValue: 0,
|
|
228
|
-
userContext
|
|
228
|
+
userContext,
|
|
229
229
|
});
|
|
230
230
|
await pvar2.loadingPromise;
|
|
231
231
|
pvar1.subscribe(() => updateCount++);
|
|
@@ -241,21 +241,21 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
241
241
|
it("alternating updates between instances should not cause infinite loop", async () => {
|
|
242
242
|
const userContext = await createTestUserContext();
|
|
243
243
|
let updateCount = 0;
|
|
244
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
245
|
-
defaultValue:
|
|
246
|
-
userContext
|
|
244
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("alternateBugVar", {
|
|
245
|
+
defaultValue: "initial",
|
|
246
|
+
userContext,
|
|
247
247
|
});
|
|
248
248
|
await pvar1.loadingPromise;
|
|
249
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
250
|
-
defaultValue:
|
|
251
|
-
userContext
|
|
249
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("alternateBugVar", {
|
|
250
|
+
defaultValue: "initial",
|
|
251
|
+
userContext,
|
|
252
252
|
});
|
|
253
253
|
await pvar2.loadingPromise;
|
|
254
254
|
pvar1.subscribe(() => updateCount++);
|
|
255
255
|
pvar2.subscribe(() => updateCount++);
|
|
256
256
|
// Alternating updates between instances
|
|
257
|
-
pvar1(
|
|
258
|
-
pvar2(
|
|
257
|
+
pvar1("from-1");
|
|
258
|
+
pvar2("from-2");
|
|
259
259
|
await (0, peers_sdk_1.sleep)(1000);
|
|
260
260
|
// Should not cause infinite loop - expect reasonable update count
|
|
261
261
|
expect(updateCount).toBeLessThan(10);
|
|
@@ -269,14 +269,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
269
269
|
const userContext = await createTestUserContext();
|
|
270
270
|
let updateCount = 0;
|
|
271
271
|
let loopDetected = false;
|
|
272
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
272
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("seqPropagationVar", {
|
|
273
273
|
defaultValue: 0,
|
|
274
|
-
userContext
|
|
274
|
+
userContext,
|
|
275
275
|
});
|
|
276
276
|
await pvar1.loadingPromise;
|
|
277
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
277
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("seqPropagationVar", {
|
|
278
278
|
defaultValue: 0,
|
|
279
|
-
userContext
|
|
279
|
+
userContext,
|
|
280
280
|
});
|
|
281
281
|
await pvar2.loadingPromise;
|
|
282
282
|
// Set up subscribers that count updates and detect loops
|
|
@@ -319,29 +319,29 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
319
319
|
const userContext = await createTestUserContext();
|
|
320
320
|
const updates = [];
|
|
321
321
|
const MAX_UPDATES = 30;
|
|
322
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
323
|
-
defaultValue:
|
|
324
|
-
userContext
|
|
322
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("crossSyncVar", {
|
|
323
|
+
defaultValue: "start",
|
|
324
|
+
userContext,
|
|
325
325
|
});
|
|
326
326
|
await pvar1.loadingPromise;
|
|
327
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
328
|
-
defaultValue:
|
|
329
|
-
userContext
|
|
327
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("crossSyncVar", {
|
|
328
|
+
defaultValue: "start",
|
|
329
|
+
userContext,
|
|
330
330
|
});
|
|
331
331
|
await pvar2.loadingPromise;
|
|
332
332
|
// Track all updates
|
|
333
|
-
pvar1.subscribe(v => {
|
|
333
|
+
pvar1.subscribe((v) => {
|
|
334
334
|
if (updates.length < MAX_UPDATES) {
|
|
335
335
|
updates.push(`pvar1:${v}`);
|
|
336
336
|
}
|
|
337
337
|
});
|
|
338
|
-
pvar2.subscribe(v => {
|
|
338
|
+
pvar2.subscribe((v) => {
|
|
339
339
|
if (updates.length < MAX_UPDATES) {
|
|
340
340
|
updates.push(`pvar2:${v}`);
|
|
341
341
|
}
|
|
342
342
|
});
|
|
343
343
|
// Single update
|
|
344
|
-
pvar1(
|
|
344
|
+
pvar1("changed");
|
|
345
345
|
// Wait for sync
|
|
346
346
|
await (0, peers_sdk_1.sleep)(500);
|
|
347
347
|
const updatesAfterSync = updates.length;
|
|
@@ -351,8 +351,8 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
351
351
|
// Should have stabilized - no new updates
|
|
352
352
|
expect(updatesAfterWait - updatesAfterSync).toBe(0);
|
|
353
353
|
// Both should have the same value
|
|
354
|
-
expect(pvar1()).toBe(
|
|
355
|
-
expect(pvar2()).toBe(
|
|
354
|
+
expect(pvar1()).toBe("changed");
|
|
355
|
+
expect(pvar2()).toBe("changed");
|
|
356
356
|
// Total updates should be reasonable (pvar1 update + pvar2 sync = ~2-4 updates)
|
|
357
357
|
expect(updates.length).toBeLessThan(10);
|
|
358
358
|
});
|
|
@@ -367,9 +367,9 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
367
367
|
*/
|
|
368
368
|
it("rapid updates should result in final value being persisted, not stale values", async () => {
|
|
369
369
|
const userContext = await createTestUserContext();
|
|
370
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
370
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("staleValueVar", {
|
|
371
371
|
defaultValue: 0,
|
|
372
|
-
userContext
|
|
372
|
+
userContext,
|
|
373
373
|
});
|
|
374
374
|
await pvar1.loadingPromise;
|
|
375
375
|
// Make rapid updates - all synchronous, before any async processing
|
|
@@ -382,9 +382,9 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
382
382
|
await pvar1.loadingPromise;
|
|
383
383
|
await (0, peers_sdk_1.sleep)(500);
|
|
384
384
|
// Create a new pvar instance to read fresh from DB
|
|
385
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
385
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("staleValueVar", {
|
|
386
386
|
defaultValue: 0,
|
|
387
|
-
userContext
|
|
387
|
+
userContext,
|
|
388
388
|
});
|
|
389
389
|
await pvar2.loadingPromise;
|
|
390
390
|
// The DB should have the final value (5), not any intermediate value
|
|
@@ -399,13 +399,13 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
399
399
|
it("value should not regress during rapid updates", async () => {
|
|
400
400
|
const userContext = await createTestUserContext();
|
|
401
401
|
const valuesObserved = [];
|
|
402
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
402
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("regressionVar", {
|
|
403
403
|
defaultValue: 0,
|
|
404
|
-
userContext
|
|
404
|
+
userContext,
|
|
405
405
|
});
|
|
406
406
|
await pvar1.loadingPromise;
|
|
407
407
|
// Track all values observed
|
|
408
|
-
pvar1.subscribe(v => {
|
|
408
|
+
pvar1.subscribe((v) => {
|
|
409
409
|
valuesObserved.push(v);
|
|
410
410
|
});
|
|
411
411
|
// Rapid sequential updates
|
|
@@ -421,7 +421,7 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
421
421
|
for (const v of valuesObserved) {
|
|
422
422
|
if (v < maxSeen) {
|
|
423
423
|
// Value regressed - this indicates the bug
|
|
424
|
-
fail(`Value regressed from ${maxSeen} to ${v}. All values: ${valuesObserved.join(
|
|
424
|
+
fail(`Value regressed from ${maxSeen} to ${v}. All values: ${valuesObserved.join(", ")}`);
|
|
425
425
|
}
|
|
426
426
|
maxSeen = Math.max(maxSeen, v);
|
|
427
427
|
}
|
|
@@ -455,24 +455,24 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
455
455
|
const pvar1Values = [];
|
|
456
456
|
const pvar2Values = [];
|
|
457
457
|
const MAX_UPDATES = 50; // If we exceed this, it's an infinite loop
|
|
458
|
-
const pvar1 = (0, peers_sdk_1.deviceVar)(
|
|
458
|
+
const pvar1 = (0, peers_sdk_1.deviceVar)("raceConditionVar", {
|
|
459
459
|
defaultValue: 0,
|
|
460
|
-
userContext
|
|
460
|
+
userContext,
|
|
461
461
|
});
|
|
462
462
|
await pvar1.loadingPromise;
|
|
463
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
463
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("raceConditionVar", {
|
|
464
464
|
defaultValue: 0,
|
|
465
|
-
userContext
|
|
465
|
+
userContext,
|
|
466
466
|
});
|
|
467
467
|
await pvar2.loadingPromise;
|
|
468
468
|
// Track observable updates and THROW if infinite loop detected
|
|
469
|
-
pvar1.subscribe(v => {
|
|
469
|
+
pvar1.subscribe((v) => {
|
|
470
470
|
pvar1Values.push(v);
|
|
471
471
|
if (pvar1Values.length + pvar2Values.length > MAX_UPDATES) {
|
|
472
472
|
throw new Error(`INFINITE LOOP DETECTED: ${pvar1Values.length + pvar2Values.length} updates`);
|
|
473
473
|
}
|
|
474
474
|
});
|
|
475
|
-
pvar2.subscribe(v => {
|
|
475
|
+
pvar2.subscribe((v) => {
|
|
476
476
|
pvar2Values.push(v);
|
|
477
477
|
if (pvar1Values.length + pvar2Values.length > MAX_UPDATES) {
|
|
478
478
|
throw new Error(`INFINITE LOOP DETECTED: ${pvar1Values.length + pvar2Values.length} updates`);
|
|
@@ -493,14 +493,14 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
493
493
|
let pvar1Max = 0;
|
|
494
494
|
for (const v of pvar1Values) {
|
|
495
495
|
if (v < pvar1Max) {
|
|
496
|
-
fail(`pvar1 regressed from ${pvar1Max} to ${v}. Values: ${pvar1Values.join(
|
|
496
|
+
fail(`pvar1 regressed from ${pvar1Max} to ${v}. Values: ${pvar1Values.join(", ")}`);
|
|
497
497
|
}
|
|
498
498
|
pvar1Max = Math.max(pvar1Max, v);
|
|
499
499
|
}
|
|
500
500
|
let pvar2Max = 0;
|
|
501
501
|
for (const v of pvar2Values) {
|
|
502
502
|
if (v < pvar2Max) {
|
|
503
|
-
fail(`pvar2 regressed from ${pvar2Max} to ${v}. Values: ${pvar2Values.join(
|
|
503
|
+
fail(`pvar2 regressed from ${pvar2Max} to ${v}. Values: ${pvar2Values.join(", ")}`);
|
|
504
504
|
}
|
|
505
505
|
pvar2Max = Math.max(pvar2Max, v);
|
|
506
506
|
}
|
|
@@ -509,138 +509,138 @@ describe("Persistent Variables - Update Loop Bug", () => {
|
|
|
509
509
|
describe("explicit delete functionality", () => {
|
|
510
510
|
it("should not auto-delete when value equals default", async () => {
|
|
511
511
|
const userContext = await createTestUserContext();
|
|
512
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
513
|
-
defaultValue:
|
|
514
|
-
userContext
|
|
512
|
+
const pvar = (0, peers_sdk_1.deviceVar)("noAutoDeleteVar", {
|
|
513
|
+
defaultValue: "default",
|
|
514
|
+
userContext,
|
|
515
515
|
});
|
|
516
516
|
await pvar.loadingPromise;
|
|
517
517
|
// Change to a non-default value and persist
|
|
518
|
-
pvar(
|
|
518
|
+
pvar("changed");
|
|
519
519
|
await pvar.loadingPromise;
|
|
520
520
|
await (0, peers_sdk_1.sleep)(100);
|
|
521
521
|
// Verify it was persisted
|
|
522
|
-
expect(pvar()).toBe(
|
|
522
|
+
expect(pvar()).toBe("changed");
|
|
523
523
|
// Set back to the default value
|
|
524
|
-
pvar(
|
|
524
|
+
pvar("default");
|
|
525
525
|
await pvar.loadingPromise;
|
|
526
526
|
await (0, peers_sdk_1.sleep)(100);
|
|
527
527
|
// Value should still be persisted (not auto-deleted)
|
|
528
528
|
// We verify by creating a new pvar instance to read fresh from DB
|
|
529
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
530
|
-
defaultValue:
|
|
531
|
-
userContext
|
|
529
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("noAutoDeleteVar", {
|
|
530
|
+
defaultValue: "default",
|
|
531
|
+
userContext,
|
|
532
532
|
});
|
|
533
533
|
await pvar2.loadingPromise;
|
|
534
534
|
// The value in DB should be 'default' (explicitly set), not missing
|
|
535
|
-
expect(pvar2()).toBe(
|
|
535
|
+
expect(pvar2()).toBe("default");
|
|
536
536
|
});
|
|
537
537
|
it("delete() should remove pvar from database and reset to default", async () => {
|
|
538
538
|
const userContext = await createTestUserContext();
|
|
539
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
540
|
-
defaultValue:
|
|
541
|
-
userContext
|
|
539
|
+
const pvar = (0, peers_sdk_1.deviceVar)("deleteTestVar", {
|
|
540
|
+
defaultValue: "default",
|
|
541
|
+
userContext,
|
|
542
542
|
});
|
|
543
543
|
await pvar.loadingPromise;
|
|
544
544
|
// Set a non-default value
|
|
545
|
-
pvar(
|
|
545
|
+
pvar("stored-value");
|
|
546
546
|
await pvar.loadingPromise;
|
|
547
547
|
await (0, peers_sdk_1.sleep)(100);
|
|
548
|
-
expect(pvar()).toBe(
|
|
548
|
+
expect(pvar()).toBe("stored-value");
|
|
549
549
|
// Call delete
|
|
550
550
|
await pvar.delete();
|
|
551
551
|
await (0, peers_sdk_1.sleep)(100);
|
|
552
552
|
// Value should be reset to default
|
|
553
|
-
expect(pvar()).toBe(
|
|
553
|
+
expect(pvar()).toBe("default");
|
|
554
554
|
// Verify it's actually deleted from DB by creating a new pvar instance
|
|
555
555
|
// The new pvar should get the default value (not 'stored-value')
|
|
556
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
557
|
-
defaultValue:
|
|
558
|
-
userContext
|
|
556
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("deleteTestVar", {
|
|
557
|
+
defaultValue: "default",
|
|
558
|
+
userContext,
|
|
559
559
|
});
|
|
560
560
|
await pvar2.loadingPromise;
|
|
561
|
-
expect(pvar2()).toBe(
|
|
561
|
+
expect(pvar2()).toBe("default");
|
|
562
562
|
});
|
|
563
563
|
it("delete() on unsaved pvar should just reset to default", async () => {
|
|
564
564
|
const userContext = await createTestUserContext();
|
|
565
565
|
// Create a pvar but don't change it from default
|
|
566
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
567
|
-
defaultValue:
|
|
568
|
-
userContext
|
|
566
|
+
const pvar = (0, peers_sdk_1.deviceVar)("neverSavedVar", {
|
|
567
|
+
defaultValue: "default",
|
|
568
|
+
userContext,
|
|
569
569
|
});
|
|
570
570
|
await pvar.loadingPromise;
|
|
571
571
|
// Call delete (should not error even though nothing to delete)
|
|
572
572
|
await pvar.delete();
|
|
573
573
|
// Should still have the default value
|
|
574
|
-
expect(pvar()).toBe(
|
|
574
|
+
expect(pvar()).toBe("default");
|
|
575
575
|
});
|
|
576
576
|
it("delete() should be awaitable", async () => {
|
|
577
577
|
const userContext = await createTestUserContext();
|
|
578
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
579
|
-
defaultValue:
|
|
580
|
-
userContext
|
|
578
|
+
const pvar = (0, peers_sdk_1.deviceVar)("awaitDeleteVar", {
|
|
579
|
+
defaultValue: "default",
|
|
580
|
+
userContext,
|
|
581
581
|
});
|
|
582
582
|
await pvar.loadingPromise;
|
|
583
|
-
pvar(
|
|
583
|
+
pvar("value");
|
|
584
584
|
await pvar.loadingPromise;
|
|
585
585
|
// delete() should return a promise that resolves
|
|
586
586
|
const deleteResult = pvar.delete();
|
|
587
587
|
expect(deleteResult).toBeInstanceOf(Promise);
|
|
588
588
|
await deleteResult;
|
|
589
|
-
expect(pvar()).toBe(
|
|
589
|
+
expect(pvar()).toBe("default");
|
|
590
590
|
});
|
|
591
591
|
it("should support auto-delete pattern via subscription and recreate on new value", async () => {
|
|
592
592
|
const userContext = await createTestUserContext();
|
|
593
593
|
// Create a pvar with auto-delete behavior (like message drafts)
|
|
594
|
-
const pvar = (0, peers_sdk_1.deviceVar)(
|
|
595
|
-
defaultValue:
|
|
596
|
-
userContext
|
|
594
|
+
const pvar = (0, peers_sdk_1.deviceVar)("autoDeletePatternVar", {
|
|
595
|
+
defaultValue: "",
|
|
596
|
+
userContext,
|
|
597
597
|
});
|
|
598
598
|
await pvar.loadingPromise;
|
|
599
599
|
// Set up auto-delete subscription (this mimics what message-compose does)
|
|
600
|
-
pvar.subscribe(value => {
|
|
600
|
+
pvar.subscribe((value) => {
|
|
601
601
|
if (!value) {
|
|
602
602
|
pvar.delete();
|
|
603
603
|
}
|
|
604
604
|
});
|
|
605
605
|
// Step 1: Add some content
|
|
606
|
-
pvar(
|
|
606
|
+
pvar("draft content");
|
|
607
607
|
await pvar.loadingPromise;
|
|
608
608
|
await (0, peers_sdk_1.sleep)(100);
|
|
609
609
|
// Verify content is persisted
|
|
610
|
-
expect(pvar()).toBe(
|
|
610
|
+
expect(pvar()).toBe("draft content");
|
|
611
611
|
// Create a fresh pvar to verify it's in DB
|
|
612
|
-
const pvar2 = (0, peers_sdk_1.deviceVar)(
|
|
613
|
-
defaultValue:
|
|
614
|
-
userContext
|
|
612
|
+
const pvar2 = (0, peers_sdk_1.deviceVar)("autoDeletePatternVar", {
|
|
613
|
+
defaultValue: "",
|
|
614
|
+
userContext,
|
|
615
615
|
});
|
|
616
616
|
await pvar2.loadingPromise;
|
|
617
|
-
expect(pvar2()).toBe(
|
|
617
|
+
expect(pvar2()).toBe("draft content");
|
|
618
618
|
// Step 2: Clear content (simulates sending message or clearing editor)
|
|
619
|
-
pvar(
|
|
619
|
+
pvar("");
|
|
620
620
|
await pvar.loadingPromise;
|
|
621
621
|
await (0, peers_sdk_1.sleep)(200); // Give time for delete to complete
|
|
622
622
|
// Value should be empty (default)
|
|
623
|
-
expect(pvar()).toBe(
|
|
623
|
+
expect(pvar()).toBe("");
|
|
624
624
|
// Verify it's deleted from DB by creating another fresh instance
|
|
625
|
-
const pvar3 = (0, peers_sdk_1.deviceVar)(
|
|
626
|
-
defaultValue:
|
|
627
|
-
userContext
|
|
625
|
+
const pvar3 = (0, peers_sdk_1.deviceVar)("autoDeletePatternVar", {
|
|
626
|
+
defaultValue: "",
|
|
627
|
+
userContext,
|
|
628
628
|
});
|
|
629
629
|
await pvar3.loadingPromise;
|
|
630
|
-
expect(pvar3()).toBe(
|
|
630
|
+
expect(pvar3()).toBe(""); // Should be default, not persisted
|
|
631
631
|
// Step 3: Add new content (should recreate the pvar in DB)
|
|
632
|
-
pvar(
|
|
632
|
+
pvar("new draft content");
|
|
633
633
|
await pvar.loadingPromise;
|
|
634
634
|
await (0, peers_sdk_1.sleep)(100);
|
|
635
635
|
// Verify the new content is persisted
|
|
636
|
-
expect(pvar()).toBe(
|
|
636
|
+
expect(pvar()).toBe("new draft content");
|
|
637
637
|
// Create yet another fresh instance to verify recreation in DB
|
|
638
|
-
const pvar4 = (0, peers_sdk_1.deviceVar)(
|
|
639
|
-
defaultValue:
|
|
640
|
-
userContext
|
|
638
|
+
const pvar4 = (0, peers_sdk_1.deviceVar)("autoDeletePatternVar", {
|
|
639
|
+
defaultValue: "",
|
|
640
|
+
userContext,
|
|
641
641
|
});
|
|
642
642
|
await pvar4.loadingPromise;
|
|
643
|
-
expect(pvar4()).toBe(
|
|
643
|
+
expect(pvar4()).toBe("new draft content");
|
|
644
644
|
});
|
|
645
645
|
});
|
|
646
646
|
});
|