@peerbit/react 0.0.33 → 0.0.35
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/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -0
- package/{lib/esm → dist/src}/lockstorage.d.ts +1 -0
- package/dist/src/lockstorage.d.ts.map +1 -0
- package/{lib/esm → dist/src}/lockstorage.js +2 -5
- package/dist/src/lockstorage.js.map +1 -0
- package/{lib/esm → dist/src}/useMount.d.ts +1 -0
- package/dist/src/useMount.d.ts.map +1 -0
- package/dist/src/useMount.js.map +1 -0
- package/{lib/esm → dist/src}/usePeer.d.ts +7 -3
- package/dist/src/usePeer.d.ts.map +1 -0
- package/{lib/esm → dist/src}/usePeer.js +25 -20
- package/dist/src/usePeer.js.map +1 -0
- package/{lib/esm → dist/src}/utils.d.ts +2 -4
- package/dist/src/utils.d.ts.map +1 -0
- package/{lib/esm → dist/src}/utils.js +17 -69
- package/dist/src/utils.js.map +1 -0
- package/package.json +59 -56
- package/src/index.ts +4 -14
- package/src/lockstorage.ts +224 -233
- package/src/useMount.ts +15 -0
- package/src/usePeer.tsx +406 -419
- package/src/utils.ts +99 -168
- package/README.md +0 -24
- package/lib/esm/__tests__/lockstorage.test.d.ts +0 -1
- package/lib/esm/__tests__/lockstorage.test.js +0 -237
- package/lib/esm/__tests__/lockstorage.test.js.map +0 -1
- package/lib/esm/__tests__/singletonLock.test.d.ts +0 -1
- package/lib/esm/__tests__/singletonLock.test.js +0 -71
- package/lib/esm/__tests__/singletonLock.test.js.map +0 -1
- package/lib/esm/__tests__/useQuery.dom.test.d.ts +0 -1
- package/lib/esm/__tests__/useQuery.dom.test.js +0 -433
- package/lib/esm/__tests__/useQuery.dom.test.js.map +0 -1
- package/lib/esm/__tests__/utils.test.d.ts +0 -1
- package/lib/esm/__tests__/utils.test.js +0 -66
- package/lib/esm/__tests__/utils.test.js.map +0 -1
- package/lib/esm/index.d.ts +0 -8
- package/lib/esm/index.js +0 -9
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/lockstorage.js.map +0 -1
- package/lib/esm/useCount.d.ts +0 -11
- package/lib/esm/useCount.js +0 -43
- package/lib/esm/useCount.js.map +0 -1
- package/lib/esm/useLocal.d.ts +0 -20
- package/lib/esm/useLocal.js +0 -73
- package/lib/esm/useLocal.js.map +0 -1
- package/lib/esm/useMount.js.map +0 -1
- package/lib/esm/useOnline.d.ts +0 -11
- package/lib/esm/useOnline.js +0 -65
- package/lib/esm/useOnline.js.map +0 -1
- package/lib/esm/usePeer.js.map +0 -1
- package/lib/esm/useProgram.d.ts +0 -16
- package/lib/esm/useProgram.js +0 -114
- package/lib/esm/useProgram.js.map +0 -1
- package/lib/esm/useQuery.d.ts +0 -49
- package/lib/esm/useQuery.js +0 -418
- package/lib/esm/useQuery.js.map +0 -1
- package/lib/esm/utils.js.map +0 -1
- package/src/__tests__/lockstorage.test.ts +0 -285
- package/src/__tests__/singletonLock.test.ts +0 -85
- package/src/__tests__/useQuery.dom.test.ts +0 -518
- package/src/__tests__/utils.test.ts +0 -90
- package/src/useCount.tsx +0 -63
- package/src/useLocal.tsx +0 -125
- package/src/useMount.tsx +0 -15
- package/src/useOnline.tsx +0 -85
- package/src/useProgram.tsx +0 -148
- package/src/useQuery.tsx +0 -548
- /package/{lib/esm → dist/src}/useMount.js +0 -0
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
ISC License (ISC)
|
|
3
|
-
Copyright (c) 2016, Wes Cruver <chieffancypants@gmail.com>
|
|
4
|
-
|
|
5
|
-
Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
6
|
-
with or without fee is hereby granted, provided that the above copyright notice
|
|
7
|
-
and this permission notice appear in all copies.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
11
|
-
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
13
|
-
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
14
|
-
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
15
|
-
THIS SOFTWARE.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { FastMutex } from "../lockstorage.js";
|
|
19
|
-
import sinon from "sinon";
|
|
20
|
-
import nodelocalstorage from "node-localstorage";
|
|
21
|
-
import { expect } from "chai";
|
|
22
|
-
import { delay } from "@peerbit/time";
|
|
23
|
-
import {
|
|
24
|
-
beforeAll,
|
|
25
|
-
afterAll,
|
|
26
|
-
beforeEach,
|
|
27
|
-
afterEach,
|
|
28
|
-
describe,
|
|
29
|
-
it,
|
|
30
|
-
} from "vitest";
|
|
31
|
-
|
|
32
|
-
describe("FastMutex", () => {
|
|
33
|
-
let sandbox;
|
|
34
|
-
|
|
35
|
-
beforeAll(() => {
|
|
36
|
-
var LocalStorage = nodelocalstorage!.LocalStorage;
|
|
37
|
-
var localStorage = new LocalStorage("./tmp/FastMutex");
|
|
38
|
-
localStorage.clear();
|
|
39
|
-
globalThis.localStorage = localStorage;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
afterAll(() => {
|
|
43
|
-
globalThis.localStorage.clear();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
sandbox = sinon.createSandbox();
|
|
48
|
-
localStorage.clear();
|
|
49
|
-
});
|
|
50
|
-
afterEach(() => {
|
|
51
|
-
sandbox.restore();
|
|
52
|
-
localStorage.clear();
|
|
53
|
-
expect(localStorage.length).to.eq(0);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should immediately establish a lock when there is no contention", async () => {
|
|
57
|
-
const fm1 = new FastMutex({ localStorage: localStorage });
|
|
58
|
-
|
|
59
|
-
expect(fm1.isLocked("clientId")).to.be.false;
|
|
60
|
-
const stats = await fm1.lock("clientId");
|
|
61
|
-
expect(fm1.isLocked("clientId")).to.be.true;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("When another client has a lock (Y is not 0), it should restart to acquire a lock at a later time", function () {
|
|
65
|
-
const fm1 = new FastMutex({
|
|
66
|
-
xPrefix: "xPrefix_",
|
|
67
|
-
yPrefix: "yPrefix_",
|
|
68
|
-
localStorage: localStorage,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const key = "clientId";
|
|
72
|
-
fm1.setItem(`yPrefix_${key}`, "someOtherMutexId");
|
|
73
|
-
|
|
74
|
-
setTimeout(() => {
|
|
75
|
-
localStorage.removeItem(`yPrefix_${key}`);
|
|
76
|
-
}, 20);
|
|
77
|
-
|
|
78
|
-
return fm1.lock(key).then(() => {
|
|
79
|
-
expect(fm1.getLockedInfo(key)).to.exist;
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("when contending for a lock and ultimately losing, it should restart", () => {
|
|
84
|
-
const key = "somekey";
|
|
85
|
-
const fm = new FastMutex({
|
|
86
|
-
localStorage: localStorage,
|
|
87
|
-
clientId: "uniqueId",
|
|
88
|
-
});
|
|
89
|
-
const stub = sandbox.stub(fm, "getItem");
|
|
90
|
-
|
|
91
|
-
// Set up scenario for lock contention where we lost Y
|
|
92
|
-
stub.onCall(0).returns(null); // getItem Y
|
|
93
|
-
stub.onCall(1).returns("lockcontention"); // getItem X
|
|
94
|
-
stub.onCall(2).returns("youLostTheLock"); // getItem Y
|
|
95
|
-
|
|
96
|
-
// fastmutex should have restarted, so let's free up the lock:
|
|
97
|
-
stub.onCall(3).returns(null);
|
|
98
|
-
stub.onCall(4).returns("uniqueId");
|
|
99
|
-
|
|
100
|
-
return fm.lock(key).then((stats) => {
|
|
101
|
-
expect(stats.restartCount).to.eq(1);
|
|
102
|
-
expect(stats.locksLost).to.eq(1);
|
|
103
|
-
expect(stats.contentionCount).to.eq(1);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("When contending for a lock and ultimately winning, it should not restart", () => {
|
|
108
|
-
const key = "somekey";
|
|
109
|
-
const fm = new FastMutex({
|
|
110
|
-
localStorage: localStorage,
|
|
111
|
-
clientId: "uniqueId",
|
|
112
|
-
});
|
|
113
|
-
const stub = sandbox.stub(fm, "getItem");
|
|
114
|
-
|
|
115
|
-
// Set up scenario for lock contention where we lost Y
|
|
116
|
-
stub.onCall(0).returns(null); // getItem Y
|
|
117
|
-
stub.onCall(1).returns("lockContention");
|
|
118
|
-
stub.onCall(2).returns("uniqueId");
|
|
119
|
-
|
|
120
|
-
const spy = sandbox.spy(fm, "lock");
|
|
121
|
-
|
|
122
|
-
return fm.lock(key).then((stats) => {
|
|
123
|
-
expect(stats.restartCount).to.eq(0);
|
|
124
|
-
expect(stats.locksLost).to.eq(0);
|
|
125
|
-
expect(stats.contentionCount).to.eq(1);
|
|
126
|
-
expect(spy.callCount).to.eq(1);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// This is just to ensure that the internals of FastMutex have prefixes on the
|
|
131
|
-
// X and Y locks such that two different FM clients can acquire locks on
|
|
132
|
-
// different keys concurrently without clashing.
|
|
133
|
-
it("should not clash with other fastMutex locks", async () => {
|
|
134
|
-
const yPrefix = "yLock";
|
|
135
|
-
const xPrefix = "xLock";
|
|
136
|
-
const opts = { localStorage, yPrefix, xPrefix };
|
|
137
|
-
|
|
138
|
-
const fm1 = new FastMutex(opts);
|
|
139
|
-
const fm2 = new FastMutex(opts);
|
|
140
|
-
|
|
141
|
-
let lock1Acquired = false;
|
|
142
|
-
let lock2Acquired = false;
|
|
143
|
-
|
|
144
|
-
/* eslint-disable jest/valid-expect-in-promise */
|
|
145
|
-
const lock1Promise = fm1.lock("lock1").then((stats) => {
|
|
146
|
-
lock1Acquired = true;
|
|
147
|
-
expect(localStorage.getItem(yPrefix + "lock1")).to.exist;
|
|
148
|
-
return stats;
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
/* eslint-disable jest/valid-expect-in-promise */
|
|
152
|
-
const lock2Promise = fm2.lock("lock2").then((stats) => {
|
|
153
|
-
lock2Acquired = true;
|
|
154
|
-
expect(localStorage.getItem(yPrefix + "lock2")).to.exist;
|
|
155
|
-
return stats;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
await Promise.all([lock1Promise, lock2Promise]).then(() => {
|
|
159
|
-
expect(lock1Acquired).to.be.true;
|
|
160
|
-
expect(lock2Acquired).to.be.true;
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("release() should remove the y lock in localStorage", () => {
|
|
165
|
-
const key = "somekey";
|
|
166
|
-
const fm1 = new FastMutex({
|
|
167
|
-
localStorage: localStorage,
|
|
168
|
-
clientId: "releaseTestId",
|
|
169
|
-
yPrefix: "yLock",
|
|
170
|
-
});
|
|
171
|
-
return fm1
|
|
172
|
-
.lock(key)
|
|
173
|
-
.then(() => {
|
|
174
|
-
expect(fm1.getItem("yLock" + key)).to.eq("releaseTestId");
|
|
175
|
-
return fm1.release(key);
|
|
176
|
-
})
|
|
177
|
-
.then(() => {
|
|
178
|
-
expect(fm1.getItem("yLock" + key)).to.be.undefined;
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// this is essentially just a better way to test that two locks cannot get
|
|
183
|
-
// an exclusive lock until the other releases. It's a bit more accurate
|
|
184
|
-
// than the test above ("release should remove the y lock in localstorage")
|
|
185
|
-
it("two clients should never get locks at the same time", function () {
|
|
186
|
-
const fm1 = new FastMutex({ localStorage: localStorage });
|
|
187
|
-
const fm2 = new FastMutex({ localStorage: localStorage });
|
|
188
|
-
let fm1LockReleased = false;
|
|
189
|
-
const lockHoldTime = 10;
|
|
190
|
-
|
|
191
|
-
return fm1
|
|
192
|
-
.lock("clientId")
|
|
193
|
-
.then(() => {
|
|
194
|
-
// before the lock is released, try to establish another lock:
|
|
195
|
-
var lock2Promise = fm2.lock("clientId");
|
|
196
|
-
expect(fm1LockReleased).to.be.false;
|
|
197
|
-
|
|
198
|
-
// in a few milliseconds, release the lock
|
|
199
|
-
setTimeout(() => {
|
|
200
|
-
fm1.release("clientId");
|
|
201
|
-
fm1LockReleased = true;
|
|
202
|
-
}, lockHoldTime);
|
|
203
|
-
|
|
204
|
-
return lock2Promise;
|
|
205
|
-
})
|
|
206
|
-
.then((lock2) => {
|
|
207
|
-
// this will only execute once the other lock was released
|
|
208
|
-
expect(fm1LockReleased).to.be.true;
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("should throw if lock is never acquired after set time period", async () => {
|
|
213
|
-
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
214
|
-
const fm2 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
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);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it("should ignore expired locks", async () => {
|
|
229
|
-
const fm1 = new FastMutex({
|
|
230
|
-
localStorage: localStorage,
|
|
231
|
-
timeout: 5000,
|
|
232
|
-
yPrefix: "yLock",
|
|
233
|
-
clientId: "timeoutClient",
|
|
234
|
-
});
|
|
235
|
-
const expiredRecord = {
|
|
236
|
-
expiresAt: new Date().getTime() - 5000,
|
|
237
|
-
value: "oldclient",
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
localStorage.setItem("yLocktimeoutTest", JSON.stringify(expiredRecord));
|
|
241
|
-
expect(
|
|
242
|
-
JSON.parse(localStorage.getItem("yLocktimeoutTest")!).value
|
|
243
|
-
).to.eq("oldclient");
|
|
244
|
-
|
|
245
|
-
await fm1.lock("timeoutTest"); // should not throw
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it("should reset the client stats after lock is released", async () => {
|
|
249
|
-
// without resetting the stats, the acquireStart will always be set, and
|
|
250
|
-
// after `timeout` ms, will be unable to acquire a lock anymore
|
|
251
|
-
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
252
|
-
let keepLock = true;
|
|
253
|
-
let keepLockFn = () => keepLock;
|
|
254
|
-
await fm1.lock("resetStats", keepLockFn);
|
|
255
|
-
expect(fm1.isLocked("resetStats")).to.be.true;
|
|
256
|
-
keepLock = false;
|
|
257
|
-
await delay(100); // await timeout
|
|
258
|
-
expect(fm1.isLocked("resetStats")).to.be.false;
|
|
259
|
-
const p = fm1.lock("resetStats").then(() => fm1.release("resetStats"));
|
|
260
|
-
|
|
261
|
-
await p; // should not throw
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("can keep lock with callback function", async () => {
|
|
265
|
-
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
266
|
-
await fm1.lock("x");
|
|
267
|
-
await fm1.release("x");
|
|
268
|
-
expect(fm1.isLocked("x")).to.be.false;
|
|
269
|
-
await fm1.lock("x").then(() => fm1.release("x"));
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it("should reset the client stats if the lock has expired", async () => {
|
|
273
|
-
// in the event a lock cannot be acquired within `timeout`, acquireStart
|
|
274
|
-
// will never be reset, and a subsequent call (after the `timeout`) would
|
|
275
|
-
// immediately fail
|
|
276
|
-
const fm1 = new FastMutex({ localStorage: localStorage, timeout: 50 });
|
|
277
|
-
|
|
278
|
-
await fm1.lock("resetStats");
|
|
279
|
-
|
|
280
|
-
// try to acquire a lock after `timeout`:
|
|
281
|
-
await delay(75); // a small buffer over timeout to avoid flakiness
|
|
282
|
-
|
|
283
|
-
await fm1.lock("resetStats"); // should not throw
|
|
284
|
-
});
|
|
285
|
-
});
|
|
@@ -1,85 +0,0 @@
|
|
|
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
|
-
});
|