Skip to content

Commit c4ed13e

Browse files
authoredJun 7, 2024··
feat: support v6 uuids (#754)
1 parent 8c3ed07 commit c4ed13e

37 files changed

+9850
-15438
lines changed
 

‎.gitignore

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
node_modules/
2-
dist/
3-
# Browserstack
1+
*.tgz
42
browserstack.err
3+
dist/
54
local.log
6-
*.tgz
5+
node_modules/
6+
vscode/

‎.local/uuid/v1tov6.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../v1tov6.js

‎.local/uuid/v6.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../v6.js

‎.local/uuid/v6tov1.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../v6tov1.js

‎.prettierignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
dist/
33
node_modules/
44
README.md
5-
*.sh
5+
*.sh
6+
.gitignore
7+
.prettierignore

‎README.md

+58-7
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
-- This file is auto-generated from README_js.md. Changes should be made there.
33
-->
44

5+
56
# uuid [![CI](https://github.com/uuidjs/uuid/workflows/CI/badge.svg)](https://github.com/uuidjs/uuid/actions?query=workflow%3ACI) [![Browser](https://github.com/uuidjs/uuid/workflows/Browser/badge.svg)](https://github.com/uuidjs/uuid/actions?query=workflow%3ABrowser)
67

78
For the creation of [RFC9562](https://www.rfc-editor.org/rfc/rfc9562.html) (formally [RFC4122](https://www.rfc-editor.org/rfc/rfc4122.html)) UUIDs
89

9-
- **Complete** - Support for all RFC9562 UUID versions
10+
- **Complete** - Support for all RFC9562 (nee RFC4122) UUID versions
1011
- **Cross-platform** - Support for ...
1112
- CommonJS, [ECMAScript Modules](#ecmascript-modules) and [CDN builds](#cdn-builds)
1213
- NodeJS 16+ ([LTS releases](https://github.com/nodejs/Release))
@@ -60,10 +61,13 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ...
6061
| [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `uuid@8.3` |
6162
| [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `uuid@8.3` |
6263
| [`uuid.v1()`](#uuidv1options-buffer-offset) | Create a version 1 (timestamp) UUID | |
64+
| [`uuid.v1ToV6()`](#uuidv1tov6uuid) | Create a version 6 UUID from a version 1 UUID | New in `uuid@10` |
6365
| [`uuid.v3()`](#uuidv3name-namespace-buffer-offset) | Create a version 3 (namespace w/ MD5) UUID | |
6466
| [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | |
6567
| [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
66-
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | `experimental support` |
68+
| [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` |
69+
| [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` |
70+
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` |
6771
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` |
6872
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` |
6973

@@ -191,13 +195,23 @@ Example using `options`:
191195
```javascript
192196
import { v1 as uuidv1 } from 'uuid';
193197

194-
const v1options = {
198+
const options = {
195199
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
196200
clockseq: 0x1234,
197201
msecs: new Date('2011-11-01').getTime(),
198202
nsecs: 5678,
199203
};
200-
uuidv1(v1options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
204+
uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
205+
```
206+
207+
### uuid.v1ToV6(uuid)
208+
209+
Convert a UUID from version 1 to version 6
210+
211+
```javascript
212+
import { v1ToV6 } from 'uuid';
213+
214+
v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'
201215
```
202216

203217
### uuid.v3(name, namespace[, buffer[, offset]])
@@ -280,6 +294,42 @@ import { v5 as uuidv5 } from 'uuid';
280294
uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'
281295
```
282296

297+
### uuid.v6([options[, buffer[, offset]]])
298+
299+
Create an RFC version 6 (timestamp, reordered) UUID
300+
301+
This method takes the same arguments as uuid.v1().
302+
303+
```javascript
304+
import { v6 as uuidv6 } from 'uuid';
305+
306+
uuidv6(); // ⇨ '1e940672-c5ea-64c0-8bad-9b1deb4d3b7d'
307+
```
308+
309+
Example using `options`:
310+
311+
```javascript
312+
import { v6 as uuidv6 } from 'uuid';
313+
314+
const options = {
315+
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
316+
clockseq: 0x1234,
317+
msecs: new Date('2011-11-01').getTime(),
318+
nsecs: 5678,
319+
};
320+
uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
321+
```
322+
323+
### uuid.v6ToV1(uuid)
324+
325+
Convert a UUID from version 6 to version 1
326+
327+
```javascript
328+
import { v6ToV1 } from 'uuid';
329+
330+
v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'
331+
```
332+
283333
### uuid.v7([options[, buffer[, offset]]])
284334

285335
Create an RFC version 7 (random) UUID
@@ -300,7 +350,7 @@ Example:
300350
```javascript
301351
import { v7 as uuidv7 } from 'uuid';
302352

303-
uuidv7(); // ⇨ '01695553-c90c-7aad-9bdd-330d7b3dcb6d'
353+
uuidv7(); // ⇨ '01695553-c90c-722d-9b5d-b38dfbbd4bed'
304354
```
305355

306356
### uuid.validate(str)
@@ -520,5 +570,6 @@ const uuid = require('uuid'); // <== REMOVED!
520570

521571
This usage pattern was already discouraged in `uuid@3` and has been removed in `uuid@7`.
522572

523-
----
524-
Markdown generated from [README_js.md](README_js.md) by [![RunMD Logo](https://i.imgur.com/h0FVyzU.png)](https://github.com/broofa/runmd)
573+
---
574+
575+
Markdown generated from [README_js.md](README_js.md) by <a href="https://github.com/broofa/runmd"><image height="12px" src="https://camo.githubusercontent.com/5c7c603cd1e6a43370b0a5063d457e0dabb74cf317adc7baba183acb686ee8d0/687474703a2f2f692e696d6775722e636f6d2f634a4b6f3662552e706e67" /></a>

‎README_js.md

+53-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ require('crypto').randomUUID = undefined;
2121

2222
For the creation of [RFC9562](https://www.rfc-editor.org/rfc/rfc9562.html) (formally [RFC4122](https://www.rfc-editor.org/rfc/rfc4122.html)) UUIDs
2323

24-
- **Complete** - Support for RFC9562 version 1, 3, 4, 5, and 7 UUIDs
24+
- **Complete** - Support for all RFC9562 (nee RFC4122) UUID versions
2525
- **Cross-platform** - Support for ...
2626
- CommonJS, [ECMAScript Modules](#ecmascript-modules) and [CDN builds](#cdn-builds)
2727
- NodeJS 16+ ([LTS releases](https://github.com/nodejs/Release))
@@ -75,10 +75,13 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ...
7575
| [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `uuid@8.3` |
7676
| [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `uuid@8.3` |
7777
| [`uuid.v1()`](#uuidv1options-buffer-offset) | Create a version 1 (timestamp) UUID | |
78+
| [`uuid.v1ToV6()`](#uuidv1tov6uuid) | Create a version 6 UUID from a version 1 UUID | New in `uuid@10` |
7879
| [`uuid.v3()`](#uuidv3name-namespace-buffer-offset) | Create a version 3 (namespace w/ MD5) UUID | |
7980
| [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | |
8081
| [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
81-
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | `experimental support` |
82+
| [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` |
83+
| [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` |
84+
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` |
8285
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` |
8386
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` |
8487

@@ -200,13 +203,23 @@ Example using `options`:
200203
```javascript --run
201204
import { v1 as uuidv1 } from 'uuid';
202205

203-
const v1options = {
206+
const options = {
204207
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
205208
clockseq: 0x1234,
206209
msecs: new Date('2011-11-01').getTime(),
207210
nsecs: 5678,
208211
};
209-
uuidv1(v1options); // RESULT
212+
uuidv1(options); // RESULT
213+
```
214+
215+
### uuid.v1ToV6(uuid)
216+
217+
Convert a UUID from version 1 to version 6
218+
219+
```javascript --run
220+
import { v1ToV6 } from 'uuid';
221+
222+
v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // RESULT
210223
```
211224

212225
### uuid.v3(name, namespace[, buffer[, offset]])
@@ -289,6 +302,42 @@ import { v5 as uuidv5 } from 'uuid';
289302
uuidv5('https://www.w3.org/', uuidv5.URL); // RESULT
290303
```
291304

305+
### uuid.v6([options[, buffer[, offset]]])
306+
307+
Create an RFC version 6 (timestamp, reordered) UUID
308+
309+
This method takes the same arguments as uuid.v1().
310+
311+
```javascript --run
312+
import { v6 as uuidv6 } from 'uuid';
313+
314+
uuidv6(); // RESULT
315+
```
316+
317+
Example using `options`:
318+
319+
```javascript --run
320+
import { v6 as uuidv6 } from 'uuid';
321+
322+
const options = {
323+
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
324+
clockseq: 0x1234,
325+
msecs: new Date('2011-11-01').getTime(),
326+
nsecs: 5678,
327+
};
328+
uuidv6(options); // RESULT
329+
```
330+
331+
### uuid.v6ToV1(uuid)
332+
333+
Convert a UUID from version 6 to version 1
334+
335+
```javascript --run
336+
import { v6ToV1 } from 'uuid';
337+
338+
v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // RESULT
339+
```
340+
292341
### uuid.v7([options[, buffer[, offset]]])
293342

294343
Create an RFC version 7 (random) UUID

‎bundlewatch.config.json

+10-33
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,17 @@
44
"trackBranches": ["main"]
55
},
66
"files": [
7-
{
8-
"path": "./examples/browser-rollup/dist/v1-size.js",
9-
"maxSize": "1.0 kB"
10-
},
11-
{
12-
"path": "./examples/browser-rollup/dist/v3-size.js",
13-
"maxSize": "2.1 kB"
14-
},
15-
{
16-
"path": "./examples/browser-rollup/dist/v4-size.js",
17-
"maxSize": "0.7 kB"
18-
},
19-
{
20-
"path": "./examples/browser-rollup/dist/v5-size.js",
21-
"maxSize": "1.5 kB"
22-
},
7+
{ "path": "./examples/browser-rollup/dist/v1-size.js", "maxSize": "1.0 kB" },
8+
{ "path": "./examples/browser-rollup/dist/v3-size.js", "maxSize": "2.1 kB" },
9+
{ "path": "./examples/browser-rollup/dist/v4-size.js", "maxSize": "0.7 kB" },
10+
{ "path": "./examples/browser-rollup/dist/v5-size.js", "maxSize": "1.5 kB" },
11+
{ "path": "./examples/browser-rollup/dist/v6-size.js", "maxSize": "1.6 kB" },
2312
{ "path": "./examples/browser-rollup/dist/v7-size.js", "maxSize": "0.8 kB" },
24-
25-
{
26-
"path": "./examples/browser-webpack/dist/v1-size.js",
27-
"maxSize": "1.0 kB"
28-
},
29-
{
30-
"path": "./examples/browser-webpack/dist/v3-size.js",
31-
"maxSize": "2.1 kB"
32-
},
33-
{
34-
"path": "./examples/browser-webpack/dist/v4-size.js",
35-
"maxSize": "0.7 kB"
36-
},
37-
{
38-
"path": "./examples/browser-webpack/dist/v5-size.js",
39-
"maxSize": "1.5 kB"
40-
},
13+
{ "path": "./examples/browser-webpack/dist/v1-size.js", "maxSize": "1.0 kB" },
14+
{ "path": "./examples/browser-webpack/dist/v3-size.js", "maxSize": "2.1 kB" },
15+
{ "path": "./examples/browser-webpack/dist/v4-size.js", "maxSize": "0.7 kB" },
16+
{ "path": "./examples/browser-webpack/dist/v5-size.js", "maxSize": "1.5 kB" },
17+
{ "path": "./examples/browser-webpack/dist/v6-size.js", "maxSize": "1.6 kB" },
4118
{ "path": "./examples/browser-webpack/dist/v7-size.js", "maxSize": "0.8 kB" }
4219
]
4320
}

‎eslint.config.cjs

+3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ module.exports = [
2121
},
2222
parser: babelParser,
2323
},
24+
},
25+
{
2426
rules: {
2527
'no-var': ['error'],
28+
curly: ['error', 'all'],
2629
},
2730
},
2831
{

‎examples/benchmark/benchmark.js

+31
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export default function benchmark(uuid, Benchmark) {
6666
.add('uuid.v5()', function () {
6767
uuid.v5('hello.example.com', uuid.v5.DNS);
6868
})
69+
.add('uuid.v6()', function () {
70+
uuid.v6();
71+
})
6972
.add('uuid.v7()', function () {
7073
uuid.v7();
7174
})
@@ -82,10 +85,38 @@ export default function benchmark(uuid, Benchmark) {
8285
})
8386
.on('complete', function () {
8487
console.log('Fastest is ' + this.filter('fastest').map('name'));
88+
console.log('---\n');
89+
})
90+
.run();
91+
}
92+
93+
function testV6Conversion() {
94+
const suite = new Benchmark.Suite({
95+
onError(event) {
96+
console.error(event.target.error);
97+
},
98+
});
99+
100+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
101+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
102+
103+
suite
104+
.add('uuid.v1ToV6()', function () {
105+
uuid.v1ToV6(V1_ID);
106+
})
107+
.add('uuid.v1ToV6() w/ randomization', function () {
108+
uuid.v1ToV6(V1_ID, true);
109+
})
110+
.add('uuid.v6ToV1()', function () {
111+
uuid.v6ToV1(V6_ID);
112+
})
113+
.on('cycle', function (event) {
114+
console.log(event.target.toString());
85115
})
86116
.run();
87117
}
88118

89119
testParseAndStringify();
90120
testGeneration();
121+
testV6Conversion();
91122
}

‎examples/benchmark/package-lock.json

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/browser-esmodules/example.js

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import pkg from 'uuid/package.json';
2+
import * as uuid from './node_modules/uuid/dist/esm-browser/index.js';
13
import {
2-
NIL as NIL_UUID,
34
MAX as MAX_UUID,
5+
NIL as NIL_UUID,
46
parse as uuidParse,
57
stringify as uuidStringify,
8+
validate as uuidValidate,
9+
version as uuidVersion,
610
v1 as uuidv1,
11+
v1ToV6 as uuidv1ToV6,
712
v3 as uuidv3,
813
v4 as uuidv4,
914
v5 as uuidv5,
15+
v6 as uuidv6,
16+
v6ToV1 as uuidv6ToV1,
1017
v7 as uuidv7,
11-
validate as uuidValidate,
12-
version as uuidVersion,
1318
} from './node_modules/uuid/dist/esm-browser/index.js';
14-
import * as uuid from './node_modules/uuid/dist/esm-browser/index.js';
1519

1620
console.log('uuidv1()', uuidv1());
1721

@@ -45,6 +49,14 @@ console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL));
4549
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
4650
console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
4751

52+
console.log('uuidv6()', uuidv6());
53+
54+
// v6 <-> v1 conversion
55+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
56+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
57+
console.log('uuidv1ToV6()', uuidv1ToV6(V1_ID));
58+
console.log('uuidv6ToV1()', uuidv6ToV1(V6_ID));
59+
4860
// Utility functions
4961
console.log('NIL_UUID', NIL_UUID);
5062
console.log('MAX_UUID', MAX_UUID);
@@ -64,10 +76,17 @@ console.log('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
6476
console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
6577
console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
6678
console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
79+
console.log('uuid.v6()', uuid.v6());
80+
81+
console.log('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
82+
console.log('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
6783

6884
console.log('uuid.NIL', uuid.NIL);
6985
console.log('uuid.MAX', uuid.MAX);
7086
console.log('uuid.parse()', uuid.parse(MY_NAMESPACE));
7187
console.log('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE)));
7288
console.log('uuid.validate()', uuid.validate(MY_NAMESPACE));
7389
console.log('uuid.version()', uuid.version(MY_NAMESPACE));
90+
91+
// Some tools like react-native need to introspect the package.json file
92+
console.log('pkg.name', pkg.name);

‎examples/browser-rollup/example-all.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
import * as uuid from 'uuid';
12
import {
2-
NIL as NIL_UUID,
33
MAX as MAX_UUID,
4+
NIL as NIL_UUID,
45
parse as uuidParse,
56
stringify as uuidStringify,
7+
validate as uuidValidate,
8+
version as uuidVersion,
69
v1 as uuidv1,
10+
v1ToV6 as uuidv1ToV6,
711
v3 as uuidv3,
812
v4 as uuidv4,
913
v5 as uuidv5,
14+
v6 as uuidv6,
15+
v6ToV1 as uuidv6ToV1,
1016
v7 as uuidv7,
11-
validate as uuidValidate,
12-
version as uuidVersion,
1317
} from 'uuid';
14-
import * as uuid from 'uuid';
1518

1619
import testpage from '../utils/testpage';
1720

@@ -50,6 +53,14 @@ testpage(function (addTest, done) {
5053
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
5154
addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
5255

56+
addTest('uuidv6()', uuidv6());
57+
58+
// v6 <-> v1 conversion
59+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
60+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
61+
addTest('uuidv1ToV6()', uuidv1ToV6(V1_ID));
62+
addTest('uuidv6ToV1()', uuidv6ToV1(V6_ID));
63+
5364
// Utility functions
5465
addTest('NIL_UUID', NIL_UUID);
5566
addTest('MAX_UUID', MAX_UUID);
@@ -69,6 +80,10 @@ testpage(function (addTest, done) {
6980
addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
7081
addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
7182
addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
83+
addTest('uuid.v6()', uuid.v6());
84+
85+
addTest('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
86+
addTest('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
7287

7388
addTest('uuid.NIL', uuid.NIL);
7489
addTest('uuid.MAX', uuid.MAX);

‎examples/browser-rollup/package-lock.json

+44-34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/browser-rollup/rollup.config.js

+8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ module.exports = [
6868
},
6969
plugins,
7070
},
71+
{
72+
input: './size-v6.js',
73+
output: {
74+
file: 'dist/v6-size.js',
75+
format: 'cjs',
76+
},
77+
plugins,
78+
},
7179
{
7280
input: './size-v7.js',
7381
output: {

‎examples/browser-rollup/size-v6.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { v6 as uuidv6 } from 'uuid';
2+
3+
uuidv6();

‎examples/browser-webpack/example-all-require.js

+15
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ const {
55
parse: uuidParse,
66
stringify: uuidStringify,
77
v1: uuidv1,
8+
v1ToV6: uuidv1ToV6,
89
v3: uuidv3,
910
v4: uuidv4,
1011
v5: uuidv5,
12+
v6: uuidv6,
13+
v6ToV1: uuidv6ToV1,
1114
v7: uuidv7,
1215
validate: uuidValidate,
1316
version: uuidVersion,
@@ -43,13 +46,21 @@ testpage(function (addTest, done) {
4346
// ... using predefined URL namespace (for, well, URLs)
4447
addTest('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL));
4548

49+
// v6 <-> v1 conversion
50+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
51+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
52+
addTest('uuidv1ToV6()', uuidv1ToV6(V1_ID));
53+
addTest('uuidv6ToV1()', uuidv6ToV1(V6_ID));
54+
4655
// ... using a custom namespace
4756
//
4857
// Note: Custom namespaces should be a UUID string specific to your application!
4958
// E.g. the one here was generated using this modules `uuid` CLI.
5059
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
5160
addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
5261

62+
addTest('uuidv6()', uuidv6());
63+
5364
// Utility functions
5465
addTest('NIL_UUID', NIL_UUID);
5566
addTest('MAX_UUID', MAX_UUID);
@@ -69,6 +80,10 @@ testpage(function (addTest, done) {
6980
addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
7081
addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
7182
addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
83+
addTest('uuid.v6()', uuid.v6());
84+
85+
addTest('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
86+
addTest('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
7287

7388
addTest('uuid.NIL', uuid.NIL);
7489
addTest('uuid.MAX', uuid.MAX);

‎examples/browser-webpack/example-all.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
import * as uuid from 'uuid';
12
import {
2-
NIL as NIL_UUID,
33
MAX as MAX_UUID,
4+
NIL as NIL_UUID,
45
parse as uuidParse,
56
stringify as uuidStringify,
7+
validate as uuidValidate,
8+
version as uuidVersion,
69
v1 as uuidv1,
10+
v1ToV6 as uuidv1ToV6,
711
v3 as uuidv3,
812
v4 as uuidv4,
913
v5 as uuidv5,
14+
v6 as uuidv6,
15+
v6ToV1 as uuidv6ToV1,
1016
v7 as uuidv7,
11-
validate as uuidValidate,
12-
version as uuidVersion,
1317
} from 'uuid';
14-
import * as uuid from 'uuid';
1518

1619
import testpage from '../utils/testpage';
1720

@@ -50,6 +53,14 @@ testpage(function (addTest, done) {
5053
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
5154
addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
5255

56+
addTest('uuidv6()', uuidv6());
57+
58+
// v6 <-> v1 conversion
59+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
60+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
61+
addTest('uuidv1ToV6()', uuidv1ToV6(V1_ID));
62+
addTest('uuidv6ToV1()', uuidv6ToV1(V6_ID));
63+
5364
// Utility functions
5465
addTest('NIL_UUID', NIL_UUID);
5566
addTest('MAX_UUID', MAX_UUID);
@@ -69,6 +80,10 @@ testpage(function (addTest, done) {
6980
addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
7081
addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
7182
addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
83+
addTest('uuid.v6()', uuid.v6());
84+
85+
addTest('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
86+
addTest('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
7287

7388
addTest('uuid.NIL', uuid.NIL);
7489
addTest('uuid.MAX', uuid.MAX);

‎examples/browser-webpack/package-lock.json

+44-34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/browser-webpack/size-v6.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { v6 as uuidv6 } from 'uuid';
2+
3+
uuidv6();

‎examples/browser-webpack/webpack.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313
'v3-size': './size-v3.js',
1414
'v4-size': './size-v4.js',
1515
'v5-size': './size-v5.js',
16+
'v6-size': './size-v6.js',
1617
'v7-size': './size-v7.js',
1718
},
1819
// Webpack now produces builds that are incompatible with IE11:

‎examples/node-commonjs/example.js

+15
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ const {
44
parse: uuidParse,
55
stringify: uuidStringify,
66
v1: uuidv1,
7+
v1ToV6: uuidv1ToV6,
78
v3: uuidv3,
89
v4: uuidv4,
910
v5: uuidv5,
11+
v6: uuidv6,
12+
v6ToV1: uuidv6ToV1,
1013
v7: uuidv7,
1114
validate: uuidValidate,
1215
version: uuidVersion,
@@ -46,6 +49,14 @@ console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL));
4649
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
4750
console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
4851

52+
console.log('uuidv6()', uuidv6());
53+
54+
// v6 <-> v1 conversion
55+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
56+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
57+
console.log('uuidv1ToV6()', uuidv1ToV6(V1_ID));
58+
console.log('uuidv6ToV1()', uuidv6ToV1(V6_ID));
59+
4960
// Utility functions
5061
console.log('NIL_UUID', NIL_UUID);
5162
console.log('MAX_UUID', MAX_UUID);
@@ -65,6 +76,10 @@ console.log('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
6576
console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
6677
console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
6778
console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
79+
console.log('uuid.v6()', uuid.v6());
80+
81+
console.log('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
82+
console.log('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
6883

6984
console.log('uuid.NIL', uuid.NIL);
7085
console.log('uuid.MAX', uuid.MAX);

‎examples/node-esmodules/example.mjs

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import * as uuid from 'uuid';
12
import {
2-
NIL as NIL_UUID,
33
MAX as MAX_UUID,
4+
NIL as NIL_UUID,
45
parse as uuidParse,
56
stringify as uuidStringify,
7+
validate as uuidValidate,
8+
version as uuidVersion,
69
v1 as uuidv1,
10+
v1ToV6 as uuidv1ToV6,
711
v3 as uuidv3,
812
v4 as uuidv4,
913
v5 as uuidv5,
14+
v6 as uuidv6,
15+
v6ToV1 as uuidv6ToV1,
1016
v7 as uuidv7,
11-
validate as uuidValidate,
12-
version as uuidVersion,
1317
} from 'uuid';
14-
import * as uuid from 'uuid';
18+
import pkg from 'uuid/package.json';
1519

1620
console.log('uuidv1()', uuidv1());
1721

@@ -45,6 +49,14 @@ console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL));
4549
// const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
4650
console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE));
4751

52+
console.log('uuidv6()', uuidv6());
53+
54+
// v6 <-> v1 conversion
55+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
56+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
57+
console.log('uuidv1ToV6()', uuidv1ToV6(V1_ID));
58+
console.log('uuidv6ToV1()', uuidv6ToV1(V6_ID));
59+
4860
// Utility functions
4961
console.log('NIL_UUID', NIL_UUID);
5062
console.log('MAX_UUID', MAX_UUID);
@@ -64,10 +76,17 @@ console.log('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
6476
console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS));
6577
console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL));
6678
console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE));
79+
console.log('uuid.v6()', uuid.v6());
80+
81+
console.log('uuid.v1ToV6()', uuid.v1ToV6(V1_ID));
82+
console.log('uuid.v6ToV1()', uuid.v6ToV1(V6_ID));
6783

6884
console.log('uuid.NIL', uuid.NIL);
6985
console.log('uuid.MAX', uuid.MAX);
7086
console.log('uuid.parse()', uuid.parse(MY_NAMESPACE));
7187
console.log('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE)));
7288
console.log('uuid.validate()', uuid.validate(MY_NAMESPACE));
7389
console.log('uuid.version()', uuid.version(MY_NAMESPACE));
90+
91+
// Some tools like react-native need to introspect the package.json file
92+
console.log('pkg.name', pkg.name);

‎examples/node-webpack/example-all.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { v1 as uuidv1, v4 as uuidv4, v3 as uuidv3, v5 as uuidv5 } from 'uuid';
21
import * as uuid from 'uuid';
2+
import { v1 as uuidv1, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5 } from 'uuid';
33

44
console.log('uuidv1()', uuidv1());
55
console.log('uuidv4()', uuidv4());

‎package-lock.json

+9,175-15,247
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+9-3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@
6262
"@babel/preset-env": "7.24.6",
6363
"@commitlint/cli": "19.3.0",
6464
"@commitlint/config-conventional": "19.2.2",
65+
"@wdio/browserstack-service": "7.16.10",
66+
"@wdio/cli": "7.16.10",
67+
"@wdio/jasmine-framework": "7.16.6",
68+
"@wdio/local-runner": "7.16.10",
69+
"@wdio/spec-reporter": "7.16.9",
70+
"@wdio/static-server-service": "7.16.6",
6571
"bundlewatch": "0.3.3",
6672
"eslint": "9.4.0",
6773
"eslint-plugin-prettier": "5.1.3",
@@ -104,7 +110,7 @@
104110
"test:node": "npm-run-all --parallel examples:node:**",
105111
"test:pack": "./scripts/testpack.sh",
106112
"pretest:benchmark": "npm run build",
107-
"test:benchmark": "cd examples/benchmark && npm install && npm test",
113+
"test:benchmark": "cd examples/benchmark && HUSKY=0 npm install && npm test",
108114
"prettier:check": "prettier --check .",
109115
"prettier:fix": "prettier --write .",
110116
"bundlewatch": "npm run pretest:browser && bundlewatch --config bundlewatch.config.json",
@@ -121,10 +127,10 @@
121127
},
122128
"lint-staged": {
123129
"*": [
124-
"prettier --write"
130+
"prettier --no-error-on-unmatched-pattern --write"
125131
],
126132
"*.{js,jsx}": [
127-
"eslint --fix"
133+
"eslint --no-error-on-unmatched-pattern --fix"
128134
]
129135
},
130136
"standard-version": {

‎src/index.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
export { default as MAX } from './max.js';
2+
export { default as NIL } from './nil.js';
3+
export { default as parse } from './parse.js';
4+
export { default as stringify } from './stringify.js';
15
export { default as v1 } from './v1.js';
6+
export { default as v1ToV6 } from './v1ToV6.js';
27
export { default as v3 } from './v3.js';
38
export { default as v4 } from './v4.js';
49
export { default as v5 } from './v5.js';
10+
export { default as v6 } from './v6.js';
11+
export { default as v6ToV1 } from './v6ToV1.js';
512
export { default as v7 } from './v7.js';
6-
export { default as NIL } from './nil.js';
7-
export { default as MAX } from './max.js';
8-
export { default as version } from './version.js';
913
export { default as validate } from './validate.js';
10-
export { default as stringify } from './stringify.js';
11-
export { default as parse } from './parse.js';
14+
export { default as version } from './version.js';

‎src/v1.js

+32-18
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,50 @@ function v1(options, buf, offset) {
1919
const b = buf || new Array(16);
2020

2121
options = options || {};
22-
let node = options.node || _nodeId;
23-
let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
22+
let node = options.node;
23+
let clockseq = options.clockseq;
2424

25-
// node and clockseq need to be initialized to random values if they're not
26-
// specified. We do this lazily to minimize issues related to insufficient
27-
// system entropy. See #189
25+
// v1 only: Use cached `node` and `clockseq` values
26+
if (!options._v6) {
27+
if (!node) {
28+
node = _nodeId;
29+
}
30+
if (clockseq == null) {
31+
clockseq = _clockseq;
32+
}
33+
}
34+
35+
// Handle cases where we need entropy. We do this lazily to minimize issues
36+
// related to insufficient system entropy. See #189
2837
if (node == null || clockseq == null) {
2938
const seedBytes = options.random || (options.rng || rng)();
3039

40+
// Randomize node
3141
if (node == null) {
32-
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
33-
node = _nodeId = [
34-
seedBytes[0] | 0x01,
35-
seedBytes[1],
36-
seedBytes[2],
37-
seedBytes[3],
38-
seedBytes[4],
39-
seedBytes[5],
40-
];
42+
node = [seedBytes[0], seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
43+
44+
// v1 only: cache node value for reuse
45+
if (!_nodeId && !options._v6) {
46+
// per RFC4122 4.5: Set MAC multicast bit (v1 only)
47+
node[0] |= 0x01; // Set multicast bit
48+
49+
_nodeId = node;
50+
}
4151
}
4252

53+
// Randomize clockseq
4354
if (clockseq == null) {
4455
// Per 4.2.2, randomize (14 bit) clockseq
45-
clockseq = _clockseq = ((seedBytes[6] << 8) | seedBytes[7]) & 0x3fff;
56+
clockseq = ((seedBytes[6] << 8) | seedBytes[7]) & 0x3fff;
57+
if (_clockseq === undefined && !options._v6) {
58+
_clockseq = clockseq;
59+
}
4660
}
4761
}
4862

49-
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
50-
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
51-
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
63+
// v1 & v6 timestamps are 100 nano-second units since the Gregorian epoch,
64+
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so time is
65+
// handled internally as 'msecs' (integer milliseconds) and 'nsecs'
5266
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
5367
let msecs = options.msecs !== undefined ? options.msecs : Date.now();
5468

‎src/v1ToV6.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import parse from './parse.js';
2+
import { unsafeStringify } from './stringify.js';
3+
4+
/**
5+
* Convert a v1 UUID to a v6 UUID
6+
*
7+
* @param {string|Uint8Array} uuid - The v1 UUID to convert to v6
8+
* @returns {string|Uint8Array} The v6 UUID as the same type as the `uuid` arg
9+
* (string or Uint8Array)
10+
*/
11+
export default function v1ToV6(uuid) {
12+
const v1Bytes = typeof uuid === 'string' ? parse(uuid) : uuid;
13+
14+
const v6Bytes = _v1ToV6(v1Bytes);
15+
16+
return typeof uuid === 'string' ? unsafeStringify(v6Bytes) : v6Bytes;
17+
}
18+
19+
// Do the field transformation needed for v1 -> v6
20+
function _v1ToV6(v1Bytes, randomize = false) {
21+
return Uint8Array.of(
22+
((v1Bytes[6] & 0x0f) << 4) | ((v1Bytes[7] >> 4) & 0x0f),
23+
((v1Bytes[7] & 0x0f) << 4) | ((v1Bytes[4] & 0xf0) >> 4),
24+
((v1Bytes[4] & 0x0f) << 4) | ((v1Bytes[5] & 0xf0) >> 4),
25+
((v1Bytes[5] & 0x0f) << 4) | ((v1Bytes[0] & 0xf0) >> 4),
26+
27+
((v1Bytes[0] & 0x0f) << 4) | ((v1Bytes[1] & 0xf0) >> 4),
28+
((v1Bytes[1] & 0x0f) << 4) | ((v1Bytes[2] & 0xf0) >> 4),
29+
30+
0x60 | (v1Bytes[2] & 0x0f),
31+
v1Bytes[3],
32+
33+
v1Bytes[8],
34+
v1Bytes[9],
35+
v1Bytes[10],
36+
v1Bytes[11],
37+
v1Bytes[12],
38+
v1Bytes[13],
39+
v1Bytes[14],
40+
v1Bytes[15]
41+
);
42+
}

‎src/v6.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { unsafeStringify } from './stringify.js';
2+
import v1 from './v1.js';
3+
import v1ToV6 from './v1ToV6.js';
4+
5+
/**
6+
*
7+
* @param {object} options
8+
* @param {Uint8Array=} buf
9+
* @param {number=} offset
10+
* @returns
11+
*/
12+
export default function v6(options = {}, buf, offset = 0) {
13+
// v6 is v1 with different field layout, so we start with a v1 UUID, albeit
14+
// with slightly different behavior around how the clock_seq and node fields
15+
// are randomized, which is why we call v1 with _v6: true.
16+
let bytes = v1({ ...options, _v6: true }, new Uint8Array(16));
17+
18+
// Reorder the fields to v6 layout.
19+
bytes = v1ToV6(bytes);
20+
21+
// Return as a byte array if requested
22+
if (buf) {
23+
for (let i = 0; i < 16; i++) {
24+
buf[offset + i] = bytes[i];
25+
}
26+
return buf;
27+
}
28+
29+
return unsafeStringify(bytes);
30+
}

‎src/v6ToV1.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import parse from './parse.js';
2+
import { unsafeStringify } from './stringify.js';
3+
4+
/**
5+
* Convert a v6 UUID to a v1 UUID
6+
*
7+
* @param {string|Uint8Array} uuid - The v6 UUID to convert to v6
8+
* @returns {string|Uint8Array} The v1 UUID as the same type as the `uuid` arg
9+
* (string or Uint8Array)
10+
*/
11+
export default function v6ToV1(uuid) {
12+
const v6Bytes = typeof uuid === 'string' ? parse(uuid) : uuid;
13+
14+
const v1Bytes = _v6ToV1(v6Bytes);
15+
16+
return typeof uuid === 'string' ? unsafeStringify(v1Bytes) : v1Bytes;
17+
}
18+
19+
// Do the field transformation needed for v6 -> v1
20+
function _v6ToV1(v6Bytes) {
21+
return Uint8Array.of(
22+
((v6Bytes[3] & 0x0f) << 4) | ((v6Bytes[4] >> 4) & 0x0f),
23+
((v6Bytes[4] & 0x0f) << 4) | ((v6Bytes[5] & 0xf0) >> 4),
24+
((v6Bytes[5] & 0x0f) << 4) | (v6Bytes[6] & 0x0f),
25+
v6Bytes[7],
26+
27+
((v6Bytes[1] & 0x0f) << 4) | ((v6Bytes[2] & 0xf0) >> 4),
28+
((v6Bytes[2] & 0x0f) << 4) | ((v6Bytes[3] & 0xf0) >> 4),
29+
30+
0x10 | ((v6Bytes[0] & 0xf0) >> 4),
31+
((v6Bytes[0] & 0x0f) << 4) | ((v6Bytes[1] & 0xf0) >> 4),
32+
33+
v6Bytes[8],
34+
v6Bytes[9],
35+
v6Bytes[10],
36+
v6Bytes[11],
37+
v6Bytes[12],
38+
v6Bytes[13],
39+
v6Bytes[14],
40+
v6Bytes[15]
41+
);
42+
}

‎test/browser/browser.spec.js

+27-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
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;
44
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;
5+
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;
56
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;
67

8+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
9+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
10+
711
const v1 = (result) => expect(result).toMatch(v1Regex);
812
const v4 = (result) => expect(result).toMatch(v4Regex);
13+
const v6 = (result) => expect(result).toMatch(v6Regex);
914
const v7 = (result) => expect(result).toMatch(v7Regex);
1015
const v3dns = (result) => expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6');
1116
const v3url = (result) => expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138');
@@ -14,6 +19,9 @@ const v5dns = (result) => expect(result).toBe('fdda765f-fc57-5604-a269-52a7df816
1419
const v5url = (result) => expect(result).toBe('3bbcee75-cecc-5b56-8031-b6641c1ed1f1');
1520
const v5custom = (result) => expect(result).toBe('c49c5142-4d9a-5940-a926-612ede0ec632');
1621

22+
const v1ToV6 = (result) => expect(result).toBe(V6_ID);
23+
const v6ToV1 = (result) => expect(result).toBe(V1_ID);
24+
1725
const nil = (result) => expect(result).toBe('00000000-0000-0000-0000-000000000000');
1826
const max = (result) => expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff');
1927
const parse = (result) =>
@@ -32,6 +40,10 @@ const expectations = {
3240
'uuidv5() DNS': v5dns,
3341
'uuidv5() URL': v5url,
3442
'uuidv5() MY_NAMESPACE': v5custom,
43+
'uuidv6()': v6,
44+
45+
'uuidv1ToV6()': v1ToV6,
46+
'uuidv6ToV1()': v6ToV1,
3547

3648
NIL_UUID: nil,
3749
MAX_UUID: max,
@@ -49,6 +61,10 @@ const expectations = {
4961
'uuid.v5() DNS': v5dns,
5062
'uuid.v5() URL': v5url,
5163
'uuid.v5() MY_NAMESPACE': v5custom,
64+
'uuid.v6()': v6,
65+
66+
'uuid.v1ToV6()': v1ToV6,
67+
'uuid.v6ToV1()': v6ToV1,
5268

5369
'uuid.NIL': nil,
5470
'uuid.MAX': max,
@@ -82,34 +98,39 @@ describe('BrowserStack Local Testing', () => {
8298
const resultEl = await element.$('dd');
8399
const result = await resultEl.getText();
84100

85-
if (!expectations[title]) throw new Error(`Unexpected title: ${title}`);
101+
if (!expectations[title]) {
102+
throw new Error(`Unexpected title: ${title}`);
103+
}
86104

87105
expectations[title](result);
88106
titles.push(title);
89107
}
90108

91-
expect(titles).toEqual(expectationTitles.filter(titleFilter));
109+
// Confirm the expected titles are all present
110+
const expectedTitles = expectationTitles.filter(titleFilter);
111+
expect(titles.length).toEqual(expectedTitles.length);
112+
expect(titles.sort()).toEqual(expectedTitles.sort());
92113
}
93114

94115
describe('webpack', () => {
95116
it('it renders all', async () =>
96117
testExpectations('browser-webpack/example-all.html', () => true));
97118

98119
it('it renders v1 only', async () =>
99-
testExpectations('browser-webpack/example-v1.html', (title) => title.includes('uuidv1')));
120+
testExpectations('browser-webpack/example-v1.html', (title) => title.includes('uuidv1()')));
100121

101122
it('it renders v4 only', async () =>
102-
testExpectations('browser-webpack/example-v4.html', (title) => title.includes('uuidv4')));
123+
testExpectations('browser-webpack/example-v4.html', (title) => title.includes('uuidv4()')));
103124
});
104125

105126
describe('rollup', () => {
106127
it('it renders all', async () =>
107128
testExpectations('browser-rollup/example-all.html', () => true));
108129

109130
it('it renders v1 only', async () =>
110-
testExpectations('browser-rollup/example-v1.html', (title) => title.includes('uuidv1')));
131+
testExpectations('browser-rollup/example-v1.html', (title) => title.includes('uuidv1()')));
111132

112133
it('it renders v4 only', async () =>
113-
testExpectations('browser-rollup/example-v4.html', (title) => title.includes('uuidv4')));
134+
testExpectations('browser-rollup/example-v4.html', (title) => title.includes('uuidv4(')));
114135
});
115136
});

‎test/unit/v1.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe('v1', () => {
7474
node: [0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10],
7575
};
7676

77-
test('explicit options product expected id', () => {
77+
test('explicit options produce expected id', () => {
7878
// Verify explicit options produce expected id
7979
const id = v1(fullOptions);
8080
assert(id === 'd9428888-122b-11e1-b85c-61cd3cbb3210', 'Explicit options produce expected id');

‎test/unit/v6.test.js

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import assert from 'assert';
2+
import v1ToV6 from '../../src/v1ToV6.js';
3+
import v6 from '../../src/v6.js';
4+
import v6ToV1 from '../../src/v6ToV1.js';
5+
6+
describe('v6', () => {
7+
const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48';
8+
const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48';
9+
10+
const fullOptions = {
11+
msecs: 1321651533573,
12+
nsecs: 5432,
13+
clockseq: 0x385c,
14+
node: [0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10],
15+
};
16+
17+
const EXPECTED_BYTES = [30, 17, 34, 189, 148, 40, 104, 136, 184, 92, 97, 205, 60, 187, 50, 16];
18+
19+
test('default behavior', () => {
20+
// Verify explicit options produce expected id
21+
const id = v6();
22+
assert(
23+
/[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(id),
24+
'id is valid v6 UUID'
25+
);
26+
});
27+
28+
test('default behavior (binary type)', () => {
29+
const buffer = [];
30+
const result = v6(fullOptions, buffer);
31+
assert.deepEqual(buffer, EXPECTED_BYTES);
32+
assert.strictEqual(buffer, result);
33+
});
34+
35+
test('all options', () => {
36+
// Verify explicit options produce expected id
37+
const id = v6(fullOptions);
38+
assert.equal(id, '1e1122bd-9428-6888-b85c-61cd3cbb3210');
39+
});
40+
41+
test('sort by creation time', () => {
42+
// Verify ids sort by creation time
43+
const ids = [];
44+
for (let i = 0; i < 5; i++) {
45+
ids.push(v6({ msecs: i * 1000 }));
46+
}
47+
assert.deepEqual(ids, ids.slice().sort());
48+
});
49+
50+
test('creating at array offset', () => {
51+
const buffer = [];
52+
v6(fullOptions, buffer, 0);
53+
v6(fullOptions, buffer, 16);
54+
assert.deepEqual(buffer, EXPECTED_BYTES.concat(EXPECTED_BYTES));
55+
});
56+
57+
test('v1 -> v6 conversion', () => {
58+
const id = v1ToV6(V1_ID);
59+
assert.equal(id, V6_ID);
60+
});
61+
62+
test('v6 -> v1 conversion', () => {
63+
const id = v6ToV1(V6_ID);
64+
assert.equal(id, V1_ID);
65+
});
66+
});

‎test/unit/validate.test.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from 'assert';
2-
import validate from '../../src/validate.js';
3-
import NIL from '../../src/nil.js';
42
import MAX from '../../src/max.js';
3+
import NIL from '../../src/nil.js';
4+
import validate from '../../src/validate.js';
55

66
describe('validate', () => {
77
test('validate uuid', () => {
@@ -22,11 +22,14 @@ describe('validate', () => {
2222
// v5
2323
assert.strictEqual(validate('90123e1c-7512-523e-bb28-76fab9f2f73d'), true);
2424

25+
// v6
26+
assert.strictEqual(validate('1ef21d2f-1207-6660-8c4f-419efbd44d48'), true);
27+
2528
// v7
2629
assert.strictEqual(validate('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'), true);
2730

2831
// test invalid/unsupported UUID versions
29-
[0, 2, 6, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'].forEach((v) => {
32+
[0, 2, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'].forEach((v) => {
3033
assert.strictEqual(
3134
validate('12300000-0000-' + v + '000-0000-000000000000'),
3235
false,
@@ -44,11 +47,15 @@ describe('validate', () => {
4447

4548
// NIL UUIDs that have a bit set (incorrectly) should not validate
4649
for (let charIndex = 0; charIndex < 36; charIndex++) {
47-
if (charIndex === 14) continue; // version field
50+
if (charIndex === 14) {
51+
continue;
52+
} // version field
4853

4954
for (let bit = 0; bit < 4; bit++) {
5055
const chars = NIL.split('');
51-
if (chars[charIndex] === '-') continue;
56+
if (chars[charIndex] === '-') {
57+
continue;
58+
}
5259

5360
chars[charIndex] = (1 << bit).toString(16);
5461
assert.strictEqual(validate(chars.join('')), false);

‎test/unit/version.test.js

+6-19
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,24 @@
11
import assert from 'assert';
2-
import version from '../../src/version.js';
3-
import NIL from '../../src/nil.js';
42
import MAX from '../../src/max.js';
3+
import NIL from '../../src/nil.js';
4+
import version from '../../src/version.js';
55

66
describe('version', () => {
77
test('check uuid version', () => {
88
assert.strictEqual(version(NIL), 0);
99
assert.strictEqual(version(MAX), 15);
1010

1111
assert.strictEqual(version('d9428888-122b-11e1-b85c-61cd3cbb3210'), 1);
12-
13-
assert.strictEqual(version('109156be-c4fb-41ea-b1b4-efe1671c5836'), 4);
14-
1512
assert.strictEqual(version('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'), 3);
16-
13+
assert.strictEqual(version('109156be-c4fb-41ea-b1b4-efe1671c5836'), 4);
1714
assert.strictEqual(version('90123e1c-7512-523e-bb28-76fab9f2f73d'), 5);
18-
15+
assert.strictEqual(version('1ef21d2f-1207-6660-8c4f-419efbd44d48'), 6);
1916
assert.strictEqual(version('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'), 7);
2017

2118
assert.throws(() => version());
22-
2319
assert.throws(() => version(''));
24-
2520
assert.throws(() => version('invalid uuid string'));
26-
27-
assert.throws(() => {
28-
version('00000000000000000000000000000000');
29-
});
30-
31-
assert.throws(() => {
32-
version(
33-
'=Y00a-f*v00b*-00c-00d#-p00f\b-00g-00h-####00i^^^-00j*1*2*3&-L00k-\n00l-/00m-----00n-fg000-00p-00r+'
34-
);
35-
});
21+
assert.throws(() => version('00000000000000000000000000000000'));
22+
assert.throws(() => version('=Y00a-f*v00b*-00c-00d#-p00f\b-00g-00h-##0p-00r+'));
3623
});
3724
});

‎wrapper.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import uuid from './dist/index.js';
22
export const v1 = uuid.v1;
3+
export const v1ToV6 = uuid.v1ToV6;
34
export const v3 = uuid.v3;
45
export const v4 = uuid.v4;
56
export const v5 = uuid.v5;
7+
export const v6 = uuid.v6;
8+
export const v6ToV1 = uuid.v6ToV1;
69
export const v7 = uuid.v7;
710
export const NIL = uuid.NIL;
811
export const MAX = uuid.MAX;

0 commit comments

Comments
 (0)
Please sign in to comment.