@peerbit/react 0.0.28 → 0.0.30
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/README.md +24 -1
- package/lib/esm/__tests__/lockstorage.test.js +17 -9
- package/lib/esm/__tests__/lockstorage.test.js.map +1 -1
- package/lib/esm/__tests__/singletonLock.test.d.ts +1 -0
- package/lib/esm/__tests__/singletonLock.test.js +71 -0
- package/lib/esm/__tests__/singletonLock.test.js.map +1 -0
- package/lib/esm/__tests__/utils.test.js +3 -2
- package/lib/esm/__tests__/utils.test.js.map +1 -1
- package/lib/esm/usePeer.d.ts +12 -2
- package/lib/esm/usePeer.js +82 -14
- package/lib/esm/usePeer.js.map +1 -1
- package/lib/esm/useProgram.js.map +1 -1
- package/package.json +5 -4
- package/src/__tests__/lockstorage.test.ts +23 -11
- package/src/__tests__/singletonLock.test.ts +85 -0
- package/src/__tests__/utils.test.ts +3 -2
- package/src/usePeer.tsx +115 -21
package/README.md
CHANGED
|
@@ -1 +1,24 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @peerbit/react utils
|
|
2
|
+
|
|
3
|
+
This package includes hooks and utilities used across the examples.
|
|
4
|
+
|
|
5
|
+
## Tests
|
|
6
|
+
|
|
7
|
+
- Unit tests run with Mocha against the compiled ESM output.
|
|
8
|
+
- There is an opt-in reproduction test for a previously observed persistent lock issue.
|
|
9
|
+
|
|
10
|
+
Run all tests:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
yarn test
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Run only the persistent-lock repro (intentionally fails):
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
yarn test:repro-lock
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Notes:
|
|
23
|
+
- The repro is gated via `REPRO_LOCK_FAIL=1` and is excluded from normal `yarn test` and CI.
|
|
24
|
+
- It simulates sequential sessions sharing a persisted localStorage directory and expects the second session to fail acquiring the singleton lock.
|
|
@@ -19,15 +19,16 @@ import sinon from "sinon";
|
|
|
19
19
|
import nodelocalstorage from "node-localstorage";
|
|
20
20
|
import { expect } from "chai";
|
|
21
21
|
import { delay } from "@peerbit/time";
|
|
22
|
+
import { beforeAll, afterAll, beforeEach, afterEach, describe, it, } from "vitest";
|
|
22
23
|
describe("FastMutex", () => {
|
|
23
24
|
let sandbox;
|
|
24
|
-
|
|
25
|
+
beforeAll(() => {
|
|
25
26
|
var LocalStorage = nodelocalstorage.LocalStorage;
|
|
26
27
|
var localStorage = new LocalStorage("./tmp/FastMutex");
|
|
27
28
|
localStorage.clear();
|
|
28
29
|
globalThis.localStorage = localStorage;
|
|
29
30
|
});
|
|
30
|
-
|
|
31
|
+
afterAll(() => {
|
|
31
32
|
globalThis.localStorage.clear();
|
|
32
33
|
});
|
|
33
34
|
beforeEach(() => {
|
|
@@ -170,14 +171,21 @@ describe("FastMutex", () => {
|
|
|
170
171
|
expect(fm1LockReleased).to.be.true;
|
|
171
172
|
});
|
|
172
173
|
});
|
|
173
|
-
it("should throw if lock is never acquired after set time period", () => {
|
|
174
|
+
it("should throw if lock is never acquired after set time period", async () => {
|
|
174
175
|
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
175
176
|
const fm2 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
await fm1.lock("timeoutTest");
|
|
178
|
+
const start = Date.now();
|
|
179
|
+
let threw = false;
|
|
180
|
+
try {
|
|
181
|
+
await fm2.lock("timeoutTest");
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
threw = true;
|
|
185
|
+
}
|
|
186
|
+
const elapsed = Date.now() - start;
|
|
187
|
+
expect(threw).to.be.true;
|
|
188
|
+
expect(elapsed).to.be.greaterThan(0);
|
|
181
189
|
});
|
|
182
190
|
it("should ignore expired locks", async () => {
|
|
183
191
|
const fm1 = new FastMutex({
|
|
@@ -222,7 +230,7 @@ describe("FastMutex", () => {
|
|
|
222
230
|
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
223
231
|
await fm1.lock("resetStats");
|
|
224
232
|
// try to acquire a lock after `timeout`:
|
|
225
|
-
await delay(
|
|
233
|
+
await delay(75); // a small buffer over timeout to avoid flakiness
|
|
226
234
|
await fm1.lock("resetStats"); // should not throw
|
|
227
235
|
});
|
|
228
236
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockstorage.test.js","sourceRoot":"","sources":["../../../src/__tests__/lockstorage.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;EAeE;AAEF,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,gBAAgB,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"lockstorage.test.js","sourceRoot":"","sources":["../../../src/__tests__/lockstorage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import nodelocalstorage from "node-localstorage";
|
|
3
|
+
import { FastMutex } from "../lockstorage.js";
|
|
4
|
+
import { beforeAll, beforeEach, afterEach, describe, it } from "vitest";
|
|
5
|
+
describe("FastMutex singleton semantics", () => {
|
|
6
|
+
let localStorage;
|
|
7
|
+
beforeAll(() => {
|
|
8
|
+
const LocalStorage = nodelocalstorage.LocalStorage;
|
|
9
|
+
localStorage = new LocalStorage("./tmp/FastMutex-singleton");
|
|
10
|
+
globalThis.localStorage = localStorage;
|
|
11
|
+
});
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
localStorage.clear();
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
localStorage.clear();
|
|
17
|
+
expect(localStorage.length).to.eq(0);
|
|
18
|
+
});
|
|
19
|
+
it("allows same-session to reacquire the singleton lock when replaceIfSameClient is true", async () => {
|
|
20
|
+
const key = "localId-singleton";
|
|
21
|
+
const fm1 = new FastMutex({
|
|
22
|
+
localStorage,
|
|
23
|
+
clientId: "session-1",
|
|
24
|
+
timeout: 200,
|
|
25
|
+
});
|
|
26
|
+
// First acquire and keep the lock alive
|
|
27
|
+
await fm1.lock(key, () => true);
|
|
28
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
29
|
+
// Reacquire from the same client with replaceIfSameClient
|
|
30
|
+
const start = Date.now();
|
|
31
|
+
await fm1.lock(key, () => true, { replaceIfSameClient: true });
|
|
32
|
+
const elapsed = Date.now() - start;
|
|
33
|
+
// Should not time out and should be very fast
|
|
34
|
+
expect(elapsed).to.be.lessThan(100);
|
|
35
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
36
|
+
fm1.release(key);
|
|
37
|
+
expect(fm1.isLocked(key)).to.be.false;
|
|
38
|
+
});
|
|
39
|
+
it("blocks a different session while held, then allows after release", async () => {
|
|
40
|
+
const key = "localId-singleton";
|
|
41
|
+
const fm1 = new FastMutex({
|
|
42
|
+
localStorage,
|
|
43
|
+
clientId: "session-1",
|
|
44
|
+
timeout: 500,
|
|
45
|
+
});
|
|
46
|
+
const fm2 = new FastMutex({
|
|
47
|
+
localStorage,
|
|
48
|
+
clientId: "session-2",
|
|
49
|
+
timeout: 100, // short timeout to trigger failure while held
|
|
50
|
+
});
|
|
51
|
+
await fm1.lock(key, () => true);
|
|
52
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
53
|
+
// Attempt to acquire from a different client should fail within timeout
|
|
54
|
+
let failed = false;
|
|
55
|
+
try {
|
|
56
|
+
await fm2.lock(key, () => true);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
failed = true;
|
|
60
|
+
}
|
|
61
|
+
expect(failed).to.be.true;
|
|
62
|
+
// After release, the second client should be able to acquire
|
|
63
|
+
fm1.release(key);
|
|
64
|
+
expect(fm1.isLocked(key)).to.be.false;
|
|
65
|
+
await fm2.lock(key, () => true);
|
|
66
|
+
expect(fm2.isLocked(key)).to.be.true;
|
|
67
|
+
fm2.release(key);
|
|
68
|
+
expect(fm2.isLocked(key)).to.be.false;
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=singletonLock.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singletonLock.test.js","sourceRoot":"","sources":["../../../src/__tests__/singletonLock.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,14 +5,15 @@ import { delay } from "@peerbit/time";
|
|
|
5
5
|
import { default as sodium } from "libsodium-wrappers";
|
|
6
6
|
import { v4 as uuid } from "uuid";
|
|
7
7
|
import { expect } from "chai";
|
|
8
|
+
import { beforeAll, afterAll, describe, it } from "vitest";
|
|
8
9
|
describe("getKeypair", () => {
|
|
9
|
-
|
|
10
|
+
beforeAll(async () => {
|
|
10
11
|
await sodium.ready;
|
|
11
12
|
var LocalStorage = nodelocalstorage.LocalStorage;
|
|
12
13
|
var localStorage = new LocalStorage("./tmp/getKeypair");
|
|
13
14
|
globalThis.localStorage = localStorage;
|
|
14
15
|
});
|
|
15
|
-
|
|
16
|
+
afterAll(() => {
|
|
16
17
|
globalThis.localStorage.clear();
|
|
17
18
|
});
|
|
18
19
|
it("can aquire multiple keypairs", async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../src/__tests__/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,gBAAgB,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../src/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/usePeer.d.ts
CHANGED
|
@@ -35,9 +35,19 @@ type IFrameOptions = {
|
|
|
35
35
|
type: "proxy";
|
|
36
36
|
targetOrigin: string;
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Network configuration for the node client.
|
|
40
|
+
*
|
|
41
|
+
* Prefer the bootstrap form when you want to dial explicit addresses.
|
|
42
|
+
* If bootstrap is provided, it takes precedence over any implicit defaults.
|
|
43
|
+
*/
|
|
38
44
|
export type NetworkOption = {
|
|
39
|
-
type: "local"
|
|
40
|
-
|
|
45
|
+
type: "local";
|
|
46
|
+
} | {
|
|
47
|
+
type: "remote";
|
|
48
|
+
} | {
|
|
49
|
+
type?: "explicit";
|
|
50
|
+
bootstrap: (Multiaddr | string)[];
|
|
41
51
|
};
|
|
42
52
|
type NodeOptions = {
|
|
43
53
|
type?: "node";
|
package/lib/esm/usePeer.js
CHANGED
|
@@ -88,6 +88,10 @@ export const PeerProvider = (options) => {
|
|
|
88
88
|
const fn = async () => {
|
|
89
89
|
await sodium.ready;
|
|
90
90
|
let newPeer;
|
|
91
|
+
// Track resolved persistence status during client creation
|
|
92
|
+
let persistedResolved = false;
|
|
93
|
+
// Controls how long we keep locks alive; flipped to false on close/hidden
|
|
94
|
+
const keepAliveRef = { current: true };
|
|
91
95
|
if (nodeOptions.type !== "proxy") {
|
|
92
96
|
const releaseFirstLock = cookiesWhereClearedJustNow();
|
|
93
97
|
const sessionId = getClientId("session");
|
|
@@ -100,13 +104,28 @@ export const PeerProvider = (options) => {
|
|
|
100
104
|
try {
|
|
101
105
|
const lockKey = localId + "-singleton";
|
|
102
106
|
subscribeToUnload(function () {
|
|
107
|
+
// Immediate release on page close
|
|
108
|
+
keepAliveRef.current = false;
|
|
103
109
|
mutex.release(lockKey);
|
|
104
110
|
});
|
|
111
|
+
// Also release when page is hidden to reduce flakiness between sequential tests
|
|
112
|
+
const onVisibility = () => {
|
|
113
|
+
if (document.visibilityState === "hidden") {
|
|
114
|
+
keepAliveRef.current = false;
|
|
115
|
+
// Mark expired and remove proactively
|
|
116
|
+
try {
|
|
117
|
+
mutex.release(lockKey);
|
|
118
|
+
}
|
|
119
|
+
catch { }
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
105
123
|
if (isInStandaloneMode()) {
|
|
106
124
|
// PWA issue fix (? TODO is this needed ?
|
|
125
|
+
keepAliveRef.current = false;
|
|
107
126
|
mutex.release(lockKey);
|
|
108
127
|
}
|
|
109
|
-
await mutex.lock(lockKey, () =>
|
|
128
|
+
await mutex.lock(lockKey, () => keepAliveRef.current, {
|
|
110
129
|
replaceIfSameClient: true,
|
|
111
130
|
});
|
|
112
131
|
}
|
|
@@ -120,11 +139,12 @@ export const PeerProvider = (options) => {
|
|
|
120
139
|
nodeId = nodeOptions.keypair;
|
|
121
140
|
}
|
|
122
141
|
else {
|
|
123
|
-
const kp = await getFreeKeypair("", mutex,
|
|
142
|
+
const kp = await getFreeKeypair("", mutex, () => keepAliveRef.current, {
|
|
124
143
|
releaseFirstLock,
|
|
125
144
|
releaseLockIfSameId: true,
|
|
126
145
|
});
|
|
127
146
|
subscribeToUnload(function () {
|
|
147
|
+
keepAliveRef.current = false;
|
|
128
148
|
mutex.release(kp.path);
|
|
129
149
|
});
|
|
130
150
|
nodeId = kp.key;
|
|
@@ -136,6 +156,7 @@ export const PeerProvider = (options) => {
|
|
|
136
156
|
!(await detectIncognito()).isPrivate) {
|
|
137
157
|
const persisted = await navigator.storage.persist();
|
|
138
158
|
setPersisted(persisted);
|
|
159
|
+
persistedResolved = persisted;
|
|
139
160
|
if (!persisted) {
|
|
140
161
|
setPersisted(false);
|
|
141
162
|
console.error("Request persistence but permission was not granted by browser.");
|
|
@@ -185,27 +206,46 @@ export const PeerProvider = (options) => {
|
|
|
185
206
|
peerHash: newPeer?.identity.publicKey.hashcode(),
|
|
186
207
|
network: nodeOptions.network === "local" ? "local" : "remote",
|
|
187
208
|
});
|
|
209
|
+
try {
|
|
210
|
+
window.__peerInfo = {
|
|
211
|
+
peerHash: newPeer?.identity.publicKey.hashcode(),
|
|
212
|
+
persisted: persistedResolved,
|
|
213
|
+
};
|
|
214
|
+
window.dispatchEvent(new CustomEvent("peer:ready", {
|
|
215
|
+
detail: window.__peerInfo,
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
catch { }
|
|
188
219
|
setConnectionState("connecting");
|
|
189
220
|
const connectFn = async () => {
|
|
190
221
|
try {
|
|
191
222
|
const network = nodeOptions.network;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
223
|
+
// 1) Explicit bootstrap addresses take precedence
|
|
224
|
+
if (typeof network !== "string" &&
|
|
225
|
+
network?.bootstrap !== undefined) {
|
|
226
|
+
const list = network.bootstrap;
|
|
227
|
+
if (list.length === 0) {
|
|
228
|
+
// Explicit offline mode: skip dialing and mark as connected (no relays)
|
|
229
|
+
console.log("Offline bootstrap: skipping relay dialing");
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
for (const addr of list) {
|
|
233
|
+
await newPeer.dial(addr);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// 2) Local development: dial local relay service
|
|
238
|
+
else if (network === "local" ||
|
|
239
|
+
(typeof network !== "string" &&
|
|
240
|
+
network?.type === "local")) {
|
|
195
241
|
const localAddress = "/ip4/127.0.0.1/tcp/8002/ws/p2p/" +
|
|
196
242
|
(await (await fetch("http://localhost:8082/peer/id")).text());
|
|
197
243
|
console.log("Dialing local address", localAddress);
|
|
198
244
|
await newPeer.dial(localAddress);
|
|
199
245
|
}
|
|
200
|
-
|
|
201
|
-
network === "remote" ||
|
|
202
|
-
(network.type === "remote" && !network.bootstrap)) {
|
|
203
|
-
await newPeer["bootstrap"]?.();
|
|
204
|
-
}
|
|
246
|
+
// 3) Remote default: use bootstrap service (no explicit bootstrap provided)
|
|
205
247
|
else {
|
|
206
|
-
|
|
207
|
-
await newPeer.dial(addr);
|
|
208
|
-
}
|
|
248
|
+
await newPeer["bootstrap"]?.();
|
|
209
249
|
}
|
|
210
250
|
setConnectionState("connected");
|
|
211
251
|
}
|
|
@@ -217,10 +257,28 @@ export const PeerProvider = (options) => {
|
|
|
217
257
|
newPeer = await createHost(newPeer);
|
|
218
258
|
}
|
|
219
259
|
};
|
|
260
|
+
const perfEnabled = new URLSearchParams(window.location.search).get("perf");
|
|
261
|
+
const t0 = performance.now();
|
|
262
|
+
const marks = {};
|
|
263
|
+
const perfMark = (label) => {
|
|
264
|
+
marks[label] = performance.now() - t0;
|
|
265
|
+
};
|
|
220
266
|
console.log("Bootstrap start...");
|
|
221
|
-
const promise = connectFn()
|
|
267
|
+
const promise = connectFn().then(() => {
|
|
268
|
+
perfMark("dialComplete");
|
|
269
|
+
});
|
|
222
270
|
promise.then(() => {
|
|
223
271
|
console.log("Bootstrap done");
|
|
272
|
+
try {
|
|
273
|
+
if (perfEnabled) {
|
|
274
|
+
const payload = { ...marks };
|
|
275
|
+
console.info("[Perf] peer bootstrap", payload);
|
|
276
|
+
window.dispatchEvent(new CustomEvent("perf:peer", {
|
|
277
|
+
detail: payload,
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch { }
|
|
224
282
|
});
|
|
225
283
|
if (nodeOptions.waitForConnnected !== false) {
|
|
226
284
|
await promise;
|
|
@@ -229,6 +287,16 @@ export const PeerProvider = (options) => {
|
|
|
229
287
|
else {
|
|
230
288
|
// When in proxy mode (iframe), use the provided targetOrigin.
|
|
231
289
|
newPeer = await createClient(nodeOptions.targetOrigin);
|
|
290
|
+
try {
|
|
291
|
+
window.__peerInfo = {
|
|
292
|
+
peerHash: newPeer?.identity.publicKey.hashcode(),
|
|
293
|
+
persisted: false,
|
|
294
|
+
};
|
|
295
|
+
window.dispatchEvent(new CustomEvent("peer:ready", {
|
|
296
|
+
detail: window.__peerInfo,
|
|
297
|
+
}));
|
|
298
|
+
}
|
|
299
|
+
catch { }
|
|
232
300
|
}
|
|
233
301
|
setPeer(newPeer);
|
|
234
302
|
setLoading(false);
|
package/lib/esm/usePeer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAO,UAAU,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EACH,cAAc,EACd,WAAW,EACX,QAAQ,EACR,0BAA0B,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAC5B,MAAM,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC,OAAO;IACvD,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAEjD,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACtC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IACpC,CAAC;CACJ;AAkCD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAe,EAAS,CAAC,CAAC;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProgram.js","sourceRoot":"","sources":["../../src/useProgram.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChE,MAAM,gBAAgB,GAAG,CACrB,CAAK,EACP,EAAE;IACA,IAAI,CAAC;QACD,OAAO,CAAC,EAAE,OAAO,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;AACL,CAAC,CAAC;AAIF,MAAM,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"useProgram.js","sourceRoot":"","sources":["../../src/useProgram.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peerbit/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"homepage": "https://dao-xyz.github.io/peerbit-examples",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@peerbit/proxy-window": "^3",
|
|
31
31
|
"@types/react": "^19.1.8",
|
|
32
32
|
"@types/react-dom": "^19.1.6",
|
|
33
|
-
"detectincognitojs": "^1.
|
|
33
|
+
"detectincognitojs": "^1.6.1",
|
|
34
34
|
"path-browserify": "^1.0.1",
|
|
35
35
|
"peerbit": "^4",
|
|
36
36
|
"react": "^19.1.0",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"clean": "shx rm -rf lib/*",
|
|
52
52
|
"build": "yarn clean && tsc -p tsconfig.json",
|
|
53
|
-
"test": "
|
|
53
|
+
"test": "vitest run",
|
|
54
|
+
"test:watch": "vitest"
|
|
54
55
|
},
|
|
55
56
|
"eslintConfig": {
|
|
56
57
|
"extends": [
|
|
@@ -71,5 +72,5 @@
|
|
|
71
72
|
"last 1 safari version"
|
|
72
73
|
]
|
|
73
74
|
},
|
|
74
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "5d95157879bc6e540c7bde79d87577d394f79c53"
|
|
75
76
|
}
|
|
@@ -20,18 +20,26 @@ import sinon from "sinon";
|
|
|
20
20
|
import nodelocalstorage from "node-localstorage";
|
|
21
21
|
import { expect } from "chai";
|
|
22
22
|
import { delay } from "@peerbit/time";
|
|
23
|
+
import {
|
|
24
|
+
beforeAll,
|
|
25
|
+
afterAll,
|
|
26
|
+
beforeEach,
|
|
27
|
+
afterEach,
|
|
28
|
+
describe,
|
|
29
|
+
it,
|
|
30
|
+
} from "vitest";
|
|
23
31
|
|
|
24
32
|
describe("FastMutex", () => {
|
|
25
33
|
let sandbox;
|
|
26
34
|
|
|
27
|
-
|
|
35
|
+
beforeAll(() => {
|
|
28
36
|
var LocalStorage = nodelocalstorage!.LocalStorage;
|
|
29
37
|
var localStorage = new LocalStorage("./tmp/FastMutex");
|
|
30
38
|
localStorage.clear();
|
|
31
39
|
globalThis.localStorage = localStorage;
|
|
32
40
|
});
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
afterAll(() => {
|
|
35
43
|
globalThis.localStorage.clear();
|
|
36
44
|
});
|
|
37
45
|
|
|
@@ -201,16 +209,20 @@ describe("FastMutex", () => {
|
|
|
201
209
|
});
|
|
202
210
|
});
|
|
203
211
|
|
|
204
|
-
it("should throw if lock is never acquired after set time period", () => {
|
|
212
|
+
it("should throw if lock is never acquired after set time period", async () => {
|
|
205
213
|
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
206
214
|
const fm2 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
await fm1.lock("timeoutTest");
|
|
216
|
+
const start = Date.now();
|
|
217
|
+
let threw = false;
|
|
218
|
+
try {
|
|
219
|
+
await fm2.lock("timeoutTest");
|
|
220
|
+
} catch (e) {
|
|
221
|
+
threw = true;
|
|
222
|
+
}
|
|
223
|
+
const elapsed = Date.now() - start;
|
|
224
|
+
expect(threw).to.be.true;
|
|
225
|
+
expect(elapsed).to.be.greaterThan(0);
|
|
214
226
|
});
|
|
215
227
|
|
|
216
228
|
it("should ignore expired locks", async () => {
|
|
@@ -266,7 +278,7 @@ describe("FastMutex", () => {
|
|
|
266
278
|
await fm1.lock("resetStats");
|
|
267
279
|
|
|
268
280
|
// try to acquire a lock after `timeout`:
|
|
269
|
-
await delay(
|
|
281
|
+
await delay(75); // a small buffer over timeout to avoid flakiness
|
|
270
282
|
|
|
271
283
|
await fm1.lock("resetStats"); // should not throw
|
|
272
284
|
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import nodelocalstorage from "node-localstorage";
|
|
3
|
+
import { FastMutex } from "../lockstorage.js";
|
|
4
|
+
import { beforeAll, beforeEach, afterEach, describe, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
describe("FastMutex singleton semantics", () => {
|
|
7
|
+
let localStorage: any;
|
|
8
|
+
|
|
9
|
+
beforeAll(() => {
|
|
10
|
+
const LocalStorage = nodelocalstorage!.LocalStorage;
|
|
11
|
+
localStorage = new LocalStorage("./tmp/FastMutex-singleton");
|
|
12
|
+
globalThis.localStorage = localStorage as any;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
localStorage.clear();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
localStorage.clear();
|
|
21
|
+
expect(localStorage.length).to.eq(0);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("allows same-session to reacquire the singleton lock when replaceIfSameClient is true", async () => {
|
|
25
|
+
const key = "localId-singleton";
|
|
26
|
+
|
|
27
|
+
const fm1 = new FastMutex({
|
|
28
|
+
localStorage,
|
|
29
|
+
clientId: "session-1",
|
|
30
|
+
timeout: 200,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// First acquire and keep the lock alive
|
|
34
|
+
await fm1.lock(key, () => true);
|
|
35
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
36
|
+
|
|
37
|
+
// Reacquire from the same client with replaceIfSameClient
|
|
38
|
+
const start = Date.now();
|
|
39
|
+
await fm1.lock(key, () => true, { replaceIfSameClient: true });
|
|
40
|
+
const elapsed = Date.now() - start;
|
|
41
|
+
|
|
42
|
+
// Should not time out and should be very fast
|
|
43
|
+
expect(elapsed).to.be.lessThan(100);
|
|
44
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
45
|
+
|
|
46
|
+
fm1.release(key);
|
|
47
|
+
expect(fm1.isLocked(key)).to.be.false;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("blocks a different session while held, then allows after release", async () => {
|
|
51
|
+
const key = "localId-singleton";
|
|
52
|
+
|
|
53
|
+
const fm1 = new FastMutex({
|
|
54
|
+
localStorage,
|
|
55
|
+
clientId: "session-1",
|
|
56
|
+
timeout: 500,
|
|
57
|
+
});
|
|
58
|
+
const fm2 = new FastMutex({
|
|
59
|
+
localStorage,
|
|
60
|
+
clientId: "session-2",
|
|
61
|
+
timeout: 100, // short timeout to trigger failure while held
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await fm1.lock(key, () => true);
|
|
65
|
+
expect(fm1.isLocked(key)).to.be.true;
|
|
66
|
+
|
|
67
|
+
// Attempt to acquire from a different client should fail within timeout
|
|
68
|
+
let failed = false;
|
|
69
|
+
try {
|
|
70
|
+
await fm2.lock(key, () => true);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
failed = true;
|
|
73
|
+
}
|
|
74
|
+
expect(failed).to.be.true;
|
|
75
|
+
|
|
76
|
+
// After release, the second client should be able to acquire
|
|
77
|
+
fm1.release(key);
|
|
78
|
+
expect(fm1.isLocked(key)).to.be.false;
|
|
79
|
+
|
|
80
|
+
await fm2.lock(key, () => true);
|
|
81
|
+
expect(fm2.isLocked(key)).to.be.true;
|
|
82
|
+
fm2.release(key);
|
|
83
|
+
expect(fm2.isLocked(key)).to.be.false;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -5,9 +5,10 @@ import { delay } from "@peerbit/time";
|
|
|
5
5
|
import { default as sodium } from "libsodium-wrappers";
|
|
6
6
|
import { v4 as uuid } from "uuid";
|
|
7
7
|
import { expect } from "chai";
|
|
8
|
+
import { beforeAll, afterAll, describe, it } from "vitest";
|
|
8
9
|
|
|
9
10
|
describe("getKeypair", () => {
|
|
10
|
-
|
|
11
|
+
beforeAll(async () => {
|
|
11
12
|
await sodium.ready;
|
|
12
13
|
|
|
13
14
|
var LocalStorage = nodelocalstorage.LocalStorage;
|
|
@@ -15,7 +16,7 @@ describe("getKeypair", () => {
|
|
|
15
16
|
globalThis.localStorage = localStorage;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
afterAll(() => {
|
|
19
20
|
globalThis.localStorage.clear();
|
|
20
21
|
});
|
|
21
22
|
|
package/src/usePeer.tsx
CHANGED
|
@@ -76,10 +76,16 @@ type IFrameOptions = {
|
|
|
76
76
|
targetOrigin: string;
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Network configuration for the node client.
|
|
81
|
+
*
|
|
82
|
+
* Prefer the bootstrap form when you want to dial explicit addresses.
|
|
83
|
+
* If bootstrap is provided, it takes precedence over any implicit defaults.
|
|
84
|
+
*/
|
|
85
|
+
export type NetworkOption =
|
|
86
|
+
| { type: "local" }
|
|
87
|
+
| { type: "remote" }
|
|
88
|
+
| { type?: "explicit"; bootstrap: (Multiaddr | string)[] };
|
|
83
89
|
|
|
84
90
|
type NodeOptions = {
|
|
85
91
|
type?: "node";
|
|
@@ -177,6 +183,10 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
177
183
|
const fn = async () => {
|
|
178
184
|
await sodium.ready;
|
|
179
185
|
let newPeer: ProgramClient;
|
|
186
|
+
// Track resolved persistence status during client creation
|
|
187
|
+
let persistedResolved = false;
|
|
188
|
+
// Controls how long we keep locks alive; flipped to false on close/hidden
|
|
189
|
+
const keepAliveRef = { current: true } as { current: boolean };
|
|
180
190
|
|
|
181
191
|
if (nodeOptions.type !== "proxy") {
|
|
182
192
|
const releaseFirstLock = cookiesWhereClearedJustNow();
|
|
@@ -191,13 +201,30 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
191
201
|
try {
|
|
192
202
|
const lockKey = localId + "-singleton";
|
|
193
203
|
subscribeToUnload(function () {
|
|
204
|
+
// Immediate release on page close
|
|
205
|
+
keepAliveRef.current = false;
|
|
194
206
|
mutex.release(lockKey);
|
|
195
207
|
});
|
|
208
|
+
// Also release when page is hidden to reduce flakiness between sequential tests
|
|
209
|
+
const onVisibility = () => {
|
|
210
|
+
if (document.visibilityState === "hidden") {
|
|
211
|
+
keepAliveRef.current = false;
|
|
212
|
+
// Mark expired and remove proactively
|
|
213
|
+
try {
|
|
214
|
+
mutex.release(lockKey);
|
|
215
|
+
} catch {}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
document.addEventListener(
|
|
219
|
+
"visibilitychange",
|
|
220
|
+
onVisibility
|
|
221
|
+
);
|
|
196
222
|
if (isInStandaloneMode()) {
|
|
197
223
|
// PWA issue fix (? TODO is this needed ?
|
|
224
|
+
keepAliveRef.current = false;
|
|
198
225
|
mutex.release(lockKey);
|
|
199
226
|
}
|
|
200
|
-
await mutex.lock(lockKey, () =>
|
|
227
|
+
await mutex.lock(lockKey, () => keepAliveRef.current, {
|
|
201
228
|
replaceIfSameClient: true,
|
|
202
229
|
});
|
|
203
230
|
} catch (error) {
|
|
@@ -212,11 +239,17 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
212
239
|
if (nodeOptions.keypair) {
|
|
213
240
|
nodeId = nodeOptions.keypair;
|
|
214
241
|
} else {
|
|
215
|
-
const kp = await getFreeKeypair(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
242
|
+
const kp = await getFreeKeypair(
|
|
243
|
+
"",
|
|
244
|
+
mutex,
|
|
245
|
+
() => keepAliveRef.current,
|
|
246
|
+
{
|
|
247
|
+
releaseFirstLock,
|
|
248
|
+
releaseLockIfSameId: true,
|
|
249
|
+
}
|
|
250
|
+
);
|
|
219
251
|
subscribeToUnload(function () {
|
|
252
|
+
keepAliveRef.current = false;
|
|
220
253
|
mutex.release(kp.path);
|
|
221
254
|
});
|
|
222
255
|
nodeId = kp.key;
|
|
@@ -231,6 +264,7 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
231
264
|
) {
|
|
232
265
|
const persisted = await navigator.storage.persist();
|
|
233
266
|
setPersisted(persisted);
|
|
267
|
+
persistedResolved = persisted;
|
|
234
268
|
if (!persisted) {
|
|
235
269
|
setPersisted(false);
|
|
236
270
|
console.error(
|
|
@@ -283,16 +317,49 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
283
317
|
network:
|
|
284
318
|
nodeOptions.network === "local" ? "local" : "remote",
|
|
285
319
|
});
|
|
320
|
+
try {
|
|
321
|
+
(window as any).__peerInfo = {
|
|
322
|
+
peerHash: newPeer?.identity.publicKey.hashcode(),
|
|
323
|
+
persisted: persistedResolved,
|
|
324
|
+
};
|
|
325
|
+
window.dispatchEvent(
|
|
326
|
+
new CustomEvent("peer:ready", {
|
|
327
|
+
detail: (window as any).__peerInfo,
|
|
328
|
+
})
|
|
329
|
+
);
|
|
330
|
+
} catch {}
|
|
286
331
|
|
|
287
332
|
setConnectionState("connecting");
|
|
288
333
|
|
|
289
334
|
const connectFn = async () => {
|
|
290
335
|
try {
|
|
291
336
|
const network = nodeOptions.network;
|
|
337
|
+
|
|
338
|
+
// 1) Explicit bootstrap addresses take precedence
|
|
292
339
|
if (
|
|
340
|
+
typeof network !== "string" &&
|
|
341
|
+
(network as any)?.bootstrap !== undefined
|
|
342
|
+
) {
|
|
343
|
+
const list = (network as any).bootstrap as (
|
|
344
|
+
| Multiaddr
|
|
345
|
+
| string
|
|
346
|
+
)[];
|
|
347
|
+
if (list.length === 0) {
|
|
348
|
+
// Explicit offline mode: skip dialing and mark as connected (no relays)
|
|
349
|
+
console.log(
|
|
350
|
+
"Offline bootstrap: skipping relay dialing"
|
|
351
|
+
);
|
|
352
|
+
} else {
|
|
353
|
+
for (const addr of list) {
|
|
354
|
+
await newPeer.dial(addr as any);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// 2) Local development: dial local relay service
|
|
359
|
+
else if (
|
|
293
360
|
network === "local" ||
|
|
294
|
-
(
|
|
295
|
-
|
|
361
|
+
(typeof network !== "string" &&
|
|
362
|
+
(network as any)?.type === "local")
|
|
296
363
|
) {
|
|
297
364
|
const localAddress =
|
|
298
365
|
"/ip4/127.0.0.1/tcp/8002/ws/p2p/" +
|
|
@@ -301,16 +368,10 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
301
368
|
).text());
|
|
302
369
|
console.log("Dialing local address", localAddress);
|
|
303
370
|
await newPeer.dial(localAddress);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
(network.type === "remote" && !network.bootstrap)
|
|
308
|
-
) {
|
|
371
|
+
}
|
|
372
|
+
// 3) Remote default: use bootstrap service (no explicit bootstrap provided)
|
|
373
|
+
else {
|
|
309
374
|
await newPeer["bootstrap"]?.();
|
|
310
|
-
} else {
|
|
311
|
-
for (const addr of network.bootstrap!) {
|
|
312
|
-
await newPeer.dial(addr);
|
|
313
|
-
}
|
|
314
375
|
}
|
|
315
376
|
setConnectionState("connected");
|
|
316
377
|
} catch (err: any) {
|
|
@@ -325,10 +386,32 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
325
386
|
}
|
|
326
387
|
};
|
|
327
388
|
|
|
389
|
+
const perfEnabled = new URLSearchParams(
|
|
390
|
+
window.location.search
|
|
391
|
+
).get("perf");
|
|
392
|
+
const t0 = performance.now();
|
|
393
|
+
const marks: Record<string, number> = {};
|
|
394
|
+
const perfMark = (label: string) => {
|
|
395
|
+
marks[label] = performance.now() - t0;
|
|
396
|
+
};
|
|
397
|
+
|
|
328
398
|
console.log("Bootstrap start...");
|
|
329
|
-
const promise = connectFn()
|
|
399
|
+
const promise = connectFn().then(() => {
|
|
400
|
+
perfMark("dialComplete");
|
|
401
|
+
});
|
|
330
402
|
promise.then(() => {
|
|
331
403
|
console.log("Bootstrap done");
|
|
404
|
+
try {
|
|
405
|
+
if (perfEnabled) {
|
|
406
|
+
const payload = { ...marks } as any;
|
|
407
|
+
console.info("[Perf] peer bootstrap", payload);
|
|
408
|
+
window.dispatchEvent(
|
|
409
|
+
new CustomEvent("perf:peer", {
|
|
410
|
+
detail: payload,
|
|
411
|
+
})
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
} catch {}
|
|
332
415
|
});
|
|
333
416
|
if (nodeOptions.waitForConnnected !== false) {
|
|
334
417
|
await promise;
|
|
@@ -338,6 +421,17 @@ export const PeerProvider = (options: PeerOptions) => {
|
|
|
338
421
|
newPeer = await createClient(
|
|
339
422
|
(nodeOptions as IFrameOptions).targetOrigin
|
|
340
423
|
);
|
|
424
|
+
try {
|
|
425
|
+
(window as any).__peerInfo = {
|
|
426
|
+
peerHash: newPeer?.identity.publicKey.hashcode(),
|
|
427
|
+
persisted: false,
|
|
428
|
+
};
|
|
429
|
+
window.dispatchEvent(
|
|
430
|
+
new CustomEvent("peer:ready", {
|
|
431
|
+
detail: (window as any).__peerInfo,
|
|
432
|
+
})
|
|
433
|
+
);
|
|
434
|
+
} catch {}
|
|
341
435
|
}
|
|
342
436
|
|
|
343
437
|
setPeer(newPeer);
|