chore: switch to Biome for parsing and linting (#932)

This commit is contained in:
Robert Kieffer
2026-04-05 04:45:29 -10:00
committed by GitHub
parent e485457c14
commit 7d21f67708
43 changed files with 1131 additions and 679 deletions
-8
View File
@@ -1,8 +0,0 @@
dist/
node_modules/
README.md
CHANGELOG.md
*.sh
.gitignore
.prettierignore
.husky
+1 -5
View File
@@ -1,7 +1,3 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next",
"esbenp.prettier-vscode"
]
"recommendations": ["biomejs.biome", "ms-vscode.vscode-typescript-next"]
}
+20
View File
@@ -0,0 +1,20 @@
{
"biome.lsp.bin": "./node_modules/.bin/biome",
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
+48 -48
View File
@@ -32,9 +32,9 @@ npm install uuid
**2. Create a UUID**
```javascript
import { v4 as uuidv4 } from 'uuid';
import { v4 as uuidv4 } from "uuid";
uuidv4(); // ⇨ '23c37ede-1c09-422a-8da8-42ad65cc33f9'
uuidv4(); // ⇨ '59c892bd-28b3-430e-a180-b02548346331'
```
For timestamp UUIDs, namespace UUIDs, and other options read on ...
@@ -42,7 +42,7 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ...
## API Summary
| | | |
| --- | --- | --- |
| -------------------------------------------------- | ----------------------------------------------- | ----------------- |
| [`uuid.NIL`](#uuidnil) | The nil UUID string (all zeros) | New in `[email protected]` |
| [`uuid.MAX`](#uuidmax) | The max UUID string (all ones) | New in `[email protected]` |
| [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `[email protected]` |
@@ -68,7 +68,7 @@ The nil UUID string (all zeros).
Example:
```javascript
import { NIL as NIL_UUID } from 'uuid';
import { NIL as NIL_UUID } from "uuid";
NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000'
```
@@ -80,7 +80,7 @@ The max UUID string (all ones).
Example:
```javascript
import { MAX as MAX_UUID } from 'uuid';
import { MAX as MAX_UUID } from "uuid";
MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff'
```
@@ -102,10 +102,10 @@ Convert UUID string to array of bytes
Example:
```javascript
import { parse as uuidParse } from 'uuid';
import { parse as uuidParse } from "uuid";
// Parse a UUID
uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨
uuidParse("6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b"); // ⇨
// Uint8Array(16) [
// 110, 192, 189, 127, 17,
// 192, 67, 218, 151, 94,
@@ -132,7 +132,7 @@ Convert array of bytes to UUID string
Example:
```javascript
import { stringify as uuidStringify } from 'uuid';
import { stringify as uuidStringify } from "uuid";
const uuidBytes = Uint8Array.of(
0x6e,
@@ -150,7 +150,7 @@ const uuidBytes = Uint8Array.of(
0xd9,
0xeb,
0xae,
0x0b
0x0b,
);
uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'
@@ -161,7 +161,7 @@ uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'
Create an RFC version 1 (timestamp) UUID
| | |
| --- | --- |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: |
| [`options.node = (random)` ] | RFC "node" field as an `Array[6]` of byte values (per 4.1.6) |
| [`options.clockseq = (random)`] | RFC "clock sequence" as a `Number` between 0 - 0x3fff |
@@ -177,20 +177,20 @@ Create an RFC version 1 (timestamp) UUID
Example:
```javascript
import { v1 as uuidv1 } from 'uuid';
import { v1 as uuidv1 } from "uuid";
uuidv1(); // ⇨ 'a2bfad10-b358-11f0-8d45-6389dd784317'
uuidv1(); // ⇨ '8c5dce80-309e-11f1-a247-d30aadaa5579'
```
Example using `options`:
```javascript
import { v1 as uuidv1 } from 'uuid';
import { v1 as uuidv1 } from "uuid";
const options = {
node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab),
clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(),
msecs: new Date("2011-11-01").getTime(),
nsecs: 5678,
};
uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
@@ -201,9 +201,9 @@ uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
Convert a UUID from version 1 to version 6
```javascript
import { v1ToV6 } from 'uuid';
import { v1ToV6 } from "uuid";
v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'
v1ToV6("92f62d9e-22c4-11ef-97e9-325096b39f47"); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'
```
### uuid.v3(name, namespace[, buffer[, offset]])
@@ -221,7 +221,7 @@ API is identical to `v5()`, but uses "v3" instead.
Create an RFC version 4 (random) UUID
| | |
| --- | --- |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: |
| [`options.random`] | `Array` of 16 random bytes (0-255) |
| [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `Array` of 16 random bytes (0-255) |
@@ -232,15 +232,15 @@ Create an RFC version 4 (random) UUID
Example:
```javascript
import { v4 as uuidv4 } from 'uuid';
import { v4 as uuidv4 } from "uuid";
uuidv4(); // ⇨ '177fac08-7fee-4a08-abda-72eb3ce87fba'
uuidv4(); // ⇨ '6aa50eb9-7f3b-4931-99c3-96153026c3a1'
```
Example using predefined `random` values:
```javascript
import { v4 as uuidv4 } from 'uuid';
import { v4 as uuidv4 } from "uuid";
const v4options = {
random: Uint8Array.of(
@@ -259,7 +259,7 @@ const v4options = {
0x67,
0x1c,
0x58,
0x36
0x36,
),
};
uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
@@ -270,7 +270,7 @@ uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
Create an RFC version 5 (namespace w/ SHA-1) UUID
| | |
| --- | --- |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `String \| Array` |
| `namespace` | `String \| Array[16]` Namespace UUID |
| [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` |
@@ -284,21 +284,21 @@ Create an RFC version 5 (namespace w/ SHA-1) UUID
Example with custom namespace:
```javascript
import { v5 as uuidv5 } from 'uuid';
import { v5 as uuidv5 } from "uuid";
// Define a custom namespace. Readers, create your own using something like
// https://www.uuidgenerator.net/
const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
const MY_NAMESPACE = "1b671a64-40d5-491e-99b0-da01ff1f3341";
uuidv5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'
uuidv5("Hello, World!", MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'
```
Example with RFC `URL` namespace:
```javascript
import { v5 as uuidv5 } from 'uuid';
import { v5 as uuidv5 } from "uuid";
uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'
uuidv5("https://www.w3.org/", uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'
```
### uuid.v6([options[, buffer[, offset]]])
@@ -308,20 +308,20 @@ Create an RFC version 6 (timestamp, reordered) UUID
This method takes the same arguments as uuid.v1().
```javascript
import { v6 as uuidv6 } from 'uuid';
import { v6 as uuidv6 } from "uuid";
uuidv6(); // ⇨ '1f0b358a-2c04-6950-8ac9-a8f01d2998d6'
uuidv6(); // ⇨ '1f1309e8-c5e6-6ac0-8f36-0cb5e9b3126a'
```
Example using `options`:
```javascript
import { v6 as uuidv6 } from 'uuid';
import { v6 as uuidv6 } from "uuid";
const options = {
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(),
msecs: new Date("2011-11-01").getTime(),
nsecs: 5678,
};
uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
@@ -332,9 +332,9 @@ uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
Convert a UUID from version 6 to version 1
```javascript
import { v6ToV1 } from 'uuid';
import { v6ToV1 } from "uuid";
v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'
v6ToV1("1ef22c49-2f62-6d9e-97e9-325096b39f47"); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'
```
### uuid.v7([options[, buffer[, offset]]])
@@ -342,7 +342,7 @@ v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-
Create an RFC version 7 (random) UUID
| | |
| --- | --- |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: |
| [`options.msecs = (current time)`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) |
| [`options.random = (random)`] | `Array` of 16 random bytes (0-255) used to generate other fields, above |
@@ -355,9 +355,9 @@ Create an RFC version 7 (random) UUID
Example:
```javascript
import { v7 as uuidv7 } from 'uuid';
import { v7 as uuidv7 } from "uuid";
uuidv7(); // ⇨ '019a26ab-9a66-71a9-a89e-63c35fce4a5a'
uuidv7(); // ⇨ '019d5ba8-fb6d-76e6-b431-ed99f3c6e608'
```
### ~~uuid.v8()~~
@@ -380,24 +380,24 @@ Test a string to see if it is a valid UUID
Example:
```javascript
import { validate as uuidValidate } from 'uuid';
import { validate as uuidValidate } from "uuid";
uuidValidate('not a UUID'); // ⇨ false
uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true
uuidValidate("not a UUID"); // ⇨ false
uuidValidate("6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b"); // ⇨ true
```
Using `validate` and `version` together it is possible to do per-version validation, e.g. validate for only v4 UUIds.
```javascript
import { version as uuidVersion } from 'uuid';
import { validate as uuidValidate } from 'uuid';
import { version as uuidVersion } from "uuid";
import { validate as uuidValidate } from "uuid";
function uuidValidateV4(uuid) {
return uuidValidate(uuid) && uuidVersion(uuid) === 4;
}
const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210';
const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836';
const v1Uuid = "d9428888-122b-11e1-b85c-61cd3cbb3210";
const v4Uuid = "109156be-c4fb-41ea-b1b4-efe1671c5836";
uuidValidateV4(v4Uuid); // ⇨ true
uuidValidateV4(v1Uuid); // ⇨ false
@@ -416,10 +416,10 @@ Detect RFC version of a UUID
Example:
```javascript
import { version as uuidVersion } from 'uuid';
import { version as uuidVersion } from "uuid";
uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // ⇨ 1
uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4
uuidVersion("45637ec4-c85f-11ea-87d0-0242ac130003"); // ⇨ 1
uuidVersion("6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b"); // ⇨ 4
```
<!-- prettier-ignore -->
@@ -482,8 +482,8 @@ This error occurs in environments where the standard [`crypto.getRandomValues()`
1. Import it _before_ `uuid`. Since `uuid` might also appear as a transitive dependency of some other imports it's safest to just import `react-native-get-random-values` as the very first thing in your entry point:
```javascript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import "react-native-get-random-values";
import { v4 as uuidv4 } from "uuid";
```
---
+31
View File
@@ -0,0 +1,31 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
"formatter": {
"indentStyle": "space",
"indentWidth": 2
},
"files": {
"includes": [
"**",
"!**/dist",
"!**/dist-node",
// We have to ignore this file because node 18 requires the "assert { type:
// 'json' }" syntax which is not supported by Biome's parser yet.
"!examples/node-esmodules/package.mjs"
]
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all"
}
},
"linter": {
"rules": {
"a11y": { "useHtmlLang": "off" },
"complexity": { "useArrowFunction": "off" },
"suspicious": { "noAssignInExpressions": "off" }
}
}
}
+48 -12
View File
@@ -4,17 +4,53 @@
"trackBranches": ["main"]
},
"files": [
{ "path": "./examples/browser-rollup/dist/v1-size.js", "maxSize": "1.0 kB" },
{ "path": "./examples/browser-rollup/dist/v3-size.js", "maxSize": "2.1 kB" },
{ "path": "./examples/browser-rollup/dist/v4-size.js", "maxSize": "0.7 kB" },
{ "path": "./examples/browser-rollup/dist/v5-size.js", "maxSize": "1.5 kB" },
{ "path": "./examples/browser-rollup/dist/v6-size.js", "maxSize": "1.6 kB" },
{ "path": "./examples/browser-rollup/dist/v7-size.js", "maxSize": "0.8 kB" },
{ "path": "./examples/browser-webpack/dist/v1-size.js", "maxSize": "1.0 kB" },
{ "path": "./examples/browser-webpack/dist/v3-size.js", "maxSize": "2.1 kB" },
{ "path": "./examples/browser-webpack/dist/v4-size.js", "maxSize": "0.7 kB" },
{ "path": "./examples/browser-webpack/dist/v5-size.js", "maxSize": "1.5 kB" },
{ "path": "./examples/browser-webpack/dist/v6-size.js", "maxSize": "1.6 kB" },
{ "path": "./examples/browser-webpack/dist/v7-size.js", "maxSize": "0.8 kB" }
{
"path": "./examples/browser-rollup/dist/v1-size.js",
"maxSize": "1.0 kB"
},
{
"path": "./examples/browser-rollup/dist/v3-size.js",
"maxSize": "2.1 kB"
},
{
"path": "./examples/browser-rollup/dist/v4-size.js",
"maxSize": "0.7 kB"
},
{
"path": "./examples/browser-rollup/dist/v5-size.js",
"maxSize": "1.5 kB"
},
{
"path": "./examples/browser-rollup/dist/v6-size.js",
"maxSize": "1.6 kB"
},
{
"path": "./examples/browser-rollup/dist/v7-size.js",
"maxSize": "0.8 kB"
},
{
"path": "./examples/browser-webpack/dist/v1-size.js",
"maxSize": "1.0 kB"
},
{
"path": "./examples/browser-webpack/dist/v3-size.js",
"maxSize": "2.1 kB"
},
{
"path": "./examples/browser-webpack/dist/v4-size.js",
"maxSize": "0.7 kB"
},
{
"path": "./examples/browser-webpack/dist/v5-size.js",
"maxSize": "1.5 kB"
},
{
"path": "./examples/browser-webpack/dist/v6-size.js",
"maxSize": "1.6 kB"
},
{
"path": "./examples/browser-webpack/dist/v7-size.js",
"maxSize": "0.8 kB"
}
]
}
-38
View File
@@ -1,38 +0,0 @@
import js from '@eslint/js';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';
import neostandard from 'neostandard';
import tseslint from 'typescript-eslint';
const neostandardConfig = neostandard({ semi: true, noStyle: true });
export default [
js.configs.recommended,
...tseslint.configs.recommended,
...neostandardConfig,
eslintPluginPrettierRecommended,
{
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...globals.browser,
...globals.commonjs,
...globals.jest,
...globals.node,
},
},
},
{
rules: {
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-require-imports': 'off',
'no-redeclare': 'off',
'no-var': ['error'],
curly: ['error', 'all'],
},
},
{
ignores: ['eslint.config.cjs', '**/dist/', 'node_modules/'],
},
];
+4 -6
View File
@@ -9,8 +9,8 @@ export default function benchmark(uuid, Benchmark) {
});
const BYTES = [
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08,
0x4b,
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7,
0x26, 0x3a, 0x08, 0x4b,
];
suite
@@ -76,15 +76,13 @@ export default function benchmark(uuid, Benchmark) {
uuid.v7(null, array, 0);
})
.add('uuid.v7() with defined time', function () {
uuid.v7({
msecs: 1645557742000,
});
uuid.v7({ msecs: 1645557742000 });
})
.on('cycle', function (event) {
console.log(event.target.toString());
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'));
console.log(`Fastest is ${this.filter('fastest').map('name')}`);
console.log('---\n');
})
.run();
+1 -1
View File
@@ -1,5 +1,5 @@
import * as uuid from 'uuid';
import Benchmark from 'benchmark';
import * as uuid from 'uuid';
import benchmark from './benchmark.js';
+1 -3
View File
@@ -19,8 +19,6 @@ module.exports = {
// Webpack now produces builds that are incompatible with IE11:
// https://webpack.js.org/migrate/5/#turn-off-es2015-syntax-in-runtime-code-if-necessary
target: ['web', 'es5'],
output: {
filename: '[name].js',
},
output: { filename: '[name].js' },
mode: 'production',
};
+4 -1
View File
@@ -19,7 +19,10 @@ import {
// Import attribute syntax is still awaiting finalization. In the meantime we
// use dynamic import to allows to specifyg both "assert" and "with" clauses.
// See https://github.com/tc39/proposal-import-attributes
const pkg = await import('uuid/package.json', { assert: { type: 'json' }, with: { type: 'json' } });
const pkg = await import('uuid/package.json', {
assert: { type: 'json' },
with: { type: 'json' },
});
console.log('uuidv1()', uuidv1());
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { v1 } from 'uuid';
v1(undefined, new Uint8Array(16)) satisfies Uint8Array;
+3 -3
View File
@@ -6,8 +6,8 @@ export default function test(callback) {
'body {font-family: monospace;}',
'dt, dd {display: inline-block; margin: 0;}',
'dt {min-width: 15em;}',
].join('\n')
)
].join('\n'),
),
);
document.body.appendChild(style);
@@ -24,7 +24,7 @@ export default function test(callback) {
} else {
el = document.createElement('div');
el.className = 'test_result';
el.innerHTML = '<dt>' + title + '</dt>: <dd>' + result + '</dd>';
el.innerHTML = `<dt>${title}</dt>: <dd>${result}</dd>`;
}
document.body.appendChild(el);
+512 -326
View File
File diff suppressed because it is too large Load Diff
+9 -18
View File
@@ -37,27 +37,21 @@
"!**/test"
],
"devDependencies": {
"@babel/eslint-parser": "7.27.1",
"@biomejs/biome": "2.4.10",
"@commitlint/cli": "19.8.0",
"@commitlint/config-conventional": "19.8.0",
"@eslint/js": "9.26.0",
"bundlewatch": "0.4.1",
"commander": "13.1.0",
"eslint": "9.26.0",
"eslint-config-prettier": "10.1.2",
"eslint-plugin-prettier": "5.4.0",
"globals": "16.0.0",
"husky": "9.1.7",
"jest": "29.7.0",
"lint-staged": "15.5.2",
"neostandard": "0.12.1",
"npm-run-all2": "7.0.2",
"prettier": "3.5.3",
"release-please": "17.0.0",
"runmd": "1.4.1",
"standard-version": "9.5.0",
"typescript": "5.2.2",
"typescript-eslint": "8.32.0"
"typescript": "5.2.2"
},
"optionalDevDependencies": {
"@wdio/browserstack-service": "9.2.1",
@@ -73,14 +67,14 @@
"bundlewatch": "npm run pretest:browser && bundlewatch --config bundlewatch.config.json",
"docs:diff": "npm run docs && git diff --quiet -I \"[0-9a-f-]{36}\" README.md",
"docs": "npm run build && npx runmd --output=README.md README_js.md",
"eslint:check": "eslint src/ test/ examples/ *.[jt]s",
"eslint:fix": "eslint --fix src/ test/ examples/ *.[jt]s",
"biome:check": "biome check .",
"biome:fix": "biome check --write .",
"examples:browser:rollup:build": "cd examples/browser-rollup && npm run build",
"examples:browser:webpack:build": "cd examples/browser-webpack && npm run build",
"examples:node:esmodules:test": "cd examples/node-esmodules && npm test",
"examples:node:jest:test": "cd examples/node-jest && npm test",
"examples:node:typescript:test": "cd examples/typescript && npm test",
"lint": "npm run eslint:check && npm run prettier:check",
"lint": "npm run biome:check",
"md": "runmd --watch --output=README.md README_js.md",
"prepack": "npm run build -- --no-pack",
"prepare": "husky",
@@ -89,8 +83,8 @@
"pretest:browser": "./scripts/iodd && npm run build && npm-run-all --parallel examples:browser:**",
"pretest:node": "npm run build",
"pretest": "npm run build",
"prettier:check": "prettier --check .",
"prettier:fix": "prettier --write .",
"format": "biome format --write .",
"format:check": "biome format --check .",
"release": "standard-version --no-verify",
"test:benchmark": "cd examples/benchmark && npm test",
"test:browser": "wdio run ./wdio.conf.js",
@@ -104,15 +98,12 @@
},
"lint-staged": {
"*": [
"prettier --no-error-on-unmatched-pattern --write"
],
"*.{js,jsx}": [
"eslint --no-error-on-unmatched-pattern --fix"
"biome check --write --no-errors-on-unmatched"
]
},
"standard-version": {
"scripts": {
"postchangelog": "prettier --write CHANGELOG.md"
"postchangelog": "biome format --write CHANGELOG.md"
}
},
"packageManager": "[email protected]"
-7
View File
@@ -1,7 +0,0 @@
export default {
arrowParens: 'always',
printWidth: 100,
proseWrap: 'never',
singleQuote: true,
trailingComma: 'es5',
};
+1 -1
View File
@@ -1,8 +1,8 @@
export type * from './types.js';
export { default as MAX } from './max.js';
export { default as NIL } from './nil.js';
export { default as parse } from './parse.js';
export { default as stringify } from './stringify.js';
export type * from './types.js';
export { default as v1 } from './v1.js';
export { default as v1ToV6 } from './v1ToV6.js';
export { default as v3 } from './v3.js';
+45 -6
View File
@@ -55,7 +55,7 @@ function wordsToMd5(x: Uint32Array, len: number) {
/* append padding */
const xpad = new Uint32Array(getOutputLength(len)).fill(0);
xpad.set(x);
xpad[len >> 5] |= 0x80 << len % 32;
xpad[len >> 5] |= 0x80 << (len % 32);
xpad[xpad.length - 1] = len;
x = xpad;
@@ -182,23 +182,62 @@ function bitRotateLeft(num: number, cnt: number) {
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5cmn(q: number, a: number, b: number, x: number, s: number, t: number) {
function md5cmn(
q: number,
a: number,
b: number,
x: number,
s: number,
t: number,
) {
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
}
function md5ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {
function md5ff(
a: number,
b: number,
c: number,
d: number,
x: number,
s: number,
t: number,
) {
return md5cmn((b & c) | (~b & d), a, b, x, s, t);
}
function md5gg(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {
function md5gg(
a: number,
b: number,
c: number,
d: number,
x: number,
s: number,
t: number,
) {
return md5cmn((b & d) | (c & ~d), a, b, x, s, t);
}
function md5hh(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {
function md5hh(
a: number,
b: number,
c: number,
d: number,
x: number,
s: number,
t: number,
) {
return md5cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5ii(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {
function md5ii(
a: number,
b: number,
c: number,
d: number,
x: number,
s: number,
t: number,
) {
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
}
+3 -1
View File
@@ -1,4 +1,6 @@
const randomUUID =
typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
typeof crypto !== 'undefined' &&
crypto.randomUUID &&
crypto.randomUUID.bind(crypto);
export default { randomUUID };
+2 -2
View File
@@ -5,7 +5,7 @@ function parse(uuid: string) {
throw TypeError('Invalid UUID');
}
let v;
let v: number;
return Uint8Array.of(
(v = parseInt(uuid.slice(0, 8), 16)) >>> 24,
(v >>> 16) & 0xff,
@@ -31,7 +31,7 @@ function parse(uuid: string) {
(v >>> 24) & 0xff,
(v >>> 16) & 0xff,
(v >>> 8) & 0xff,
v & 0xff
v & 0xff,
);
}
+1 -1
View File
@@ -11,7 +11,7 @@ export default function rng() {
if (!getRandomValues) {
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
throw new Error(
'crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'
'crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported',
);
}
+2 -2
View File
@@ -44,7 +44,7 @@ function sha1(bytes: Uint8Array): Uint8Array {
M[i] = arr;
}
M[N - 1][14] = ((bytes.length - 1) * 8) / Math.pow(2, 32);
M[N - 1][14] = ((bytes.length - 1) * 8) / 2 ** 32;
M[N - 1][14] = Math.floor(M[N - 1][14]);
M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff;
@@ -103,7 +103,7 @@ function sha1(bytes: Uint8Array): Uint8Array {
H[4] >> 24,
H[4] >> 16,
H[4] >> 8,
H[4]
H[4],
);
}
+5 -5
View File
@@ -32,9 +32,9 @@ describe('parse', () => {
assert.deepStrictEqual(
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'),
Uint8Array.from([
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08,
0x4b,
])
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7,
0x26, 0x3a, 0x08, 0x4b,
]),
);
});
@@ -49,14 +49,14 @@ describe('parse', () => {
// Verify upper/lower case neutrality
assert.deepStrictEqual(
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'),
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase())
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()),
);
});
test('Null UUID case', () => {
assert.deepStrictEqual(
parse('00000000-0000-0000-0000-000000000000'),
Uint8Array.from(new Array(16).fill(0))
Uint8Array.from(new Array(16).fill(0)),
);
});
+9 -3
View File
@@ -18,18 +18,24 @@ const BYTES = Uint8Array.of(
0x26,
0x3a,
0x08,
0x4b
0x4b,
);
describe('stringify', () => {
test('Stringify Array (unsafe)', () => {
assert.equal(unsafeStringify(BYTES), '0f5abcd1-c194-47f3-905b-2df7263a084b');
assert.equal(
unsafeStringify(BYTES),
'0f5abcd1-c194-47f3-905b-2df7263a084b',
);
});
test('Stringify w/ offset (unsafe)', () => {
const bytes = new Uint8Array(19).fill(0);
bytes.set(BYTES, 3);
assert.equal(unsafeStringify(bytes, 3), '0f5abcd1-c194-47f3-905b-2df7263a084b');
assert.equal(
unsafeStringify(bytes, 3),
'0f5abcd1-c194-47f3-905b-2df7263a084b',
);
});
test('Stringify Array (safe)', () => {
+140 -28
View File
@@ -8,22 +8,86 @@ export const TESTS = [
{ value: MAX, expectedValidate: true, expectedVersion: 15 },
// each version, with either all 0's or all 1's in settable bits
{ value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 },
{ value: 'ffffffff-ffff-1fff-8fff-ffffffffffff', expectedValidate: true, expectedVersion: 1 },
{ value: '00000000-0000-2000-8000-000000000000', expectedValidate: true, expectedVersion: 2 },
{ value: 'ffffffff-ffff-2fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 2 },
{ value: '00000000-0000-3000-8000-000000000000', expectedValidate: true, expectedVersion: 3 },
{ value: 'ffffffff-ffff-3fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 3 },
{ value: '00000000-0000-4000-8000-000000000000', expectedValidate: true, expectedVersion: 4 },
{ value: 'ffffffff-ffff-4fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 4 },
{ value: '00000000-0000-5000-8000-000000000000', expectedValidate: true, expectedVersion: 5 },
{ value: 'ffffffff-ffff-5fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 5 },
{ value: '00000000-0000-6000-8000-000000000000', expectedValidate: true, expectedVersion: 6 },
{ value: 'ffffffff-ffff-6fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 6 },
{ value: '00000000-0000-7000-8000-000000000000', expectedValidate: true, expectedVersion: 7 },
{ value: 'ffffffff-ffff-7fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 7 },
{ value: '00000000-0000-8000-8000-000000000000', expectedValidate: true, expectedVersion: 8 },
{ value: 'ffffffff-ffff-8fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 8 },
{
value: '00000000-0000-1000-8000-000000000000',
expectedValidate: true,
expectedVersion: 1,
},
{
value: 'ffffffff-ffff-1fff-8fff-ffffffffffff',
expectedValidate: true,
expectedVersion: 1,
},
{
value: '00000000-0000-2000-8000-000000000000',
expectedValidate: true,
expectedVersion: 2,
},
{
value: 'ffffffff-ffff-2fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 2,
},
{
value: '00000000-0000-3000-8000-000000000000',
expectedValidate: true,
expectedVersion: 3,
},
{
value: 'ffffffff-ffff-3fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 3,
},
{
value: '00000000-0000-4000-8000-000000000000',
expectedValidate: true,
expectedVersion: 4,
},
{
value: 'ffffffff-ffff-4fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 4,
},
{
value: '00000000-0000-5000-8000-000000000000',
expectedValidate: true,
expectedVersion: 5,
},
{
value: 'ffffffff-ffff-5fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 5,
},
{
value: '00000000-0000-6000-8000-000000000000',
expectedValidate: true,
expectedVersion: 6,
},
{
value: 'ffffffff-ffff-6fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 6,
},
{
value: '00000000-0000-7000-8000-000000000000',
expectedValidate: true,
expectedVersion: 7,
},
{
value: 'ffffffff-ffff-7fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 7,
},
{
value: '00000000-0000-8000-8000-000000000000',
expectedValidate: true,
expectedVersion: 8,
},
{
value: 'ffffffff-ffff-8fff-bfff-ffffffffffff',
expectedValidate: true,
expectedVersion: 8,
},
{ value: '00000000-0000-9000-8000-000000000000', expectedValidate: false },
{ value: 'ffffffff-ffff-9fff-bfff-ffffffffffff', expectedValidate: false },
{ value: '00000000-0000-a000-8000-000000000000', expectedValidate: false },
@@ -38,14 +102,46 @@ export const TESTS = [
{ value: 'ffffffff-ffff-efff-bfff-ffffffffffff', expectedValidate: false },
// selection of normal, valid UUIDs
{ value: 'd9428888-122b-11e1-b85c-61cd3cbb3210', expectedValidate: true, expectedVersion: 1 },
{ value: '000003e8-2363-21ef-b200-325096b39f47', expectedValidate: true, expectedVersion: 2 },
{ value: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec', expectedValidate: true, expectedVersion: 3 },
{ value: '109156be-c4fb-41ea-b1b4-efe1671c5836', expectedValidate: true, expectedVersion: 4 },
{ value: '90123e1c-7512-523e-bb28-76fab9f2f73d', expectedValidate: true, expectedVersion: 5 },
{ value: '1ef21d2f-1207-6660-8c4f-419efbd44d48', expectedValidate: true, expectedVersion: 6 },
{ value: '017f22e2-79b0-7cc3-98c4-dc0c0c07398f', expectedValidate: true, expectedVersion: 7 },
{ value: '0d8f23a0-697f-83ae-802e-48f3756dd581', expectedValidate: true, expectedVersion: 8 },
{
value: 'd9428888-122b-11e1-b85c-61cd3cbb3210',
expectedValidate: true,
expectedVersion: 1,
},
{
value: '000003e8-2363-21ef-b200-325096b39f47',
expectedValidate: true,
expectedVersion: 2,
},
{
value: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec',
expectedValidate: true,
expectedVersion: 3,
},
{
value: '109156be-c4fb-41ea-b1b4-efe1671c5836',
expectedValidate: true,
expectedVersion: 4,
},
{
value: '90123e1c-7512-523e-bb28-76fab9f2f73d',
expectedValidate: true,
expectedVersion: 5,
},
{
value: '1ef21d2f-1207-6660-8c4f-419efbd44d48',
expectedValidate: true,
expectedVersion: 6,
},
{
value: '017f22e2-79b0-7cc3-98c4-dc0c0c07398f',
expectedValidate: true,
expectedVersion: 7,
},
{
value: '0d8f23a0-697f-83ae-802e-48f3756dd581',
expectedValidate: true,
expectedVersion: 8,
},
// all variant octet values
{ value: '00000000-0000-1000-0000-000000000000', expectedValidate: false },
@@ -56,10 +152,26 @@ export const TESTS = [
{ value: '00000000-0000-1000-5000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-6000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-7000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 },
{ value: '00000000-0000-1000-9000-000000000000', expectedValidate: true, expectedVersion: 1 },
{ value: '00000000-0000-1000-a000-000000000000', expectedValidate: true, expectedVersion: 1 },
{ value: '00000000-0000-1000-b000-000000000000', expectedValidate: true, expectedVersion: 1 },
{
value: '00000000-0000-1000-8000-000000000000',
expectedValidate: true,
expectedVersion: 1,
},
{
value: '00000000-0000-1000-9000-000000000000',
expectedValidate: true,
expectedVersion: 1,
},
{
value: '00000000-0000-1000-a000-000000000000',
expectedValidate: true,
expectedVersion: 1,
},
{
value: '00000000-0000-1000-b000-000000000000',
expectedValidate: true,
expectedVersion: 1,
},
{ value: '00000000-0000-1000-c000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-d000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-e000-000000000000', expectedValidate: false },
+21 -5
View File
@@ -36,7 +36,7 @@ const RFC_RANDOM = Uint8Array.of(
RFC_OPTIONS.clockseq & 0xff,
// node
...RFC_OPTIONS.node
...RFC_OPTIONS.node,
);
// Compare v1 timestamp fields chronologically
@@ -69,13 +69,25 @@ describe('v1', () => {
});
test('v1(options)', () => {
assert.equal(v1({ msecs: RFC_OPTIONS.msecs, random: RFC_RANDOM }), RFC_V1, 'minimal options');
assert.equal(
v1({ msecs: RFC_OPTIONS.msecs, random: RFC_RANDOM }),
RFC_V1,
'minimal options',
);
assert.equal(v1(RFC_OPTIONS), RFC_V1, 'full options');
});
test('v1(options) equality', () => {
assert.notEqual(v1({ msecs: TIME }), v1({ msecs: TIME }), 'UUIDs with minimal options differ');
assert.equal(v1(RFC_OPTIONS), v1(RFC_OPTIONS), 'UUIDs with full options are identical');
assert.notEqual(
v1({ msecs: TIME }),
v1({ msecs: TIME }),
'UUIDs with minimal options differ',
);
assert.equal(
v1(RFC_OPTIONS),
v1(RFC_OPTIONS),
'UUIDs with full options are identical',
);
});
test('fills one UUID into a buffer as expected', () => {
@@ -165,7 +177,11 @@ describe('v1', () => {
},
];
for (const { title, state, now, expected } of tests) {
assert.deepStrictEqual(updateV1State(state, now, RFC_RANDOM), expected, `Failed: ${title}`);
assert.deepStrictEqual(
updateV1State(state, now, RFC_RANDOM),
expected,
`Failed: ${title}`,
);
}
});
+23 -17
View File
@@ -3,8 +3,8 @@ import { describe, test } from 'node:test';
import md5 from '../md5.js';
import sha1 from '../sha1.js';
import v3 from '../v3.js';
import { stringToBytes } from '../v35.js';
import v5 from '../v5.js';
import { stringToBytes } from '../v35.js';
describe('v35', () => {
const HASH_SAMPLES = [
@@ -17,7 +17,7 @@ describe('v35', () => {
// Extended ascii chars
{
input: stringToBytes(
'\t\b\f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF'
'\t\b\f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF',
),
sha1: 'ca4a426a3d536f14cfd79011e79e10d64de950a0',
md5: 'e8098ec21950f841731d28749129d3ee',
@@ -26,7 +26,7 @@ describe('v35', () => {
// A sampling from the Unicode BMP
{
input: stringToBytes(
'\u00A5\u0104\u018F\u0256\u02B1o\u0315\u038E\u0409\u0500\u0531\u05E1\u05B6\u0920\u0903\u09A4\u0983\u0A20\u0A02\u0AA0\u0A83\u0B06\u0C05\u0C03\u1401\u16A0'
'\u00A5\u0104\u018F\u0256\u02B1o\u0315\u038E\u0409\u0500\u0531\u05E1\u05B6\u0920\u0903\u09A4\u0983\u0A20\u0A02\u0AA0\u0A83\u0B06\u0C05\u0C03\u1401\u16A0',
),
sha1: 'f2753ebc390e5f637e333c2a4179644a93ae9f65',
md5: '231b309e277b6be8bb3d6c688b7f098b',
@@ -55,33 +55,36 @@ describe('v35', () => {
test('v3', () => {
// Expect to get the same results as http://tools.adjet.org/uuid-v3
assert.strictEqual(v3('hello.example.com', v3.DNS), '9125a8dc-52ee-365b-a5aa-81b0b3681cf6');
assert.strictEqual(
v3('hello.example.com', v3.DNS),
'9125a8dc-52ee-365b-a5aa-81b0b3681cf6',
);
assert.strictEqual(
v3('http://example.com/hello', v3.URL),
'c6235813-3ba4-3801-ae84-e0a6ebb7d138'
'c6235813-3ba4-3801-ae84-e0a6ebb7d138',
);
assert.strictEqual(
v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'),
'a981a0c2-68b1-35dc-bcfc-296e52ab01ec'
'a981a0c2-68b1-35dc-bcfc-296e52ab01ec',
);
});
test('v3 namespace.toUpperCase', () => {
assert.strictEqual(
v3('hello.example.com', v3.DNS.toUpperCase()),
'9125a8dc-52ee-365b-a5aa-81b0b3681cf6'
'9125a8dc-52ee-365b-a5aa-81b0b3681cf6',
);
assert.strictEqual(
v3('http://example.com/hello', v3.URL.toUpperCase()),
'c6235813-3ba4-3801-ae84-e0a6ebb7d138'
'c6235813-3ba4-3801-ae84-e0a6ebb7d138',
);
assert.strictEqual(
v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()),
'a981a0c2-68b1-35dc-bcfc-296e52ab01ec'
'a981a0c2-68b1-35dc-bcfc-296e52ab01ec',
);
});
@@ -128,7 +131,7 @@ describe('v35', () => {
0xb3,
0x68,
0x1c,
0xf6
0xf6,
);
const result = v3('hello.example.com', v3.DNS, buf);
@@ -160,16 +163,19 @@ describe('v35', () => {
test('v5', () => {
// Expect to get the same results as http://tools.adjet.org/uuid-v5
assert.strictEqual(v5('hello.example.com', v5.DNS), 'fdda765f-fc57-5604-a269-52a7df8164ec');
assert.strictEqual(
v5('hello.example.com', v5.DNS),
'fdda765f-fc57-5604-a269-52a7df8164ec',
);
assert.strictEqual(
v5('http://example.com/hello', v5.URL),
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1'
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1',
);
assert.strictEqual(
v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'),
'90123e1c-7512-523e-bb28-76fab9f2f73d'
'90123e1c-7512-523e-bb28-76fab9f2f73d',
);
});
@@ -177,17 +183,17 @@ describe('v35', () => {
// Expect to get the same results as http://tools.adjet.org/uuid-v5
assert.strictEqual(
v5('hello.example.com', v5.DNS.toUpperCase()),
'fdda765f-fc57-5604-a269-52a7df8164ec'
'fdda765f-fc57-5604-a269-52a7df8164ec',
);
assert.strictEqual(
v5('http://example.com/hello', v5.URL.toUpperCase()),
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1'
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1',
);
assert.strictEqual(
v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()),
'90123e1c-7512-523e-bb28-76fab9f2f73d'
'90123e1c-7512-523e-bb28-76fab9f2f73d',
);
});
@@ -234,7 +240,7 @@ describe('v35', () => {
0xdf,
0x81,
0x64,
0xec
0xec,
);
const result = v5('hello.example.com', v5.DNS, buf);
+2 -2
View File
@@ -19,7 +19,7 @@ const randomBytesFixture = Uint8Array.of(
0x67,
0x1c,
0x58,
0x36
0x36,
);
const expectedBytes = Uint8Array.of(
@@ -38,7 +38,7 @@ const expectedBytes = Uint8Array.of(
103,
28,
88,
54
54,
);
describe('v4', () => {
+5 -3
View File
@@ -31,16 +31,18 @@ describe('v6', () => {
0x3c,
0xbb,
0x32,
0x10
0x10,
);
test('default behavior', () => {
// Verify explicit options produce expected id
const id = v6();
assert.ok(
/[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(id),
/[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(
id,
),
'id is valid v6 UUID'
'id is valid v6 UUID',
);
});
+17 -11
View File
@@ -2,7 +2,7 @@ import * as assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import parse from '../parse.js';
import stringify from '../stringify.js';
import { Version7Options } from '../types.js';
import type { Version7Options } from '../types.js';
import v7, { updateV7State } from '../v7.js';
// Fixture values for testing with the rfc v7 UUID example:
@@ -31,7 +31,7 @@ const RFC_RANDOM = Uint8Array.of(
0x0c,
0x07,
0x39,
0x8f
0x8f,
);
describe('v7', () => {
@@ -74,7 +74,7 @@ describe('v7', () => {
msecs: RFC_MSECS,
seq: RFC_SEQ,
},
buffer
buffer,
);
stringify(buffer);
@@ -92,7 +92,7 @@ describe('v7', () => {
seq: RFC_SEQ,
},
buffer,
0
0,
);
v7(
{
@@ -101,7 +101,7 @@ describe('v7', () => {
seq: RFC_SEQ,
},
buffer,
16
16,
);
const expected = new Uint8Array(32);
expected.set(RFC_V7_BYTES);
@@ -114,8 +114,8 @@ describe('v7', () => {
//
test('lexicographical sorting is preserved', () => {
let id;
let prior;
let id: string;
let prior: string | undefined;
let msecs = RFC_MSECS;
for (let i = 0; i < 20000; ++i) {
if (i % 1500 === 0) {
@@ -218,16 +218,22 @@ describe('v7', () => {
},
];
for (const { title, state, now, expected } of tests) {
assert.deepStrictEqual(updateV7State(state, now, RFC_RANDOM), expected, `Failed: ${title}`);
assert.deepStrictEqual(
updateV7State(state, now, RFC_RANDOM),
expected,
`Failed: ${title}`,
);
}
});
test('flipping bits changes the result', () => {
// convert uint8array to BigInt (BE)
const asBigInt = (buf: Uint8Array) => buf.reduce((acc, v) => (acc << 8n) | BigInt(v), 0n);
const asBigInt = (buf: Uint8Array) =>
buf.reduce((acc, v) => (acc << 8n) | BigInt(v), 0n);
// convert the given number of bits (LE) to number
const asNumber = (bits: number, data: bigint) => Number(BigInt.asUintN(bits, data));
const asNumber = (bits: number, data: bigint) =>
Number(BigInt.asUintN(bits, data));
// flip the nth bit (BE) in a BigInt
const flip = (data: bigint, n: number) => data ^ (1n << BigInt(127 - n));
@@ -262,7 +268,7 @@ describe('v7', () => {
assert.strictEqual(
asBigInt(v7(optionsFrom(flipped), buf)).toString(16),
flipped.toString(16),
`Unequal uuids at bit ${i}`
`Unequal uuids at bit ${i}`,
);
assert.notStrictEqual(stringify(buf), id);
}
+1 -1
View File
@@ -9,7 +9,7 @@ describe('validate()', () => {
assert.strictEqual(
validate(value),
expectedValidate,
`validate(${value}) should be ${expectedValidate}`
`validate(${value}) should be ${expectedValidate}`,
);
}
});
+1 -1
View File
@@ -18,7 +18,7 @@ function usage() {
console.log(' uuid v7');
console.log(' uuid --help');
console.log(
'\nNote: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC9562'
'\nNote: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC9562',
);
}
+14 -8
View File
@@ -1,6 +1,6 @@
import rng from './rng.js';
import { unsafeStringify } from './stringify.js';
import { UUIDTypes, Version1Options } from './types.js';
import type { UUIDTypes, Version1Options } from './types.js';
// **`v1()` - Generate time-based UUID**
//
@@ -24,16 +24,20 @@ type V1State = {
const _state: V1State = {};
function v1(options?: Version1Options, buf?: undefined, offset?: number): string;
function v1(
options?: Version1Options,
buf?: undefined,
offset?: number,
): string;
function v1<Buf extends Uint8Array = Uint8Array>(
options: Version1Options | undefined,
buf: Buf,
offset?: number
offset?: number,
): Buf;
function v1<TBuf extends Uint8Array = Uint8Array>(
options?: Version1Options,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
let bytes: Uint8Array;
@@ -55,7 +59,7 @@ function v1<TBuf extends Uint8Array = Uint8Array>(
options.clockseq,
options.node,
buf,
offset
offset,
);
} else {
// Without options: Make UUID from internal state
@@ -77,7 +81,7 @@ function v1<TBuf extends Uint8Array = Uint8Array>(
isV6 ? undefined : _state.clockseq,
isV6 ? undefined : _state.node,
buf,
offset
offset,
);
}
@@ -145,7 +149,7 @@ function v1Bytes(
clockseq?: number,
node?: Uint8Array,
buf?: Uint8Array,
offset = 0
offset = 0,
) {
if (rnds.length < 16) {
throw new Error('Random bytes length must be >= 16');
@@ -157,7 +161,9 @@ function v1Bytes(
offset = 0;
} else {
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
throw new RangeError(
`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`,
);
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { UUIDTypes } from './types.js';
import parse from './parse.js';
import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
/**
* Convert a v1 UUID to a v6 UUID
@@ -40,6 +40,6 @@ function _v1ToV6(v1Bytes: Uint8Array) {
v1Bytes[12],
v1Bytes[13],
v1Bytes[14],
v1Bytes[15]
v1Bytes[15],
);
}
+4 -4
View File
@@ -1,5 +1,5 @@
import { UUIDTypes } from './types.js';
import md5 from './md5.js';
import type { UUIDTypes } from './types.js';
import v35, { DNS, URL } from './v35.js';
export { DNS, URL } from './v35.js';
@@ -8,19 +8,19 @@ function v3(
value: string | Uint8Array,
namespace: UUIDTypes,
buf?: undefined,
offset?: number
offset?: number,
): string;
function v3<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array,
namespace: UUIDTypes,
buf: TBuf,
offset?: number
offset?: number,
): TBuf;
function v3<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array,
namespace: UUIDTypes,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
return v35(0x30, md5, value, namespace, buf, offset);
}
+9 -5
View File
@@ -1,6 +1,6 @@
import { UUIDTypes } from './types.js';
import parse from './parse.js';
import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
export function stringToBytes(str: string) {
// TODO: Use TextEncoder (see https://stackoverflow.com/a/48762658/109538)
@@ -26,17 +26,21 @@ export default function v35<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array,
namespace: UUIDTypes,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
const valueBytes: Uint8Array = typeof value === 'string' ? stringToBytes(value) : value;
const namespaceBytes: Uint8Array = typeof namespace === 'string' ? parse(namespace) : namespace;
const valueBytes: Uint8Array =
typeof value === 'string' ? stringToBytes(value) : value;
const namespaceBytes: Uint8Array =
typeof namespace === 'string' ? parse(namespace) : namespace;
if (typeof namespace === 'string') {
namespace = parse(namespace);
}
if (namespace?.length !== 16) {
throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
throw TypeError(
'Namespace must be array-like (16 iterable integer values, 0-255)',
);
}
// Compute hash of namespace and value, Per 4.3
+12 -6
View File
@@ -1,12 +1,12 @@
import native from './native.js';
import rng from './rng.js';
import { unsafeStringify } from './stringify.js';
import { UUIDTypes, Version4Options } from './types.js';
import type { UUIDTypes, Version4Options } from './types.js';
function _v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
options = options || {};
@@ -23,7 +23,9 @@ function _v4<TBuf extends Uint8Array = Uint8Array>(
if (buf) {
offset = offset || 0;
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
throw new RangeError(
`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`,
);
}
for (let i = 0; i < 16; ++i) {
@@ -36,16 +38,20 @@ function _v4<TBuf extends Uint8Array = Uint8Array>(
return unsafeStringify(rnds);
}
function v4(options?: Version4Options, buf?: undefined, offset?: number): string;
function v4(
options?: Version4Options,
buf?: undefined,
offset?: number,
): string;
function v4<TBuf extends Uint8Array = Uint8Array>(
options: Version4Options | undefined,
buf: TBuf,
offset?: number
offset?: number,
): TBuf;
function v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
if (native.randomUUID && !buf && !options) {
return native.randomUUID();
+4 -4
View File
@@ -1,5 +1,5 @@
import { UUIDTypes } from './types.js';
import sha1 from './sha1.js';
import type { UUIDTypes } from './types.js';
import v35, { DNS, URL } from './v35.js';
export { DNS, URL } from './v35.js';
@@ -8,19 +8,19 @@ function v5(
value: string | Uint8Array,
namespace: UUIDTypes,
buf?: undefined,
offset?: number
offset?: number,
): string;
function v5<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array,
namespace: UUIDTypes,
buf: TBuf,
offset?: number
offset?: number,
): TBuf;
function v5<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array,
namespace: UUIDTypes,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
return v35(0x50, sha1, value, namespace, buf, offset);
}
+8 -4
View File
@@ -1,18 +1,22 @@
import { UUIDTypes, Version6Options } from './types.js';
import { unsafeStringify } from './stringify.js';
import type { UUIDTypes, Version6Options } from './types.js';
import v1 from './v1.js';
import v1ToV6 from './v1ToV6.js';
function v6(options?: Version6Options, buf?: undefined, offset?: number): string;
function v6(
options?: Version6Options,
buf?: undefined,
offset?: number,
): string;
function v6<TBuf extends Uint8Array = Uint8Array>(
options: Version6Options | undefined,
buf: TBuf,
offset?: number
offset?: number,
): TBuf;
function v6<TBuf extends Uint8Array = Uint8Array>(
options?: Version6Options,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
options ??= {};
offset ??= 0;
+2 -2
View File
@@ -1,6 +1,6 @@
import { UUIDTypes } from './types.js';
import parse from './parse.js';
import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
/**
* Convert a v6 UUID to a v1 UUID
@@ -40,6 +40,6 @@ function _v6ToV1(v6Bytes: Uint8Array) {
v6Bytes[12],
v6Bytes[13],
v6Bytes[14],
v6Bytes[15]
v6Bytes[15],
);
}
+19 -7
View File
@@ -1,6 +1,6 @@
import rng from './rng.js';
import { unsafeStringify } from './stringify.js';
import { UUIDTypes, Version7Options } from './types.js';
import type { UUIDTypes, Version7Options } from './types.js';
type V7State = {
msecs?: number; // time, milliseconds
@@ -9,16 +9,20 @@ type V7State = {
const _state: V7State = {};
function v7(options?: Version7Options, buf?: undefined, offset?: number): string;
function v7(
options?: Version7Options,
buf?: undefined,
offset?: number,
): string;
function v7<TBuf extends Uint8Array = Uint8Array>(
options: Version7Options | undefined,
buf: TBuf,
offset?: number
offset?: number,
): TBuf;
function v7<TBuf extends Uint8Array = Uint8Array>(
options?: Version7Options,
buf?: TBuf,
offset?: number
offset?: number,
): UUIDTypes<TBuf> {
let bytes: Uint8Array;
@@ -29,7 +33,7 @@ function v7<TBuf extends Uint8Array = Uint8Array>(
options.msecs,
options.seq,
buf,
offset
offset,
);
} else {
// No options: Use internal state
@@ -69,7 +73,13 @@ export function updateV7State(state: V7State, now: number, rnds: Uint8Array) {
return state;
}
function v7Bytes(rnds: Uint8Array, msecs?: number, seq?: number, buf?: Uint8Array, offset = 0) {
function v7Bytes(
rnds: Uint8Array,
msecs?: number,
seq?: number,
buf?: Uint8Array,
offset = 0,
) {
if (rnds.length < 16) {
throw new Error('Random bytes length must be >= 16');
}
@@ -79,7 +89,9 @@ function v7Bytes(rnds: Uint8Array, msecs?: number, seq?: number, buf?: Uint8Arra
offset = 0;
} else {
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
throw new RangeError(
`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`,
);
}
}
+45 -20
View File
@@ -1,9 +1,13 @@
/* global browser:false, $:false, $$:false */
const v1Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v4Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v6Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-6[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v7Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v1Regex =
/^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v4Regex =
/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v6Regex =
/^[0-9A-F]{8}-[0-9A-F]{4}-6[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const v7Regex =
/^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
@@ -12,21 +16,32 @@ const v1 = (result) => expect(result).toMatch(v1Regex);
const v4 = (result) => expect(result).toMatch(v4Regex);
const v6 = (result) => expect(result).toMatch(v6Regex);
const v7 = (result) => expect(result).toMatch(v7Regex);
const v3dns = (result) => expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6');
const v3url = (result) => expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138');
const v3custom = (result) => expect(result).toBe('f5a52d34-dcd7-30f7-b581-0112fab43d0c');
const v5dns = (result) => expect(result).toBe('fdda765f-fc57-5604-a269-52a7df8164ec');
const v5url = (result) => expect(result).toBe('3bbcee75-cecc-5b56-8031-b6641c1ed1f1');
const v5custom = (result) => expect(result).toBe('c49c5142-4d9a-5940-a926-612ede0ec632');
const v3dns = (result) =>
expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6');
const v3url = (result) =>
expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138');
const v3custom = (result) =>
expect(result).toBe('f5a52d34-dcd7-30f7-b581-0112fab43d0c');
const v5dns = (result) =>
expect(result).toBe('fdda765f-fc57-5604-a269-52a7df8164ec');
const v5url = (result) =>
expect(result).toBe('3bbcee75-cecc-5b56-8031-b6641c1ed1f1');
const v5custom = (result) =>
expect(result).toBe('c49c5142-4d9a-5940-a926-612ede0ec632');
const v1ToV6 = (result) => expect(result).toBe(V6_ID);
const v6ToV1 = (result) => expect(result).toBe(V1_ID);
const nil = (result) => expect(result).toBe('00000000-0000-0000-0000-000000000000');
const max = (result) => expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff');
const nil = (result) =>
expect(result).toBe('00000000-0000-0000-0000-000000000000');
const max = (result) =>
expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff');
const parse = (result) =>
expect(result).toEqual('85,35,141,21,201,38,69,152,180,157,207,78,145,59,161,60');
const stringify = (result) => expect(result).toBe('55238d15-c926-4598-b49d-cf4e913ba13c');
expect(result).toEqual(
'85,35,141,21,201,38,69,152,180,157,207,78,145,59,161,60',
);
const stringify = (result) =>
expect(result).toBe('55238d15-c926-4598-b49d-cf4e913ba13c');
const validate = (result) => expect(result).toBe('true');
const version = (result) => expect(result).toBe('4');
@@ -113,22 +128,32 @@ describe('BrowserStack Local Testing', () => {
}
describe('webpack', () => {
it('renders all', async () => testExpectations('browser-webpack/example-all.html', () => true));
it('renders all', async () =>
testExpectations('browser-webpack/example-all.html', () => true));
it('renders v1 only', async () =>
testExpectations('browser-webpack/example-v1.html', (title) => title.includes('uuidv1()')));
testExpectations('browser-webpack/example-v1.html', (title) =>
title.includes('uuidv1()'),
));
it('renders v4 only', async () =>
testExpectations('browser-webpack/example-v4.html', (title) => title.includes('uuidv4()')));
testExpectations('browser-webpack/example-v4.html', (title) =>
title.includes('uuidv4()'),
));
});
describe('rollup', () => {
it('renders all', async () => testExpectations('browser-rollup/example-all.html', () => true));
it('renders all', async () =>
testExpectations('browser-rollup/example-all.html', () => true));
it('renders v1 only', async () =>
testExpectations('browser-rollup/example-v1.html', (title) => title.includes('uuidv1()')));
testExpectations('browser-rollup/example-v1.html', (title) =>
title.includes('uuidv1()'),
));
it('renders v4 only', async () =>
testExpectations('browser-rollup/example-v4.html', (title) => title.includes('uuidv4(')));
testExpectations('browser-rollup/example-v4.html', (title) =>
title.includes('uuidv4('),
));
});
});
+2 -1
View File
@@ -2,7 +2,8 @@ const PORT = 9000;
const PROJECT = process.env.GITHUB_REPOSITORY || 'node-uuid';
const GITHUB_SHA = process.env.GITHUB_SHA || '';
const GITHUB_REF = process.env.GITHUB_REF || '';
const BUILD = GITHUB_SHA || GITHUB_REF ? `${GITHUB_REF} ${GITHUB_SHA}` : 'manual build';
const BUILD =
GITHUB_SHA || GITHUB_REF ? `${GITHUB_REF} ${GITHUB_SHA}` : 'manual build';
const commonCapabilities = {
projectName: PROJECT,