entangld 2.7.0 → 2.7.1
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/lib/Datastore.js +1 -1
- package/lib/Message.js +1 -1
- package/lib/uuid.js +51 -0
- package/package.json +4 -1
- package/test/uuid.js +37 -0
package/lib/Datastore.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const uuidv4 = require("./uuid.js");
|
|
2
2
|
const EventEmitter = require("events");
|
|
3
3
|
const uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4
4
|
const MAX_TIMEOUT_MS = 2147483647; // Longer setTimeout delays fire after 1 ms
|
package/lib/Message.js
CHANGED
package/lib/uuid.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A random (v4) uuid, in Node and in browsers.
|
|
3
|
+
*
|
|
4
|
+
* Browsers on secure pages and Node 19 and later have crypto.randomUUID() on
|
|
5
|
+
* globalThis. Node 18 has it in its crypto module, which the "browser" field in
|
|
6
|
+
* package.json leaves out of browser bundles. A browser page that isn't secure
|
|
7
|
+
* (plain http, not localhost) has only crypto.getRandomValues().
|
|
8
|
+
*
|
|
9
|
+
* @author Claude <noreply@anthropic.com>
|
|
10
|
+
* Reviewed-by: Jonathan D. B. Van Schenck <jvschenck@novadynamics.com>
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A v4 uuid from 16 random bytes.
|
|
15
|
+
*
|
|
16
|
+
* @param {Uint8Array} bytes
|
|
17
|
+
* @return {string}
|
|
18
|
+
*/
|
|
19
|
+
function format_v4(bytes) {
|
|
20
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
|
|
21
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC 4122 variant
|
|
22
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
23
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Pick the uuid source for this runtime.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} [web_crypto] - globalThis.crypto, if any.
|
|
30
|
+
* @param {Function} [load_node_crypto] - returns Node's crypto module, or {} in a browser bundle.
|
|
31
|
+
* @return {Function} returns a new uuid string.
|
|
32
|
+
*/
|
|
33
|
+
// randomUUID needs Node 14.17 anyway, which has globalThis
|
|
34
|
+
function make_uuid(web_crypto = globalThis.crypto, load_node_crypto = () => require("crypto")) { // eslint-disable-line node/no-unsupported-features/es-builtins
|
|
35
|
+
if ( typeof web_crypto?.randomUUID == "function" ) return () => web_crypto.randomUUID();
|
|
36
|
+
let node_crypto = {};
|
|
37
|
+
try {
|
|
38
|
+
node_crypto = load_node_crypto() || {};
|
|
39
|
+
} catch (err) {
|
|
40
|
+
// Not in Node
|
|
41
|
+
}
|
|
42
|
+
if ( typeof node_crypto.randomUUID == "function" ) return () => node_crypto.randomUUID();
|
|
43
|
+
if ( typeof web_crypto?.getRandomValues == "function" ) {
|
|
44
|
+
return () => format_v4(web_crypto.getRandomValues(new Uint8Array(16)));
|
|
45
|
+
}
|
|
46
|
+
throw new Error("entangld needs crypto.randomUUID or crypto.getRandomValues");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = make_uuid();
|
|
50
|
+
module.exports.make_uuid = make_uuid;
|
|
51
|
+
module.exports.format_v4 = format_v4;
|
package/package.json
CHANGED
package/test/uuid.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const assert = require("assert");
|
|
2
|
+
const uuidv4 = require("../lib/uuid.js");
|
|
3
|
+
const { make_uuid } = uuidv4;
|
|
4
|
+
|
|
5
|
+
const V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
6
|
+
const node_crypto = require("crypto");
|
|
7
|
+
|
|
8
|
+
describe("uuid", () => {
|
|
9
|
+
it("makes distinct v4 uuids", () => {
|
|
10
|
+
const ids = new Set(Array.from({ length: 1000 }, () => uuidv4()));
|
|
11
|
+
assert.strictEqual(ids.size, 1000);
|
|
12
|
+
for ( const id of ids ) assert.match(id, V4);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("uses globalThis.crypto.randomUUID when there is one (browsers, Node 19+)", () => {
|
|
16
|
+
const uuid = make_uuid({ randomUUID: () => "from-web-crypto" }, () => assert.fail("Node's crypto was loaded"));
|
|
17
|
+
assert.strictEqual(uuid(), "from-web-crypto");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("falls back to Node's crypto module (Node 18)", () => {
|
|
21
|
+
const uuid = make_uuid(null, () => ({ randomUUID: () => "from-node-crypto" }));
|
|
22
|
+
assert.strictEqual(uuid(), "from-node-crypto");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("builds one from getRandomValues on a page that isn't secure", () => {
|
|
26
|
+
// In a browser bundle, the "browser" field turns require("crypto") into {}
|
|
27
|
+
const page = { getRandomValues: (a) => node_crypto.getRandomValues(a) };
|
|
28
|
+
const uuid = make_uuid(page, () => ({}));
|
|
29
|
+
const ids = new Set(Array.from({ length: 1000 }, () => uuid()));
|
|
30
|
+
assert.strictEqual(ids.size, 1000);
|
|
31
|
+
for ( const id of ids ) assert.match(id, V4);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("says what's missing when there's no crypto at all", () => {
|
|
35
|
+
assert.throws(() => make_uuid(null, () => { throw new Error("no module"); }), /crypto.randomUUID or crypto.getRandomValues/);
|
|
36
|
+
});
|
|
37
|
+
});
|