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": [ "recommendations": ["biomejs.biome", "ms-vscode.vscode-typescript-next"]
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next",
"esbenp.prettier-vscode"
]
} }
+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"
}
}
+98 -98
View File
@@ -32,32 +32,32 @@ npm install uuid
**2. Create a UUID** **2. Create a UUID**
```javascript ```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 ... For timestamp UUIDs, namespace UUIDs, and other options read on ...
## API Summary ## API Summary
| | | | | | | |
| --- | --- | --- | | -------------------------------------------------- | ----------------------------------------------- | ----------------- |
| [`uuid.NIL`](#uuidnil) | The nil UUID string (all zeros) | New in `[email protected]` | | [`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.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]` | | [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `[email protected]` |
| [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `[email protected]` | | [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `[email protected]` |
| [`uuid.v1()`](#uuidv1options-buffer-offset) | Create a version 1 (timestamp) UUID | | | [`uuid.v1()`](#uuidv1options-buffer-offset) | Create a version 1 (timestamp) UUID | |
| [`uuid.v1ToV6()`](#uuidv1tov6uuid) | Create a version 6 UUID from a version 1 UUID | New in `uuid@10` | | [`uuid.v1ToV6()`](#uuidv1tov6uuid) | Create a version 6 UUID from a version 1 UUID | New in `uuid@10` |
| [`uuid.v3()`](#uuidv3name-namespace-buffer-offset) | Create a version 3 (namespace w/ MD5) UUID | | | [`uuid.v3()`](#uuidv3name-namespace-buffer-offset) | Create a version 3 (namespace w/ MD5) UUID | |
| [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | | | [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | |
| [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | | | [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
| [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` | | [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` |
| [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` | | [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` |
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` | | [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` |
| ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | | | ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | |
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `[email protected]` | | [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `[email protected]` |
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `[email protected]` | | [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `[email protected]` |
## API ## API
@@ -68,7 +68,7 @@ The nil UUID string (all zeros).
Example: Example:
```javascript ```javascript
import { NIL as NIL_UUID } from 'uuid'; import { NIL as NIL_UUID } from "uuid";
NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000' NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000'
``` ```
@@ -80,7 +80,7 @@ The max UUID string (all ones).
Example: Example:
```javascript ```javascript
import { MAX as MAX_UUID } from 'uuid'; import { MAX as MAX_UUID } from "uuid";
MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff' MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff'
``` ```
@@ -102,10 +102,10 @@ Convert UUID string to array of bytes
Example: Example:
```javascript ```javascript
import { parse as uuidParse } from 'uuid'; import { parse as uuidParse } from "uuid";
// Parse a UUID // Parse a UUID
uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ uuidParse("6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b"); // ⇨
// Uint8Array(16) [ // Uint8Array(16) [
// 110, 192, 189, 127, 17, // 110, 192, 189, 127, 17,
// 192, 67, 218, 151, 94, // 192, 67, 218, 151, 94,
@@ -132,7 +132,7 @@ Convert array of bytes to UUID string
Example: Example:
```javascript ```javascript
import { stringify as uuidStringify } from 'uuid'; import { stringify as uuidStringify } from "uuid";
const uuidBytes = Uint8Array.of( const uuidBytes = Uint8Array.of(
0x6e, 0x6e,
@@ -150,7 +150,7 @@ const uuidBytes = Uint8Array.of(
0xd9, 0xd9,
0xeb, 0xeb,
0xae, 0xae,
0x0b 0x0b,
); );
uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b' uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'
@@ -160,37 +160,37 @@ uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'
Create an RFC version 1 (timestamp) UUID Create an RFC version 1 (timestamp) UUID
| | | | | |
| --- | --- | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: | | [`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.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 | | [`options.clockseq = (random)`] | RFC "clock sequence" as a `Number` between 0 - 0x3fff |
| [`options.msecs = (current time)`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) | | [`options.msecs = (current time)`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) |
| [`options.nsecs = 0`] | RFC "timestamp" field (`Number` of nanoseconds to add to `msecs`, should be 0-10,000) | | [`options.nsecs = 0`] | RFC "timestamp" field (`Number` of nanoseconds to add to `msecs`, should be 0-10,000) |
| [`options.random = (random)`] | `Array` of 16 random bytes (0-255) used to generate other fields, above | | [`options.random = (random)`] | `Array` of 16 random bytes (0-255) used to generate other fields, above |
| [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `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) |
| [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |
| _throws_ | `Error` if more than 10M UUIDs/sec are requested | | _throws_ | `Error` if more than 10M UUIDs/sec are requested |
Example: Example:
```javascript ```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`: Example using `options`:
```javascript ```javascript
import { v1 as uuidv1 } from 'uuid'; import { v1 as uuidv1 } from "uuid";
const options = { const options = {
node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab), node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab),
clockseq: 0x1234, clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(), msecs: new Date("2011-11-01").getTime(),
nsecs: 5678, nsecs: 5678,
}; };
uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab' 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 Convert a UUID from version 1 to version 6
```javascript ```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]]) ### uuid.v3(name, namespace[, buffer[, offset]])
@@ -220,27 +220,27 @@ API is identical to `v5()`, but uses "v3" instead.
Create an RFC version 4 (random) UUID Create an RFC version 4 (random) UUID
| | | | | |
| --- | --- | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: | | [`options`] | `Object` with one or more of the following properties: |
| [`options.random`] | `Array` of 16 random bytes (0-255) | | [`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) | | [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `Array` of 16 random bytes (0-255) |
| [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |
Example: Example:
```javascript ```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: Example using predefined `random` values:
```javascript ```javascript
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from "uuid";
const v4options = { const v4options = {
random: Uint8Array.of( random: Uint8Array.of(
@@ -259,7 +259,7 @@ const v4options = {
0x67, 0x67,
0x1c, 0x1c,
0x58, 0x58,
0x36 0x36,
), ),
}; };
uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836' uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
@@ -269,13 +269,13 @@ uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
Create an RFC version 5 (namespace w/ SHA-1) UUID Create an RFC version 5 (namespace w/ SHA-1) UUID
| | | | | |
| --- | --- | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `String \| Array` | | `name` | `String \| Array` |
| `namespace` | `String \| Array[16]` Namespace UUID | | `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` | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |
<!-- prettier-ignore --> <!-- prettier-ignore -->
> [!NOTE] > [!NOTE]
@@ -284,21 +284,21 @@ Create an RFC version 5 (namespace w/ SHA-1) UUID
Example with custom namespace: Example with custom namespace:
```javascript ```javascript
import { v5 as uuidv5 } from 'uuid'; import { v5 as uuidv5 } from "uuid";
// Define a custom namespace. Readers, create your own using something like // Define a custom namespace. Readers, create your own using something like
// https://www.uuidgenerator.net/ // 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: Example with RFC `URL` namespace:
```javascript ```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]]]) ### 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(). This method takes the same arguments as uuid.v1().
```javascript ```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`: Example using `options`:
```javascript ```javascript
import { v6 as uuidv6 } from 'uuid'; import { v6 as uuidv6 } from "uuid";
const options = { const options = {
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab], node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
clockseq: 0x1234, clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(), msecs: new Date("2011-11-01").getTime(),
nsecs: 5678, nsecs: 5678,
}; };
uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab' uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
@@ -332,32 +332,32 @@ uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
Convert a UUID from version 6 to version 1 Convert a UUID from version 6 to version 1
```javascript ```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]]]) ### uuid.v7([options[, buffer[, offset]]])
Create an RFC version 7 (random) UUID Create an RFC version 7 (random) UUID
| | | | | |
| --- | --- | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`options`] | `Object` with one or more of the following properties: | | [`options`] | `Object` with one or more of the following properties: |
| [`options.msecs = (current time)`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) | | [`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 | | [`options.random = (random)`] | `Array` of 16 random bytes (0-255) used to generate other fields, above |
| [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `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) |
| [`options.seq = (random)`] | 32-bit sequence `Number` between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value. | | [`options.seq = (random)`] | 32-bit sequence `Number` between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value. |
| [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |
Example: Example:
```javascript ```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()~~ ### ~~uuid.v8()~~
@@ -380,24 +380,24 @@ Test a string to see if it is a valid UUID
Example: Example:
```javascript ```javascript
import { validate as uuidValidate } from 'uuid'; import { validate as uuidValidate } from "uuid";
uuidValidate('not a UUID'); // ⇨ false uuidValidate("not a UUID"); // ⇨ false
uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true 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. Using `validate` and `version` together it is possible to do per-version validation, e.g. validate for only v4 UUIds.
```javascript ```javascript
import { version as uuidVersion } from 'uuid'; import { version as uuidVersion } from "uuid";
import { validate as uuidValidate } from 'uuid'; import { validate as uuidValidate } from "uuid";
function uuidValidateV4(uuid) { function uuidValidateV4(uuid) {
return uuidValidate(uuid) && uuidVersion(uuid) === 4; return uuidValidate(uuid) && uuidVersion(uuid) === 4;
} }
const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210'; const v1Uuid = "d9428888-122b-11e1-b85c-61cd3cbb3210";
const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836'; const v4Uuid = "109156be-c4fb-41ea-b1b4-efe1671c5836";
uuidValidateV4(v4Uuid); // ⇨ true uuidValidateV4(v4Uuid); // ⇨ true
uuidValidateV4(v1Uuid); // ⇨ false uuidValidateV4(v1Uuid); // ⇨ false
@@ -416,10 +416,10 @@ Detect RFC version of a UUID
Example: Example:
```javascript ```javascript
import { version as uuidVersion } from 'uuid'; import { version as uuidVersion } from "uuid";
uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // ⇨ 1 uuidVersion("45637ec4-c85f-11ea-87d0-0242ac130003"); // ⇨ 1
uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4 uuidVersion("6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b"); // ⇨ 4
``` ```
<!-- prettier-ignore --> <!-- 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: 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 ```javascript
import 'react-native-get-random-values'; import "react-native-get-random-values";
import { v4 as uuidv4 } from 'uuid'; 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"] "trackBranches": ["main"]
}, },
"files": [ "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/v1-size.js",
{ "path": "./examples/browser-rollup/dist/v4-size.js", "maxSize": "0.7 kB" }, "maxSize": "1.0 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-rollup/dist/v3-size.js",
{ "path": "./examples/browser-webpack/dist/v1-size.js", "maxSize": "1.0 kB" }, "maxSize": "2.1 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-rollup/dist/v4-size.js",
{ "path": "./examples/browser-webpack/dist/v6-size.js", "maxSize": "1.6 kB" }, "maxSize": "0.7 kB"
{ "path": "./examples/browser-webpack/dist/v7-size.js", "maxSize": "0.8 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 = [ const BYTES = [
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08, 0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7,
0x4b, 0x26, 0x3a, 0x08, 0x4b,
]; ];
suite suite
@@ -76,15 +76,13 @@ export default function benchmark(uuid, Benchmark) {
uuid.v7(null, array, 0); uuid.v7(null, array, 0);
}) })
.add('uuid.v7() with defined time', function () { .add('uuid.v7() with defined time', function () {
uuid.v7({ uuid.v7({ msecs: 1645557742000 });
msecs: 1645557742000,
});
}) })
.on('cycle', function (event) { .on('cycle', function (event) {
console.log(event.target.toString()); console.log(event.target.toString());
}) })
.on('complete', function () { .on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name')); console.log(`Fastest is ${this.filter('fastest').map('name')}`);
console.log('---\n'); console.log('---\n');
}) })
.run(); .run();
+1 -1
View File
@@ -1,5 +1,5 @@
import * as uuid from 'uuid';
import Benchmark from 'benchmark'; import Benchmark from 'benchmark';
import * as uuid from 'uuid';
import benchmark from './benchmark.js'; import benchmark from './benchmark.js';
+1 -3
View File
@@ -19,8 +19,6 @@ module.exports = {
// Webpack now produces builds that are incompatible with IE11: // Webpack now produces builds that are incompatible with IE11:
// https://webpack.js.org/migrate/5/#turn-off-es2015-syntax-in-runtime-code-if-necessary // https://webpack.js.org/migrate/5/#turn-off-es2015-syntax-in-runtime-code-if-necessary
target: ['web', 'es5'], target: ['web', 'es5'],
output: { output: { filename: '[name].js' },
filename: '[name].js',
},
mode: 'production', mode: 'production',
}; };
+4 -1
View File
@@ -19,7 +19,10 @@ import {
// Import attribute syntax is still awaiting finalization. In the meantime we // Import attribute syntax is still awaiting finalization. In the meantime we
// use dynamic import to allows to specifyg both "assert" and "with" clauses. // use dynamic import to allows to specifyg both "assert" and "with" clauses.
// See https://github.com/tc39/proposal-import-attributes // 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()); console.log('uuidv1()', uuidv1());
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { v1 } from 'uuid'; import { v1 } from 'uuid';
v1(undefined, new Uint8Array(16)) satisfies Uint8Array; v1(undefined, new Uint8Array(16)) satisfies Uint8Array;
+3 -3
View File
@@ -6,8 +6,8 @@ export default function test(callback) {
'body {font-family: monospace;}', 'body {font-family: monospace;}',
'dt, dd {display: inline-block; margin: 0;}', 'dt, dd {display: inline-block; margin: 0;}',
'dt {min-width: 15em;}', 'dt {min-width: 15em;}',
].join('\n') ].join('\n'),
) ),
); );
document.body.appendChild(style); document.body.appendChild(style);
@@ -24,7 +24,7 @@ export default function test(callback) {
} else { } else {
el = document.createElement('div'); el = document.createElement('div');
el.className = 'test_result'; el.className = 'test_result';
el.innerHTML = '<dt>' + title + '</dt>: <dd>' + result + '</dd>'; el.innerHTML = `<dt>${title}</dt>: <dd>${result}</dd>`;
} }
document.body.appendChild(el); 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" "!**/test"
], ],
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "7.27.1", "@biomejs/biome": "2.4.10",
"@commitlint/cli": "19.8.0", "@commitlint/cli": "19.8.0",
"@commitlint/config-conventional": "19.8.0", "@commitlint/config-conventional": "19.8.0",
"@eslint/js": "9.26.0",
"bundlewatch": "0.4.1", "bundlewatch": "0.4.1",
"commander": "13.1.0", "commander": "13.1.0",
"eslint": "9.26.0",
"eslint-config-prettier": "10.1.2",
"eslint-plugin-prettier": "5.4.0",
"globals": "16.0.0", "globals": "16.0.0",
"husky": "9.1.7", "husky": "9.1.7",
"jest": "29.7.0", "jest": "29.7.0",
"lint-staged": "15.5.2", "lint-staged": "15.5.2",
"neostandard": "0.12.1", "neostandard": "0.12.1",
"npm-run-all2": "7.0.2", "npm-run-all2": "7.0.2",
"prettier": "3.5.3",
"release-please": "17.0.0", "release-please": "17.0.0",
"runmd": "1.4.1", "runmd": "1.4.1",
"standard-version": "9.5.0", "standard-version": "9.5.0",
"typescript": "5.2.2", "typescript": "5.2.2"
"typescript-eslint": "8.32.0"
}, },
"optionalDevDependencies": { "optionalDevDependencies": {
"@wdio/browserstack-service": "9.2.1", "@wdio/browserstack-service": "9.2.1",
@@ -73,14 +67,14 @@
"bundlewatch": "npm run pretest:browser && bundlewatch --config bundlewatch.config.json", "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: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", "docs": "npm run build && npx runmd --output=README.md README_js.md",
"eslint:check": "eslint src/ test/ examples/ *.[jt]s", "biome:check": "biome check .",
"eslint:fix": "eslint --fix src/ test/ examples/ *.[jt]s", "biome:fix": "biome check --write .",
"examples:browser:rollup:build": "cd examples/browser-rollup && npm run build", "examples:browser:rollup:build": "cd examples/browser-rollup && npm run build",
"examples:browser:webpack:build": "cd examples/browser-webpack && 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:esmodules:test": "cd examples/node-esmodules && npm test",
"examples:node:jest:test": "cd examples/node-jest && npm test", "examples:node:jest:test": "cd examples/node-jest && npm test",
"examples:node:typescript:test": "cd examples/typescript && 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", "md": "runmd --watch --output=README.md README_js.md",
"prepack": "npm run build -- --no-pack", "prepack": "npm run build -- --no-pack",
"prepare": "husky", "prepare": "husky",
@@ -89,8 +83,8 @@
"pretest:browser": "./scripts/iodd && npm run build && npm-run-all --parallel examples:browser:**", "pretest:browser": "./scripts/iodd && npm run build && npm-run-all --parallel examples:browser:**",
"pretest:node": "npm run build", "pretest:node": "npm run build",
"pretest": "npm run build", "pretest": "npm run build",
"prettier:check": "prettier --check .", "format": "biome format --write .",
"prettier:fix": "prettier --write .", "format:check": "biome format --check .",
"release": "standard-version --no-verify", "release": "standard-version --no-verify",
"test:benchmark": "cd examples/benchmark && npm test", "test:benchmark": "cd examples/benchmark && npm test",
"test:browser": "wdio run ./wdio.conf.js", "test:browser": "wdio run ./wdio.conf.js",
@@ -104,15 +98,12 @@
}, },
"lint-staged": { "lint-staged": {
"*": [ "*": [
"prettier --no-error-on-unmatched-pattern --write" "biome check --write --no-errors-on-unmatched"
],
"*.{js,jsx}": [
"eslint --no-error-on-unmatched-pattern --fix"
] ]
}, },
"standard-version": { "standard-version": {
"scripts": { "scripts": {
"postchangelog": "prettier --write CHANGELOG.md" "postchangelog": "biome format --write CHANGELOG.md"
} }
}, },
"packageManager": "[email protected]" "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 MAX } from './max.js';
export { default as NIL } from './nil.js'; export { default as NIL } from './nil.js';
export { default as parse } from './parse.js'; export { default as parse } from './parse.js';
export { default as stringify } from './stringify.js'; export { default as stringify } from './stringify.js';
export type * from './types.js';
export { default as v1 } from './v1.js'; export { default as v1 } from './v1.js';
export { default as v1ToV6 } from './v1ToV6.js'; export { default as v1ToV6 } from './v1ToV6.js';
export { default as v3 } from './v3.js'; export { default as v3 } from './v3.js';
+45 -6
View File
@@ -55,7 +55,7 @@ function wordsToMd5(x: Uint32Array, len: number) {
/* append padding */ /* append padding */
const xpad = new Uint32Array(getOutputLength(len)).fill(0); const xpad = new Uint32Array(getOutputLength(len)).fill(0);
xpad.set(x); xpad.set(x);
xpad[len >> 5] |= 0x80 << len % 32; xpad[len >> 5] |= 0x80 << (len % 32);
xpad[xpad.length - 1] = len; xpad[xpad.length - 1] = len;
x = xpad; x = xpad;
@@ -182,23 +182,62 @@ function bitRotateLeft(num: number, cnt: number) {
/* /*
* These functions implement the four basic operations the algorithm uses. * 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); 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); 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); 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); 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); return md5cmn(c ^ (b | ~d), a, b, x, s, t);
} }
+3 -1
View File
@@ -1,4 +1,6 @@
const randomUUID = const randomUUID =
typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); typeof crypto !== 'undefined' &&
crypto.randomUUID &&
crypto.randomUUID.bind(crypto);
export default { randomUUID }; export default { randomUUID };
+2 -2
View File
@@ -5,7 +5,7 @@ function parse(uuid: string) {
throw TypeError('Invalid UUID'); throw TypeError('Invalid UUID');
} }
let v; let v: number;
return Uint8Array.of( return Uint8Array.of(
(v = parseInt(uuid.slice(0, 8), 16)) >>> 24, (v = parseInt(uuid.slice(0, 8), 16)) >>> 24,
(v >>> 16) & 0xff, (v >>> 16) & 0xff,
@@ -31,7 +31,7 @@ function parse(uuid: string) {
(v >>> 24) & 0xff, (v >>> 24) & 0xff,
(v >>> 16) & 0xff, (v >>> 16) & 0xff,
(v >>> 8) & 0xff, (v >>> 8) & 0xff,
v & 0xff v & 0xff,
); );
} }
+1 -1
View File
@@ -11,7 +11,7 @@ export default function rng() {
if (!getRandomValues) { if (!getRandomValues) {
if (typeof crypto === 'undefined' || !crypto.getRandomValues) { if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
throw new Error( 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[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][14] = Math.floor(M[N - 1][14]);
M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff; M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff;
@@ -103,7 +103,7 @@ function sha1(bytes: Uint8Array): Uint8Array {
H[4] >> 24, H[4] >> 24,
H[4] >> 16, H[4] >> 16,
H[4] >> 8, H[4] >> 8,
H[4] H[4],
); );
} }
+5 -5
View File
@@ -32,9 +32,9 @@ describe('parse', () => {
assert.deepStrictEqual( assert.deepStrictEqual(
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'), parse('0f5abcd1-c194-47f3-905b-2df7263a084b'),
Uint8Array.from([ Uint8Array.from([
0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08, 0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7,
0x4b, 0x26, 0x3a, 0x08, 0x4b,
]) ]),
); );
}); });
@@ -49,14 +49,14 @@ describe('parse', () => {
// Verify upper/lower case neutrality // Verify upper/lower case neutrality
assert.deepStrictEqual( assert.deepStrictEqual(
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'), parse('0f5abcd1-c194-47f3-905b-2df7263a084b'),
parse('0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()) parse('0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()),
); );
}); });
test('Null UUID case', () => { test('Null UUID case', () => {
assert.deepStrictEqual( assert.deepStrictEqual(
parse('00000000-0000-0000-0000-000000000000'), 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, 0x26,
0x3a, 0x3a,
0x08, 0x08,
0x4b 0x4b,
); );
describe('stringify', () => { describe('stringify', () => {
test('Stringify Array (unsafe)', () => { 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)', () => { test('Stringify w/ offset (unsafe)', () => {
const bytes = new Uint8Array(19).fill(0); const bytes = new Uint8Array(19).fill(0);
bytes.set(BYTES, 3); 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)', () => { test('Stringify Array (safe)', () => {
+140 -28
View File
@@ -8,22 +8,86 @@ export const TESTS = [
{ value: MAX, expectedValidate: true, expectedVersion: 15 }, { value: MAX, expectedValidate: true, expectedVersion: 15 },
// each version, with either all 0's or all 1's in settable bits // 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-1000-8000-000000000000',
{ value: '00000000-0000-2000-8000-000000000000', expectedValidate: true, expectedVersion: 2 }, expectedValidate: true,
{ value: 'ffffffff-ffff-2fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 2 }, expectedVersion: 1,
{ 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-1fff-8fff-ffffffffffff',
{ value: 'ffffffff-ffff-4fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 4 }, expectedValidate: true,
{ value: '00000000-0000-5000-8000-000000000000', expectedValidate: true, expectedVersion: 5 }, expectedVersion: 1,
{ 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-2000-8000-000000000000',
{ value: '00000000-0000-7000-8000-000000000000', expectedValidate: true, expectedVersion: 7 }, expectedValidate: true,
{ value: 'ffffffff-ffff-7fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 7 }, expectedVersion: 2,
{ value: '00000000-0000-8000-8000-000000000000', expectedValidate: true, expectedVersion: 8 }, },
{ value: 'ffffffff-ffff-8fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 8 }, {
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: '00000000-0000-9000-8000-000000000000', expectedValidate: false },
{ value: 'ffffffff-ffff-9fff-bfff-ffffffffffff', expectedValidate: false }, { value: 'ffffffff-ffff-9fff-bfff-ffffffffffff', expectedValidate: false },
{ value: '00000000-0000-a000-8000-000000000000', 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 }, { value: 'ffffffff-ffff-efff-bfff-ffffffffffff', expectedValidate: false },
// selection of normal, valid UUIDs // 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: 'd9428888-122b-11e1-b85c-61cd3cbb3210',
{ value: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec', expectedValidate: true, expectedVersion: 3 }, expectedValidate: true,
{ value: '109156be-c4fb-41ea-b1b4-efe1671c5836', expectedValidate: true, expectedVersion: 4 }, expectedVersion: 1,
{ 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: '000003e8-2363-21ef-b200-325096b39f47',
{ value: '0d8f23a0-697f-83ae-802e-48f3756dd581', expectedValidate: true, expectedVersion: 8 }, 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 // all variant octet values
{ value: '00000000-0000-1000-0000-000000000000', expectedValidate: false }, { 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-5000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-6000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-6000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-7000-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-8000-000000000000',
{ value: '00000000-0000-1000-a000-000000000000', expectedValidate: true, expectedVersion: 1 }, expectedValidate: true,
{ value: '00000000-0000-1000-b000-000000000000', expectedValidate: true, expectedVersion: 1 }, 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-c000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-d000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-d000-000000000000', expectedValidate: false },
{ value: '00000000-0000-1000-e000-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, RFC_OPTIONS.clockseq & 0xff,
// node // node
...RFC_OPTIONS.node ...RFC_OPTIONS.node,
); );
// Compare v1 timestamp fields chronologically // Compare v1 timestamp fields chronologically
@@ -69,13 +69,25 @@ describe('v1', () => {
}); });
test('v1(options)', () => { 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'); assert.equal(v1(RFC_OPTIONS), RFC_V1, 'full options');
}); });
test('v1(options) equality', () => { test('v1(options) equality', () => {
assert.notEqual(v1({ msecs: TIME }), v1({ msecs: TIME }), 'UUIDs with minimal options differ'); assert.notEqual(
assert.equal(v1(RFC_OPTIONS), v1(RFC_OPTIONS), 'UUIDs with full options are identical'); 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', () => { test('fills one UUID into a buffer as expected', () => {
@@ -165,7 +177,11 @@ describe('v1', () => {
}, },
]; ];
for (const { title, state, now, expected } of tests) { 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 md5 from '../md5.js';
import sha1 from '../sha1.js'; import sha1 from '../sha1.js';
import v3 from '../v3.js'; import v3 from '../v3.js';
import { stringToBytes } from '../v35.js';
import v5 from '../v5.js'; import v5 from '../v5.js';
import { stringToBytes } from '../v35.js';
describe('v35', () => { describe('v35', () => {
const HASH_SAMPLES = [ const HASH_SAMPLES = [
@@ -17,7 +17,7 @@ describe('v35', () => {
// Extended ascii chars // Extended ascii chars
{ {
input: stringToBytes( 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', sha1: 'ca4a426a3d536f14cfd79011e79e10d64de950a0',
md5: 'e8098ec21950f841731d28749129d3ee', md5: 'e8098ec21950f841731d28749129d3ee',
@@ -26,7 +26,7 @@ describe('v35', () => {
// A sampling from the Unicode BMP // A sampling from the Unicode BMP
{ {
input: stringToBytes( 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', sha1: 'f2753ebc390e5f637e333c2a4179644a93ae9f65',
md5: '231b309e277b6be8bb3d6c688b7f098b', md5: '231b309e277b6be8bb3d6c688b7f098b',
@@ -55,33 +55,36 @@ describe('v35', () => {
test('v3', () => { test('v3', () => {
// Expect to get the same results as http://tools.adjet.org/uuid-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( assert.strictEqual(
v3('http://example.com/hello', v3.URL), v3('http://example.com/hello', v3.URL),
'c6235813-3ba4-3801-ae84-e0a6ebb7d138' 'c6235813-3ba4-3801-ae84-e0a6ebb7d138',
); );
assert.strictEqual( assert.strictEqual(
v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'), v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'),
'a981a0c2-68b1-35dc-bcfc-296e52ab01ec' 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec',
); );
}); });
test('v3 namespace.toUpperCase', () => { test('v3 namespace.toUpperCase', () => {
assert.strictEqual( assert.strictEqual(
v3('hello.example.com', v3.DNS.toUpperCase()), v3('hello.example.com', v3.DNS.toUpperCase()),
'9125a8dc-52ee-365b-a5aa-81b0b3681cf6' '9125a8dc-52ee-365b-a5aa-81b0b3681cf6',
); );
assert.strictEqual( assert.strictEqual(
v3('http://example.com/hello', v3.URL.toUpperCase()), v3('http://example.com/hello', v3.URL.toUpperCase()),
'c6235813-3ba4-3801-ae84-e0a6ebb7d138' 'c6235813-3ba4-3801-ae84-e0a6ebb7d138',
); );
assert.strictEqual( assert.strictEqual(
v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()), 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, 0xb3,
0x68, 0x68,
0x1c, 0x1c,
0xf6 0xf6,
); );
const result = v3('hello.example.com', v3.DNS, buf); const result = v3('hello.example.com', v3.DNS, buf);
@@ -160,16 +163,19 @@ describe('v35', () => {
test('v5', () => { test('v5', () => {
// Expect to get the same results as http://tools.adjet.org/uuid-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( assert.strictEqual(
v5('http://example.com/hello', v5.URL), v5('http://example.com/hello', v5.URL),
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1' '3bbcee75-cecc-5b56-8031-b6641c1ed1f1',
); );
assert.strictEqual( assert.strictEqual(
v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'), 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 // Expect to get the same results as http://tools.adjet.org/uuid-v5
assert.strictEqual( assert.strictEqual(
v5('hello.example.com', v5.DNS.toUpperCase()), v5('hello.example.com', v5.DNS.toUpperCase()),
'fdda765f-fc57-5604-a269-52a7df8164ec' 'fdda765f-fc57-5604-a269-52a7df8164ec',
); );
assert.strictEqual( assert.strictEqual(
v5('http://example.com/hello', v5.URL.toUpperCase()), v5('http://example.com/hello', v5.URL.toUpperCase()),
'3bbcee75-cecc-5b56-8031-b6641c1ed1f1' '3bbcee75-cecc-5b56-8031-b6641c1ed1f1',
); );
assert.strictEqual( assert.strictEqual(
v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()), 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, 0xdf,
0x81, 0x81,
0x64, 0x64,
0xec 0xec,
); );
const result = v5('hello.example.com', v5.DNS, buf); const result = v5('hello.example.com', v5.DNS, buf);
+2 -2
View File
@@ -19,7 +19,7 @@ const randomBytesFixture = Uint8Array.of(
0x67, 0x67,
0x1c, 0x1c,
0x58, 0x58,
0x36 0x36,
); );
const expectedBytes = Uint8Array.of( const expectedBytes = Uint8Array.of(
@@ -38,7 +38,7 @@ const expectedBytes = Uint8Array.of(
103, 103,
28, 28,
88, 88,
54 54,
); );
describe('v4', () => { describe('v4', () => {
+5 -3
View File
@@ -31,16 +31,18 @@ describe('v6', () => {
0x3c, 0x3c,
0xbb, 0xbb,
0x32, 0x32,
0x10 0x10,
); );
test('default behavior', () => { test('default behavior', () => {
// Verify explicit options produce expected id // Verify explicit options produce expected id
const id = v6(); const id = v6();
assert.ok( 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 { describe, test } from 'node:test';
import parse from '../parse.js'; import parse from '../parse.js';
import stringify from '../stringify.js'; import stringify from '../stringify.js';
import { Version7Options } from '../types.js'; import type { Version7Options } from '../types.js';
import v7, { updateV7State } from '../v7.js'; import v7, { updateV7State } from '../v7.js';
// Fixture values for testing with the rfc v7 UUID example: // Fixture values for testing with the rfc v7 UUID example:
@@ -31,7 +31,7 @@ const RFC_RANDOM = Uint8Array.of(
0x0c, 0x0c,
0x07, 0x07,
0x39, 0x39,
0x8f 0x8f,
); );
describe('v7', () => { describe('v7', () => {
@@ -74,7 +74,7 @@ describe('v7', () => {
msecs: RFC_MSECS, msecs: RFC_MSECS,
seq: RFC_SEQ, seq: RFC_SEQ,
}, },
buffer buffer,
); );
stringify(buffer); stringify(buffer);
@@ -92,7 +92,7 @@ describe('v7', () => {
seq: RFC_SEQ, seq: RFC_SEQ,
}, },
buffer, buffer,
0 0,
); );
v7( v7(
{ {
@@ -101,7 +101,7 @@ describe('v7', () => {
seq: RFC_SEQ, seq: RFC_SEQ,
}, },
buffer, buffer,
16 16,
); );
const expected = new Uint8Array(32); const expected = new Uint8Array(32);
expected.set(RFC_V7_BYTES); expected.set(RFC_V7_BYTES);
@@ -114,8 +114,8 @@ describe('v7', () => {
// //
test('lexicographical sorting is preserved', () => { test('lexicographical sorting is preserved', () => {
let id; let id: string;
let prior; let prior: string | undefined;
let msecs = RFC_MSECS; let msecs = RFC_MSECS;
for (let i = 0; i < 20000; ++i) { for (let i = 0; i < 20000; ++i) {
if (i % 1500 === 0) { if (i % 1500 === 0) {
@@ -218,16 +218,22 @@ describe('v7', () => {
}, },
]; ];
for (const { title, state, now, expected } of tests) { 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', () => { test('flipping bits changes the result', () => {
// convert uint8array to BigInt (BE) // 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 // 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 // flip the nth bit (BE) in a BigInt
const flip = (data: bigint, n: number) => data ^ (1n << BigInt(127 - n)); const flip = (data: bigint, n: number) => data ^ (1n << BigInt(127 - n));
@@ -262,7 +268,7 @@ describe('v7', () => {
assert.strictEqual( assert.strictEqual(
asBigInt(v7(optionsFrom(flipped), buf)).toString(16), asBigInt(v7(optionsFrom(flipped), buf)).toString(16),
flipped.toString(16), flipped.toString(16),
`Unequal uuids at bit ${i}` `Unequal uuids at bit ${i}`,
); );
assert.notStrictEqual(stringify(buf), id); assert.notStrictEqual(stringify(buf), id);
} }
+1 -1
View File
@@ -9,7 +9,7 @@ describe('validate()', () => {
assert.strictEqual( assert.strictEqual(
validate(value), validate(value),
expectedValidate, 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 v7');
console.log(' uuid --help'); console.log(' uuid --help');
console.log( 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 rng from './rng.js';
import { unsafeStringify } from './stringify.js'; import { unsafeStringify } from './stringify.js';
import { UUIDTypes, Version1Options } from './types.js'; import type { UUIDTypes, Version1Options } from './types.js';
// **`v1()` - Generate time-based UUID** // **`v1()` - Generate time-based UUID**
// //
@@ -24,16 +24,20 @@ type V1State = {
const _state: 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>( function v1<Buf extends Uint8Array = Uint8Array>(
options: Version1Options | undefined, options: Version1Options | undefined,
buf: Buf, buf: Buf,
offset?: number offset?: number,
): Buf; ): Buf;
function v1<TBuf extends Uint8Array = Uint8Array>( function v1<TBuf extends Uint8Array = Uint8Array>(
options?: Version1Options, options?: Version1Options,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
let bytes: Uint8Array; let bytes: Uint8Array;
@@ -55,7 +59,7 @@ function v1<TBuf extends Uint8Array = Uint8Array>(
options.clockseq, options.clockseq,
options.node, options.node,
buf, buf,
offset offset,
); );
} else { } else {
// Without options: Make UUID from internal state // Without options: Make UUID from internal state
@@ -77,7 +81,7 @@ function v1<TBuf extends Uint8Array = Uint8Array>(
isV6 ? undefined : _state.clockseq, isV6 ? undefined : _state.clockseq,
isV6 ? undefined : _state.node, isV6 ? undefined : _state.node,
buf, buf,
offset offset,
); );
} }
@@ -145,7 +149,7 @@ function v1Bytes(
clockseq?: number, clockseq?: number,
node?: Uint8Array, node?: Uint8Array,
buf?: Uint8Array, buf?: Uint8Array,
offset = 0 offset = 0,
) { ) {
if (rnds.length < 16) { if (rnds.length < 16) {
throw new Error('Random bytes length must be >= 16'); throw new Error('Random bytes length must be >= 16');
@@ -157,7 +161,9 @@ function v1Bytes(
offset = 0; offset = 0;
} else { } else {
if (offset < 0 || offset + 16 > buf.length) { 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 parse from './parse.js';
import { unsafeStringify } from './stringify.js'; import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
/** /**
* Convert a v1 UUID to a v6 UUID * Convert a v1 UUID to a v6 UUID
@@ -40,6 +40,6 @@ function _v1ToV6(v1Bytes: Uint8Array) {
v1Bytes[12], v1Bytes[12],
v1Bytes[13], v1Bytes[13],
v1Bytes[14], 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 md5 from './md5.js';
import type { UUIDTypes } from './types.js';
import v35, { DNS, URL } from './v35.js'; import v35, { DNS, URL } from './v35.js';
export { DNS, URL } from './v35.js'; export { DNS, URL } from './v35.js';
@@ -8,19 +8,19 @@ function v3(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf?: undefined, buf?: undefined,
offset?: number offset?: number,
): string; ): string;
function v3<TBuf extends Uint8Array = Uint8Array>( function v3<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf: TBuf, buf: TBuf,
offset?: number offset?: number,
): TBuf; ): TBuf;
function v3<TBuf extends Uint8Array = Uint8Array>( function v3<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
return v35(0x30, md5, value, namespace, buf, offset); 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 parse from './parse.js';
import { unsafeStringify } from './stringify.js'; import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
export function stringToBytes(str: string) { export function stringToBytes(str: string) {
// TODO: Use TextEncoder (see https://stackoverflow.com/a/48762658/109538) // 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, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
const valueBytes: Uint8Array = typeof value === 'string' ? stringToBytes(value) : value; const valueBytes: Uint8Array =
const namespaceBytes: Uint8Array = typeof namespace === 'string' ? parse(namespace) : namespace; typeof value === 'string' ? stringToBytes(value) : value;
const namespaceBytes: Uint8Array =
typeof namespace === 'string' ? parse(namespace) : namespace;
if (typeof namespace === 'string') { if (typeof namespace === 'string') {
namespace = parse(namespace); namespace = parse(namespace);
} }
if (namespace?.length !== 16) { 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 // Compute hash of namespace and value, Per 4.3
+12 -6
View File
@@ -1,12 +1,12 @@
import native from './native.js'; import native from './native.js';
import rng from './rng.js'; import rng from './rng.js';
import { unsafeStringify } from './stringify.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>( function _v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options, options?: Version4Options,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
options = options || {}; options = options || {};
@@ -23,7 +23,9 @@ function _v4<TBuf extends Uint8Array = Uint8Array>(
if (buf) { if (buf) {
offset = offset || 0; offset = offset || 0;
if (offset < 0 || offset + 16 > buf.length) { 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) { for (let i = 0; i < 16; ++i) {
@@ -36,16 +38,20 @@ function _v4<TBuf extends Uint8Array = Uint8Array>(
return unsafeStringify(rnds); 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>( function v4<TBuf extends Uint8Array = Uint8Array>(
options: Version4Options | undefined, options: Version4Options | undefined,
buf: TBuf, buf: TBuf,
offset?: number offset?: number,
): TBuf; ): TBuf;
function v4<TBuf extends Uint8Array = Uint8Array>( function v4<TBuf extends Uint8Array = Uint8Array>(
options?: Version4Options, options?: Version4Options,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
if (native.randomUUID && !buf && !options) { if (native.randomUUID && !buf && !options) {
return native.randomUUID(); return native.randomUUID();
+4 -4
View File
@@ -1,5 +1,5 @@
import { UUIDTypes } from './types.js';
import sha1 from './sha1.js'; import sha1 from './sha1.js';
import type { UUIDTypes } from './types.js';
import v35, { DNS, URL } from './v35.js'; import v35, { DNS, URL } from './v35.js';
export { DNS, URL } from './v35.js'; export { DNS, URL } from './v35.js';
@@ -8,19 +8,19 @@ function v5(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf?: undefined, buf?: undefined,
offset?: number offset?: number,
): string; ): string;
function v5<TBuf extends Uint8Array = Uint8Array>( function v5<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf: TBuf, buf: TBuf,
offset?: number offset?: number,
): TBuf; ): TBuf;
function v5<TBuf extends Uint8Array = Uint8Array>( function v5<TBuf extends Uint8Array = Uint8Array>(
value: string | Uint8Array, value: string | Uint8Array,
namespace: UUIDTypes, namespace: UUIDTypes,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
return v35(0x50, sha1, value, namespace, buf, offset); 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 { unsafeStringify } from './stringify.js';
import type { UUIDTypes, Version6Options } from './types.js';
import v1 from './v1.js'; import v1 from './v1.js';
import v1ToV6 from './v1ToV6.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>( function v6<TBuf extends Uint8Array = Uint8Array>(
options: Version6Options | undefined, options: Version6Options | undefined,
buf: TBuf, buf: TBuf,
offset?: number offset?: number,
): TBuf; ): TBuf;
function v6<TBuf extends Uint8Array = Uint8Array>( function v6<TBuf extends Uint8Array = Uint8Array>(
options?: Version6Options, options?: Version6Options,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
options ??= {}; options ??= {};
offset ??= 0; offset ??= 0;
+2 -2
View File
@@ -1,6 +1,6 @@
import { UUIDTypes } from './types.js';
import parse from './parse.js'; import parse from './parse.js';
import { unsafeStringify } from './stringify.js'; import { unsafeStringify } from './stringify.js';
import type { UUIDTypes } from './types.js';
/** /**
* Convert a v6 UUID to a v1 UUID * Convert a v6 UUID to a v1 UUID
@@ -40,6 +40,6 @@ function _v6ToV1(v6Bytes: Uint8Array) {
v6Bytes[12], v6Bytes[12],
v6Bytes[13], v6Bytes[13],
v6Bytes[14], v6Bytes[14],
v6Bytes[15] v6Bytes[15],
); );
} }
+19 -7
View File
@@ -1,6 +1,6 @@
import rng from './rng.js'; import rng from './rng.js';
import { unsafeStringify } from './stringify.js'; import { unsafeStringify } from './stringify.js';
import { UUIDTypes, Version7Options } from './types.js'; import type { UUIDTypes, Version7Options } from './types.js';
type V7State = { type V7State = {
msecs?: number; // time, milliseconds msecs?: number; // time, milliseconds
@@ -9,16 +9,20 @@ type V7State = {
const _state: 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>( function v7<TBuf extends Uint8Array = Uint8Array>(
options: Version7Options | undefined, options: Version7Options | undefined,
buf: TBuf, buf: TBuf,
offset?: number offset?: number,
): TBuf; ): TBuf;
function v7<TBuf extends Uint8Array = Uint8Array>( function v7<TBuf extends Uint8Array = Uint8Array>(
options?: Version7Options, options?: Version7Options,
buf?: TBuf, buf?: TBuf,
offset?: number offset?: number,
): UUIDTypes<TBuf> { ): UUIDTypes<TBuf> {
let bytes: Uint8Array; let bytes: Uint8Array;
@@ -29,7 +33,7 @@ function v7<TBuf extends Uint8Array = Uint8Array>(
options.msecs, options.msecs,
options.seq, options.seq,
buf, buf,
offset offset,
); );
} else { } else {
// No options: Use internal state // No options: Use internal state
@@ -69,7 +73,13 @@ export function updateV7State(state: V7State, now: number, rnds: Uint8Array) {
return state; 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) { if (rnds.length < 16) {
throw new Error('Random bytes length must be >= 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; offset = 0;
} else { } else {
if (offset < 0 || offset + 16 > buf.length) { 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 */ /* 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 v1Regex =
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; /^[0-9A-F]{8}-[0-9A-F]{4}-1[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 v4Regex =
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; /^[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 V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
const V6_ID = '1ef21d2f-1207-6660-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 v4 = (result) => expect(result).toMatch(v4Regex);
const v6 = (result) => expect(result).toMatch(v6Regex); const v6 = (result) => expect(result).toMatch(v6Regex);
const v7 = (result) => expect(result).toMatch(v7Regex); const v7 = (result) => expect(result).toMatch(v7Regex);
const v3dns = (result) => expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6'); const v3dns = (result) =>
const v3url = (result) => expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138'); expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6');
const v3custom = (result) => expect(result).toBe('f5a52d34-dcd7-30f7-b581-0112fab43d0c'); const v3url = (result) =>
const v5dns = (result) => expect(result).toBe('fdda765f-fc57-5604-a269-52a7df8164ec'); expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138');
const v5url = (result) => expect(result).toBe('3bbcee75-cecc-5b56-8031-b6641c1ed1f1'); const v3custom = (result) =>
const v5custom = (result) => expect(result).toBe('c49c5142-4d9a-5940-a926-612ede0ec632'); 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 v1ToV6 = (result) => expect(result).toBe(V6_ID);
const v6ToV1 = (result) => expect(result).toBe(V1_ID); const v6ToV1 = (result) => expect(result).toBe(V1_ID);
const nil = (result) => expect(result).toBe('00000000-0000-0000-0000-000000000000'); const nil = (result) =>
const max = (result) => expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff'); expect(result).toBe('00000000-0000-0000-0000-000000000000');
const max = (result) =>
expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff');
const parse = (result) => const parse = (result) =>
expect(result).toEqual('85,35,141,21,201,38,69,152,180,157,207,78,145,59,161,60'); expect(result).toEqual(
const stringify = (result) => expect(result).toBe('55238d15-c926-4598-b49d-cf4e913ba13c'); '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 validate = (result) => expect(result).toBe('true');
const version = (result) => expect(result).toBe('4'); const version = (result) => expect(result).toBe('4');
@@ -113,22 +128,32 @@ describe('BrowserStack Local Testing', () => {
} }
describe('webpack', () => { 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 () => 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 () => 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', () => { 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 () => 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 () => 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 PROJECT = process.env.GITHUB_REPOSITORY || 'node-uuid';
const GITHUB_SHA = process.env.GITHUB_SHA || ''; const GITHUB_SHA = process.env.GITHUB_SHA || '';
const GITHUB_REF = process.env.GITHUB_REF || ''; 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 = { const commonCapabilities = {
projectName: PROJECT, projectName: PROJECT,