Skip to content

Commit

Permalink
feat: implement uuid7 (uuidjs#580)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmccarren committed Jan 22, 2023
1 parent eca69af commit 0b8f680
Show file tree
Hide file tree
Showing 32 changed files with 235 additions and 6 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -3,3 +3,4 @@ Christoph Tavan <dev@tavan.de>
AJ ONeal <coolaj86@gmail.com>
Vincent Voyer <vincent@zeroload.net>
Roman Shtylman <shtylman@gmail.com>
Patrick McCarren <patrick@cumulative.io>
27 changes: 26 additions & 1 deletion README.md
Expand Up @@ -6,7 +6,7 @@

For the creation of [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) UUIDs

- **Complete** - Support for RFC4122 version 1, 3, 4, and 5 UUIDs
- **Complete** - Support for RFC4122 version 1, 3, 4, 5, and 7 UUIDs
- **Cross-platform** - Support for ...
- CommonJS, [ECMAScript Modules](#ecmascript-modules) and [CDN builds](#cdn-builds)
- Node 12, 14, 16, 18
Expand Down Expand Up @@ -56,6 +56,7 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ...
| [`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.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
| [`uuid.v7()`](#uuidv7unix-epoch-time-based) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@9.?` |
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` |
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` |

Expand Down Expand Up @@ -248,6 +249,28 @@ import { v5 as uuidv5 } from 'uuid';
uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'
```

### uuid.v7([options[, buffer[, offset]]])

Create an RFC version 7 (random) UUID

| | |
| --- | --- |
| [`options`] | `Object` with one or more of the following properties: |
| [`options.msecs`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) |
| [`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) |
| [`buffer`] | `Array \| Buffer` If specified, uuid will be written here in byte-form, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |

Example:

```javascript
import { v7 as uuidv7 } from 'uuid';

uuidv7(); // ⇨ '017f22e2-79b0-7cc3-98c4-dc0c0c07398f'
```

### uuid.validate(str)

Test a string to see if it is a valid UUID
Expand Down Expand Up @@ -322,6 +345,8 @@ Usage:
uuid v3 <name> <namespace uuid>
uuid v4
uuid v5 <name> <namespace uuid>
uuid v7
uuid v7 <unix timestamp>
uuid --help

Note: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs
Expand Down
25 changes: 24 additions & 1 deletion README_js.md
Expand Up @@ -21,7 +21,7 @@ require('crypto').randomUUID = undefined;

For the creation of [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) UUIDs

- **Complete** - Support for RFC4122 version 1, 3, 4, and 5 UUIDs
- **Complete** - Support for RFC4122 version 1, 3, 4, 5, and 7 UUIDs
- **Cross-platform** - Support for ...
- CommonJS, [ECMAScript Modules](#ecmascript-modules) and [CDN builds](#cdn-builds)
- Node 12, 14, 16, 18
Expand Down Expand Up @@ -71,6 +71,7 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ...
| [`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.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
| [`uuid.v7()`](#uuidv7unix-epoch-time-based) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@9.?` |
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` |
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` |

Expand Down Expand Up @@ -257,6 +258,28 @@ import { v5 as uuidv5 } from 'uuid';
uuidv5('https://www.w3.org/', uuidv5.URL); // RESULT
```

### uuid.v7([options[, buffer[, offset]]])

Create an RFC version 7 (random) UUID

| | |
| --- | --- |
| [`options`] | `Object` with one or more of the following properties: |
| [`options.msecs`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) |
| [`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) |
| [`buffer`] | `Array \| Buffer` If specified, uuid will be written here in byte-form, starting at `offset` |
| [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` |
| _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` |

Example:

```javascript --run
import { v7 as uuidv7 } from 'uuid';

uuidv7(); // RESULT
```

### uuid.validate(str)

Test a string to see if it is a valid UUID
Expand Down
4 changes: 3 additions & 1 deletion bundlewatch.config.json
Expand Up @@ -4,10 +4,12 @@
{ "path": "./examples/browser-rollup/dist/v3-size.js", "maxSize": "2.1 kB" },
{ "path": "./examples/browser-rollup/dist/v4-size.js", "maxSize": "0.7 kB" },
{ "path": "./examples/browser-rollup/dist/v5-size.js", "maxSize": "1.5 kB" },
{ "path": "./examples/browser-rollup/dist/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/v5-size.js", "maxSize": "1.5 kB" },
{ "path": "./examples/browser-webpack/dist/v7-size.js", "maxSize": "0.8 kB" }
]
}
14 changes: 14 additions & 0 deletions examples/benchmark/benchmark.js
Expand Up @@ -57,12 +57,26 @@ export default function benchmark(uuid, Benchmark) {
.add('uuid.v4() fill existing array', function () {
uuid.v4(null, array, 0);
})
.add('uuid.v4() without native generation', function () {
uuid.v4({}); // passing an object instead of null bypasses native.randomUUID
})
.add('uuid.v3()', function () {
uuid.v3('hello.example.com', uuid.v3.DNS);
})
.add('uuid.v5()', function () {
uuid.v5('hello.example.com', uuid.v5.DNS);
})
.add('uuid.v7()', function () {
uuid.v7();
})
.add('uuid.v7() fill existing array', function () {
uuid.v7(null, array, 0);
})
.add('uuid.v7() with defined time', function () {
uuid.v7({
msecs: 1645557742000,
});
})
.on('cycle', function (event) {
console.log(event.target.toString());
})
Expand Down
4 changes: 4 additions & 0 deletions examples/browser-esmodules/example.js
Expand Up @@ -6,6 +6,7 @@ import {
v3 as uuidv3,
v4 as uuidv4,
v5 as uuidv5,
v7 as uuidv7,
validate as uuidValidate,
version as uuidVersion,
} from './node_modules/uuid/dist/esm-browser/index.js';
Expand All @@ -15,6 +16,8 @@ console.log('uuidv1()', uuidv1());

console.log('uuidv4()', uuidv4());

console.log('uuidv7()', uuidv7());

// ... using predefined DNS namespace (for domain names)
console.log('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));

Expand Down Expand Up @@ -52,6 +55,7 @@ console.log('Same with default export');

console.log('uuid.v1()', uuid.v1());
console.log('uuid.v4()', uuid.v4());
console.log('uuid.v7()', uuid.v7());
console.log('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
console.log('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
console.log('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
Expand Down
3 changes: 2 additions & 1 deletion examples/browser-rollup/README.md
Expand Up @@ -7,11 +7,12 @@ npm start

Then navigate to `example-*.html`.

The `example-v{1,4}.js` demonstrate that treeshaking works as expected:
The `example-v{1,4,7}.js` demonstrate that treeshaking works as expected:

```
$ du -sh dist/*
20K dist/all.js
8.0K dist/v1.js
4.0K dist/v4.js
4.0K dist/v7.js
```
4 changes: 4 additions & 0 deletions examples/browser-rollup/example-all.js
Expand Up @@ -6,6 +6,7 @@ import {
v3 as uuidv3,
v4 as uuidv4,
v5 as uuidv5,
v7 as uuidv7,
validate as uuidValidate,
version as uuidVersion,
} from 'uuid';
Expand All @@ -20,6 +21,8 @@ testpage(function (addTest, done) {

addTest('uuidv4()', uuidv4());

addTest('uuidv7()', uuidv7());

// ... using predefined DNS namespace (for domain names)
addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));

Expand Down Expand Up @@ -57,6 +60,7 @@ testpage(function (addTest, done) {

addTest('uuid.v1()', uuid.v1());
addTest('uuid.v4()', uuid.v4());
addTest('uuid.v7()', uuid.v7());
addTest('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
addTest('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
addTest('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
Expand Down
12 changes: 12 additions & 0 deletions examples/browser-rollup/example-v7.html
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>

<head>
<title>UUID esmodule webpack example</title>
</head>

<body>
<script type="text/javascript" src="./dist/v7.js"></script>
</body>

</html>
8 changes: 8 additions & 0 deletions examples/browser-rollup/example-v7.js
@@ -0,0 +1,8 @@
import { v7 as uuidv7 } from 'uuid';

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

testpage(function (addTest, done) {
addTest('uuidv7()', uuidv7());
done();
});
1 change: 1 addition & 0 deletions examples/browser-rollup/example.html
Expand Up @@ -3,4 +3,5 @@
<p>Please open the Developer Console to view output</p>
<script type="text/javascript" src="./dist/v1.js"></script>
<script type="text/javascript" src="./dist/v4.js"></script>
<script type="text/javascript" src="./dist/v7.js"></script>
<script type="text/javascript" src="./dist/all.js"></script>
16 changes: 16 additions & 0 deletions examples/browser-rollup/rollup.config.js
Expand Up @@ -27,6 +27,14 @@ module.exports = [
},
plugins,
},
{
input: './example-v7.js',
output: {
file: 'dist/v7.js',
format: 'iife',
},
plugins,
},

{
input: './size-v1.js',
Expand Down Expand Up @@ -60,4 +68,12 @@ module.exports = [
},
plugins,
},
{
input: './size-v7.js',
output: {
file: 'dist/v7-size.js',
format: 'cjs',
},
plugins,
},
];
3 changes: 3 additions & 0 deletions examples/browser-rollup/size-v7.js
@@ -0,0 +1,3 @@
import { v7 as uuidv7 } from 'uuid';

uuidv7();
4 changes: 4 additions & 0 deletions examples/browser-webpack/example-all-require.js
Expand Up @@ -7,6 +7,7 @@ const {
v3: uuidv3,
v4: uuidv4,
v5: uuidv5,
v7: uuidv7,
validate: uuidValidate,
version: uuidVersion,
} = uuid;
Expand All @@ -20,6 +21,8 @@ testpage(function (addTest, done) {

addTest('uuidv4()', uuidv4());

addTest('uuidv7()', uuidv7());

// ... using predefined DNS namespace (for domain names)
addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));

Expand Down Expand Up @@ -57,6 +60,7 @@ testpage(function (addTest, done) {

addTest('uuid.v1()', uuid.v1());
addTest('uuid.v4()', uuid.v4());
addTest('uuid.v7()', uuid.v7());
addTest('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
addTest('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
addTest('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
Expand Down
4 changes: 4 additions & 0 deletions examples/browser-webpack/example-all.js
Expand Up @@ -6,6 +6,7 @@ import {
v3 as uuidv3,
v4 as uuidv4,
v5 as uuidv5,
v7 as uuidv7,
validate as uuidValidate,
version as uuidVersion,
} from 'uuid';
Expand All @@ -20,6 +21,8 @@ testpage(function (addTest, done) {

addTest('uuidv4()', uuidv4());

addTest('uuidv7()', uuidv7());

// ... using predefined DNS namespace (for domain names)
addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));

Expand Down Expand Up @@ -57,6 +60,7 @@ testpage(function (addTest, done) {

addTest('uuid.v1()', uuid.v1());
addTest('uuid.v4()', uuid.v4());
addTest('uuid.v7()', uuid.v7());
addTest('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
addTest('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
addTest('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
Expand Down
12 changes: 12 additions & 0 deletions examples/browser-webpack/example-v7.html
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>

<head>
<title>UUID esmodule webpack example</title>
</head>

<body>
<script type="text/javascript" src="./dist/v7.js"></script>
</body>

</html>
9 changes: 9 additions & 0 deletions examples/browser-webpack/example-v7.js
@@ -0,0 +1,9 @@
import { v7 as uuidv7 } from 'uuid';

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

testpage(function (addTest, done) {
addTest('uuidv7()', uuidv7());

done();
});
1 change: 1 addition & 0 deletions examples/browser-webpack/example.html
Expand Up @@ -3,4 +3,5 @@
<p>Please open the Developer Console to view output</p>
<script type="text/javascript" src="./dist/v1.js"></script>
<script type="text/javascript" src="./dist/v4.js"></script>
<script type="text/javascript" src="./dist/v7.js"></script>
<script type="text/javascript" src="./dist/all.js"></script>
3 changes: 3 additions & 0 deletions examples/browser-webpack/size-v7.js
@@ -0,0 +1,3 @@
import { v7 as uuidv7 } from 'uuid';

uuidv7();
2 changes: 2 additions & 0 deletions examples/browser-webpack/webpack.config.js
Expand Up @@ -7,11 +7,13 @@ module.exports = {
allRequire: './example-all-require.js',
v1: './example-v1.js',
v4: './example-v4.js',
v7: './example-v7.js',

'v1-size': './size-v1.js',
'v3-size': './size-v3.js',
'v4-size': './size-v4.js',
'v5-size': './size-v5.js',
'v7-size': './size-v7.js',
},
// Webpack now produces builds that are incompatible with IE11:
// https://webpack.js.org/migrate/5/#turn-off-es2015-syntax-in-runtime-code-if-necessary
Expand Down
4 changes: 4 additions & 0 deletions examples/node-commonjs/example.js
Expand Up @@ -6,6 +6,7 @@ const {
v3: uuidv3,
v4: uuidv4,
v5: uuidv5,
v7: uuidv7,
validate: uuidValidate,
version: uuidVersion,
} = require('uuid');
Expand All @@ -16,6 +17,8 @@ console.log('uuidv1()', uuidv1());

console.log('uuidv4()', uuidv4());

console.log('uuidv7()', uuidv7());

// ... using predefined DNS namespace (for domain names)
console.log('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS));

Expand Down Expand Up @@ -53,6 +56,7 @@ console.log('Same with default export');

console.log('uuid.v1()', uuid.v1());
console.log('uuid.v4()', uuid.v4());
console.log('uuid.v7()', uuid.v7());
console.log('uuid.v3() DNS', uuid.v3('hello.example.com', uuid.v3.DNS));
console.log('uuid.v3() URL', uuid.v3('http://example.com/hello', uuid.v3.URL));
console.log('uuid.v3() MY_NAMESPACE', uuid.v3('Hello, World!', MY_NAMESPACE));
Expand Down

0 comments on commit 0b8f680

Please sign in to comment.