@peerbit/react 0.0.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/LICENSE +202 -0
- package/README.md +1 -0
- package/lib/esm/__tests__/lockstorage.test.d.ts +1 -0
- package/lib/esm/__tests__/lockstorage.test.js +225 -0
- package/lib/esm/__tests__/lockstorage.test.js.map +1 -0
- package/lib/esm/__tests__/utils.test.d.ts +1 -0
- package/lib/esm/__tests__/utils.test.js +61 -0
- package/lib/esm/__tests__/utils.test.js.map +1 -0
- package/lib/esm/index.d.ts +3 -0
- package/lib/esm/index.js +4 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/lockstorage.d.ts +32 -0
- package/lib/esm/lockstorage.js +178 -0
- package/lib/esm/lockstorage.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/useMount.d.ts +2 -0
- package/lib/esm/useMount.js +12 -0
- package/lib/esm/useMount.js.map +1 -0
- package/lib/esm/usePeer.d.ts +25 -0
- package/lib/esm/usePeer.js +180 -0
- package/lib/esm/usePeer.js.map +1 -0
- package/lib/esm/utils.d.ts +11 -0
- package/lib/esm/utils.js +96 -0
- package/lib/esm/utils.js.map +1 -0
- package/package.json +76 -0
- package/src/__tests__/lockstorage.test.ts +264 -0
- package/src/__tests__/utils.test.ts +83 -0
- package/src/index.ts +8 -0
- package/src/lockstorage.ts +249 -0
- package/src/useMount.tsx +15 -0
- package/src/usePeer.tsx +270 -0
- package/src/utils.ts +116 -0
|
@@ -0,0 +1,178 @@
|
|
|
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
|
+
import debugFn from "debug";
|
|
18
|
+
import { v4 as uuid } from "uuid";
|
|
19
|
+
const debug = debugFn("FastMutex");
|
|
20
|
+
export class FastMutex {
|
|
21
|
+
clientId;
|
|
22
|
+
xPrefix;
|
|
23
|
+
yPrefix;
|
|
24
|
+
timeout;
|
|
25
|
+
localStorage;
|
|
26
|
+
intervals;
|
|
27
|
+
constructor({ clientId = uuid(), xPrefix = "_MUTEX_LOCK_X_", yPrefix = "_MUTEX_LOCK_Y_", timeout = 5000, localStorage = undefined, } = {}) {
|
|
28
|
+
this.clientId = clientId;
|
|
29
|
+
this.xPrefix = xPrefix;
|
|
30
|
+
this.yPrefix = yPrefix;
|
|
31
|
+
this.timeout = timeout;
|
|
32
|
+
this.intervals = new Map();
|
|
33
|
+
this.localStorage = localStorage || window.localStorage;
|
|
34
|
+
}
|
|
35
|
+
lock(key, keepLocked) {
|
|
36
|
+
debug('Attempting to acquire Lock on "%s" using FastMutex instance "%s"', key, this.clientId);
|
|
37
|
+
const x = this.xPrefix + key;
|
|
38
|
+
const y = this.yPrefix + key;
|
|
39
|
+
let acquireStart = +new Date();
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
// we need to differentiate between API calls to lock() and our internal
|
|
42
|
+
// recursive calls so that we can timeout based on the original lock() and
|
|
43
|
+
// not each subsequent call. Therefore, create a new function here within
|
|
44
|
+
// the promise closure that we use for subsequent calls:
|
|
45
|
+
let restartCount = 0;
|
|
46
|
+
let contentionCount = 0;
|
|
47
|
+
let locksLost = 0;
|
|
48
|
+
const acquireLock = (key) => {
|
|
49
|
+
if (restartCount > 1000 ||
|
|
50
|
+
contentionCount > 1000 ||
|
|
51
|
+
locksLost > 1000) {
|
|
52
|
+
reject("Failed to resolve lock");
|
|
53
|
+
}
|
|
54
|
+
const elapsedTime = new Date().getTime() - acquireStart;
|
|
55
|
+
if (elapsedTime >= this.timeout) {
|
|
56
|
+
debug('Lock on "%s" could not be acquired within %sms by FastMutex client "%s"', key, this.timeout, this.clientId);
|
|
57
|
+
return reject(new Error(`Lock could not be acquired within ${this.timeout}ms`));
|
|
58
|
+
}
|
|
59
|
+
this.setItem(x, this.clientId, keepLocked);
|
|
60
|
+
// if y exists, another client is getting a lock, so retry in a bit
|
|
61
|
+
let lsY = this.getItem(y);
|
|
62
|
+
if (lsY) {
|
|
63
|
+
debug("Lock exists on Y (%s), restarting...", lsY);
|
|
64
|
+
restartCount++;
|
|
65
|
+
setTimeout(() => acquireLock(key));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// ask for inner lock
|
|
69
|
+
this.setItem(y, this.clientId, keepLocked);
|
|
70
|
+
// if x was changed, another client is contending for an inner lock
|
|
71
|
+
let lsX = this.getItem(x);
|
|
72
|
+
if (lsX !== this.clientId) {
|
|
73
|
+
contentionCount++;
|
|
74
|
+
debug('Lock contention detected. X="%s"', lsX);
|
|
75
|
+
// Give enough time for critical section:
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
lsY = this.getItem(y);
|
|
78
|
+
if (lsY === this.clientId) {
|
|
79
|
+
// we have a lock
|
|
80
|
+
debug('FastMutex client "%s" won the lock contention on "%s"', this.clientId, key);
|
|
81
|
+
resolve({
|
|
82
|
+
contentionCount,
|
|
83
|
+
locksLost,
|
|
84
|
+
restartCount,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// we lost the lock, restart the process again
|
|
89
|
+
restartCount++;
|
|
90
|
+
locksLost++;
|
|
91
|
+
debug('FastMutex client "%s" lost the lock contention on "%s" to another process (%s). Restarting...', this.clientId, key, lsY);
|
|
92
|
+
setTimeout(() => acquireLock(key));
|
|
93
|
+
}
|
|
94
|
+
}, 50);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// no contention:
|
|
98
|
+
debug('FastMutex client "%s" acquired a lock on "%s" with no contention', this.clientId, key);
|
|
99
|
+
resolve({ contentionCount, locksLost, restartCount });
|
|
100
|
+
};
|
|
101
|
+
acquireLock(key);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
isLocked(key) {
|
|
105
|
+
const x = this.xPrefix + key;
|
|
106
|
+
const y = this.yPrefix + key;
|
|
107
|
+
return !!this.getItem(x) || !!this.getItem(y);
|
|
108
|
+
}
|
|
109
|
+
getLockedInfo(key) {
|
|
110
|
+
const x = this.xPrefix + key;
|
|
111
|
+
const y = this.yPrefix + key;
|
|
112
|
+
return this.getItem(x) || this.getItem(y);
|
|
113
|
+
}
|
|
114
|
+
release(key) {
|
|
115
|
+
debug('FastMutex client "%s" is releasing lock on "%s"', this.clientId, key);
|
|
116
|
+
let ps = [this.yPrefix + key, this.xPrefix + key];
|
|
117
|
+
for (const p of ps) {
|
|
118
|
+
clearInterval(this.intervals.get(p));
|
|
119
|
+
this.intervals.delete(p);
|
|
120
|
+
this.localStorage.removeItem(p);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Helper function to wrap all values in an object that includes the time (so
|
|
125
|
+
* that we can expire it in the future) and json.stringify's it
|
|
126
|
+
*/
|
|
127
|
+
setItem(key, value, keepLocked) {
|
|
128
|
+
if (!keepLocked) {
|
|
129
|
+
return this.localStorage.setItem(key, JSON.stringify({
|
|
130
|
+
expiresAt: new Date().getTime() + this.timeout,
|
|
131
|
+
value,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
let getExpiry = () => +new Date() + this.timeout;
|
|
136
|
+
const ret = this.localStorage.setItem(key, JSON.stringify({
|
|
137
|
+
expiresAt: getExpiry(),
|
|
138
|
+
value,
|
|
139
|
+
}));
|
|
140
|
+
const interval = setInterval(() => {
|
|
141
|
+
if (!keepLocked()) {
|
|
142
|
+
this.localStorage.setItem(
|
|
143
|
+
// TODO, release directly?
|
|
144
|
+
key, JSON.stringify({
|
|
145
|
+
expiresAt: 0,
|
|
146
|
+
value,
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
this.localStorage.setItem(key, JSON.stringify({
|
|
151
|
+
expiresAt: getExpiry(),
|
|
152
|
+
value,
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
}, this.timeout);
|
|
156
|
+
this.intervals.set(key, interval);
|
|
157
|
+
return ret;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Helper function to parse JSON encoded values set in localStorage
|
|
162
|
+
*/
|
|
163
|
+
getItem(key) {
|
|
164
|
+
const item = this.localStorage.getItem(key);
|
|
165
|
+
if (!item)
|
|
166
|
+
return;
|
|
167
|
+
const parsed = JSON.parse(item);
|
|
168
|
+
if (new Date().getTime() - parsed.expiresAt >= this.timeout) {
|
|
169
|
+
debug('FastMutex client "%s" removed an expired record on "%s"', this.clientId, key);
|
|
170
|
+
this.localStorage.removeItem(key);
|
|
171
|
+
clearInterval(this.intervals.get(key));
|
|
172
|
+
this.intervals.delete(key);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
return JSON.parse(item).value;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=lockstorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lockstorage.js","sourceRoot":"","sources":["../../src/lockstorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
export const useMount = (effect) => {
|
|
3
|
+
const mounted = useRef(false);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
if (!mounted.current) {
|
|
6
|
+
effect();
|
|
7
|
+
}
|
|
8
|
+
mounted.current = true;
|
|
9
|
+
return () => { };
|
|
10
|
+
}, [mounted.current]);
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=useMount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMount.js","sourceRoot":"","sources":["../../src/useMount.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/D,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAsB,EAAE,EAAE;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YAClB,MAAM,EAAE,CAAC;SACZ;QAED,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QAEvB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IACpB,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1B,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Multiaddr } from "@multiformats/multiaddr";
|
|
3
|
+
import { Peerbit } from "peerbit";
|
|
4
|
+
import { Ed25519Keypair } from "@peerbit/crypto";
|
|
5
|
+
export type ConnectionStatus = "disconnected" | "connected" | "connecting" | "failed";
|
|
6
|
+
interface IPeerContext {
|
|
7
|
+
peer: Peerbit | undefined;
|
|
8
|
+
promise: Promise<void> | undefined;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
status: ConnectionStatus;
|
|
11
|
+
}
|
|
12
|
+
export declare const subscribeToKeypairChange: (onChange: (keypair: Ed25519Keypair) => any) => void;
|
|
13
|
+
export declare const submitKeypairChange: (element: HTMLIFrameElement, keypair: Ed25519Keypair, origin: string) => void;
|
|
14
|
+
export declare const PeerContext: React.Context<IPeerContext>;
|
|
15
|
+
export declare const usePeer: () => IPeerContext;
|
|
16
|
+
export declare const PeerProvider: ({ network, bootstrap, children, inMemory, keypair, waitForConnnected, waitForKeypairInIFrame, }: {
|
|
17
|
+
network: "local" | "remote";
|
|
18
|
+
inMemory?: boolean | undefined;
|
|
19
|
+
waitForConnnected?: boolean | undefined;
|
|
20
|
+
keypair?: Ed25519Keypair | undefined;
|
|
21
|
+
waitForKeypairInIFrame?: boolean | undefined;
|
|
22
|
+
bootstrap?: (string | Multiaddr)[] | undefined;
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useContext } from "react";
|
|
3
|
+
import { multiaddr } from "@multiformats/multiaddr";
|
|
4
|
+
import { Peerbit } from "peerbit";
|
|
5
|
+
import { webSockets } from "@libp2p/websockets";
|
|
6
|
+
import { mplex } from "@libp2p/mplex";
|
|
7
|
+
import { getFreeKeypair, getTabId, inIframe } from "./utils.js";
|
|
8
|
+
import { resolveBootstrapAddresses } from "@peerbit/network-utils";
|
|
9
|
+
import { noise } from "@dao-xyz/libp2p-noise";
|
|
10
|
+
import { v4 as uuid } from "uuid";
|
|
11
|
+
import { Ed25519Keypair } from "@peerbit/crypto";
|
|
12
|
+
import { FastMutex } from "./lockstorage.js";
|
|
13
|
+
import { serialize, deserialize } from "@dao-xyz/borsh";
|
|
14
|
+
import { waitFor } from "@peerbit/time";
|
|
15
|
+
import sodium from "libsodium-wrappers";
|
|
16
|
+
import * as filters from "@libp2p/websockets/filters";
|
|
17
|
+
import { useMount } from "./useMount.js";
|
|
18
|
+
if (!window.name) {
|
|
19
|
+
window.name = uuid();
|
|
20
|
+
}
|
|
21
|
+
export const subscribeToKeypairChange = (onChange) => {
|
|
22
|
+
window.onmessage = (c) => {
|
|
23
|
+
if (c.data.type == "keypair") {
|
|
24
|
+
onChange(deserialize(c.data.bytes, Ed25519Keypair));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export const submitKeypairChange = (element, keypair, origin) => {
|
|
29
|
+
element.contentWindow.postMessage({ type: "keypair", bytes: serialize(keypair) }, origin);
|
|
30
|
+
};
|
|
31
|
+
let keypairMessages = [];
|
|
32
|
+
subscribeToKeypairChange((keypair) => {
|
|
33
|
+
console.log("got keypair!", keypair);
|
|
34
|
+
keypairMessages.push(keypair);
|
|
35
|
+
});
|
|
36
|
+
export const PeerContext = React.createContext({});
|
|
37
|
+
export const usePeer = () => useContext(PeerContext);
|
|
38
|
+
export const PeerProvider = ({ network, bootstrap, children, inMemory, keypair, waitForConnnected, waitForKeypairInIFrame, }) => {
|
|
39
|
+
const [peer, setPeer] = React.useState(undefined);
|
|
40
|
+
const [promise, setPromise] = React.useState(undefined);
|
|
41
|
+
const [loading, setLoading] = React.useState(false);
|
|
42
|
+
const [connectionState, setConnectionState] = React.useState("disconnected");
|
|
43
|
+
const memo = React.useMemo(() => ({
|
|
44
|
+
peer,
|
|
45
|
+
promise,
|
|
46
|
+
loading,
|
|
47
|
+
connectionState,
|
|
48
|
+
status: connectionState,
|
|
49
|
+
}), [
|
|
50
|
+
loading,
|
|
51
|
+
!!promise,
|
|
52
|
+
connectionState,
|
|
53
|
+
peer?.identity?.publicKey.toString(),
|
|
54
|
+
]);
|
|
55
|
+
useMount(() => {
|
|
56
|
+
setLoading(true);
|
|
57
|
+
const fn = async (keypair = keypairMessages[keypairMessages.length - 1]) => {
|
|
58
|
+
await sodium.ready;
|
|
59
|
+
if (!keypair && waitForKeypairInIFrame && inIframe()) {
|
|
60
|
+
await waitFor(() => (keypair = keypairMessages[keypairMessages.length - 1]));
|
|
61
|
+
}
|
|
62
|
+
if (keypair &&
|
|
63
|
+
keypairMessages[keypairMessages.length - 1] &&
|
|
64
|
+
keypairMessages[keypairMessages.length - 1].equals(keypair)) {
|
|
65
|
+
console.log("Creating client from identity sent from parent window: " +
|
|
66
|
+
keypair.publicKey.hashcode());
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (!keypair) {
|
|
70
|
+
console.log("Generating new keypair for client");
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log("Keypair missmatch with latest keypair message", keypairMessages.map((x) => x.publicKey.hashcode()), keypair.publicKey.hashcode());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (peer) {
|
|
77
|
+
await peer.stop();
|
|
78
|
+
setPeer(undefined);
|
|
79
|
+
}
|
|
80
|
+
const nodeId = keypair ||
|
|
81
|
+
(await getFreeKeypair("", new FastMutex({ clientId: getTabId(), timeout: 1000 }), undefined, true // reuse keypairs from same tab, (force release)
|
|
82
|
+
)).key;
|
|
83
|
+
// We create a new directrory to make tab to tab communication go smoothly
|
|
84
|
+
const newPeer = await Peerbit.create({
|
|
85
|
+
libp2p: {
|
|
86
|
+
addresses: {
|
|
87
|
+
listen: [
|
|
88
|
+
/* '/webrtc' */
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
connectionEncryption: [noise()],
|
|
92
|
+
peerId: await nodeId.toPeerId(),
|
|
93
|
+
connectionManager: {
|
|
94
|
+
maxConnections: 100,
|
|
95
|
+
minConnections: 0,
|
|
96
|
+
},
|
|
97
|
+
streamMuxers: [mplex()],
|
|
98
|
+
...(network === "local"
|
|
99
|
+
? {
|
|
100
|
+
connectionGater: {
|
|
101
|
+
denyDialMultiaddr: () => {
|
|
102
|
+
// by default we refuse to dial local addresses from the browser since they
|
|
103
|
+
// are usually sent by remote peers broadcasting undialable multiaddrs but
|
|
104
|
+
// here we are explicitly connecting to a local node so do not deny dialing
|
|
105
|
+
// any discovered address
|
|
106
|
+
return false;
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
transports: [
|
|
110
|
+
// Add websocket impl so we can connect to "unsafe" ws (production only allows wss)
|
|
111
|
+
webSockets({
|
|
112
|
+
filter: filters.all,
|
|
113
|
+
}),
|
|
114
|
+
/* circuitRelayTransport({ discoverRelays: 1 }),
|
|
115
|
+
webRTC(), */
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
: {
|
|
119
|
+
connectionGater: {
|
|
120
|
+
denyDialMultiaddr: () => {
|
|
121
|
+
// by default we refuse to dial local addresses from the browser since they
|
|
122
|
+
// are usually sent by remote peers broadcasting undialable multiaddrs but
|
|
123
|
+
// here we are explicitly connecting to a local node so do not deny dialing
|
|
124
|
+
// any discovered address
|
|
125
|
+
return false;
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
transports: [
|
|
129
|
+
webSockets({ filter: filters.all }),
|
|
130
|
+
/* circuitRelayTransport({ discoverRelays: 1 }),
|
|
131
|
+
webRTC(), */
|
|
132
|
+
],
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
directory: !inMemory ? "./repo" : undefined,
|
|
136
|
+
limitSigning: true,
|
|
137
|
+
});
|
|
138
|
+
setConnectionState("connecting");
|
|
139
|
+
// Resolve bootstrap nodes async (we want to return before this is done)
|
|
140
|
+
const connectFn = async () => {
|
|
141
|
+
try {
|
|
142
|
+
const addresses = await (bootstrap
|
|
143
|
+
? Promise.resolve(bootstrap)
|
|
144
|
+
: resolveBootstrapAddresses(network));
|
|
145
|
+
if (addresses && addresses?.length > 0) {
|
|
146
|
+
try {
|
|
147
|
+
await Promise.all(addresses
|
|
148
|
+
.map((a) => typeof a === "string" ? multiaddr(a) : a)
|
|
149
|
+
.map((a) => newPeer.dial(a)));
|
|
150
|
+
setConnectionState("connected");
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error("Failed to resolve relay node. Please come back later or start the demo locally");
|
|
154
|
+
setConnectionState("failed");
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.error("No addresses to connect to");
|
|
160
|
+
setConnectionState("failed");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
console.error("Failed to resolve relay addresses. " + err?.message);
|
|
165
|
+
setConnectionState("failed");
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const promise = connectFn();
|
|
169
|
+
// Make sure data flow as expected between tabs and windows locally (offline states)
|
|
170
|
+
if (waitForConnnected) {
|
|
171
|
+
await promise;
|
|
172
|
+
}
|
|
173
|
+
setPeer(newPeer);
|
|
174
|
+
setLoading(false);
|
|
175
|
+
};
|
|
176
|
+
setPromise(fn(keypair));
|
|
177
|
+
});
|
|
178
|
+
return _jsx(PeerContext.Provider, { value: memo, children: children });
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=usePeer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAa,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAazC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;IACd,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;CACxB;AAMD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACpC,QAA0C,EAC5C,EAAE;IACA,MAAM,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;QACnC,IAAK,CAAC,CAAC,IAAuB,CAAC,IAAI,IAAI,SAAS,EAAE;YAC9C,QAAQ,CACJ,WAAW,CAAE,CAAC,CAAC,IAAuB,CAAC,KAAK,EAAE,cAAc,CAAC,CAChE,CAAC;SACL;IACL,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAC/B,OAA0B,EAC1B,OAAuB,EACvB,MAAc,EAChB,EAAE;IACA,OAAO,CAAC,aAAc,CAAC,WAAW,CAC9B,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAoB,EAChE,MAAM,CACT,CAAC;AACN,CAAC,CAAC;AAEF,IAAI,eAAe,GAAqB,EAAE,CAAC;AAC3C,wBAAwB,CAAC,CAAC,OAAO,EAAE,EAAE;IACjC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,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;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EACzB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,sBAAsB,GASzB,EAAE,EAAE;IACD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAsB,SAAS,CAAC,CAAC;IACvE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CACxC,SAAS,CACZ,CAAC;IAEF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC7D,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GACvC,KAAK,CAAC,QAAQ,CAAmB,cAAc,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CACtB,GAAG,EAAE,CAAC,CAAC;QACH,IAAI;QACJ,OAAO;QACP,OAAO;QACP,eAAe;QACf,MAAM,EAAE,eAAe;KAC1B,CAAC,EACF;QACI,OAAO;QACP,CAAC,CAAC,OAAO;QACT,eAAe;QACf,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE;KACvC,CACJ,CAAC;IAEF,QAAQ,CAAC,GAAG,EAAE;QACV,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,EAAE,GAAG,KAAK,EACZ,UAA0B,eAAe,CACrC,eAAe,CAAC,MAAM,GAAG,CAAC,CAC7B,EACH,EAAE;YACA,MAAM,MAAM,CAAC,KAAK,CAAC;YAEnB,IAAI,CAAC,OAAO,IAAI,sBAAsB,IAAI,QAAQ,EAAE,EAAE;gBAClD,MAAM,OAAO,CACT,GAAG,EAAE,CACD,CAAC,OAAO,GAAG,eAAe,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAC9D,CAAC;aACL;YAED,IACI,OAAO;gBACP,eAAe,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC3C,eAAe,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAC7D;gBACE,OAAO,CAAC,GAAG,CACP,yDAAyD;oBACrD,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CACnC,CAAC;aACL;iBAAM;gBACH,IAAI,CAAC,OAAO,EAAE;oBACV,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;iBACpD;qBAAM;oBACH,OAAO,CAAC,GAAG,CACP,+CAA+C,EAC/C,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,EAClD,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAC/B,CAAC;iBACL;aACJ;YAED,IAAI,IAAI,EAAE;gBACN,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClB,OAAO,CAAC,SAAS,CAAC,CAAC;aACtB;YAED,MAAM,MAAM,GACR,OAAO;gBACP,CACI,MAAM,cAAc,CAChB,EAAE,EACF,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EACtD,SAAS,EACT,IAAI,CAAC,gDAAgD;iBACxD,CACJ,CAAC,GAAG,CAAC;YAEV,0EAA0E;YAC1E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;gBACjC,MAAM,EAAE;oBACJ,SAAS,EAAE;wBACP,MAAM,EAAE;wBACJ,kBAAkB;yBACrB;qBACJ;oBACD,oBAAoB,EAAE,CAAC,KAAK,EAAE,CAAC;oBAC/B,MAAM,EAAE,MAAM,MAAM,CAAC,QAAQ,EAAE;oBAC/B,iBAAiB,EAAE;wBACf,cAAc,EAAE,GAAG;wBACnB,cAAc,EAAE,CAAC;qBACpB;oBACD,YAAY,EAAE,CAAC,KAAK,EAAE,CAAC;oBACvB,GAAG,CAAC,OAAO,KAAK,OAAO;wBACnB,CAAC,CAAC;4BACI,eAAe,EAAE;gCACb,iBAAiB,EAAE,GAAG,EAAE;oCACpB,2EAA2E;oCAC3E,0EAA0E;oCAC1E,2EAA2E;oCAC3E,yBAAyB;oCACzB,OAAO,KAAK,CAAC;gCACjB,CAAC;6BACJ;4BACD,UAAU,EAAE;gCACR,mFAAmF;gCACnF,UAAU,CAAC;oCACP,MAAM,EAAE,OAAO,CAAC,GAAG;iCACtB,CAAC;gCACF;2BACL;6BACE;yBACJ;wBACH,CAAC,CAAC;4BACI,eAAe,EAAE;gCACb,iBAAiB,EAAE,GAAG,EAAE;oCACpB,2EAA2E;oCAC3E,0EAA0E;oCAC1E,2EAA2E;oCAC3E,yBAAyB;oCACzB,OAAO,KAAK,CAAC;gCACjB,CAAC;6BACJ;4BACD,UAAU,EAAE;gCACR,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;gCACnC;4BACJ;6BACC;yBACJ,CAAC;iBACX;gBACD,SAAS,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBAC3C,YAAY,EAAE,IAAI;aACrB,CAAC,CAAC;YAEH,kBAAkB,CAAC,YAAY,CAAC,CAAC;YAEjC,wEAAwE;YACxE,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;gBACzB,IAAI;oBACA,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS;wBAC9B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;wBAC5B,CAAC,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC1C,IAAI,SAAS,IAAI,SAAS,EAAE,MAAM,GAAG,CAAC,EAAE;wBACpC,IAAI;4BACA,MAAM,OAAO,CAAC,GAAG,CACb,SAAS;iCACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACP,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3C;iCACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC;4BACF,kBAAkB,CAAC,WAAW,CAAC,CAAC;yBACnC;wBAAC,OAAO,KAAK,EAAE;4BACZ,OAAO,CAAC,KAAK,CACT,gFAAgF,CACnF,CAAC;4BACF,kBAAkB,CAAC,QAAQ,CAAC,CAAC;4BAC7B,MAAM,KAAK,CAAC;yBACf;qBACJ;yBAAM;wBACH,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAC5C,kBAAkB,CAAC,QAAQ,CAAC,CAAC;qBAChC;iBACJ;gBAAC,OAAO,GAAQ,EAAE;oBACf,OAAO,CAAC,KAAK,CACT,qCAAqC,GAAG,GAAG,EAAE,OAAO,CACvD,CAAC;oBACF,kBAAkB,CAAC,QAAQ,CAAC,CAAC;iBAChC;YACL,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;YAE5B,oFAAoF;YAEpF,IAAI,iBAAiB,EAAE;gBACnB,MAAM,OAAO,CAAC;aACjB;YAED,OAAO,CAAC,OAAO,CAAC,CAAC;YACjB,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,OAAO,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAAwB,CAAC;AAChF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Ed25519Keypair } from "@peerbit/crypto";
|
|
2
|
+
import { FastMutex } from "./lockstorage";
|
|
3
|
+
export declare const getTabId: () => any;
|
|
4
|
+
export declare const releaseKey: (path: string, lock?: FastMutex) => void;
|
|
5
|
+
export declare const getFreeKeypair: (id?: string, lock?: FastMutex, lockCondition?: () => boolean, releaseLockIfSameId?: boolean) => Promise<{
|
|
6
|
+
path: string;
|
|
7
|
+
key: Ed25519Keypair;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const getAllKeyPairs: (id?: string) => Promise<Ed25519Keypair[]>;
|
|
10
|
+
export declare const getKeypair: (keyName: string) => Promise<Ed25519Keypair>;
|
|
11
|
+
export declare const inIframe: () => boolean;
|
package/lib/esm/utils.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { serialize, deserialize } from "@dao-xyz/borsh";
|
|
2
|
+
import { Ed25519Keypair, toBase64, fromBase64 } from "@peerbit/crypto";
|
|
3
|
+
import { FastMutex } from "./lockstorage";
|
|
4
|
+
import { v4 as uuid } from "uuid";
|
|
5
|
+
import sodium from "libsodium-wrappers";
|
|
6
|
+
export const getTabId = () => {
|
|
7
|
+
const idFromStorage = sessionStorage.getItem("TAB_ID");
|
|
8
|
+
if (idFromStorage) {
|
|
9
|
+
return idFromStorage;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
const id = uuid(); // generate unique UUID
|
|
13
|
+
sessionStorage.setItem("TAB_ID", id);
|
|
14
|
+
return id;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const ID_COUNTER_KEY = "idc/";
|
|
18
|
+
const getKeyId = (prefix, id) => prefix + "/" + id;
|
|
19
|
+
export const releaseKey = (path, lock = new FastMutex({ clientId: getTabId() })) => {
|
|
20
|
+
lock.release(path);
|
|
21
|
+
};
|
|
22
|
+
export const getFreeKeypair = async (id = "", lock = new FastMutex({ clientId: getTabId() }), lockCondition = () => true, releaseLockIfSameId) => {
|
|
23
|
+
await sodium.ready;
|
|
24
|
+
const idCounterKey = ID_COUNTER_KEY + id;
|
|
25
|
+
await lock.lock(idCounterKey, () => true);
|
|
26
|
+
let idCounter = JSON.parse(localStorage.getItem(idCounterKey) || "0");
|
|
27
|
+
for (let i = 0; i < 10000; i++) {
|
|
28
|
+
const key = getKeyId(id, i);
|
|
29
|
+
let lockedInfo = lock.getLockedInfo(key);
|
|
30
|
+
if (lockedInfo) {
|
|
31
|
+
if (lockedInfo === lock.clientId && releaseLockIfSameId) {
|
|
32
|
+
await lock.release(key); // Release lock
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
console.log("aquire id at", i);
|
|
39
|
+
await lock.lock(key, lockCondition);
|
|
40
|
+
localStorage.setItem(idCounterKey, JSON.stringify(Math.max(idCounter, i + 1)));
|
|
41
|
+
await lock.release(idCounterKey);
|
|
42
|
+
return {
|
|
43
|
+
path: key,
|
|
44
|
+
key: await getKeypair(key),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
throw new Error("Failed to resolve key");
|
|
48
|
+
};
|
|
49
|
+
export const getAllKeyPairs = async (id = "") => {
|
|
50
|
+
const idCounterKey = ID_COUNTER_KEY + id;
|
|
51
|
+
const counter = JSON.parse(localStorage.getItem(idCounterKey) || "0");
|
|
52
|
+
let ret = [];
|
|
53
|
+
for (let i = 0; i < counter; i++) {
|
|
54
|
+
const key = getKeyId(id, i);
|
|
55
|
+
const kp = loadKeypair(key);
|
|
56
|
+
if (kp) {
|
|
57
|
+
ret.push(kp);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return ret;
|
|
61
|
+
};
|
|
62
|
+
let _getKeypair;
|
|
63
|
+
export const getKeypair = async (keyName) => {
|
|
64
|
+
await _getKeypair;
|
|
65
|
+
const fn = async () => {
|
|
66
|
+
let keypair = loadKeypair(keyName);
|
|
67
|
+
if (keypair) {
|
|
68
|
+
return keypair;
|
|
69
|
+
}
|
|
70
|
+
keypair = await Ed25519Keypair.create();
|
|
71
|
+
saveKeypair(keyName, keypair);
|
|
72
|
+
return keypair;
|
|
73
|
+
};
|
|
74
|
+
_getKeypair = fn();
|
|
75
|
+
return _getKeypair;
|
|
76
|
+
};
|
|
77
|
+
const saveKeypair = (path, key) => {
|
|
78
|
+
const str = toBase64(serialize(key));
|
|
79
|
+
localStorage.setItem("_keys/" + path, str);
|
|
80
|
+
};
|
|
81
|
+
const loadKeypair = (path) => {
|
|
82
|
+
let item = localStorage.getItem("_keys/" + path);
|
|
83
|
+
if (!item) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
return deserialize(fromBase64(item), Ed25519Keypair);
|
|
87
|
+
};
|
|
88
|
+
export const inIframe = () => {
|
|
89
|
+
try {
|
|
90
|
+
return window.self !== window.top;
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peerbit/react",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"homepage": "https://dao-xyz.github.io/peerbit-examples",
|
|
5
|
+
"module": "lib/esm/index.js",
|
|
6
|
+
"types": "lib/esm/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./lib/esm/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"lib",
|
|
15
|
+
"src",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"react": "*"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@emotion/react": "^11.10.5",
|
|
26
|
+
"@emotion/styled": "^11.10.5",
|
|
27
|
+
"@libp2p/webrtc": "^2.0.11",
|
|
28
|
+
"@mui/icons-material": "^5.10.16",
|
|
29
|
+
"@mui/material": "^5.10.13",
|
|
30
|
+
"@peerbit/network-utils": "^0.0.2",
|
|
31
|
+
"@types/react": "^18.0.25",
|
|
32
|
+
"@types/react-dom": "^18.0.8",
|
|
33
|
+
"path-browserify": "^1.0.1",
|
|
34
|
+
"peerbit": "*",
|
|
35
|
+
"react": "^18.2.0",
|
|
36
|
+
"react-dom": "^18.2.0",
|
|
37
|
+
"react-router-dom": "^6.8.0",
|
|
38
|
+
"react-use": "^17.4.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@babel/plugin-proposal-private-property-in-object": "^7.18.6",
|
|
42
|
+
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
43
|
+
"@babel/plugin-transform-typescript": "^7.20.2",
|
|
44
|
+
"@types/sinon": "^10.0.13",
|
|
45
|
+
"gh-pages": "^4.0.0",
|
|
46
|
+
"node-localstorage": "^2.2.1",
|
|
47
|
+
"sinon": "^15.0.1"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"clean": "shx rm -rf lib/*",
|
|
51
|
+
"build": "yarn clean && tsc -p tsconfig.json",
|
|
52
|
+
"test": "jest",
|
|
53
|
+
"postbuild": "echo '{\"type\":\"module\"} ' | node ../../node_modules/.bin/json > lib/esm/package.json"
|
|
54
|
+
},
|
|
55
|
+
"eslintConfig": {
|
|
56
|
+
"extends": [
|
|
57
|
+
"react-app",
|
|
58
|
+
"react-app/jest"
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"browserslist": {
|
|
62
|
+
"production": [
|
|
63
|
+
"chrome >= 67",
|
|
64
|
+
"edge >= 79",
|
|
65
|
+
"firefox >= 68",
|
|
66
|
+
"opera >= 54",
|
|
67
|
+
"safari >= 14"
|
|
68
|
+
],
|
|
69
|
+
"development": [
|
|
70
|
+
"last 1 chrome version",
|
|
71
|
+
"last 1 firefox version",
|
|
72
|
+
"last 1 safari version"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"gitHead": "827830c2a71751da42f2ce8b95b3ed81493e85b7"
|
|
76
|
+
}
|