Repository: uuidjs/uuid Branch: main Commit: ffa31383e8e4 Files: 137 Total size: 184.5 KB Directory structure: gitextract_wopsulqn/ ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ └── feature_request.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── SECURITY.md │ └── workflows/ │ ├── browser.yml │ ├── ci.yml │ ├── release-please.yml │ └── stale-issues.yml ├── .gitignore ├── .husky/ │ ├── commit-msg │ └── pre-commit ├── .npmrc ├── .prettierignore ├── .vscode/ │ ├── extensions.json │ └── tasks.json ├── AUTHORS ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── README_js.md ├── bundlewatch.config.json ├── eslint.config.mjs ├── examples/ │ ├── benchmark/ │ │ ├── README.md │ │ ├── benchmark.html │ │ ├── benchmark.js │ │ ├── browser.js │ │ ├── node.js │ │ └── package.json │ ├── browser-esmodules/ │ │ ├── README.md │ │ ├── example.html │ │ ├── example.js │ │ └── package.json │ ├── browser-rollup/ │ │ ├── README.md │ │ ├── example-all.html │ │ ├── example-all.js │ │ ├── example-v1.html │ │ ├── example-v1.js │ │ ├── example-v4.html │ │ ├── example-v4.js │ │ ├── example-v7.html │ │ ├── example-v7.js │ │ ├── example.html │ │ ├── package.json │ │ ├── rollup.config.js │ │ ├── size-v1.js │ │ ├── size-v3.js │ │ ├── size-v4.js │ │ ├── size-v5.js │ │ ├── size-v6.js │ │ └── size-v7.js │ ├── browser-webpack/ │ │ ├── README.md │ │ ├── example-all.html │ │ ├── example-all.js │ │ ├── example-v1.html │ │ ├── example-v1.js │ │ ├── example-v4.html │ │ ├── example-v4.js │ │ ├── example-v7.html │ │ ├── example-v7.js │ │ ├── example.html │ │ ├── package.json │ │ ├── size-v1.js │ │ ├── size-v3.js │ │ ├── size-v4.js │ │ ├── size-v5.js │ │ ├── size-v6.js │ │ ├── size-v7.js │ │ └── webpack.config.js │ ├── node-esmodules/ │ │ ├── README.md │ │ ├── example.mjs │ │ ├── package.json │ │ └── package.mjs │ ├── node-jest/ │ │ ├── README.md │ │ ├── jsdom.test.js │ │ ├── node.test.js │ │ └── package.json │ ├── node-webpack/ │ │ ├── README.md │ │ ├── example-all.js │ │ ├── example-v1.js │ │ ├── example-v4.js │ │ ├── example-v7.js │ │ ├── package.json │ │ └── webpack.config.js │ ├── typescript/ │ │ ├── README.md │ │ ├── buffer.test.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ └── utils/ │ └── testpage.js ├── package.json ├── prettier.config.js ├── scripts/ │ ├── build.sh │ └── iodd ├── src/ │ ├── bin/ │ │ └── uuid │ ├── index.ts │ ├── max.ts │ ├── md5-browser.ts │ ├── md5.ts │ ├── native-browser.ts │ ├── native.ts │ ├── nil.ts │ ├── parse.ts │ ├── regex.ts │ ├── rng-browser.ts │ ├── rng.ts │ ├── sha1-browser.ts │ ├── sha1.ts │ ├── stringify.ts │ ├── test/ │ │ ├── parse.test.ts │ │ ├── rng.test.ts │ │ ├── stringify.test.ts │ │ ├── test_constants.ts │ │ ├── v1.test.ts │ │ ├── v35.test.ts │ │ ├── v4.test.ts │ │ ├── v6.test.ts │ │ ├── v7.test.ts │ │ ├── validate.test.ts │ │ └── version.test.ts │ ├── types.ts │ ├── uuid-bin.ts │ ├── v1.ts │ ├── v1ToV6.ts │ ├── v3.ts │ ├── v35.ts │ ├── v4.ts │ ├── v5.ts │ ├── v6.ts │ ├── v6ToV1.ts │ ├── v7.ts │ ├── validate.ts │ └── version.ts ├── test/ │ └── browser/ │ └── browser.spec.js ├── tsconfig.json └── wdio.conf.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ github: [broofa, ctavan] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug report description: File a bug against the `uuid` project labels: ['bug'] title: '[BUG] ' body: - type: checkboxes attributes: label: Before you begin... options: - label: I have searched the existing issues required: true - label: My issue title is descriptive and specific to the problem (i.e. search-engine friendly) required: true - label: I understand what an "MRE" is, and why providing one is important. (If not, [read this](https://stackoverflow.com/help/minimal-reproducible-example)) required: true - type: textarea attributes: label: MRE and Description description: '**IMPORTANT**: Failure to provide an MRE is likely to result in your issue being closed without comment.' validations: required: false - type: textarea attributes: label: Environment description: 'Output of `npx envinfo --system --browsers --npmPackages --binaries` goes here:' validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ name: Feature request description: Suggest an idea for this project labels: ['feature'] body: - type: textarea attributes: label: Feature description - type: textarea attributes: label: Additional information description: E.g. alternatives you've considered, examples, screenshots, or anything else that may be helpful ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ <!-- Thank you for your contribution! If your pull request contains considerable changes please run the benchmark before and after your changes and include the results in the pull request description. To run the benchmark execute: npm run test:benchmark from the root of this repository. --> ================================================ FILE: .github/SECURITY.md ================================================ For issues related to `uuid` security please email the module maintainers. Their email addresses are available via `npm owner ls uuid`. ================================================ FILE: .github/workflows/browser.yml ================================================ name: Browser on: workflow_dispatch: push: pull_request_target: types: [labeled] permissions: contents: read env: HUSKY: 0 jobs: browser: if: github.repository == 'uuidjs/uuid' && (contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push') runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: fetch-depth: 10 - name: Use Node.js 20.x uses: actions/setup-node@v4 with: node-version: 20.x - run: npm ci - name: Test Browser run: npm run test:browser env: CI: true BROWSERSTACK_USER: ${{ secrets.BROWSERSTACK_USER }} BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - run: npx bundlewatch --config bundlewatch.config.json env: BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }} ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: [push, pull_request] permissions: contents: read env: HUSKY: 0 jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: node-version: 24.x - run: npm ci - run: npm run lint - run: npm run docs:diff test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [18.x, 20.x, 22.x, 24.x] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: npm - run: npm ci - run: npm run test - run: npm run test:node ================================================ FILE: .github/workflows/release-please.yml ================================================ # Relevent docs: # - https://github.com/googleapis/release-please # - https://github.com/googleapis/release-please-action on: workflow_dispatch: push: branches: - main permissions: contents: write id-token: write pull-requests: write name: release-please jobs: release-please: runs-on: ubuntu-latest steps: - uses: googleapis/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} release-type: node - run: echo "Release created?... ${{ steps.release.outputs.release_created }}" # Steps below handle publication to NPM - uses: actions/checkout@v4 if: ${{ steps.release.outputs.release_created }} - uses: actions/setup-node@v4 with: node-version: 24 registry-url: 'https://registry.npmjs.org' if: ${{ steps.release.outputs.release_created }} - run: npm ci if: ${{ steps.release.outputs.release_created }} - run: npm test if: ${{ steps.release.outputs.release_created }} - run: npm publish --provenance if: ${{ steps.release.outputs.release_created }} ================================================ FILE: .github/workflows/stale-issues.yml ================================================ name: Close inactive issues on: schedule: - cron: '45 2 * * *' jobs: close-issues: runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - uses: actions/stale@v7 with: close-issue-message: 'Closing issue due to 30 days since being marked as stale.' days-before-issue-close: 30 days-before-issue-stale: 90 days-before-pr-close: -1 days-before-pr-stale: -1 exempt-issue-labels: 'stale-exempt' exempt-pr-labels: 'stale-exempt' repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-label: 'stale' stale-issue-message: 'Marking as stale due to 90 days with no activity.' ================================================ FILE: .gitignore ================================================ *.tgz browserstack.err dist/ dist-*/ .build/ local.log logs/ node_modules/ examples/**/package-lock.json ================================================ FILE: .husky/commit-msg ================================================ #!/bin/sh npx --no-install commitlint --edit $1 ================================================ FILE: .husky/pre-commit ================================================ npx --no-install lint-staged ================================================ FILE: .npmrc ================================================ tag-version-prefix="v" save-prefix="" ================================================ FILE: .prettierignore ================================================ dist/ node_modules/ README.md CHANGELOG.md *.sh .gitignore .prettierignore .husky ================================================ FILE: .vscode/extensions.json ================================================ { "recommendations": [ "dbaeumer.vscode-eslint", "ms-vscode.vscode-typescript-next", "esbenp.prettier-vscode" ] } ================================================ FILE: .vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "Build watcher", "group": "build", "type": "shell", "command": "npm run build:watch", "runOptions": { "runOn": "folderOpen" } }, { "label": "Test watcher", "group": "build", "type": "shell", "command": "npm run test:watch", "windows": { "command": "npm run test:watch" }, "presentation": { "reveal": "always", "panel": "new" }, "runOptions": { "runOn": "folderOpen" } } ] } ================================================ FILE: AUTHORS ================================================ Robert Kieffer <robert@broofa.com> 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> ================================================ FILE: CHANGELOG.md ================================================ # Change Log ## [13.0.0](https://github.com/uuidjs/uuid/compare/v12.0.0...v13.0.0) (2025-09-08) ### ⚠ BREAKING CHANGES * make browser exports the default ([#901](https://github.com/uuidjs/uuid/issues/901)) ### Bug Fixes * make browser exports the default ([#901](https://github.com/uuidjs/uuid/issues/901)) ([bce9d72](https://github.com/uuidjs/uuid/commit/bce9d72a3ae5b9a3dcd8eb21ef6d1820288a427a)) ## [12.0.0](https://github.com/uuidjs/uuid/compare/v11.1.0...v12.0.0) (2025-09-05) ### ⚠ BREAKING CHANGES * update to typescript@5.2 ([#887](https://github.com/uuidjs/uuid/issues/887)) * remove CommonJS support ([#886](https://github.com/uuidjs/uuid/issues/886)) * drop node@16 support ([#883](https://github.com/uuidjs/uuid/issues/883)) ### Features * add node@24 to ci matrix ([#879](https://github.com/uuidjs/uuid/issues/879)) ([42b6178](https://github.com/uuidjs/uuid/commit/42b6178aa21a593257f0a72abacd220f0b7b8a92)) * drop node@16 support ([#883](https://github.com/uuidjs/uuid/issues/883)) ([0f38cf1](https://github.com/uuidjs/uuid/commit/0f38cf10366ab074f9328ae2021eea04d5f2e530)) * remove CommonJS support ([#886](https://github.com/uuidjs/uuid/issues/886)) ([ae786e2](https://github.com/uuidjs/uuid/commit/ae786e27265f50bcf7cead196c29f1869297c42f)) * update to typescript@5.2 ([#887](https://github.com/uuidjs/uuid/issues/887)) ([c7ee405](https://github.com/uuidjs/uuid/commit/c7ee40598ed78584d81ab78dffded9fe5ff20b01)) ### Bug Fixes * improve v4() performance ([#894](https://github.com/uuidjs/uuid/issues/894)) ([5fd974c](https://github.com/uuidjs/uuid/commit/5fd974c12718c8848035650b69b8948f12ace197)) * restore node: prefix ([#889](https://github.com/uuidjs/uuid/issues/889)) ([e1f42a3](https://github.com/uuidjs/uuid/commit/e1f42a354593093ba0479f0b4047dae82d28c507)) ## [11.1.0](https://github.com/uuidjs/uuid/compare/v11.0.5...v11.1.0) (2025-02-19) ### Features * update TS types to allow`Uint8Array` subtypes for `buffer` option ([#865](https://github.com/uuidjs/uuid/issues/865)) ([a5231e7](https://github.com/uuidjs/uuid/commit/a5231e7e1b98c20b23c35402a232167f476b39a2)) ## [11.0.5](https://github.com/uuidjs/uuid/compare/v11.0.4...v11.0.5) (2025-01-09) ### Bug Fixes * add TS unit test, pin to typescript@5.0.4 ([#860](https://github.com/uuidjs/uuid/issues/860)) ([24ac2fd](https://github.com/uuidjs/uuid/commit/24ac2fd067e5bab97a5ccea3f6f365a64c01d140)) ## [11.0.4](https://github.com/uuidjs/uuid/compare/v11.0.3...v11.0.4) (2025-01-05) ### Bug Fixes * **docs:** insure -> ensure ([#843](https://github.com/uuidjs/uuid/issues/843)) ([d2a61e1](https://github.com/uuidjs/uuid/commit/d2a61e154d861e58549466e753bb9e4d5bfffb68)) * exclude tests from published package ([#840](https://github.com/uuidjs/uuid/issues/840)) ([f992ff4](https://github.com/uuidjs/uuid/commit/f992ff4780937089b0134195fa22e76e2e1cb3a7)) * Test for invalid byte array sizes and ranges in `v1()`, `v4()`, and `v7()` ([#845](https://github.com/uuidjs/uuid/issues/845)) ([e0ee900](https://github.com/uuidjs/uuid/commit/e0ee90051ebd13475bbcff4d371330aa4f9bd1dd)) ## [11.0.3](https://github.com/uuidjs/uuid/compare/v11.0.2...v11.0.3) (2024-11-04) ### Bug Fixes * apply stricter typing to the v* signatures ([#831](https://github.com/uuidjs/uuid/issues/831)) ([c2d3fed](https://github.com/uuidjs/uuid/commit/c2d3fed22cfd47c22c8f22f6154abb5060648ce5)) * export internal uuid types ([#833](https://github.com/uuidjs/uuid/issues/833)) ([341edf4](https://github.com/uuidjs/uuid/commit/341edf444ced63708ba336285dbec29443523939)) * remove sourcemaps ([#827](https://github.com/uuidjs/uuid/issues/827)) ([b93ea10](https://github.com/uuidjs/uuid/commit/b93ea101af7382053032d4fb61cc85599d6c7216)) * revert "simplify type for v3 and v5" ([#835](https://github.com/uuidjs/uuid/issues/835)) ([e2dee69](https://github.com/uuidjs/uuid/commit/e2dee691e95aba854a892d2507d8cd9f009bf61d)) ## [11.0.2](https://github.com/uuidjs/uuid/compare/v11.0.1...v11.0.2) (2024-10-28) ### Bug Fixes * remove wrapper.mjs ([#822](https://github.com/uuidjs/uuid/issues/822)) ([6683ad3](https://github.com/uuidjs/uuid/commit/6683ad38b048375b451eac1194960f24ba20e0ca)) ## [11.0.1](https://github.com/uuidjs/uuid/compare/v11.0.0...v11.0.1) (2024-10-27) ### Bug Fixes * restore package.json#browser field ([#817](https://github.com/uuidjs/uuid/issues/817)) ([ae8f386](https://github.com/uuidjs/uuid/commit/ae8f38657bca0ee053bf29c88c006b1ea05af1b5)) ## [11.0.0](https://github.com/uuidjs/uuid/compare/v9.0.0...v11.0.0) (2024-10-26) ### ⚠ BREAKING CHANGES - refactor v1 internal state and options logic ([#780](https://github.com/uuidjs/uuid/issues/780)) - refactor v7 internal state and options logic, fixes [#764](https://github.com/uuidjs/uuid/issues/764) ([#779](https://github.com/uuidjs/uuid/issues/779)) - Port to TypeScript, closes [#762](https://github.com/uuidjs/uuid/issues/762) ([#763](https://github.com/uuidjs/uuid/issues/763)) - update node support matrix (only support node 16-20) ([#750](https://github.com/uuidjs/uuid/issues/750)) ### Features - Port to TypeScript, closes [#762](https://github.com/uuidjs/uuid/issues/762) ([#763](https://github.com/uuidjs/uuid/issues/763)) ([1e0f987](https://github.com/uuidjs/uuid/commit/1e0f9870db864ca93f7a69db0d468b5e1b7605e7)) - update node support matrix (only support node 16-20) ([#750](https://github.com/uuidjs/uuid/issues/750)) ([883b163](https://github.com/uuidjs/uuid/commit/883b163b9ab9d6655bfbd8a35e61a3c71674dfe1)) ### Bug Fixes - missing v7 expectations in browser spec ([#751](https://github.com/uuidjs/uuid/issues/751)) ([f54a866](https://github.com/uuidjs/uuid/commit/f54a866cedb2b3b96581157c1f4ac935a0b11411)) - refactor v1 internal state and options logic ([#780](https://github.com/uuidjs/uuid/issues/780)) ([031b3d3](https://github.com/uuidjs/uuid/commit/031b3d3d738bc6694501ac0a37152b95ed500989)) - refactor v7 internal state and options logic, fixes [#764](https://github.com/uuidjs/uuid/issues/764) ([#779](https://github.com/uuidjs/uuid/issues/779)) ([9dbd1cd](https://github.com/uuidjs/uuid/commit/9dbd1cd4177c43fcaac961a3b16fb2d044c9940a)) - remove v4 options default assignment preventing native.randomUUID from being used ([#786](https://github.com/uuidjs/uuid/issues/786)) ([afe6232](https://github.com/uuidjs/uuid/commit/afe62323c4408a824755a39d7b971a8ae06f7199)), closes [#763](https://github.com/uuidjs/uuid/issues/763) - seq_hi shift for byte 6 ([#775](https://github.com/uuidjs/uuid/issues/775)) ([1d532ca](https://github.com/uuidjs/uuid/commit/1d532ca374f181932a24a83fa98f71a5bd4f3e96)) - tsconfig module type ([#778](https://github.com/uuidjs/uuid/issues/778)) ([7eff835](https://github.com/uuidjs/uuid/commit/7eff835cba334ad418f57768c00d15b918a9b419)) ## [10.0.0](https://github.com/uuidjs/uuid/compare/v9.0.0...v10.0.0) (2024-06-07) ### ⚠ BREAKING CHANGES - update node support (drop node@12, node@14, add node@20) (#750) ### Features - support support rfc9562 MAX uuid (new in RFC9562) ([#714](https://github.com/uuidjs/uuid/issues/714)) ([0385cd3](https://github.com/uuidjs/uuid/commit/0385cd3f18ae9920678b2849932fa7a9d9aee7d0)) - support rfc9562 v6 uuids ([#754](https://github.com/uuidjs/uuid/issues/754)) ([c4ed13e](https://github.com/uuidjs/uuid/commit/c4ed13e7159d87c9e42a349bdd9dc955f1af46b6)) - support rfc9562 v7 uuids ([#681](https://github.com/uuidjs/uuid/issues/681)) ([db76a12](https://github.com/uuidjs/uuid/commit/db76a1284760c441438f50a57924b322dae08891)) - update node support matrix (only support node 16-20) ([#750](https://github.com/uuidjs/uuid/issues/750)) ([883b163](https://github.com/uuidjs/uuid/commit/883b163b9ab9d6655bfbd8a35e61a3c71674dfe1)) - support rfc9562 v8 uuids ([#759](https://github.com/uuidjs/uuid/issues/759)) ([35a5342](https://github.com/uuidjs/uuid/commit/35a53428202657e402e6b4aa68f56c08194541bf)) ### Bug Fixes - revert "perf: remove superfluous call to toLowerCase ([#677](https://github.com/uuidjs/uuid/issues/677))" ([#738](https://github.com/uuidjs/uuid/issues/738)) ([e267b90](https://github.com/uuidjs/uuid/commit/e267b9073df1d0ce119ee53c0487fe76acb2be37)) ## [9.0.1](https://github.com/uuidjs/uuid/compare/v9.0.0...v9.0.1) (2023-09-12) ### build - Fix CI to work with Node.js 20.x ## [9.0.0](https://github.com/uuidjs/uuid/compare/v8.3.2...v9.0.0) (2022-09-05) ### ⚠ BREAKING CHANGES - Drop Node.js 10.x support. This library always aims at supporting one EOLed LTS release which by this time now is 12.x which has reached EOL 30 Apr 2022. - Remove the minified UMD build from the package. Minified code is hard to audit and since this is a widely used library it seems more appropriate nowadays to optimize for auditability than to ship a legacy module format that, at best, serves educational purposes nowadays. For production browser use cases, users should be using a bundler. For educational purposes, today's online sandboxes like replit.com offer convenient ways to load npm modules, so the use case for UMD through repos like UNPKG or jsDelivr has largely vanished. - Drop IE 11 and Safari 10 support. Drop support for browsers that don't correctly implement const/let and default arguments, and no longer transpile the browser build to ES2015. This also removes the fallback on msCrypto instead of the crypto API. Browser tests are run in the first supported version of each supported browser and in the latest (as of this commit) version available on Browserstack. ### Features - optimize uuid.v1 by 1.3x uuid.v4 by 4.3x (430%) ([#597](https://github.com/uuidjs/uuid/issues/597)) ([3a033f6](https://github.com/uuidjs/uuid/commit/3a033f6bab6bb3780ece6d645b902548043280bc)) - remove UMD build ([#645](https://github.com/uuidjs/uuid/issues/645)) ([e948a0f](https://github.com/uuidjs/uuid/commit/e948a0f22bf22f4619b27bd913885e478e20fe6f)), closes [#620](https://github.com/uuidjs/uuid/issues/620) - use native crypto.randomUUID when available ([#600](https://github.com/uuidjs/uuid/issues/600)) ([c9e076c](https://github.com/uuidjs/uuid/commit/c9e076c852edad7e9a06baaa1d148cf4eda6c6c4)) ### Bug Fixes - add Jest/jsdom compatibility ([#642](https://github.com/uuidjs/uuid/issues/642)) ([16f9c46](https://github.com/uuidjs/uuid/commit/16f9c469edf46f0786164cdf4dc980743984a6fd)) - change default export to named function ([#545](https://github.com/uuidjs/uuid/issues/545)) ([c57bc5a](https://github.com/uuidjs/uuid/commit/c57bc5a9a0653273aa639cda9177ce52efabe42a)) - handle error when parameter is not set in v3 and v5 ([#622](https://github.com/uuidjs/uuid/issues/622)) ([fcd7388](https://github.com/uuidjs/uuid/commit/fcd73881692d9fabb63872576ba28e30ff852091)) - run npm audit fix ([#644](https://github.com/uuidjs/uuid/issues/644)) ([04686f5](https://github.com/uuidjs/uuid/commit/04686f54c5fed2cfffc1b619f4970c4bb8532353)) - upgrading from uuid3 broken link ([#568](https://github.com/uuidjs/uuid/issues/568)) ([1c849da](https://github.com/uuidjs/uuid/commit/1c849da6e164259e72e18636726345b13a7eddd6)) ### build - drop Node.js 8.x from babel transpile target ([#603](https://github.com/uuidjs/uuid/issues/603)) ([aa11485](https://github.com/uuidjs/uuid/commit/aa114858260402107ec8a1e1a825dea0a259bcb5)) - drop support for legacy browsers (IE11, Safari 10) ([#604](https://github.com/uuidjs/uuid/issues/604)) ([0f433e5](https://github.com/uuidjs/uuid/commit/0f433e5ec444edacd53016de67db021102f36148)) - drop node 10.x to upgrade dev dependencies ([#653](https://github.com/uuidjs/uuid/issues/653)) ([28a5712](https://github.com/uuidjs/uuid/commit/28a571283f8abda6b9d85e689f95b7d3ee9e282e)), closes [#643](https://github.com/uuidjs/uuid/issues/643) ### [8.3.2](https://github.com/uuidjs/uuid/compare/v8.3.1...v8.3.2) (2020-12-08) ### Bug Fixes - lazy load getRandomValues ([#537](https://github.com/uuidjs/uuid/issues/537)) ([16c8f6d](https://github.com/uuidjs/uuid/commit/16c8f6df2f6b09b4d6235602d6a591188320a82e)), closes [#536](https://github.com/uuidjs/uuid/issues/536) ### [8.3.1](https://github.com/uuidjs/uuid/compare/v8.3.0...v8.3.1) (2020-10-04) ### Bug Fixes - support expo>=39.0.0 ([#515](https://github.com/uuidjs/uuid/issues/515)) ([c65a0f3](https://github.com/uuidjs/uuid/commit/c65a0f3fa73b901959d638d1e3591dfacdbed867)), closes [#375](https://github.com/uuidjs/uuid/issues/375) ## [8.3.0](https://github.com/uuidjs/uuid/compare/v8.2.0...v8.3.0) (2020-07-27) ### Features - add parse/stringify/validate/version/NIL APIs ([#479](https://github.com/uuidjs/uuid/issues/479)) ([0e6c10b](https://github.com/uuidjs/uuid/commit/0e6c10ba1bf9517796ff23c052fc0468eedfd5f4)), closes [#475](https://github.com/uuidjs/uuid/issues/475) [#478](https://github.com/uuidjs/uuid/issues/478) [#480](https://github.com/uuidjs/uuid/issues/480) [#481](https://github.com/uuidjs/uuid/issues/481) [#180](https://github.com/uuidjs/uuid/issues/180) ## [8.2.0](https://github.com/uuidjs/uuid/compare/v8.1.0...v8.2.0) (2020-06-23) ### Features - improve performance of v1 string representation ([#453](https://github.com/uuidjs/uuid/issues/453)) ([0ee0b67](https://github.com/uuidjs/uuid/commit/0ee0b67c37846529c66089880414d29f3ae132d5)) - remove deprecated v4 string parameter ([#454](https://github.com/uuidjs/uuid/issues/454)) ([88ce3ca](https://github.com/uuidjs/uuid/commit/88ce3ca0ba046f60856de62c7ce03f7ba98ba46c)), closes [#437](https://github.com/uuidjs/uuid/issues/437) - support jspm ([#473](https://github.com/uuidjs/uuid/issues/473)) ([e9f2587](https://github.com/uuidjs/uuid/commit/e9f2587a92575cac31bc1d4ae944e17c09756659)) ### Bug Fixes - prepare package exports for webpack 5 ([#468](https://github.com/uuidjs/uuid/issues/468)) ([8d6e6a5](https://github.com/uuidjs/uuid/commit/8d6e6a5f8965ca9575eb4d92e99a43435f4a58a8)) ## [8.1.0](https://github.com/uuidjs/uuid/compare/v8.0.0...v8.1.0) (2020-05-20) ### Features - improve v4 performance by reusing random number array ([#435](https://github.com/uuidjs/uuid/issues/435)) ([bf4af0d](https://github.com/uuidjs/uuid/commit/bf4af0d711b4d2ed03d1f74fd12ad0baa87dc79d)) - optimize V8 performance of bytesToUuid ([#434](https://github.com/uuidjs/uuid/issues/434)) ([e156415](https://github.com/uuidjs/uuid/commit/e156415448ec1af2351fa0b6660cfb22581971f2)) ### Bug Fixes - export package.json required by react-native and bundlers ([#449](https://github.com/uuidjs/uuid/issues/449)) ([be1c8fe](https://github.com/uuidjs/uuid/commit/be1c8fe9a3206c358e0059b52fafd7213aa48a52)), closes [ai/nanoevents#44](https://github.com/ai/nanoevents/issues/44#issuecomment-602010343) [#444](https://github.com/uuidjs/uuid/issues/444) ## [8.0.0](https://github.com/uuidjs/uuid/compare/v7.0.3...v8.0.0) (2020-04-29) ### ⚠ BREAKING CHANGES - For native ECMAScript Module (ESM) usage in Node.js only named exports are exposed, there is no more default export. ```diff -import uuid from 'uuid'; -console.log(uuid.v4()); // -> 'cd6c3b08-0adc-4f4b-a6ef-36087a1c9869' +import { v4 as uuidv4 } from 'uuid'; +uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d' ``` - Deep requiring specific algorithms of this library like `require('uuid/v4')`, which has been deprecated in `uuid@7`, is no longer supported. Instead use the named exports that this module exports. For ECMAScript Modules (ESM): ```diff -import uuidv4 from 'uuid/v4'; +import { v4 as uuidv4 } from 'uuid'; uuidv4(); ``` For CommonJS: ```diff -const uuidv4 = require('uuid/v4'); +const { v4: uuidv4 } = require('uuid'); uuidv4(); ``` ### Features - native Node.js ES Modules (wrapper approach) ([#423](https://github.com/uuidjs/uuid/issues/423)) ([2d9f590](https://github.com/uuidjs/uuid/commit/2d9f590ad9701d692625c07ed62f0a0f91227991)), closes [#245](https://github.com/uuidjs/uuid/issues/245) [#419](https://github.com/uuidjs/uuid/issues/419) [#342](https://github.com/uuidjs/uuid/issues/342) - remove deep requires ([#426](https://github.com/uuidjs/uuid/issues/426)) ([daf72b8](https://github.com/uuidjs/uuid/commit/daf72b84ceb20272a81bb5fbddb05dd95922cbba)) ### Bug Fixes - add CommonJS syntax example to README quickstart section ([#417](https://github.com/uuidjs/uuid/issues/417)) ([e0ec840](https://github.com/uuidjs/uuid/commit/e0ec8402c7ad44b7ef0453036c612f5db513fda0)) ### [7.0.3](https://github.com/uuidjs/uuid/compare/v7.0.2...v7.0.3) (2020-03-31) ### Bug Fixes - make deep require deprecation warning work in browsers ([#409](https://github.com/uuidjs/uuid/issues/409)) ([4b71107](https://github.com/uuidjs/uuid/commit/4b71107d8c0d2ef56861ede6403fc9dc35a1e6bf)), closes [#408](https://github.com/uuidjs/uuid/issues/408) ### [7.0.2](https://github.com/uuidjs/uuid/compare/v7.0.1...v7.0.2) (2020-03-04) ### Bug Fixes - make access to msCrypto consistent ([#393](https://github.com/uuidjs/uuid/issues/393)) ([8bf2a20](https://github.com/uuidjs/uuid/commit/8bf2a20f3565df743da7215eebdbada9d2df118c)) - simplify link in deprecation warning ([#391](https://github.com/uuidjs/uuid/issues/391)) ([bb2c8e4](https://github.com/uuidjs/uuid/commit/bb2c8e4e9f4c5f9c1eaaf3ea59710c633cd90cb7)) - update links to match content in readme ([#386](https://github.com/uuidjs/uuid/issues/386)) ([44f2f86](https://github.com/uuidjs/uuid/commit/44f2f86e9d2bbf14ee5f0f00f72a3db1292666d4)) ### [7.0.1](https://github.com/uuidjs/uuid/compare/v7.0.0...v7.0.1) (2020-02-25) ### Bug Fixes - clean up esm builds for node and browser ([#383](https://github.com/uuidjs/uuid/issues/383)) ([59e6a49](https://github.com/uuidjs/uuid/commit/59e6a49e7ce7b3e8fb0f3ee52b9daae72af467dc)) - provide browser versions independent from module system ([#380](https://github.com/uuidjs/uuid/issues/380)) ([4344a22](https://github.com/uuidjs/uuid/commit/4344a22e7aed33be8627eeaaf05360f256a21753)), closes [#378](https://github.com/uuidjs/uuid/issues/378) ## [7.0.0](https://github.com/uuidjs/uuid/compare/v3.4.0...v7.0.0) (2020-02-24) ### ⚠ BREAKING CHANGES - The default export, which used to be the v4() method but which was already discouraged in v3.x of this library, has been removed. - Explicitly note that deep imports of the different uuid version functions are deprecated and no longer encouraged and that ECMAScript module named imports should be used instead. Emit a deprecation warning for people who deep-require the different algorithm variants. - Remove builtin support for insecure random number generators in the browser. Users who want that will have to supply their own random number generator function. - Remove support for generating v3 and v5 UUIDs in Node.js<4.x - Convert code base to ECMAScript Modules (ESM) and release CommonJS build for node and ESM build for browser bundlers. ### Features - add UMD build to npm package ([#357](https://github.com/uuidjs/uuid/issues/357)) ([4e75adf](https://github.com/uuidjs/uuid/commit/4e75adf435196f28e3fbbe0185d654b5ded7ca2c)), closes [#345](https://github.com/uuidjs/uuid/issues/345) - add various es module and CommonJS examples ([b238510](https://github.com/uuidjs/uuid/commit/b238510bf352463521f74bab175a3af9b7a42555)) - ensure that docs are up-to-date in CI ([ee5e77d](https://github.com/uuidjs/uuid/commit/ee5e77db547474f5a8f23d6c857a6d399209986b)) - hybrid CommonJS & ECMAScript modules build ([a3f078f](https://github.com/uuidjs/uuid/commit/a3f078faa0baff69ab41aed08e041f8f9c8993d0)) - remove insecure fallback random number generator ([3a5842b](https://github.com/uuidjs/uuid/commit/3a5842b141a6e5de0ae338f391661e6b84b167c9)), closes [#173](https://github.com/uuidjs/uuid/issues/173) - remove support for pre Node.js v4 Buffer API ([#356](https://github.com/uuidjs/uuid/issues/356)) ([b59b5c5](https://github.com/uuidjs/uuid/commit/b59b5c5ecad271c5453f1a156f011671f6d35627)) - rename repository to github:uuidjs/uuid ([#351](https://github.com/uuidjs/uuid/issues/351)) ([c37a518](https://github.com/uuidjs/uuid/commit/c37a518e367ac4b6d0aa62dba1bc6ce9e85020f7)), closes [#338](https://github.com/uuidjs/uuid/issues/338) ### Bug Fixes - add deep-require proxies for local testing and adjust tests ([#365](https://github.com/uuidjs/uuid/issues/365)) ([7fedc79](https://github.com/uuidjs/uuid/commit/7fedc79ac8fda4bfd1c566c7f05ef4ac13b2db48)) - add note about removal of default export ([#372](https://github.com/uuidjs/uuid/issues/372)) ([12749b7](https://github.com/uuidjs/uuid/commit/12749b700eb49db8a9759fd306d8be05dbfbd58c)), closes [#370](https://github.com/uuidjs/uuid/issues/370) - deprecated deep requiring of the different algorithm versions ([#361](https://github.com/uuidjs/uuid/issues/361)) ([c0bdf15](https://github.com/uuidjs/uuid/commit/c0bdf15e417639b1aeb0b247b2fb11f7a0a26b23)) ## [3.4.0](https://github.com/uuidjs/uuid/compare/v3.3.3...v3.4.0) (2020-01-16) ### Features - rename repository to github:uuidjs/uuid ([#351](https://github.com/uuidjs/uuid/issues/351)) ([e2d7314](https://github.com/uuidjs/uuid/commit/e2d7314)), closes [#338](https://github.com/uuidjs/uuid/issues/338) ## [3.3.3](https://github.com/uuidjs/uuid/compare/v3.3.2...v3.3.3) (2019-08-19) ### Bug Fixes - no longer run ci tests on node v4 - upgrade dependencies ## [3.3.2](https://github.com/uuidjs/uuid/compare/v3.3.1...v3.3.2) (2018-06-28) ### Bug Fixes - typo ([305d877](https://github.com/uuidjs/uuid/commit/305d877)) ## [3.3.1](https://github.com/uuidjs/uuid/compare/v3.3.0...v3.3.1) (2018-06-28) ### Bug Fixes - fix [#284](https://github.com/uuidjs/uuid/issues/284) by setting function name in try-catch ([f2a60f2](https://github.com/uuidjs/uuid/commit/f2a60f2)) # [3.3.0](https://github.com/uuidjs/uuid/compare/v3.2.1...v3.3.0) (2018-06-22) ### Bug Fixes - assignment to readonly property to allow running in strict mode ([#270](https://github.com/uuidjs/uuid/issues/270)) ([d062fdc](https://github.com/uuidjs/uuid/commit/d062fdc)) - fix [#229](https://github.com/uuidjs/uuid/issues/229) ([c9684d4](https://github.com/uuidjs/uuid/commit/c9684d4)) - Get correct version of IE11 crypto ([#274](https://github.com/uuidjs/uuid/issues/274)) ([153d331](https://github.com/uuidjs/uuid/commit/153d331)) - mem issue when generating uuid ([#267](https://github.com/uuidjs/uuid/issues/267)) ([c47702c](https://github.com/uuidjs/uuid/commit/c47702c)) ### Features - enforce Conventional Commit style commit messages ([#282](https://github.com/uuidjs/uuid/issues/282)) ([cc9a182](https://github.com/uuidjs/uuid/commit/cc9a182)) ## [3.2.1](https://github.com/uuidjs/uuid/compare/v3.2.0...v3.2.1) (2018-01-16) ### Bug Fixes - use msCrypto if available. Fixes [#241](https://github.com/uuidjs/uuid/issues/241) ([#247](https://github.com/uuidjs/uuid/issues/247)) ([1fef18b](https://github.com/uuidjs/uuid/commit/1fef18b)) # [3.2.0](https://github.com/uuidjs/uuid/compare/v3.1.0...v3.2.0) (2018-01-16) ### Bug Fixes - remove mistakenly added typescript dependency, rollback version (standard-version will auto-increment) ([09fa824](https://github.com/uuidjs/uuid/commit/09fa824)) - use msCrypto if available. Fixes [#241](https://github.com/uuidjs/uuid/issues/241) ([#247](https://github.com/uuidjs/uuid/issues/247)) ([1fef18b](https://github.com/uuidjs/uuid/commit/1fef18b)) ### Features - Add v3 Support ([#217](https://github.com/uuidjs/uuid/issues/217)) ([d94f726](https://github.com/uuidjs/uuid/commit/d94f726)) # [3.1.0](https://github.com/uuidjs/uuid/compare/v3.1.0...v3.0.1) (2017-06-17) ### Bug Fixes - (fix) Add .npmignore file to exclude test/ and other non-essential files from packing. (#183) - Fix typo (#178) - Simple typo fix (#165) ### Features - v5 support in CLI (#197) - V5 support (#188) # 3.0.1 (2016-11-28) - split uuid versions into separate files # 3.0.0 (2016-11-17) - remove .parse and .unparse # 2.0.0 - Removed uuid.BufferClass # 1.4.0 - Improved module context detection - Removed public RNG functions # 1.3.2 - Improve tests and handling of v1() options (Issue #24) - Expose RNG option to allow for perf testing with different generators # 1.3.0 - Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)! - Support for node.js crypto API - De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing ## Development 1. Clone this repo 2. `npm install` to install dev dependencies 3. VSCode is the recommended dev environment - Includes "Build Watcher" and "Test Watcher" tasks (Terminal pane) - (optional) Install the recommended extensions (Extensions sidebar) 4. Before submitting your PR, make sure tests pass: - `npm test && npm run test:node` ## README updates **Do not edit README.md manually**. To make changes to the README: 1. Edit README_js.md 2. Run `npm run docs` to regenerate README.md 3. If using VSCode, it's ## Testing ```shell npm test ``` ================================================ FILE: LICENSE.md ================================================ The MIT License (MIT) Copyright (c) 2010-2020 Robert Kieffer and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ <!-- -- This file is auto-generated from README_js.md. Changes should be made there. --> # 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/workflows/browser.yml) For the creation of [RFC9562](https://www.rfc-editor.org/rfc/rfc9562.html) (formerly [RFC4122](https://www.rfc-editor.org/rfc/rfc4122.html)) UUIDs - **Complete** - Support for all RFC9562 UUID versions - **Cross-platform** - Support for... - [Typescript](#support) - [Chrome, Safari, Firefox, and Edge](#support) - [NodeJS](#support) - [React Native / Expo](#react-native--expo) - **Secure** - Uses modern `crypto` API for random values - **Compact** - Zero-dependency, [tree-shakable](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking) - **CLI** - [`uuid` command line](#command-line) utility <!-- prettier-ignore --> > [!NOTE] > > Starting with `uuid@12` CommonJS is no longer supported. See [implications](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and [motivation](https://github.com/uuidjs/uuid/issues/881) for details. ## Quickstart **1. Install** ```shell npm install uuid ``` **2. Create a UUID** ```javascript import { v4 as uuidv4 } from 'uuid'; uuidv4(); // ⇨ '23c37ede-1c09-422a-8da8-42ad65cc33f9' ``` For timestamp UUIDs, namespace UUIDs, and other options read on ... ## API Summary | | | | | --- | --- | --- | | [`uuid.NIL`](#uuidnil) | The nil UUID string (all zeros) | New in `uuid@8.3` | | [`uuid.MAX`](#uuidmax) | The max UUID string (all ones) | New in `uuid@9.1` | | [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `uuid@8.3` | | [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `uuid@8.3` | | [`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.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.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.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` | | ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | | | [`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` | ## API ### uuid.NIL The nil UUID string (all zeros). Example: ```javascript import { NIL as NIL_UUID } from 'uuid'; NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000' ``` ### uuid.MAX The max UUID string (all ones). Example: ```javascript import { MAX as MAX_UUID } from 'uuid'; MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff' ``` ### uuid.parse(str) Convert UUID string to array of bytes | | | | --------- | ---------------------------------------- | | `str` | A valid UUID `String` | | _returns_ | `Uint8Array[16]` | | _throws_ | `TypeError` if `str` is not a valid UUID | <!-- prettier-ignore --> > [!NOTE] > Ordering of values in the byte arrays used by `parse()` and `stringify()` follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below. Example: ```javascript import { parse as uuidParse } from 'uuid'; // Parse a UUID uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ // Uint8Array(16) [ // 110, 192, 189, 127, 17, // 192, 67, 218, 151, 94, // 42, 138, 217, 235, 174, // 11 // ] ``` ### uuid.stringify(arr[, offset]) Convert array of bytes to UUID string | | | | -------------- | ---------------------------------------------------------------------------- | | `arr` | `Array`-like collection of 16 values (starting from `offset`) between 0-255. | | [`offset` = 0] | `Number` Starting index in the Array | | _returns_ | `String` | | _throws_ | `TypeError` if a valid UUID string cannot be generated | <!-- prettier-ignore --> > [!NOTE] > Ordering of values in the byte arrays used by `parse()` and `stringify()` follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below. Example: ```javascript import { stringify as uuidStringify } from 'uuid'; const uuidBytes = Uint8Array.of( 0x6e, 0xc0, 0xbd, 0x7f, 0x11, 0xc0, 0x43, 0xda, 0x97, 0x5e, 0x2a, 0x8a, 0xd9, 0xeb, 0xae, 0x0b ); uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b' ``` ### uuid.v1([options[, buffer[, offset]]]) Create an RFC version 1 (timestamp) UUID | | | | --- | --- | | [`options`] | `Object` with one or more of the following properties: | | [`options.node = (random)` ] | RFC "node" field as an `Array[6]` of byte values (per 4.1.6) | | [`options.clockseq = (random)`] | RFC "clock sequence" as a `Number` between 0 - 0x3fff | | [`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.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) | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _throws_ | `Error` if more than 10M UUIDs/sec are requested | Example: ```javascript import { v1 as uuidv1 } from 'uuid'; uuidv1(); // ⇨ 'a2bfad10-b358-11f0-8d45-6389dd784317' ``` Example using `options`: ```javascript import { v1 as uuidv1 } from 'uuid'; const options = { node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab), clockseq: 0x1234, msecs: new Date('2011-11-01').getTime(), nsecs: 5678, }; uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab' ``` ### uuid.v1ToV6(uuid) Convert a UUID from version 1 to version 6 ```javascript import { v1ToV6 } from 'uuid'; v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47' ``` ### uuid.v3(name, namespace[, buffer[, offset]]) Create an RFC version 3 (namespace w/ MD5) UUID API is identical to `v5()`, but uses "v3" instead. <!-- prettier-ignore --> > [!IMPORTANT] > Per the RFC, "_If backward compatibility is not an issue, SHA-1 [Version 5] is preferred_." ### uuid.v4([options[, buffer[, offset]]]) Create an RFC version 4 (random) UUID | | | | --- | --- | | [`options`] | `Object` with one or more of the following properties: | | [`options.random`] | `Array` of 16 random bytes (0-255) | | [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `Array` of 16 random bytes (0-255) | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | Example: ```javascript import { v4 as uuidv4 } from 'uuid'; uuidv4(); // ⇨ '177fac08-7fee-4a08-abda-72eb3ce87fba' ``` Example using predefined `random` values: ```javascript import { v4 as uuidv4 } from 'uuid'; const v4options = { random: Uint8Array.of( 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea, 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36 ), }; uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836' ``` ### uuid.v5(name, namespace[, buffer[, offset]]) Create an RFC version 5 (namespace w/ SHA-1) UUID | | | | --- | --- | | `name` | `String \| Array` | | `namespace` | `String \| Array[16]` Namespace UUID | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | <!-- prettier-ignore --> > [!NOTE] > The RFC `DNS` and `URL` namespaces are available as `v5.DNS` and `v5.URL`. Example with custom namespace: ```javascript import { v5 as uuidv5 } from 'uuid'; // Define a custom namespace. Readers, create your own using something like // https://www.uuidgenerator.net/ const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; uuidv5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681' ``` Example with RFC `URL` namespace: ```javascript import { v5 as uuidv5 } from 'uuid'; uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1' ``` ### uuid.v6([options[, buffer[, offset]]]) Create an RFC version 6 (timestamp, reordered) UUID This method takes the same arguments as uuid.v1(). ```javascript import { v6 as uuidv6 } from 'uuid'; uuidv6(); // ⇨ '1f0b358a-2c04-6950-8ac9-a8f01d2998d6' ``` Example using `options`: ```javascript import { v6 as uuidv6 } from 'uuid'; const options = { node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab], clockseq: 0x1234, msecs: new Date('2011-11-01').getTime(), nsecs: 5678, }; uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab' ``` ### uuid.v6ToV1(uuid) Convert a UUID from version 6 to version 1 ```javascript import { v6ToV1 } from 'uuid'; v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47' ``` ### uuid.v7([options[, buffer[, offset]]]) Create an RFC version 7 (random) UUID | | | | --- | --- | | [`options`] | `Object` with one or more of the following properties: | | [`options.msecs = (current time)`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) | | [`options.random = (random)`] | `Array` of 16 random bytes (0-255) used to generate other fields, above | | [`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. | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | Example: ```javascript import { v7 as uuidv7 } from 'uuid'; uuidv7(); // ⇨ '019a26ab-9a66-71a9-a89e-63c35fce4a5a' ``` ### ~~uuid.v8()~~ **_"Intentionally left blank"_** <!-- prettier-ignore --> > [!NOTE] > Version 8 (experimental) UUIDs are "[for experimental or vendor-specific use cases](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-8)". The RFC does not define a creation algorithm for them, which is why this package does not offer a `v8()` method. The `validate()` and `version()` methods do work with such UUIDs, however. ### uuid.validate(str) Test a string to see if it is a valid UUID | | | | --------- | --------------------------------------------------- | | `str` | `String` to validate | | _returns_ | `true` if string is a valid UUID, `false` otherwise | Example: ```javascript import { validate as uuidValidate } from 'uuid'; uuidValidate('not a UUID'); // ⇨ false uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true ``` Using `validate` and `version` together it is possible to do per-version validation, e.g. validate for only v4 UUIds. ```javascript import { version as uuidVersion } from 'uuid'; import { validate as uuidValidate } from 'uuid'; function uuidValidateV4(uuid) { return uuidValidate(uuid) && uuidVersion(uuid) === 4; } const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210'; const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836'; uuidValidateV4(v4Uuid); // ⇨ true uuidValidateV4(v1Uuid); // ⇨ false ``` ### uuid.version(str) Detect RFC version of a UUID | | | | --------- | ---------------------------------------- | | `str` | A valid UUID `String` | | _returns_ | `Number` The RFC version of the UUID | | _throws_ | `TypeError` if `str` is not a valid UUID | Example: ```javascript import { version as uuidVersion } from 'uuid'; uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // ⇨ 1 uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4 ``` <!-- prettier-ignore --> > [!NOTE] > This method returns `0` for the `NIL` UUID, and `15` for the `MAX` UUID. ## Command Line UUIDs can be generated from the command line using `uuid`. ```shell $ npx uuid ddeb27fb-d9a0-4624-be4d-4615062daed4 ``` The default is to generate version 4 UUIDS, however the other versions are supported. Type `uuid --help` for details: ```shell $ npx uuid --help Usage: uuid uuid v1 uuid v3 <name> <namespace uuid> uuid v4 uuid v5 <name> <namespace uuid> uuid v7 uuid --help Note: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC9562 ``` ## `options` Handling for Timestamp UUIDs Prior to `uuid@11`, it was possible for `options` state to interfere with the internal state used to ensure uniqueness of timestamp-based UUIDs (the `v1()`, `v6()`, and `v7()` methods). Starting with `uuid@11`, this issue has been addressed by using the presence of the `options` argument as a flag to select between two possible behaviors: - Without `options`: Internal state is utilized to improve UUID uniqueness. - With `options`: Internal state is **NOT** used and, instead, appropriate defaults are applied as needed. ## Support **Browsers**: `uuid` [builds are tested](/uuidjs/uuid/blob/main/wdio.conf.js) against the latest version of desktop Chrome, Safari, Firefox, and Edge. Mobile versions of these same browsers are expected to work but aren't currently tested. **Node**: `uuid` [builds are tested](https://github.com/uuidjs/uuid/blob/main/.github/workflows/ci.yml#L26-L27) against node ([LTS releases](https://github.com/nodejs/Release)), plus one prior. E.g. At the time of this writing `node@20` is the "maintenance" release and `node@24` is the "current" release, so `uuid` supports `node@18`-`node@24`. **Typescript**: TS versions released within the past two years are supported. [source](https://github.com/microsoft/TypeScript/issues/49088#issuecomment-2468723715) ## Known issues <!-- This header is referenced as an anchor in src/rng-browser.ts --> ### "getRandomValues() not supported" This error occurs in environments where the standard [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) API is not supported. This issue can be resolved by adding an appropriate polyfill: #### React Native / Expo 1. Install [`react-native-get-random-values`](https://github.com/LinusU/react-native-get-random-values#readme) 1. Import it _before_ `uuid`. Since `uuid` might also appear as a transitive dependency of some other imports it's safest to just import `react-native-get-random-values` as the very first thing in your entry point: ```javascript import 'react-native-get-random-values'; import { v4 as uuidv4 } from 'uuid'; ``` --- Markdown generated from [README_js.md](README_js.md) by <a href="https://github.com/broofa/runmd"><image height="13" src="https://camo.githubusercontent.com/5c7c603cd1e6a43370b0a5063d457e0dabb74cf317adc7baba183acb686ee8d0/687474703a2f2f692e696d6775722e636f6d2f634a4b6f3662552e706e67" /></a> ================================================ FILE: README_js.md ================================================ ```javascript --hide runmd.onRequire = (path) => { if (path == 'rng') return fun; return path.replace(/^uuid/, './dist/'); }; ``` # 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/workflows/browser.yml) For the creation of [RFC9562](https://www.rfc-editor.org/rfc/rfc9562.html) (formerly [RFC4122](https://www.rfc-editor.org/rfc/rfc4122.html)) UUIDs - **Complete** - Support for all RFC9562 UUID versions - **Cross-platform** - Support for... - [Typescript](#support) - [Chrome, Safari, Firefox, and Edge](#support) - [NodeJS](#support) - [React Native / Expo](#react-native--expo) - **Secure** - Uses modern `crypto` API for random values - **Compact** - Zero-dependency, [tree-shakable](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking) - **CLI** - [`uuid` command line](#command-line) utility <!-- prettier-ignore --> > [!NOTE] > > Starting with `uuid@12` CommonJS is no longer supported. See [implications](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and [motivation](https://github.com/uuidjs/uuid/issues/881) for details. ## Quickstart **1. Install** ```shell npm install uuid ``` **2. Create a UUID** ```javascript --run import { v4 as uuidv4 } from 'uuid'; uuidv4(); // RESULT ``` For timestamp UUIDs, namespace UUIDs, and other options read on ... ## API Summary | | | | | --- | --- | --- | | [`uuid.NIL`](#uuidnil) | The nil UUID string (all zeros) | New in `uuid@8.3` | | [`uuid.MAX`](#uuidmax) | The max UUID string (all ones) | New in `uuid@9.1` | | [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `uuid@8.3` | | [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `uuid@8.3` | | [`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.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.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.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` | | ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | | | [`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` | ## API ### uuid.NIL The nil UUID string (all zeros). Example: ```javascript --run import { NIL as NIL_UUID } from 'uuid'; NIL_UUID; // RESULT ``` ### uuid.MAX The max UUID string (all ones). Example: ```javascript --run import { MAX as MAX_UUID } from 'uuid'; MAX_UUID; // RESULT ``` ### uuid.parse(str) Convert UUID string to array of bytes | | | | --------- | ---------------------------------------- | | `str` | A valid UUID `String` | | _returns_ | `Uint8Array[16]` | | _throws_ | `TypeError` if `str` is not a valid UUID | <!-- prettier-ignore --> > [!NOTE] > Ordering of values in the byte arrays used by `parse()` and `stringify()` follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below. Example: ```javascript --run import { parse as uuidParse } from 'uuid'; // Parse a UUID uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // RESULT ``` ### uuid.stringify(arr[, offset]) Convert array of bytes to UUID string | | | | -------------- | ---------------------------------------------------------------------------- | | `arr` | `Array`-like collection of 16 values (starting from `offset`) between 0-255. | | [`offset` = 0] | `Number` Starting index in the Array | | _returns_ | `String` | | _throws_ | `TypeError` if a valid UUID string cannot be generated | <!-- prettier-ignore --> > [!NOTE] > Ordering of values in the byte arrays used by `parse()` and `stringify()` follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below. Example: ```javascript --run import { stringify as uuidStringify } from 'uuid'; const uuidBytes = Uint8Array.of( 0x6e, 0xc0, 0xbd, 0x7f, 0x11, 0xc0, 0x43, 0xda, 0x97, 0x5e, 0x2a, 0x8a, 0xd9, 0xeb, 0xae, 0x0b ); uuidStringify(uuidBytes); // RESULT ``` ### uuid.v1([options[, buffer[, offset]]]) Create an RFC version 1 (timestamp) UUID | | | | --- | --- | | [`options`] | `Object` with one or more of the following properties: | | [`options.node = (random)` ] | RFC "node" field as an `Array[6]` of byte values (per 4.1.6) | | [`options.clockseq = (random)`] | RFC "clock sequence" as a `Number` between 0 - 0x3fff | | [`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.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) | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | | _throws_ | `Error` if more than 10M UUIDs/sec are requested | Example: ```javascript --run import { v1 as uuidv1 } from 'uuid'; uuidv1(); // RESULT ``` Example using `options`: ```javascript --run import { v1 as uuidv1 } from 'uuid'; const options = { node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab), clockseq: 0x1234, msecs: new Date('2011-11-01').getTime(), nsecs: 5678, }; uuidv1(options); // RESULT ``` ### uuid.v1ToV6(uuid) Convert a UUID from version 1 to version 6 ```javascript --run import { v1ToV6 } from 'uuid'; v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // RESULT ``` ### uuid.v3(name, namespace[, buffer[, offset]]) Create an RFC version 3 (namespace w/ MD5) UUID API is identical to `v5()`, but uses "v3" instead. <!-- prettier-ignore --> > [!IMPORTANT] > Per the RFC, "_If backward compatibility is not an issue, SHA-1 [Version 5] is preferred_." ### uuid.v4([options[, buffer[, offset]]]) Create an RFC version 4 (random) UUID | | | | --- | --- | | [`options`] | `Object` with one or more of the following properties: | | [`options.random`] | `Array` of 16 random bytes (0-255) | | [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `Array` of 16 random bytes (0-255) | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | Example: ```javascript --run import { v4 as uuidv4 } from 'uuid'; uuidv4(); // RESULT ``` Example using predefined `random` values: ```javascript --run import { v4 as uuidv4 } from 'uuid'; const v4options = { random: Uint8Array.of( 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea, 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36 ), }; uuidv4(v4options); // RESULT ``` ### uuid.v5(name, namespace[, buffer[, offset]]) Create an RFC version 5 (namespace w/ SHA-1) UUID | | | | --- | --- | | `name` | `String \| Array` | | `namespace` | `String \| Array[16]` Namespace UUID | | [`buffer`] | `Uint8Array` or `Uint8Array` subtype (e.g. Node.js `Buffer`). If provided, binary UUID is written into the array, starting at `offset` | | [`offset` = 0] | `Number` Index to start writing UUID bytes in `buffer` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | <!-- prettier-ignore --> > [!NOTE] > The RFC `DNS` and `URL` namespaces are available as `v5.DNS` and `v5.URL`. Example with custom namespace: ```javascript --run import { v5 as uuidv5 } from 'uuid'; // Define a custom namespace. Readers, create your own using something like // https://www.uuidgenerator.net/ const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; uuidv5('Hello, World!', MY_NAMESPACE); // RESULT ``` Example with RFC `URL` namespace: ```javascript --run import { v5 as uuidv5 } from 'uuid'; uuidv5('https://www.w3.org/', uuidv5.URL); // RESULT ``` ### uuid.v6([options[, buffer[, offset]]]) Create an RFC version 6 (timestamp, reordered) UUID This method takes the same arguments as uuid.v1(). ```javascript --run import { v6 as uuidv6 } from 'uuid'; uuidv6(); // RESULT ``` Example using `options`: ```javascript --run import { v6 as uuidv6 } from 'uuid'; const options = { node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab], clockseq: 0x1234, msecs: new Date('2011-11-01').getTime(), nsecs: 5678, }; uuidv6(options); // RESULT ``` ### uuid.v6ToV1(uuid) Convert a UUID from version 6 to version 1 ```javascript --run import { v6ToV1 } from 'uuid'; v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // 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 = (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.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. | | [`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` | | _returns_ | UUID `String` if no `buffer` is specified, otherwise returns `buffer` | Example: ```javascript --run import { v7 as uuidv7 } from 'uuid'; uuidv7(); // RESULT ``` ### ~~uuid.v8()~~ **_"Intentionally left blank"_** <!-- prettier-ignore --> > [!NOTE] > Version 8 (experimental) UUIDs are "[for experimental or vendor-specific use cases](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-8)". The RFC does not define a creation algorithm for them, which is why this package does not offer a `v8()` method. The `validate()` and `version()` methods do work with such UUIDs, however. ### uuid.validate(str) Test a string to see if it is a valid UUID | | | | --------- | --------------------------------------------------- | | `str` | `String` to validate | | _returns_ | `true` if string is a valid UUID, `false` otherwise | Example: ```javascript --run import { validate as uuidValidate } from 'uuid'; uuidValidate('not a UUID'); // RESULT uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // RESULT ``` Using `validate` and `version` together it is possible to do per-version validation, e.g. validate for only v4 UUIds. ```javascript --run import { version as uuidVersion } from 'uuid'; import { validate as uuidValidate } from 'uuid'; function uuidValidateV4(uuid) { return uuidValidate(uuid) && uuidVersion(uuid) === 4; } const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210'; const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836'; uuidValidateV4(v4Uuid); // RESULT uuidValidateV4(v1Uuid); // RESULT ``` ### uuid.version(str) Detect RFC version of a UUID | | | | --------- | ---------------------------------------- | | `str` | A valid UUID `String` | | _returns_ | `Number` The RFC version of the UUID | | _throws_ | `TypeError` if `str` is not a valid UUID | Example: ```javascript --run import { version as uuidVersion } from 'uuid'; uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // RESULT uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // RESULT ``` <!-- prettier-ignore --> > [!NOTE] > This method returns `0` for the `NIL` UUID, and `15` for the `MAX` UUID. ## Command Line UUIDs can be generated from the command line using `uuid`. ```shell $ npx uuid ddeb27fb-d9a0-4624-be4d-4615062daed4 ``` The default is to generate version 4 UUIDS, however the other versions are supported. Type `uuid --help` for details: ```shell $ npx uuid --help Usage: uuid uuid v1 uuid v3 <name> <namespace uuid> uuid v4 uuid v5 <name> <namespace uuid> uuid v7 uuid --help Note: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC9562 ``` ## `options` Handling for Timestamp UUIDs Prior to `uuid@11`, it was possible for `options` state to interfere with the internal state used to ensure uniqueness of timestamp-based UUIDs (the `v1()`, `v6()`, and `v7()` methods). Starting with `uuid@11`, this issue has been addressed by using the presence of the `options` argument as a flag to select between two possible behaviors: - Without `options`: Internal state is utilized to improve UUID uniqueness. - With `options`: Internal state is **NOT** used and, instead, appropriate defaults are applied as needed. ## Support **Browsers**: `uuid` [builds are tested](/uuidjs/uuid/blob/main/wdio.conf.js) against the latest version of desktop Chrome, Safari, Firefox, and Edge. Mobile versions of these same browsers are expected to work but aren't currently tested. **Node**: `uuid` [builds are tested](https://github.com/uuidjs/uuid/blob/main/.github/workflows/ci.yml#L26-L27) against node ([LTS releases](https://github.com/nodejs/Release)), plus one prior. E.g. At the time of this writing `node@20` is the "maintenance" release and `node@24` is the "current" release, so `uuid` supports `node@18`-`node@24`. **Typescript**: TS versions released within the past two years are supported. [source](https://github.com/microsoft/TypeScript/issues/49088#issuecomment-2468723715) ## Known issues <!-- This header is referenced as an anchor in src/rng-browser.ts --> ### "getRandomValues() not supported" This error occurs in environments where the standard [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) API is not supported. This issue can be resolved by adding an appropriate polyfill: #### React Native / Expo 1. Install [`react-native-get-random-values`](https://github.com/LinusU/react-native-get-random-values#readme) 1. Import it _before_ `uuid`. Since `uuid` might also appear as a transitive dependency of some other imports it's safest to just import `react-native-get-random-values` as the very first thing in your entry point: ```javascript import 'react-native-get-random-values'; import { v4 as uuidv4 } from 'uuid'; ``` ================================================ FILE: bundlewatch.config.json ================================================ { "ci": { "repoBranchBase": "main", "trackBranches": ["main"] }, "files": [ { "path": "./examples/browser-rollup/dist/v1-size.js", "maxSize": "1.0 kB" }, { "path": "./examples/browser-rollup/dist/v3-size.js", "maxSize": "2.1 kB" }, { "path": "./examples/browser-rollup/dist/v4-size.js", "maxSize": "0.7 kB" }, { "path": "./examples/browser-rollup/dist/v5-size.js", "maxSize": "1.5 kB" }, { "path": "./examples/browser-rollup/dist/v6-size.js", "maxSize": "1.6 kB" }, { "path": "./examples/browser-rollup/dist/v7-size.js", "maxSize": "0.8 kB" }, { "path": "./examples/browser-webpack/dist/v1-size.js", "maxSize": "1.0 kB" }, { "path": "./examples/browser-webpack/dist/v3-size.js", "maxSize": "2.1 kB" }, { "path": "./examples/browser-webpack/dist/v4-size.js", "maxSize": "0.7 kB" }, { "path": "./examples/browser-webpack/dist/v5-size.js", "maxSize": "1.5 kB" }, { "path": "./examples/browser-webpack/dist/v6-size.js", "maxSize": "1.6 kB" }, { "path": "./examples/browser-webpack/dist/v7-size.js", "maxSize": "0.8 kB" } ] } ================================================ FILE: eslint.config.mjs ================================================ 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/'], }, ]; ================================================ FILE: examples/benchmark/README.md ================================================ # uuid Benchmark ``` npm install ``` ## Node.js To run the benchmark in Node.js, run `npm test`. ## Browser To run the benchmark in the browser run `npm run start`, open `benchmark.html`, and check the console. Example output (`uuid@8.0.0`, MacBook Pro (Retina, 13-inch, Early 2015), 3.1 GHz Dual-Core Intel Core i7): ``` Starting. Tests take ~1 minute to run ... uuidv1() x 1,306,861 ops/sec ±2.62% (85 runs sampled) uuidv1() fill existing array x 4,750,515 ops/sec ±2.76% (88 runs sampled) uuidv4() x 302,174 ops/sec ±3.06% (81 runs sampled) uuidv4() fill existing array x 359,703 ops/sec ±3.67% (82 runs sampled) uuidv3() x 105,667 ops/sec ±3.84% (79 runs sampled) uuidv5() x 110,886 ops/sec ±2.55% (81 runs sampled) Fastest is uuidv1() fill existing array ``` ================================================ FILE: examples/benchmark/benchmark.html ================================================ <!doctype html> <title>UUID Benchmark

Please open the Developer Console to view output

================================================ FILE: examples/benchmark/benchmark.js ================================================ export default function benchmark(uuid, Benchmark) { console.log('Starting. Tests take ~1 minute to run ...'); function testParseAndStringify() { const suite = new Benchmark.Suite({ onError(event) { console.error(event.target.error); }, }); const BYTES = [ 0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08, 0x4b, ]; suite .add('uuid.stringify()', function () { uuid.stringify(BYTES); }) .add('uuid.parse()', function () { uuid.parse('0f5abcd1-c194-47f3-905b-2df7263a084b'); }) .on('cycle', function (event) { console.log(event.target.toString()); }) .on('complete', function () { console.log('---\n'); }) .run(); } function testGeneration() { const array = new Array(16); const suite = new Benchmark.Suite({ onError(event) { console.error(event.target.error); }, }); suite .add('uuid.v1()', function () { uuid.v1(); }) .add('uuid.v1() fill existing array', function () { try { uuid.v1(null, array, 0); } catch { // The spec (https://datatracker.ietf.org/doc/html/rfc9562#name-timestamp-considerations) defines that only 10M/s v1 // UUIDs can be generated on a single node. This library throws an error if we hit that limit // (which can happen on modern hardware and modern Node.js versions). } }) .add('uuid.v4() using crypto.randomUUID', function () { uuid.v4(); }) .add('uuid.v4() w/out crypto.randomUUID', function () { uuid.v4({}); // passing an object instead of null bypasses native.randomUUID }) .add('uuid.v4() fill existing array', function () { uuid.v4(null, array, 0); }) .add('crypto.randomUUID()', function () { crypto.randomUUID(); }) .add('uuid.v5()', function () { uuid.v5('hello.example.com', uuid.v5.DNS); }) .add('uuid.v6()', function () { uuid.v6(); }) .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()); }) .on('complete', function () { console.log('Fastest is ' + this.filter('fastest').map('name')); console.log('---\n'); }) .run(); } function testV6Conversion() { const suite = new Benchmark.Suite({ onError(event) { console.error(event.target.error); }, }); const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; suite .add('uuid.v1ToV6()', function () { uuid.v1ToV6(V1_ID); }) .add('uuid.v6ToV1()', function () { uuid.v6ToV1(V6_ID); }) .on('cycle', function (event) { console.log(event.target.toString()); }) .run(); } testParseAndStringify(); testGeneration(); testV6Conversion(); } ================================================ FILE: examples/benchmark/browser.js ================================================ import * as uuid from './node_modules/uuid/dist/index.js'; import './node_modules/lodash/lodash.js'; import './node_modules/benchmark/benchmark.js'; import benchmark from './benchmark.js'; benchmark(uuid, window.Benchmark); ================================================ FILE: examples/benchmark/node.js ================================================ import * as uuid from 'uuid'; import Benchmark from 'benchmark'; import benchmark from './benchmark.js'; benchmark(uuid, Benchmark); ================================================ FILE: examples/benchmark/package.json ================================================ { "name": "uuid-benchmark", "version": "0.0.0", "private": true, "scripts": { "build": "true", "start": "npm run build && npx http-server . -o", "pretest": "rm -fr node_modules && npm install --no-package-lock", "test": "node node.js" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "devDependencies": { "benchmark": "^2.1.4" }, "type": "module" } ================================================ FILE: examples/browser-esmodules/README.md ================================================ # uuid example Browser with native ECMAScript Modules ``` npm install npm start ``` Then navigate to `example.html`. ================================================ FILE: examples/browser-esmodules/example.html ================================================ UUID esmodule native example

Please open the Developer Console to view output

================================================ FILE: examples/browser-esmodules/example.js ================================================ import * as uuid from './node_modules/uuid/dist/index.js'; import { MAX as MAX_UUID, NIL as NIL_UUID, parse as uuidParse, stringify as uuidStringify, validate as uuidValidate, version as uuidVersion, v1 as uuidv1, v1ToV6 as uuidv1ToV6, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5, v6 as uuidv6, v6ToV1 as uuidv6ToV1, v7 as uuidv7, } from './node_modules/uuid/dist/index.js'; // Import attribute syntax is still awaiting finalization. In the meantime we // use dynamic import to allows to specifyg both "assert" and "with" clauses. // See https://github.com/tc39/proposal-import-attributes const pkg = await import('./node_modules/uuid/package.json', { assert: { type: 'json' }, with: { type: 'json' }, }); console.log('pkg', pkg); 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)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c'; console.log('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE)); // ... using predefined DNS namespace (for domain names) console.log('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. // const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE)); console.log('uuidv6()', uuidv6()); // v6 <-> v1 conversion const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; console.log('uuidv1ToV6()', uuidv1ToV6(V1_ID)); console.log('uuidv6ToV1()', uuidv6ToV1(V6_ID)); // Utility functions console.log('NIL_UUID', NIL_UUID); console.log('MAX_UUID', MAX_UUID); console.log('uuidParse()', uuidParse(MY_NAMESPACE)); console.log('uuidStringify()', uuidStringify(uuidParse(MY_NAMESPACE))); console.log('uuidValidate()', uuidValidate(MY_NAMESPACE)); console.log('uuidVersion()', uuidVersion(MY_NAMESPACE)); 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)); console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS)); console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL)); console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE)); console.log('uuid.v6()', uuid.v6()); console.log('uuid.v1ToV6()', uuid.v1ToV6(V1_ID)); console.log('uuid.v6ToV1()', uuid.v6ToV1(V6_ID)); console.log('uuid.NIL', uuid.NIL); console.log('uuid.MAX', uuid.MAX); console.log('uuid.parse()', uuid.parse(MY_NAMESPACE)); console.log('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE))); console.log('uuid.validate()', uuid.validate(MY_NAMESPACE)); console.log('uuid.version()', uuid.version(MY_NAMESPACE)); // Some tools like react-native need to introspect the package.json file console.log('pkg.name', pkg.name); ================================================ FILE: examples/browser-esmodules/package.json ================================================ { "name": "uuid-example-browser-esmodules", "version": "0.0.0", "private": true, "scripts": { "build": "true", "start": "npm run build && npx http-server . -o" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" } } ================================================ FILE: examples/browser-rollup/README.md ================================================ # uuid example Browser with rollup.js ``` npm install npm start ``` Then navigate to `example-*.html`. 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 ``` ================================================ FILE: examples/browser-rollup/example-all.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-rollup/example-all.js ================================================ import * as uuid from 'uuid'; import { MAX as MAX_UUID, NIL as NIL_UUID, parse as uuidParse, stringify as uuidStringify, validate as uuidValidate, version as uuidVersion, v1 as uuidv1, v1ToV6 as uuidv1ToV6, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5, v6 as uuidv6, v6ToV1 as uuidv6ToV1, v7 as uuidv7, } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('Named exports'); addTest('uuidv1()', uuidv1()); addTest('uuidv4()', uuidv4()); addTest('uuidv7()', uuidv7()); // ... using predefined DNS namespace (for domain names) addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS)); // ... using predefined URL namespace (for, well, URLs) addTest('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c'; addTest('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE)); // ... using predefined DNS namespace (for domain names) addTest('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS)); // ... using predefined URL namespace (for, well, URLs) addTest('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. // const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE)); addTest('uuidv6()', uuidv6()); // v6 <-> v1 conversion const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; addTest('uuidv1ToV6()', uuidv1ToV6(V1_ID)); addTest('uuidv6ToV1()', uuidv6ToV1(V6_ID)); // Utility functions addTest('NIL_UUID', NIL_UUID); addTest('MAX_UUID', MAX_UUID); addTest('uuidParse()', uuidParse(MY_NAMESPACE)); addTest('uuidStringify()', uuidStringify(uuidParse(MY_NAMESPACE))); addTest('uuidValidate()', uuidValidate(MY_NAMESPACE)); addTest('uuidVersion()', uuidVersion(MY_NAMESPACE)); addTest('Default export'); 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)); addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS)); addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL)); addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE)); addTest('uuid.v6()', uuid.v6()); addTest('uuid.v1ToV6()', uuid.v1ToV6(V1_ID)); addTest('uuid.v6ToV1()', uuid.v6ToV1(V6_ID)); addTest('uuid.NIL', uuid.NIL); addTest('uuid.MAX', uuid.MAX); addTest('uuid.parse()', uuid.parse(MY_NAMESPACE)); addTest('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE))); addTest('uuid.validate()', uuid.validate(MY_NAMESPACE)); addTest('uuid.version()', uuid.version(MY_NAMESPACE)); done(); }); ================================================ FILE: examples/browser-rollup/example-v1.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-rollup/example-v1.js ================================================ import { v1 as uuidv1 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv1()', uuidv1()); done(); }); ================================================ FILE: examples/browser-rollup/example-v4.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-rollup/example-v4.js ================================================ import { v4 as uuidv4 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv4()', uuidv4()); done(); }); ================================================ FILE: examples/browser-rollup/example-v7.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-rollup/example-v7.js ================================================ import { v7 as uuidv7 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv7()', uuidv7()); done(); }); ================================================ FILE: examples/browser-rollup/example.html ================================================ UUID esmodule webpack example

Please open the Developer Console to view output

================================================ FILE: examples/browser-rollup/package.json ================================================ { "name": "uuid-example-browser-rollup", "version": "0.0.0", "private": true, "scripts": { "build": "rm -fr node_modules && npm install --no-package-lock && rm -rf dist && rollup -c", "start": "npm run build && npx http-server . -o" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "0.4.4", "rollup": "^4.19.0" } } ================================================ FILE: examples/browser-rollup/rollup.config.js ================================================ import { nodeResolve } from '@rollup/plugin-node-resolve'; import terser from '@rollup/plugin-terser'; const plugins = [nodeResolve({ browser: true }), terser()]; export default [ { input: './example-all.js', output: { file: 'dist/all.js', format: 'iife', globals: { crypto: 'crypto' }, }, plugins, }, { input: './example-v1.js', output: { file: 'dist/v1.js', format: 'iife', globals: { crypto: 'crypto' }, }, plugins, }, { input: './example-v4.js', output: { file: 'dist/v4.js', format: 'iife', globals: { crypto: 'crypto' }, }, plugins, }, { input: './example-v7.js', output: { file: 'dist/v7.js', format: 'iife', globals: { crypto: 'crypto' }, }, plugins, }, { input: './size-v1.js', output: { file: 'dist/v1-size.js', format: 'es', }, plugins, }, { input: './size-v3.js', output: { file: 'dist/v3-size.js', format: 'es', }, plugins, }, { input: './size-v4.js', output: { file: 'dist/v4-size.js', format: 'es', }, plugins, }, { input: './size-v5.js', output: { file: 'dist/v5-size.js', format: 'es', }, plugins, }, { input: './size-v6.js', output: { file: 'dist/v6-size.js', format: 'es', }, plugins, }, { input: './size-v7.js', output: { file: 'dist/v7-size.js', format: 'es', }, plugins, }, ]; ================================================ FILE: examples/browser-rollup/size-v1.js ================================================ import { v1 as uuidv1 } from 'uuid'; uuidv1(); ================================================ FILE: examples/browser-rollup/size-v3.js ================================================ import { v3 as uuidv3 } from 'uuid'; uuidv3(); ================================================ FILE: examples/browser-rollup/size-v4.js ================================================ import { v4 as uuidv4 } from 'uuid'; uuidv4(); ================================================ FILE: examples/browser-rollup/size-v5.js ================================================ import { v5 as uuidv5 } from 'uuid'; uuidv5(); ================================================ FILE: examples/browser-rollup/size-v6.js ================================================ import { v6 as uuidv6 } from 'uuid'; uuidv6(); ================================================ FILE: examples/browser-rollup/size-v7.js ================================================ import { v7 as uuidv7 } from 'uuid'; uuidv7(); ================================================ FILE: examples/browser-webpack/README.md ================================================ # uuid example Browser with Webpack ``` npm install npm start ``` Then navigate to `example-*.html`. The `example-v{1,4}.js` demonstrate that treeshaking works as expected (webpack output below): ``` Asset Size Chunks Chunk Names all.js 8.54 KiB 0 [emitted] all v1.js 2.6 KiB 1 [emitted] v1 v4.js 2 KiB 2 [emitted] v4 ``` ================================================ FILE: examples/browser-webpack/example-all.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-webpack/example-all.js ================================================ import * as uuid from 'uuid'; import { MAX as MAX_UUID, NIL as NIL_UUID, parse as uuidParse, stringify as uuidStringify, validate as uuidValidate, version as uuidVersion, v1 as uuidv1, v1ToV6 as uuidv1ToV6, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5, v6 as uuidv6, v6ToV1 as uuidv6ToV1, v7 as uuidv7, } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('Named exports'); addTest('uuidv1()', uuidv1()); addTest('uuidv4()', uuidv4()); addTest('uuidv7()', uuidv7()); // ... using predefined DNS namespace (for domain names) addTest('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS)); // ... using predefined URL namespace (for, well, URLs) addTest('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c'; addTest('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE)); // ... using predefined DNS namespace (for domain names) addTest('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS)); // ... using predefined URL namespace (for, well, URLs) addTest('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. // const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; addTest('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE)); addTest('uuidv6()', uuidv6()); // v6 <-> v1 conversion const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; addTest('uuidv1ToV6()', uuidv1ToV6(V1_ID)); addTest('uuidv6ToV1()', uuidv6ToV1(V6_ID)); // Utility functions addTest('NIL_UUID', NIL_UUID); addTest('MAX_UUID', MAX_UUID); addTest('uuidParse()', uuidParse(MY_NAMESPACE)); addTest('uuidStringify()', uuidStringify(uuidParse(MY_NAMESPACE))); addTest('uuidValidate()', uuidValidate(MY_NAMESPACE)); addTest('uuidVersion()', uuidVersion(MY_NAMESPACE)); addTest('Default export'); 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)); addTest('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS)); addTest('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL)); addTest('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE)); addTest('uuid.v6()', uuid.v6()); addTest('uuid.v1ToV6()', uuid.v1ToV6(V1_ID)); addTest('uuid.v6ToV1()', uuid.v6ToV1(V6_ID)); addTest('uuid.NIL', uuid.NIL); addTest('uuid.MAX', uuid.MAX); addTest('uuid.parse()', uuid.parse(MY_NAMESPACE)); addTest('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE))); addTest('uuid.validate()', uuid.validate(MY_NAMESPACE)); addTest('uuid.version()', uuid.version(MY_NAMESPACE)); done(); }); ================================================ FILE: examples/browser-webpack/example-v1.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-webpack/example-v1.js ================================================ import { v1 as uuidv1 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv1()', uuidv1()); done(); }); ================================================ FILE: examples/browser-webpack/example-v4.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-webpack/example-v4.js ================================================ import { v4 as uuidv4 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv4()', uuidv4()); done(); }); ================================================ FILE: examples/browser-webpack/example-v7.html ================================================ UUID esmodule webpack example ================================================ FILE: examples/browser-webpack/example-v7.js ================================================ import { v7 as uuidv7 } from 'uuid'; import testpage from '../utils/testpage'; testpage(function (addTest, done) { addTest('uuidv7()', uuidv7()); done(); }); ================================================ FILE: examples/browser-webpack/example.html ================================================ UUID esmodule webpack example

Please open the Developer Console to view output

================================================ FILE: examples/browser-webpack/package.json ================================================ { "name": "uuid-example-browser-webpack", "version": "0.0.0", "private": true, "scripts": { "build": "rm -fr node_modules && npm install --no-package-lock && rm -rf dist && webpack", "start": "npm run build && npx http-server . -o" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "devDependencies": { "webpack": "5.93.0", "webpack-cli": "5.1.4" } } ================================================ FILE: examples/browser-webpack/size-v1.js ================================================ import { v1 as uuidv1 } from 'uuid'; uuidv1(); ================================================ FILE: examples/browser-webpack/size-v3.js ================================================ import { v3 as uuidv3 } from 'uuid'; uuidv3(); ================================================ FILE: examples/browser-webpack/size-v4.js ================================================ import { v4 as uuidv4 } from 'uuid'; uuidv4(); ================================================ FILE: examples/browser-webpack/size-v5.js ================================================ import { v5 as uuidv5 } from 'uuid'; uuidv5(); ================================================ FILE: examples/browser-webpack/size-v6.js ================================================ import { v6 as uuidv6 } from 'uuid'; uuidv6(); ================================================ FILE: examples/browser-webpack/size-v7.js ================================================ import { v7 as uuidv7 } from 'uuid'; uuidv7(); ================================================ FILE: examples/browser-webpack/webpack.config.js ================================================ module.exports = { resolve: { extensions: ['*', '.js'], fallback: { crypto: false }, }, entry: { all: './example-all.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', 'v6-size': './size-v6.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 target: ['web', 'es5'], output: { filename: '[name].js', }, mode: 'production', }; ================================================ FILE: examples/node-esmodules/README.md ================================================ # uuid example Node.js ESModules ``` npm install npm test ``` ================================================ FILE: examples/node-esmodules/example.mjs ================================================ import * as uuid from 'uuid'; import { MAX as MAX_UUID, NIL as NIL_UUID, parse as uuidParse, stringify as uuidStringify, validate as uuidValidate, version as uuidVersion, v1 as uuidv1, v1ToV6 as uuidv1ToV6, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5, v6 as uuidv6, v6ToV1 as uuidv6ToV1, v7 as uuidv7, } from 'uuid'; // Import attribute syntax is still awaiting finalization. In the meantime we // use dynamic import to allows to specifyg both "assert" and "with" clauses. // See https://github.com/tc39/proposal-import-attributes const pkg = await import('uuid/package.json', { assert: { type: 'json' }, with: { type: 'json' } }); 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)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c'; console.log('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE)); // ... using predefined DNS namespace (for domain names) console.log('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. // const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE)); console.log('uuidv6()', uuidv6()); // v6 <-> v1 conversion const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; console.log('uuidv1ToV6()', uuidv1ToV6(V1_ID)); console.log('uuidv6ToV1()', uuidv6ToV1(V6_ID)); // Utility functions console.log('NIL_UUID', NIL_UUID); console.log('MAX_UUID', MAX_UUID); console.log('uuidParse()', uuidParse(MY_NAMESPACE)); console.log('uuidStringify()', uuidStringify(uuidParse(MY_NAMESPACE))); console.log('uuidValidate()', uuidValidate(MY_NAMESPACE)); console.log('uuidVersion()', uuidVersion(MY_NAMESPACE)); 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)); console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS)); console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL)); console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE)); console.log('uuid.v6()', uuid.v6()); console.log('uuid.v1ToV6()', uuid.v1ToV6(V1_ID)); console.log('uuid.v6ToV1()', uuid.v6ToV1(V6_ID)); console.log('uuid.NIL', uuid.NIL); console.log('uuid.MAX', uuid.MAX); console.log('uuid.parse()', uuid.parse(MY_NAMESPACE)); console.log('uuid.stringify()', uuid.stringify(uuid.parse(MY_NAMESPACE))); console.log('uuid.validate()', uuid.validate(MY_NAMESPACE)); console.log('uuid.version()', uuid.version(MY_NAMESPACE)); // Some tools like react-native need to introspect the package.json file console.log('pkg.name', pkg.default.name); ================================================ FILE: examples/node-esmodules/package.json ================================================ { "name": "uuid-example-node-esmodules", "version": "0.0.0", "private": true, "scripts": { "test:package": "( node --version | grep -vq 'v18' ) || ( node package.mjs )", "test:example": "node example.mjs", "pretest": "rm -fr node_modules && npm install --no-package-lock", "test": "npm-run-all test:*" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" } } ================================================ FILE: examples/node-esmodules/package.mjs ================================================ import pkg from 'uuid/package.json' assert { type: 'json' }; // Some tools like react-native need to introspect the package.json file console.log('pkg.name', pkg.name); ================================================ FILE: examples/node-jest/README.md ================================================ # uuid example Node.js Jest ``` npm install npm test ``` ================================================ FILE: examples/node-jest/jsdom.test.js ================================================ /** @jest-environment jsdom */ import * as uuid from 'uuid'; test('uuidv4()', () => { const val = uuid.v4(); expect(uuid.version(val)).toBe(4); }); test('uuidv7()', () => { const val = uuid.v7(); expect(uuid.version(val)).toBe(7); }); ================================================ FILE: examples/node-jest/node.test.js ================================================ import * as uuid from 'uuid'; test('uuidv4()', () => { const val = uuid.v4(); expect(uuid.version(val)).toBe(4); }); test('uuidv7()', () => { const val = uuid.v7(); expect(uuid.version(val)).toBe(7); }); ================================================ FILE: examples/node-jest/package.json ================================================ { "name": "uuid-example-node-jest", "version": "0.0.0", "private": true, "type": "module", "scripts": { "pretest": "rm -fr node_modules && npm install --no-package-lock", "test": "NODE_OPTIONS=\"--experimental-vm-modules\" jest" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "devDependencies": { "jest": "30.0.2", "jest-environment-jsdom": "30.0.2" } } ================================================ FILE: examples/node-webpack/README.md ================================================ # uuid example Node.js with Webpack ``` npm install npm test ``` This will run webpack and execute the resulting bundles in `./dist`. ================================================ FILE: examples/node-webpack/example-all.js ================================================ import * as uuid from 'uuid'; import { v1 as uuidv1, v3 as uuidv3, v4 as uuidv4, v5 as uuidv5 } from 'uuid'; console.log('uuidv1()', uuidv1()); console.log('uuidv4()', uuidv4()); // ... using predefined DNS namespace (for domain names) console.log('uuidv3() DNS', uuidv3('hello.example.com', uuidv3.DNS)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv3() URL', uuidv3('http://example.com/hello', uuidv3.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. const MY_NAMESPACE = '55238d15-c926-4598-b49d-cf4e913ba13c'; console.log('uuidv3() MY_NAMESPACE', uuidv3('Hello, World!', MY_NAMESPACE)); // ... using predefined DNS namespace (for domain names) console.log('uuidv5() DNS', uuidv5('hello.example.com', uuidv5.DNS)); // ... using predefined URL namespace (for, well, URLs) console.log('uuidv5() URL', uuidv5('http://example.com/hello', uuidv5.URL)); // ... using a custom namespace // // Note: Custom namespaces should be a UUID string specific to your application! // E.g. the one here was generated using this modules `uuid` CLI. // const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341'; console.log('uuidv5() MY_NAMESPACE', uuidv5('Hello, World!', MY_NAMESPACE)); console.log('Same with default export'); console.log('uuid.v1()', uuid.v1()); console.log('uuid.v4()', uuid.v4()); 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)); console.log('uuid.v5() DNS', uuid.v5('hello.example.com', uuid.v5.DNS)); console.log('uuid.v5() URL', uuid.v5('http://example.com/hello', uuid.v5.URL)); console.log('uuid.v5() MY_NAMESPACE', uuid.v5('Hello, World!', MY_NAMESPACE)); ================================================ FILE: examples/node-webpack/example-v1.js ================================================ import { v1 as uuidv1 } from 'uuid'; console.log('uuidv1()', uuidv1()); ================================================ FILE: examples/node-webpack/example-v4.js ================================================ import { v4 as uuidv4 } from 'uuid'; console.log('uuidv4()', uuidv4()); ================================================ FILE: examples/node-webpack/example-v7.js ================================================ import { v7 as uuidv7 } from 'uuid'; console.log('uuidv7()', uuidv7()); ================================================ FILE: examples/node-webpack/package.json ================================================ { "name": "uuid-example-node-webpack", "version": "0.0.0", "private": true, "scripts": { "build": "rm -rf dist && webpack", "pretest": "rm -fr node_modules && npm install --no-package-lock", "test": "npm run build && node dist/v1.js && node dist/v4.js && node dist/v7.js && node dist/all.js" }, "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "devDependencies": { "webpack": "^5.74.0", "webpack-cli": "^4.10.0" } } ================================================ FILE: examples/node-webpack/webpack.config.js ================================================ module.exports = { resolve: { extensions: ['*', '.js'], }, entry: { all: './example-all.js', v1: './example-v1.js', v4: './example-v4.js', v7: './example-v7.js', }, output: { filename: '[name].js', }, mode: 'production', target: 'node', }; ================================================ FILE: examples/typescript/README.md ================================================ # uuid test for typescript support (not really an example) ``` npm install npm test ``` This runs `tsc` using the oldest version of TypeScript supported by this project ================================================ FILE: examples/typescript/buffer.test.ts ================================================ /* eslint-disable @typescript-eslint/ban-ts-comment */ import { v1 } from 'uuid'; v1(undefined, new Uint8Array(16)) satisfies Uint8Array; v1(undefined, Buffer.alloc(16)) satisfies Buffer; // @ts-expect-error v1(undefined, new Uint8Array(16)) satisfies Buffer; ================================================ FILE: examples/typescript/index.ts ================================================ import * as uuid from 'uuid'; console.log(uuid); ================================================ FILE: examples/typescript/package.json ================================================ { "dependencies": { "uuid": "file:../../.build/uuid.tgz" }, "scripts": { "pretest": "rm -fr node_modules && npm install --no-package-lock", "test": "npx -y --package=typescript@5.0.4 -- tsc --noEmit" } } ================================================ FILE: examples/typescript/tsconfig.json ================================================ {} ================================================ FILE: examples/utils/testpage.js ================================================ export default function test(callback) { const style = document.createElement('style'); style.appendChild( document.createTextNode( [ 'body {font-family: monospace;}', 'dt, dd {display: inline-block; margin: 0;}', 'dt {min-width: 15em;}', ].join('\n') ) ); document.body.appendChild(style); function addTest(title, result) { // join() result if it's array-like if (result instanceof Uint8Array || Array.isArray(result)) { result = Array.prototype.join.apply(result); } let el; if (result === undefined) { el = document.createElement('h2'); el.innerHTML = title; } else { el = document.createElement('div'); el.className = 'test_result'; el.innerHTML = '
' + title + '
:
' + result + '
'; } document.body.appendChild(el); } function done() { const div = document.createElement('h2'); div.id = 'done'; document.body.appendChild(div); } window.onload = function () { callback(addTest, done); }; } ================================================ FILE: package.json ================================================ { "name": "uuid", "version": "13.0.0", "description": "RFC9562 UUIDs", "type": "module", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "commitlint": { "extends": [ "@commitlint/config-conventional" ] }, "keywords": [ "uuid", "guid", "rfc4122", "rfc9562" ], "license": "MIT", "bin": { "uuid": "./dist-node/bin/uuid" }, "sideEffects": false, "types": "./dist/index.d.ts", "exports": { ".": { "node": "./dist-node/index.js", "default": "./dist/index.js" }, "./package.json": "./package.json" }, "files": [ "dist", "dist-node", "!**/test" ], "devDependencies": { "@babel/eslint-parser": "7.27.1", "@commitlint/cli": "19.8.0", "@commitlint/config-conventional": "19.8.0", "@eslint/js": "9.26.0", "bundlewatch": "0.4.1", "commander": "13.1.0", "eslint": "9.26.0", "eslint-config-prettier": "10.1.2", "eslint-plugin-prettier": "5.4.0", "globals": "16.0.0", "husky": "9.1.7", "jest": "29.7.0", "lint-staged": "15.5.2", "neostandard": "0.12.1", "npm-run-all": "4.1.5", "prettier": "3.5.3", "release-please": "17.0.0", "runmd": "1.4.1", "standard-version": "9.5.0", "typescript": "5.2.2", "typescript-eslint": "8.32.0" }, "optionalDevDependencies": { "@wdio/browserstack-service": "9.2.1", "@wdio/cli": "9.2.1", "@wdio/jasmine-framework": "9.2.1", "@wdio/local-runner": "9.2.1", "@wdio/spec-reporter": "9.1.3", "@wdio/static-server-service": "9.1.3" }, "scripts": { "build": "./scripts/build.sh", "build:watch": "tsc --watch -p tsconfig.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": "npm run build && npx runmd --output=README.md README_js.md", "eslint:check": "eslint src/ test/ examples/ *.[jt]s", "eslint:fix": "eslint --fix src/ test/ examples/ *.[jt]s", "examples:browser:rollup:build": "cd examples/browser-rollup && npm run build", "examples:browser:webpack:build": "cd examples/browser-webpack && npm run build", "examples:node:esmodules:test": "cd examples/node-esmodules && npm test", "examples:node:jest:test": "cd examples/node-jest && npm test", "examples:node:typescript:test": "cd examples/typescript && npm test", "lint": "npm run eslint:check && npm run prettier:check", "md": "runmd --watch --output=README.md README_js.md", "prepack": "npm run build -- --no-pack", "prepare": "husky", "prepublishOnly": "npm run build", "pretest:benchmark": "npm run build", "pretest:browser": "./scripts/iodd && npm run build && npm-run-all --parallel examples:browser:**", "pretest:node": "npm run build", "pretest": "npm run build", "prettier:check": "prettier --check .", "prettier:fix": "prettier --write .", "release": "standard-version --no-verify", "test:benchmark": "cd examples/benchmark && npm test", "test:browser": "wdio run ./wdio.conf.js", "test:node": "npm-run-all --parallel examples:node:**", "test:watch": "node --test --enable-source-maps --watch dist-node/test/*.js", "test": "node --test --enable-source-maps dist-node/test/*.js" }, "repository": { "type": "git", "url": "https://github.com/uuidjs/uuid.git" }, "lint-staged": { "*": [ "prettier --no-error-on-unmatched-pattern --write" ], "*.{js,jsx}": [ "eslint --no-error-on-unmatched-pattern --fix" ] }, "standard-version": { "scripts": { "postchangelog": "prettier --write CHANGELOG.md" } }, "packageManager": "npm@11.3.0" } ================================================ FILE: prettier.config.js ================================================ export default { arrowParens: 'always', printWidth: 100, proseWrap: 'never', singleQuote: true, trailingComma: 'es5', }; ================================================ FILE: scripts/build.sh ================================================ #!/bin/bash -eu # This script generates 4 builds, as follows: # - dist: ESM build for the Browser # - dist-node: ESM build for Node.js # # Note: that the "preferred" build for testing (local and CI) is the ESM build, # except where we specifically test the other builds set -e # exit on error # Change to project root ROOT=$(builtin cd $(pwd)/$(dirname "$0")/..; pwd) # Prep TS output dir DIST_DIR="$ROOT/dist" NODE_DIST_DIR="$ROOT/dist-node" echo "Building in $DIST_DIR and $NODE_DIST_DIR" cd "$ROOT" || exit 1 # Remove old builds rm -rf $DIST_DIR* # Make default dist dir mkdir -p "$DIST_DIR" # Compile typescript echo "Compiling TypeScript files to $NODE_DIST_DIR" tsc -p tsconfig.json # Clone files for node builds cp -pr "$DIST_DIR" "$NODE_DIST_DIR" # Remove browser files in node build for FILE in ${NODE_DIST_DIR}/*-browser*; do rm -f $FILE done # Move browser files into place for default build ( cd "$DIST_DIR" for FILE in *-browser*;do mv "$FILE" "${FILE/-browser/}" done ) # Remove type definition files where they're not needed ( cd "$NODE_DIST_DIR" find . -name '*.d.ts' -exec rm -f {} \; ) # Copy bin files into place cp -pr "$ROOT/src/bin" "$NODE_DIST_DIR" if [ "${1-}" != "--no-pack" ]; then # Prep tarball dir BUILD_DIR="$ROOT/.build" rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" # Create tarball for local installation (in tests and examples) echo "Packing tarball" npm pack --pack-destination "$BUILD_DIR" > /dev/null 2>&1 mv $BUILD_DIR/uuid-*.tgz $BUILD_DIR/uuid.tgz fi echo "-- fin --" ================================================ FILE: scripts/iodd ================================================ #!/usr/bin/env node import { program } from 'commander'; import { spawn } from 'node:child_process'; import fs from 'node:fs/promises'; import path from 'node:path'; program .name('iodd') .description( '(I)nstall (o)ptional (d)ev (d)ependencies from package.json#optionalDevDependencies' ) .option('-v, --verbose', 'Output npm install output to stdout/stderr') .option('-r, --required', 'Exit with non-zero code if dependencies fail to install') .argument('[packagePath]', 'Path to package.json file', './package.json') .action(main); async function main(packagePath, options) { // Get list of optional dependencies from package.json const json = await fs.readFile(path.join(process.cwd(), packagePath)); const packageJson = JSON.parse(json); const { optionalDevDependencies: deps } = packageJson; if (!deps) { console.error(`No optional dependencies found in ${packagePath}`); process.exit(1); } const packageRefs = Object.entries(deps).map(([name, version]) => `${name}@${version}`); // Install optional dependencies with child_process running npm const args = ['install', '--no-save', ...packageRefs]; console.log('Running: ', 'npm', args.join(' ')); const cp = spawn('npm', args); if (options.verbose) { cp.stdout.pipe(process.stdout); cp.stderr.pipe(process.stderr); } const exitCode = await new Promise((resolve) => { cp.on('close', resolve); }); if (exitCode !== 0) { console.error('Dependencies failed to install'); if (options.required) { process.exit(exitCode); } } } program.parseAsync(); ================================================ FILE: src/bin/uuid ================================================ #!/usr/bin/env node import '../uuid-bin.js'; ================================================ FILE: src/index.ts ================================================ export type * from './types.js'; export { default as MAX } from './max.js'; export { default as NIL } from './nil.js'; export { default as parse } from './parse.js'; export { default as stringify } from './stringify.js'; export { default as v1 } from './v1.js'; export { default as v1ToV6 } from './v1ToV6.js'; export { default as v3 } from './v3.js'; export { default as v4 } from './v4.js'; export { default as v5 } from './v5.js'; export { default as v6 } from './v6.js'; export { default as v6ToV1 } from './v6ToV1.js'; export { default as v7 } from './v7.js'; export { default as validate } from './validate.js'; export { default as version } from './version.js'; ================================================ FILE: src/max.ts ================================================ export default 'ffffffff-ffff-ffff-ffff-ffffffffffff'; ================================================ FILE: src/md5-browser.ts ================================================ /* * Browser-compatible JavaScript MD5 * * Modification of JavaScript MD5 * https://github.com/blueimp/JavaScript-MD5 * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * https://opensource.org/licenses/MIT * * Based on * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ function md5(bytes: Uint8Array) { const words = uint8ToUint32(bytes); const md5Bytes = wordsToMd5(words, bytes.length * 8); return uint32ToUint8(md5Bytes); } /* * Convert an array of little-endian words to an array of bytes */ function uint32ToUint8(input: Uint32Array) { // Note: On little endian platforms we could simply return `new // Uint8Array(input.buffer)` here, but that that won't work on big-endian // systems. (That said, there's code below that appears to already assume // little-endian, so maybe this is a moot point? Either way, keeping the // existing code for now to be safe.) const bytes = new Uint8Array(input.length * 4); for (let i = 0; i < input.length * 4; i++) { bytes[i] = (input[i >> 2] >>> ((i % 4) * 8)) & 0xff; } return bytes; } /** * Calculate output length with padding and bit length */ function getOutputLength(inputLength8: number) { return (((inputLength8 + 64) >>> 9) << 4) + 14 + 1; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function wordsToMd5(x: Uint32Array, len: number) { /* append padding */ const xpad = new Uint32Array(getOutputLength(len)).fill(0); xpad.set(x); xpad[len >> 5] |= 0x80 << len % 32; xpad[xpad.length - 1] = len; x = xpad; let a = 1732584193; let b = -271733879; let c = -1732584194; let d = 271733878; for (let i = 0; i < x.length; i += 16) { const olda = a; const oldb = b; const oldc = c; const oldd = d; a = md5ff(a, b, c, d, x[i], 7, -680876936); d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); c = md5ff(c, d, a, b, x[i + 10], 17, -42063); b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); b = md5gg(b, c, d, a, x[i], 20, -373897302); a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); a = md5hh(a, b, c, d, x[i + 5], 4, -378558); d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); d = md5hh(d, a, b, c, x[i], 11, -358537222); c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); a = md5ii(a, b, c, d, x[i], 6, -198630844); d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); a = safeAdd(a, olda); b = safeAdd(b, oldb); c = safeAdd(c, oldc); d = safeAdd(d, oldd); } return Uint32Array.of(a, b, c, d); } /* * Convert Uint8Array to Uint32 array (little-endian) */ function uint8ToUint32(input: Uint8Array) { if (input.length === 0) { return new Uint32Array(); } const output = new Uint32Array(getOutputLength(input.length * 8)).fill(0); for (let i = 0; i < input.length; i++) { output[i >> 2] |= (input[i] & 0xff) << ((i % 4) * 8); } return output; } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safeAdd(x: number, y: number) { const lsw = (x & 0xffff) + (y & 0xffff); const msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xffff); } /* * Bitwise rotate a 32-bit number to the left. */ function bitRotateLeft(num: number, cnt: number) { return (num << cnt) | (num >>> (32 - cnt)); } /* * These functions implement the four basic operations the algorithm uses. */ function md5cmn(q: number, a: number, b: number, x: number, s: number, t: number) { return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); } function md5ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number) { 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) { 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) { 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) { return md5cmn(c ^ (b | ~d), a, b, x, s, t); } export default md5; ================================================ FILE: src/md5.ts ================================================ import { createHash } from 'node:crypto'; function md5(bytes: Uint8Array) { if (Array.isArray(bytes)) { bytes = Buffer.from(bytes); } else if (typeof bytes === 'string') { bytes = Buffer.from(bytes, 'utf8'); } return createHash('md5').update(bytes).digest(); } export default md5; ================================================ FILE: src/native-browser.ts ================================================ const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); export default { randomUUID }; ================================================ FILE: src/native.ts ================================================ import { randomUUID } from 'node:crypto'; export default { randomUUID }; ================================================ FILE: src/nil.ts ================================================ export default '00000000-0000-0000-0000-000000000000'; ================================================ FILE: src/parse.ts ================================================ import validate from './validate.js'; function parse(uuid: string) { if (!validate(uuid)) { throw TypeError('Invalid UUID'); } let v; return Uint8Array.of( (v = parseInt(uuid.slice(0, 8), 16)) >>> 24, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff, // Parse ........-####-....-....-............ (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 0xff, // Parse ........-....-####-....-............ (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 0xff, // Parse ........-....-....-####-............ (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 0xff, // Parse ........-....-....-....-############ // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) ((v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000) & 0xff, (v / 0x100000000) & 0xff, (v >>> 24) & 0xff, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff ); } export default parse; ================================================ FILE: src/regex.ts ================================================ export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i; ================================================ FILE: src/rng-browser.ts ================================================ // Unique ID creation requires a high quality random # generator. In the browser we therefore // require the crypto API and do not support built-in fallback to lower quality random number // generators (like Math.random()). let getRandomValues: typeof crypto.getRandomValues | undefined; const rnds8 = new Uint8Array(16); export default function rng() { // lazy load so that environments that need to polyfill have a chance to do so if (!getRandomValues) { if (typeof crypto === 'undefined' || !crypto.getRandomValues) { throw new Error( 'crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported' ); } getRandomValues = crypto.getRandomValues.bind(crypto); } return getRandomValues(rnds8); } ================================================ FILE: src/rng.ts ================================================ import { randomFillSync } from 'node:crypto'; const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate let poolPtr = rnds8Pool.length; export default function rng() { if (poolPtr > rnds8Pool.length - 16) { randomFillSync(rnds8Pool); poolPtr = 0; } return rnds8Pool.slice(poolPtr, (poolPtr += 16)); } ================================================ FILE: src/sha1-browser.ts ================================================ // Adapted from Chris Veness' SHA1 code at // http://www.movable-type.co.uk/scripts/sha1.html function f(s: 0 | 1 | 2 | 3, x: number, y: number, z: number) { switch (s) { case 0: return (x & y) ^ (~x & z); case 1: return x ^ y ^ z; case 2: return (x & y) ^ (x & z) ^ (y & z); case 3: return x ^ y ^ z; } } function ROTL(x: number, n: number) { return (x << n) | (x >>> (32 - n)); } function sha1(bytes: Uint8Array): Uint8Array { const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; const newBytes = new Uint8Array(bytes.length + 1); newBytes.set(bytes); newBytes[bytes.length] = 0x80; bytes = newBytes; const l = bytes.length / 4 + 2; const N = Math.ceil(l / 16); const M: Uint32Array[] = new Array(N); for (let i = 0; i < N; ++i) { const arr = new Uint32Array(16); for (let j = 0; j < 16; ++j) { arr[j] = (bytes[i * 64 + j * 4] << 24) | (bytes[i * 64 + j * 4 + 1] << 16) | (bytes[i * 64 + j * 4 + 2] << 8) | bytes[i * 64 + j * 4 + 3]; } M[i] = arr; } M[N - 1][14] = ((bytes.length - 1) * 8) / Math.pow(2, 32); M[N - 1][14] = Math.floor(M[N - 1][14]); M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff; for (let i = 0; i < N; ++i) { const W = new Uint32Array(80); for (let t = 0; t < 16; ++t) { W[t] = M[i][t]; } for (let t = 16; t < 80; ++t) { W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); } let a = H[0]; let b = H[1]; let c = H[2]; let d = H[3]; let e = H[4]; for (let t = 0; t < 80; ++t) { const s = Math.floor(t / 20) as 0 | 1 | 2 | 3; const T = (ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t]) >>> 0; e = d; d = c; c = ROTL(b, 30) >>> 0; b = a; a = T; } H[0] = (H[0] + a) >>> 0; H[1] = (H[1] + b) >>> 0; H[2] = (H[2] + c) >>> 0; H[3] = (H[3] + d) >>> 0; H[4] = (H[4] + e) >>> 0; } // Note: Uint8Array.of() does `& 0xff` for each value return Uint8Array.of( H[0] >> 24, H[0] >> 16, H[0] >> 8, H[0], H[1] >> 24, H[1] >> 16, H[1] >> 8, H[1], H[2] >> 24, H[2] >> 16, H[2] >> 8, H[2], H[3] >> 24, H[3] >> 16, H[3] >> 8, H[3], H[4] >> 24, H[4] >> 16, H[4] >> 8, H[4] ); } export default sha1; ================================================ FILE: src/sha1.ts ================================================ import { createHash } from 'node:crypto'; function sha1(bytes: Uint8Array) { if (Array.isArray(bytes)) { bytes = Buffer.from(bytes); } else if (typeof bytes === 'string') { bytes = Buffer.from(bytes, 'utf8'); } return createHash('sha1').update(bytes).digest(); } export default sha1; ================================================ FILE: src/stringify.ts ================================================ import validate from './validate.js'; /** * Convert array of 16 byte values to UUID string format of the form: * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ const byteToHex: string[] = []; for (let i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).slice(1)); } export function unsafeStringify(arr: Uint8Array, offset = 0): string { // Note: Be careful editing this code! It's been tuned for performance // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 // // Note to future-self: No, you can't remove the `toLowerCase()` call. // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351 return ( byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]] ).toLowerCase(); } function stringify(arr: Uint8Array, offset = 0) { const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one // of the following: // - One or more input array values don't map to a hex octet (leading to // "undefined" in the uuid) // - Invalid input values for the RFC `version` or `variant` fields if (!validate(uuid)) { throw TypeError('Stringified UUID is invalid'); } return uuid; } export default stringify; ================================================ FILE: src/test/parse.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import parse from '../parse.js'; import stringify from '../stringify.js'; import uuidv4 from '../v4.js'; // Deterministic PRNG for reproducible tests // See https://stackoverflow.com/a/47593316/109538 function splitmix32(a: number) { return function () { a |= 0; a = (a + 0x9e3779b9) | 0; let t = a ^ (a >>> 16); t = Math.imul(t, 0x21f0aaad); t = t ^ (t >>> 15); t = Math.imul(t, 0x735a2d97); return ((t = t ^ (t >>> 15)) >>> 0) / 4294967296; }; } const rand = splitmix32(0x12345678); function rng(bytes = new Uint8Array(16)) { for (let i = 0; i < 16; i++) { bytes[i] = rand() * 256; } return bytes; } describe('parse', () => { test('String -> bytes parsing', () => { assert.deepStrictEqual( parse('0f5abcd1-c194-47f3-905b-2df7263a084b'), Uint8Array.from([ 0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08, 0x4b, ]) ); }); test('String -> bytes -> string symmetry for assorted uuids', () => { for (let i = 0; i < 1000; i++) { const uuid = uuidv4({ rng }); assert.equal(stringify(parse(uuid)), uuid); } }); test('Case neutrality', () => { // Verify upper/lower case neutrality assert.deepStrictEqual( parse('0f5abcd1-c194-47f3-905b-2df7263a084b'), parse('0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()) ); }); test('Null UUID case', () => { assert.deepStrictEqual( parse('00000000-0000-0000-0000-000000000000'), Uint8Array.from(new Array(16).fill(0)) ); }); test('UUID validation', () => { // @ts-expect-error testing invalid input assert.throws(() => parse()); assert.throws(() => parse('invalid uuid')); assert.throws(() => parse('zyxwvuts-rqpo-nmlk-jihg-fedcba000000')); }); }); ================================================ FILE: src/test/rng.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import rng from '../rng.js'; describe('rng', () => { test('Node.js RNG', () => { const bytes = rng(); assert.equal(bytes.length, 16); for (let i = 0; i < bytes.length; ++i) { assert.equal(typeof bytes[i], 'number'); } }); // Test of whatwgRNG missing for now since with esmodules we can no longer manipulate the // require.cache. }); ================================================ FILE: src/test/stringify.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import stringify, { unsafeStringify } from '../stringify.js'; const BYTES = Uint8Array.of( 0x0f, 0x5a, 0xbc, 0xd1, 0xc1, 0x94, 0x47, 0xf3, 0x90, 0x5b, 0x2d, 0xf7, 0x26, 0x3a, 0x08, 0x4b ); describe('stringify', () => { test('Stringify Array (unsafe)', () => { assert.equal(unsafeStringify(BYTES), '0f5abcd1-c194-47f3-905b-2df7263a084b'); }); test('Stringify w/ offset (unsafe)', () => { const bytes = new Uint8Array(19).fill(0); bytes.set(BYTES, 3); assert.equal(unsafeStringify(bytes, 3), '0f5abcd1-c194-47f3-905b-2df7263a084b'); }); test('Stringify Array (safe)', () => { assert.equal(stringify(BYTES), '0f5abcd1-c194-47f3-905b-2df7263a084b'); }); test('Throws on not enough values (safe)', () => { const bytes = BYTES.slice(0, 15); assert.throws(() => stringify(bytes)); }); }); ================================================ FILE: src/test/test_constants.ts ================================================ import MAX from '../max.js'; import NIL from '../nil.js'; // Table of [uuid value, expected validate(), [expected version()]] export const TESTS = [ // constants { value: NIL, expectedValidate: true, expectedVersion: 0 }, { value: MAX, expectedValidate: true, expectedVersion: 15 }, // each version, with either all 0's or all 1's in settable bits { value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 }, { value: 'ffffffff-ffff-1fff-8fff-ffffffffffff', expectedValidate: true, expectedVersion: 1 }, { value: '00000000-0000-2000-8000-000000000000', expectedValidate: true, expectedVersion: 2 }, { value: 'ffffffff-ffff-2fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 2 }, { value: '00000000-0000-3000-8000-000000000000', expectedValidate: true, expectedVersion: 3 }, { value: 'ffffffff-ffff-3fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 3 }, { value: '00000000-0000-4000-8000-000000000000', expectedValidate: true, expectedVersion: 4 }, { value: 'ffffffff-ffff-4fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 4 }, { value: '00000000-0000-5000-8000-000000000000', expectedValidate: true, expectedVersion: 5 }, { value: 'ffffffff-ffff-5fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 5 }, { value: '00000000-0000-6000-8000-000000000000', expectedValidate: true, expectedVersion: 6 }, { value: 'ffffffff-ffff-6fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 6 }, { value: '00000000-0000-7000-8000-000000000000', expectedValidate: true, expectedVersion: 7 }, { value: 'ffffffff-ffff-7fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 7 }, { value: '00000000-0000-8000-8000-000000000000', expectedValidate: true, expectedVersion: 8 }, { value: 'ffffffff-ffff-8fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 8 }, { value: '00000000-0000-9000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-9fff-bfff-ffffffffffff', expectedValidate: false }, { value: '00000000-0000-a000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-afff-bfff-ffffffffffff', expectedValidate: false }, { value: '00000000-0000-b000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-bfff-bfff-ffffffffffff', expectedValidate: false }, { value: '00000000-0000-c000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-cfff-bfff-ffffffffffff', expectedValidate: false }, { value: '00000000-0000-d000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-dfff-bfff-ffffffffffff', expectedValidate: false }, { value: '00000000-0000-e000-8000-000000000000', expectedValidate: false }, { value: 'ffffffff-ffff-efff-bfff-ffffffffffff', expectedValidate: false }, // selection of normal, valid UUIDs { value: 'd9428888-122b-11e1-b85c-61cd3cbb3210', expectedValidate: true, expectedVersion: 1 }, { value: '000003e8-2363-21ef-b200-325096b39f47', expectedValidate: true, expectedVersion: 2 }, { value: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec', expectedValidate: true, expectedVersion: 3 }, { value: '109156be-c4fb-41ea-b1b4-efe1671c5836', expectedValidate: true, expectedVersion: 4 }, { value: '90123e1c-7512-523e-bb28-76fab9f2f73d', expectedValidate: true, expectedVersion: 5 }, { value: '1ef21d2f-1207-6660-8c4f-419efbd44d48', expectedValidate: true, expectedVersion: 6 }, { value: '017f22e2-79b0-7cc3-98c4-dc0c0c07398f', expectedValidate: true, expectedVersion: 7 }, { value: '0d8f23a0-697f-83ae-802e-48f3756dd581', expectedValidate: true, expectedVersion: 8 }, // all variant octet values { value: '00000000-0000-1000-0000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-1000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-2000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-3000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-4000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-5000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-6000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-7000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 }, { value: '00000000-0000-1000-9000-000000000000', expectedValidate: true, expectedVersion: 1 }, { value: '00000000-0000-1000-a000-000000000000', expectedValidate: true, expectedVersion: 1 }, { value: '00000000-0000-1000-b000-000000000000', expectedValidate: true, expectedVersion: 1 }, { value: '00000000-0000-1000-c000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-d000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-e000-000000000000', expectedValidate: false }, { value: '00000000-0000-1000-f000-000000000000', expectedValidate: false }, // invalid strings { value: '00000000000000000000000000000000', expectedValidate: false }, // unhyphenated NIL { value: '', expectedValidate: false }, { value: 'invalid uuid string', expectedValidate: false }, { value: '=Y00a-f*vb*-c-d#-p00f\b-g0h-#i^-j*3&-L00k-\nl---00n-fg000-00p-00r+', expectedValidate: false, }, // invalid types { value: undefined, expectedValidate: false }, { value: null, expectedValidate: false }, { value: 123, expectedValidate: false }, { value: /regex/, expectedValidate: false }, { value: new Date(0), expectedValidate: false }, { value: false, expectedValidate: false }, ]; // Add NIL and MAX UUIDs with 1-bit flipped in each position for (let charIndex = 0; charIndex < 36; charIndex++) { // Skip hyphens and version char if ( charIndex === 8 || charIndex === 13 || charIndex === 14 || // version char charIndex === 18 || charIndex === 23 ) { continue; } const nilChars = NIL.split(''); const maxChars = MAX.split(''); for (let i = 0; i < 4; i++) { nilChars[charIndex] = (0x0 ^ (1 << i)).toString(16); // NIL UUIDs w/ a single 1-bit TESTS.push({ value: nilChars.join(''), expectedValidate: false }); // MAX UUIDs w/ a single 0-bit maxChars[charIndex] = (0xf ^ (1 << i)).toString(16); TESTS.push({ value: maxChars.join(''), expectedValidate: false }); } } ================================================ FILE: src/test/v1.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import parse from '../parse.js'; import v1, { updateV1State } from '../v1.js'; // Verify ordering of v1 ids created with explicit times const TIME = 1321644961388; // 2011-11-18 11:36:01.388-08:00 // Fixture values for testing with the rfc v1 UUID example: // https://www.rfc-editor.org/rfc/rfc9562.html#name-example-of-a-uuidv1-value const RFC_V1 = 'c232ab00-9414-11ec-b3c8-9f68deced846'; const RFC_V1_BYTES = parse(RFC_V1); // `options` for producing the above RFC UUID const RFC_OPTIONS = { msecs: 0x17f22e279b0, nsecs: 0, clockseq: 0x33c8, node: Uint8Array.of(0x9f, 0x68, 0xde, 0xce, 0xd8, 0x46), }; // random bytes for producing the above RFC UUID const RFC_RANDOM = Uint8Array.of( // unused 0, 0, 0, 0, 0, 0, 0, 0, // clock seq RFC_OPTIONS.clockseq >> 8, RFC_OPTIONS.clockseq & 0xff, // node ...RFC_OPTIONS.node ); // Compare v1 timestamp fields chronologically function compareV1TimeField(a: string, b: string) { a = a.split('-').slice(0, 3).reverse().join(''); b = b.split('-').slice(0, 3).reverse().join(''); return a < b ? -1 : a > b ? 1 : 0; } describe('v1', () => { test('v1 sort order (default)', () => { const ids = [v1(), v1(), v1(), v1(), v1()]; const sorted = [...ids].sort(compareV1TimeField); assert.deepEqual(ids, sorted); }); // Verify ordering of v1 ids created with explicit times test('v1 sort order (time option)', () => { const ids = [ v1({ msecs: TIME - 10 * 3600 * 1000 }), v1({ msecs: TIME - 1 }), v1({ msecs: TIME }), v1({ msecs: TIME + 1 }), v1({ msecs: TIME + 28 * 24 * 3600 * 1000 }), ]; const sorted = [...ids].sort(compareV1TimeField); assert.deepEqual(ids, sorted); }); test('v1(options)', () => { assert.equal(v1({ msecs: RFC_OPTIONS.msecs, random: RFC_RANDOM }), RFC_V1, 'minimal options'); assert.equal(v1(RFC_OPTIONS), RFC_V1, 'full options'); }); test('v1(options) equality', () => { assert.notEqual(v1({ msecs: TIME }), v1({ msecs: TIME }), 'UUIDs with minimal options differ'); assert.equal(v1(RFC_OPTIONS), v1(RFC_OPTIONS), 'UUIDs with full options are identical'); }); test('fills one UUID into a buffer as expected', () => { const buffer = new Uint8Array(16); const result = v1(RFC_OPTIONS, buffer); assert.deepEqual(buffer, RFC_V1_BYTES); assert.strictEqual(buffer, result); }); test('fills two UUIDs into a buffer as expected', () => { const buffer = new Uint8Array(32); v1(RFC_OPTIONS, buffer, 0); v1(RFC_OPTIONS, buffer, 16); const expectedBuf = new Uint8Array(32); expectedBuf.set(RFC_V1_BYTES); expectedBuf.set(RFC_V1_BYTES, 16); assert.deepEqual(buffer, expectedBuf); }); test('v1() state transitions', () => { // Test fixture for internal state passed into updateV1State function const PRE_STATE = { msecs: 10, nsecs: 20, clockseq: 0x1234, node: Uint8Array.of(0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc), }; // Note: The test code, below, passes RFC_RANDOM as the `rnds` argument for // convenience. This allows us to test that fields have been initialized from // the rnds argument by testing for RFC_OPTIONS values in the output state. const tests = [ { title: 'initial state', state: {}, now: 10, expected: { msecs: 10, // -> now nsecs: 0, // -> init clockseq: RFC_OPTIONS.clockseq, // -> random node: RFC_OPTIONS.node, // -> random }, }, { title: 'same time interval', state: { ...PRE_STATE }, now: PRE_STATE.msecs, expected: { ...PRE_STATE, nsecs: 21, // -> +1 }, }, { title: 'new time interval', state: { ...PRE_STATE }, now: PRE_STATE.msecs + 1, expected: { ...PRE_STATE, msecs: PRE_STATE.msecs + 1, // -> +1 nsecs: 0, // -> init }, }, { title: 'same time interval (nsecs overflow)', state: { ...PRE_STATE, nsecs: 9999 }, now: PRE_STATE.msecs, expected: { ...PRE_STATE, nsecs: 0, // -> init clockseq: RFC_OPTIONS.clockseq, // -> init node: RFC_OPTIONS.node, // -> init }, }, { title: 'time regression', state: { ...PRE_STATE }, now: PRE_STATE.msecs - 1, expected: { ...PRE_STATE, msecs: PRE_STATE.msecs - 1, // -> now clockseq: RFC_OPTIONS.clockseq, // -> init node: RFC_OPTIONS.node, // -> init }, }, ]; for (const { title, state, now, expected } of tests) { assert.deepStrictEqual(updateV1State(state, now, RFC_RANDOM), expected, `Failed: ${title}`); } }); test('throws when option.random is too short', () => { const random = Uint8Array.of(16); const buffer = new Uint8Array(16).fill(0); assert.throws(() => { v1({ random }, buffer); }); }); test('throws when options.rng() is too short', () => { const buffer = new Uint8Array(16); const rng = () => Uint8Array.of(0); // length = 1 assert.throws(() => { v1({ rng }, buffer); }); }); test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); assert.throws(() => v1({}, buf15)); assert.throws(() => v1({}, buf30, -1)); assert.throws(() => v1({}, buf30, 15)); }); }); ================================================ FILE: src/test/v35.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import md5 from '../md5.js'; import sha1 from '../sha1.js'; import v3 from '../v3.js'; import { stringToBytes } from '../v35.js'; import v5 from '../v5.js'; describe('v35', () => { const HASH_SAMPLES = [ { input: stringToBytes(''), sha1: 'da39a3ee5e6b4b0d3255bfef95601890afd80709', md5: 'd41d8cd98f00b204e9800998ecf8427e', }, // Extended ascii chars { input: stringToBytes( '\t\b\f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF' ), sha1: 'ca4a426a3d536f14cfd79011e79e10d64de950a0', md5: 'e8098ec21950f841731d28749129d3ee', }, // A sampling from the Unicode BMP { input: stringToBytes( '\u00A5\u0104\u018F\u0256\u02B1o\u0315\u038E\u0409\u0500\u0531\u05E1\u05B6\u0920\u0903\u09A4\u0983\u0A20\u0A02\u0AA0\u0A83\u0B06\u0C05\u0C03\u1401\u16A0' ), sha1: 'f2753ebc390e5f637e333c2a4179644a93ae9f65', md5: '231b309e277b6be8bb3d6c688b7f098b', }, ]; function hashToHex(hash: Uint8Array) { const chars = new Array(hash.length); for (let i = 0; i < hash.length; i++) { chars[i] = hash[i].toString(16).padStart(2, '0'); } return chars.join(''); } HASH_SAMPLES.forEach(function (sample, i) { test(`sha1(node) HASH_SAMPLES[${i}]`, () => { assert.equal(hashToHex(sha1(sample.input)), sample.sha1); }); }); HASH_SAMPLES.forEach(function (sample, i) { test(`md5(node) HASH_SAMPLES[${i}]`, () => { assert.equal(hashToHex(md5(sample.input)), sample.md5); }); }); test('v3', () => { // Expect to get the same results as http://tools.adjet.org/uuid-v3 assert.strictEqual(v3('hello.example.com', v3.DNS), '9125a8dc-52ee-365b-a5aa-81b0b3681cf6'); assert.strictEqual( v3('http://example.com/hello', v3.URL), 'c6235813-3ba4-3801-ae84-e0a6ebb7d138' ); assert.strictEqual( v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'), 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec' ); }); test('v3 namespace.toUpperCase', () => { assert.strictEqual( v3('hello.example.com', v3.DNS.toUpperCase()), '9125a8dc-52ee-365b-a5aa-81b0b3681cf6' ); assert.strictEqual( v3('http://example.com/hello', v3.URL.toUpperCase()), 'c6235813-3ba4-3801-ae84-e0a6ebb7d138' ); assert.strictEqual( v3('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()), 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec' ); }); test('v3 namespace string validation', () => { assert.throws(() => { v3('hello.example.com', 'zyxwvuts-rqpo-nmlk-jihg-fedcba000000'); }); assert.throws(() => { v3('hello.example.com', 'invalid uuid value'); }); assert.ok(v3('hello.example.com', '00000000-0000-0000-0000-000000000000')); }); test('v3 namespace buffer validation', () => { assert.throws(() => { v3('hello.example.com', new Uint8Array(15)); }); assert.throws(() => { v3('hello.example.com', new Uint8Array(17)); }); assert.ok(v3('hello.example.com', new Uint8Array(16).fill(0))); }); test('v3 fill buffer', () => { let buf = new Uint8Array(16); const expectedUuid = Uint8Array.of( 0x91, 0x25, 0xa8, 0xdc, 0x52, 0xee, 0x36, 0x5b, 0xa5, 0xaa, 0x81, 0xb0, 0xb3, 0x68, 0x1c, 0xf6 ); const result = v3('hello.example.com', v3.DNS, buf); assert.deepEqual(buf, expectedUuid); assert.strictEqual(result, buf); // test offsets as well buf = new Uint8Array(19).fill(0xaa); const expectedBuf = new Uint8Array(19).fill(0xaa); expectedBuf.set(expectedUuid, 3); v3('hello.example.com', v3.DNS, buf, 3); assert.deepEqual(buf, expectedBuf); }); test('v3 undefined/null', () => { // @ts-expect-error testing invalid input assert.throws(() => v3()); // @ts-expect-error testing invalid input assert.throws(() => v3('hello')); // @ts-expect-error testing invalid input assert.throws(() => v3('hello.example.com', undefined)); // @ts-expect-error testing invalid input assert.throws(() => v3('hello.example.com', null, new Uint8Array(16))); }); test('v5', () => { // Expect to get the same results as http://tools.adjet.org/uuid-v5 assert.strictEqual(v5('hello.example.com', v5.DNS), 'fdda765f-fc57-5604-a269-52a7df8164ec'); assert.strictEqual( v5('http://example.com/hello', v5.URL), '3bbcee75-cecc-5b56-8031-b6641c1ed1f1' ); assert.strictEqual( v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'), '90123e1c-7512-523e-bb28-76fab9f2f73d' ); }); test('v5 namespace.toUpperCase', () => { // Expect to get the same results as http://tools.adjet.org/uuid-v5 assert.strictEqual( v5('hello.example.com', v5.DNS.toUpperCase()), 'fdda765f-fc57-5604-a269-52a7df8164ec' ); assert.strictEqual( v5('http://example.com/hello', v5.URL.toUpperCase()), '3bbcee75-cecc-5b56-8031-b6641c1ed1f1' ); assert.strictEqual( v5('hello', '0f5abcd1-c194-47f3-905b-2df7263a084b'.toUpperCase()), '90123e1c-7512-523e-bb28-76fab9f2f73d' ); }); test('v5 namespace string validation', () => { assert.throws(() => { v5('hello.example.com', 'zyxwvuts-rqpo-nmlk-jihg-fedcba000000'); }); assert.throws(() => { v5('hello.example.com', 'invalid uuid value'); }); assert.ok(v5('hello.example.com', '00000000-0000-0000-0000-000000000000')); }); test('v5 namespace buffer validation', () => { assert.throws(() => { v5('hello.example.com', new Uint8Array(15)); }); assert.throws(() => { v5('hello.example.com', new Uint8Array(17)); }); assert.ok(v5('hello.example.com', new Uint8Array(16).fill(0))); }); test('v5 fill buffer', () => { let buf = new Uint8Array(16); const expectedUuid = Uint8Array.of( 0xfd, 0xda, 0x76, 0x5f, 0xfc, 0x57, 0x56, 0x04, 0xa2, 0x69, 0x52, 0xa7, 0xdf, 0x81, 0x64, 0xec ); const result = v5('hello.example.com', v5.DNS, buf); assert.deepEqual(buf, expectedUuid); assert.strictEqual(result, buf); // test offsets as well buf = new Uint8Array(19).fill(0xaa); const expectedBuf = new Uint8Array(19).fill(0xaa); expectedBuf.set(expectedUuid, 3); v5('hello.example.com', v5.DNS, buf, 3); assert.deepEqual(buf, expectedBuf); }); test('v5 undefined/null', () => { // @ts-expect-error testing invalid input assert.throws(() => v5()); // @ts-expect-error testing invalid input assert.throws(() => v5('hello')); // @ts-expect-error testing invalid input assert.throws(() => v5('hello.example.com', undefined)); // @ts-expect-error testing invalid input assert.throws(() => v5('hello.example.com', null, new Uint8Array(16))); }); test('v3/v5 constants', () => { assert.strictEqual(v3.DNS, '6ba7b810-9dad-11d1-80b4-00c04fd430c8'); assert.strictEqual(v3.URL, '6ba7b811-9dad-11d1-80b4-00c04fd430c8'); assert.strictEqual(v5.DNS, '6ba7b810-9dad-11d1-80b4-00c04fd430c8'); assert.strictEqual(v5.URL, '6ba7b811-9dad-11d1-80b4-00c04fd430c8'); }); }); ================================================ FILE: src/test/v4.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import native from '../native.js'; import v4 from '../v4.js'; const randomBytesFixture = Uint8Array.of( 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea, 0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36 ); const expectedBytes = Uint8Array.of( 16, 145, 86, 190, 196, 251, 65, 234, 177, 180, 239, 225, 103, 28, 88, 54 ); describe('v4', () => { test('subsequent UUIDs are different', () => { const id1 = v4(); const id2 = v4(); assert.ok(id1 !== id2); }); test('should uses native randomUUID() if no option is passed', async () => { // TODO: `mock` is not supported until node@18, so we feature-detect it // here. Once node@16 drops off our support matrix, we can just // static-import it normally const mock = (await import('node:test')).default.mock; if (!mock) { return; } const mockRandomUUID = mock.method(native, 'randomUUID'); assert.equal(mockRandomUUID.mock.callCount(), 0); v4(); assert.equal(mockRandomUUID.mock.callCount(), 1); mock.restoreAll(); }); test('should not use native randomUUID() if an option is passed', async () => { // TODO: `mock` is not supported until node@18, so we feature-detect it // here. Once node@16 drops off our support matrix, we can just // static-import it normally const mock = (await import('node:test')).default.mock; if (!mock) { return; } const mockRandomUUID = mock.method(native, 'randomUUID'); assert.equal(mockRandomUUID.mock.callCount(), 0); v4({}); assert.equal(mockRandomUUID.mock.callCount(), 0); mock.restoreAll(); }); test('explicit options.random produces expected result', () => { const id = v4({ random: randomBytesFixture }); assert.strictEqual(id, '109156be-c4fb-41ea-b1b4-efe1671c5836'); }); test('explicit options.rng produces expected result', () => { const id = v4({ rng: () => randomBytesFixture }); assert.strictEqual(id, '109156be-c4fb-41ea-b1b4-efe1671c5836'); }); test('fills one UUID into a buffer as expected', () => { const buffer = new Uint8Array(16); const result = v4({ random: randomBytesFixture }, buffer); assert.deepEqual(buffer, expectedBytes); assert.strictEqual(buffer, result); }); test('fills two UUIDs into a buffer as expected', () => { const buffer = new Uint8Array(32); v4({ random: randomBytesFixture }, buffer, 0); v4({ random: randomBytesFixture }, buffer, 16); const expectedBuf = new Uint8Array(32); expectedBuf.set(expectedBytes); expectedBuf.set(expectedBytes, 16); assert.deepEqual(buffer, expectedBuf); }); test('throws when option.random is too short', () => { const random = Uint8Array.of(16); const buffer = new Uint8Array(16).fill(0); assert.throws(() => { v4({ random }, buffer); }); }); test('throws when options.rng() is too short', () => { const buffer = new Uint8Array(16); const rng = () => Uint8Array.of(0); // length = 1 assert.throws(() => { v4({ rng }, buffer); }); }); test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); assert.throws(() => v4({}, buf15)); assert.throws(() => v4({}, buf30, -1)); assert.throws(() => v4({}, buf30, 15)); }); }); ================================================ FILE: src/test/v6.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import v1ToV6 from '../v1ToV6.js'; import v6 from '../v6.js'; import v6ToV1 from '../v6ToV1.js'; describe('v6', () => { const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; const fullOptions = { msecs: 0x133b891f705, nsecs: 0x1538, clockseq: 0x385c, node: Uint8Array.of(0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10), }; const EXPECTED_BYTES = Uint8Array.of( 0x1e, 0x11, 0x22, 0xbd, 0x94, 0x28, 0x68, 0x88, 0xb8, 0x5c, 0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10 ); test('default behavior', () => { // Verify explicit options produce expected id const id = v6(); assert.ok( /[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/.test(id), 'id is valid v6 UUID' ); }); test('default behavior (binary type)', () => { const buffer = new Uint8Array(16); const result = v6(fullOptions, buffer); assert.deepEqual(buffer, EXPECTED_BYTES); assert.strictEqual(buffer, result); }); test('all options', () => { // Verify explicit options produce expected id const id = v6(fullOptions); assert.equal(id, '1e1122bd-9428-6888-b85c-61cd3cbb3210'); }); test('sort by creation time', () => { // Verify ids sort by creation time const ids = []; for (let i = 0; i < 5; i++) { ids.push(v6({ msecs: i * 1000 })); } assert.deepEqual(ids, ids.slice().sort()); }); test('creating at array offset', () => { const buffer = new Uint8Array(32); v6(fullOptions, buffer, 0); v6(fullOptions, buffer, 16); const expectedBuf = new Uint8Array(32); expectedBuf.set(EXPECTED_BYTES, 0); expectedBuf.set(EXPECTED_BYTES, 16); assert.deepEqual(buffer, expectedBuf); }); test('v1 -> v6 conversion', () => { const id = v1ToV6(V1_ID); assert.equal(id, V6_ID); }); test('v6 -> v1 conversion', () => { const id = v6ToV1(V6_ID); assert.equal(id, V1_ID); }); }); ================================================ FILE: src/test/v7.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import parse from '../parse.js'; import stringify from '../stringify.js'; import { Version7Options } from '../types.js'; import v7, { updateV7State } from '../v7.js'; // Fixture values for testing with the rfc v7 UUID example: // https://www.rfc-editor.org/rfc/rfc9562.html#name-example-of-a-uuidv7-value const RFC_V7 = '017f22e2-79b0-7cc3-98c4-dc0c0c07398f'; const RFC_V7_BYTES = parse('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'); const RFC_MSECS = 0x17f22e279b0; // `option.seq` for the above RFC uuid const RFC_SEQ = (0x0cc3 << 20) | (0x98c4dc >> 2); // `option,random` for the above RFC uuid const RFC_RANDOM = Uint8Array.of( 0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0x0c, 0xc3, 0x18, 0xc4, 0x6c, 0x0c, 0x0c, 0x07, 0x39, 0x8f ); describe('v7', () => { test('subsequent UUIDs are different', () => { const id1 = v7(); const id2 = v7(); assert.ok(id1 !== id2); }); test('explicit options.random and options.msecs produces expected result', () => { const id = v7({ random: RFC_RANDOM, msecs: RFC_MSECS, seq: RFC_SEQ, }); assert.strictEqual(id, RFC_V7); }); test('explicit options.rng produces expected result', () => { const id = v7({ rng: () => RFC_RANDOM, msecs: RFC_MSECS, seq: RFC_SEQ, }); assert.strictEqual(id, RFC_V7); }); test('explicit options.msecs produces expected result', () => { const id = v7({ msecs: RFC_MSECS, }); assert.strictEqual(id.indexOf('017f22e2'), 0); }); test('fills one UUID into a buffer as expected', () => { const buffer = new Uint8Array(16); const result = v7( { random: RFC_RANDOM, msecs: RFC_MSECS, seq: RFC_SEQ, }, buffer ); stringify(buffer); assert.deepEqual(buffer, RFC_V7_BYTES); assert.strictEqual(buffer, result); }); test('fills two UUIDs into a buffer as expected', () => { const buffer = new Uint8Array(32); v7( { random: RFC_RANDOM, msecs: RFC_MSECS, seq: RFC_SEQ, }, buffer, 0 ); v7( { random: RFC_RANDOM, msecs: RFC_MSECS, seq: RFC_SEQ, }, buffer, 16 ); const expected = new Uint8Array(32); expected.set(RFC_V7_BYTES); expected.set(RFC_V7_BYTES, 16); assert.deepEqual(buffer, expected); }); // // monotonic and lexicographical sorting tests // test('lexicographical sorting is preserved', () => { let id; let prior; let msecs = RFC_MSECS; for (let i = 0; i < 20000; ++i) { if (i % 1500 === 0) { // every 1500 runs increment msecs so seq is // reinitialized, simulating passage of time msecs += 1; } id = v7({ msecs, seq: i }); if (prior !== undefined) { assert.ok(prior < id, `${prior} < ${id}`); } prior = id; } }); test('can supply seq', () => { let seq = 0x12345; let uuid = v7({ msecs: RFC_MSECS, seq, }); assert.strictEqual(uuid.substr(0, 25), '017f22e2-79b0-7000-848d-1'); seq = 0x6fffffff; uuid = v7({ msecs: RFC_MSECS, seq, }); assert.strictEqual(uuid.substring(0, 25), '017f22e2-79b0-76ff-bfff-f'); }); test('internal seq is reset upon timestamp change', () => { v7({ msecs: RFC_MSECS, seq: 0x6fffffff, }); const uuid = v7({ msecs: RFC_MSECS + 1, }); assert.ok(uuid.indexOf('fff') !== 15); }); test('v7() state transitions', () => { const tests = [ { title: 'new time interval', state: { msecs: 1, seq: 123 }, now: 2, expected: { msecs: 2, // time interval should update seq: 0x6c318c4, // sequence should be randomized }, }, { title: 'same time interval', state: { msecs: 1, seq: 123 }, now: 1, expected: { msecs: 1, // timestamp unchanged seq: 124, // sequence increments }, }, { title: 'same time interval (sequence rollover)', state: { msecs: 1, seq: 0xffffffff }, now: 1, expected: { msecs: 2, // timestamp increments seq: 0, // sequence rolls over }, }, { title: 'time regression', state: { msecs: 2, seq: 123 }, now: 1, expected: { msecs: 2, // timestamp unchanged seq: 124, // sequence increments }, }, { title: 'time regression (sequence rollover)', state: { msecs: 2, seq: 0xffffffff }, now: 1, expected: { // timestamp increments (crazy, right? The system clock goes backwards // but the UUID timestamp moves forward? Weird, but it's what's // required to maintain monotonicity... and this is why we have unit // tests!) msecs: 3, seq: 0, // sequence rolls over }, }, ]; for (const { title, state, now, expected } of tests) { assert.deepStrictEqual(updateV7State(state, now, RFC_RANDOM), expected, `Failed: ${title}`); } }); test('flipping bits changes the result', () => { // convert uint8array to BigInt (BE) const asBigInt = (buf: Uint8Array) => buf.reduce((acc, v) => (acc << 8n) | BigInt(v), 0n); // convert the given number of bits (LE) to number const asNumber = (bits: number, data: bigint) => Number(BigInt.asUintN(bits, data)); // flip the nth bit (BE) in a BigInt const flip = (data: bigint, n: number) => data ^ (1n << BigInt(127 - n)); // Extract v7 `options` from a (BigInt) UUID const optionsFrom = (data: bigint): Version7Options => { const ms = asNumber(48, data >> 80n); const hi = asNumber(12, data >> 64n); const lo = asNumber(20, data >> 42n); const r = BigInt.asUintN(42, data); return { msecs: ms, seq: (hi << 20) | lo, random: Uint8Array.from([ ...Array(10).fill(0), ...Array(6) .fill(0) .map((_, i) => asNumber(8, r >> (BigInt(i) * 8n))) .reverse(), ]), }; }; const buf = new Uint8Array(16); const data = asBigInt(v7({}, buf)); const id = stringify(buf); const reserved = [48, 49, 50, 51, 64, 65]; for (let i = 0; i < 128; ++i) { if (reserved.includes(i)) { continue; // skip bits used for version and variant } const flipped = flip(data, i); assert.strictEqual( asBigInt(v7(optionsFrom(flipped), buf)).toString(16), flipped.toString(16), `Unequal uuids at bit ${i}` ); assert.notStrictEqual(stringify(buf), id); } }); test('throws when option.random is too short', () => { const random = Uint8Array.of(16); const buffer = new Uint8Array(16).fill(0); assert.throws(() => { v7({ random }, buffer); }); }); test('throws when options.rng() is too short', () => { const buffer = new Uint8Array(16); const rng = () => Uint8Array.of(0); // length = 1 assert.throws(() => { v7({ rng }, buffer); }); }); test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); assert.throws(() => v7({}, buf15)); assert.throws(() => v7({}, buf30, -1)); assert.throws(() => v7({}, buf30, 15)); }); }); ================================================ FILE: src/test/validate.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import validate from '../validate.js'; import { TESTS } from './test_constants.js'; describe('validate()', () => { test('TESTS cases', () => { for (const { value, expectedValidate } of TESTS) { assert.strictEqual( validate(value), expectedValidate, `validate(${value}) should be ${expectedValidate}` ); } }); }); ================================================ FILE: src/test/version.test.ts ================================================ import * as assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import version from '../version.js'; import { TESTS } from './test_constants.js'; describe('version()', () => { test('TESTS cases', () => { for (const { value, expectedValidate, expectedVersion } of TESTS) { try { // @ts-expect-error testing invalid input const actualVersion = version(value); assert.ok(expectedValidate, `version(${value}) should throw`); assert.strictEqual(actualVersion, expectedVersion); } catch { assert.ok(!expectedValidate, `version(${value}) threw unexpectedly`); } } }); }); ================================================ FILE: src/types.ts ================================================ export type UUIDTypes = string | TBuf; export type Version1Options = { node?: Uint8Array; clockseq?: number; random?: Uint8Array; rng?: () => Uint8Array; msecs?: number; nsecs?: number; _v6?: boolean; // Internal use only! }; export type Version4Options = { random?: Uint8Array; rng?: () => Uint8Array; }; export type Version6Options = Version1Options; export type Version7Options = { random?: Uint8Array; msecs?: number; seq?: number; rng?: () => Uint8Array; }; ================================================ FILE: src/uuid-bin.ts ================================================ import * as assert from 'node:assert/strict'; import v1 from './v1.js'; import v3 from './v3.js'; import v4 from './v4.js'; import v5 from './v5.js'; import v6 from './v6.js'; import v7 from './v7.js'; function usage() { console.log('Usage:'); console.log(' uuid'); console.log(' uuid v1'); console.log(' uuid v3 '); console.log(' uuid v4'); console.log(' uuid v5 '); console.log(' uuid v6'); console.log(' uuid v7'); console.log(' uuid --help'); console.log( '\nNote: may be "URL" or "DNS" to use the corresponding UUIDs defined by RFC9562' ); } const args = process.argv.slice(2); if (args.indexOf('--help') >= 0) { usage(); process.exit(0); } const version = args.shift() || 'v4'; switch (version) { case 'v1': console.log(v1()); break; case 'v3': { const name = args.shift(); let namespace = args.shift(); assert.ok(name != null, 'v3 name not specified'); assert.ok(namespace != null, 'v3 namespace not specified'); if (namespace === 'URL') { namespace = v3.URL; } if (namespace === 'DNS') { namespace = v3.DNS; } console.log(v3(name, namespace)); break; } case 'v4': console.log(v4()); break; case 'v5': { const name = args.shift(); let namespace = args.shift(); assert.ok(name != null, 'v5 name not specified'); assert.ok(namespace != null, 'v5 namespace not specified'); if (namespace === 'URL') { namespace = v5.URL; } if (namespace === 'DNS') { namespace = v5.DNS; } console.log(v5(name, namespace)); break; } case 'v6': console.log(v6()); break; case 'v7': console.log(v7()); break; default: usage(); process.exit(1); } ================================================ FILE: src/v1.ts ================================================ import rng from './rng.js'; import { unsafeStringify } from './stringify.js'; import { UUIDTypes, Version1Options } from './types.js'; // **`v1()` - Generate time-based UUID** // // Inspired by https://github.com/LiosK/UUID.js // and http://docs.python.org/library/uuid.html type V1State = { node?: Uint8Array; // node id (47-bit random) clockseq?: number; // sequence number (14-bit) // v1 & v6 timestamps are a pain to deal with. They specify time from the // Gregorian epoch in 100ns intervals, which requires values with 57+ bits of // precision. But that's outside the precision of IEEE754 floats (i.e. JS // numbers). To work around this, we represent them internally using 'msecs' // (milliseconds since unix epoch) and 'nsecs' (100-nanoseconds offset from // `msecs`). msecs?: number; // timestamp (milliseconds, unix epoch) nsecs?: number; // timestamp (100-nanoseconds offset from 'msecs') }; const _state: V1State = {}; function v1(options?: Version1Options, buf?: undefined, offset?: number): string; function v1( options: Version1Options | undefined, buf: Buf, offset?: number ): Buf; function v1( options?: Version1Options, buf?: TBuf, offset?: number ): UUIDTypes { let bytes: Uint8Array; // Extract _v6 flag from options, clearing options if appropriate const isV6 = options?._v6 ?? false; if (options) { const optionsKeys = Object.keys(options); if (optionsKeys.length === 1 && optionsKeys[0] === '_v6') { options = undefined; } } if (options) { // With options: Make UUID independent of internal state bytes = v1Bytes( options.random ?? options.rng?.() ?? rng(), options.msecs, options.nsecs, options.clockseq, options.node, buf, offset ); } else { // Without options: Make UUID from internal state const now = Date.now(); const rnds = rng(); updateV1State(_state, now, rnds); // Geenerate UUID. Note that v6 uses random values for `clockseq` and // `node`. // // https://www.rfc-editor.org/rfc/rfc9562.html#section-5.6-4 bytes = v1Bytes( rnds, _state.msecs, _state.nsecs, // v6 UUIDs get random `clockseq` and `node` for every UUID // https://www.rfc-editor.org/rfc/rfc9562.html#section-5.6-4 isV6 ? undefined : _state.clockseq, isV6 ? undefined : _state.node, buf, offset ); } return buf ?? unsafeStringify(bytes); } // (Private!) Do not use. This method is only exported for testing purposes // and may change without notice. export function updateV1State(state: V1State, now: number, rnds: Uint8Array) { state.msecs ??= -Infinity; state.nsecs ??= 0; // Update timestamp if (now === state.msecs) { // Same msec-interval = simulate higher clock resolution by bumping `nsecs` // https://www.rfc-editor.org/rfc/rfc9562.html#section-6.1-2.6 state.nsecs++; // Check for `nsecs` overflow (nsecs is capped at 10K intervals / msec) if (state.nsecs >= 10000) { // Prior to uuid@11 this would throw an error, however the RFCs allow for // changing the node in this case. This slightly breaks monotonicity at // msec granularity, but that's not a significant concern. // https://www.rfc-editor.org/rfc/rfc9562.html#section-6.1-2.16 state.node = undefined; state.nsecs = 0; } } else if (now > state.msecs) { // Reset nsec counter when clock advances to a new msec interval state.nsecs = 0; } else if (now < state.msecs) { // Handle clock regression // https://www.rfc-editor.org/rfc/rfc9562.html#section-6.1-2.7 // // Note: Unsetting node here causes both it and clockseq to be randomized, // below. state.node = undefined; } // Init node and clock sequence (do this after timestamp update which may // reset the node) https://www.rfc-editor.org/rfc/rfc9562.html#section-5.1-7 // // Note: if (!state.node) { state.node = rnds.slice(10, 16); // Set multicast bit // https://www.rfc-editor.org/rfc/rfc9562.html#section-6.10-3 state.node[0] |= 0x01; // Set multicast bit // Clock sequence must be randomized // https://www.rfc-editor.org/rfc/rfc9562.html#section-5.1-8 state.clockseq = ((rnds[8] << 8) | rnds[9]) & 0x3fff; } state.msecs = now; return state; } function v1Bytes( rnds: Uint8Array, msecs?: number, nsecs?: number, clockseq?: number, node?: Uint8Array, buf?: Uint8Array, offset = 0 ) { if (rnds.length < 16) { throw new Error('Random bytes length must be >= 16'); } // Defaults if (!buf) { buf = new Uint8Array(16); offset = 0; } else { if (offset < 0 || offset + 16 > buf.length) { throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); } } msecs ??= Date.now(); nsecs ??= 0; clockseq ??= ((rnds[8] << 8) | rnds[9]) & 0x3fff; node ??= rnds.slice(10, 16); // Offset to Gregorian epoch // https://www.rfc-editor.org/rfc/rfc9562.html#section-5.1-1 msecs += 12219292800000; // `time_low` const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; buf[offset++] = (tl >>> 24) & 0xff; buf[offset++] = (tl >>> 16) & 0xff; buf[offset++] = (tl >>> 8) & 0xff; buf[offset++] = tl & 0xff; // `time_mid` const tmh = ((msecs / 0x100000000) * 10000) & 0xfffffff; buf[offset++] = (tmh >>> 8) & 0xff; buf[offset++] = tmh & 0xff; // `time_high_and_version` buf[offset++] = ((tmh >>> 24) & 0xf) | 0x10; // include version buf[offset++] = (tmh >>> 16) & 0xff; // `clock_seq_hi_and_reserved` | variant buf[offset++] = (clockseq >>> 8) | 0x80; // `clock_seq_low` buf[offset++] = clockseq & 0xff; // `node` for (let n = 0; n < 6; ++n) { buf[offset++] = node[n]; } return buf; } export default v1; ================================================ FILE: src/v1ToV6.ts ================================================ import { UUIDTypes } from './types.js'; import parse from './parse.js'; import { unsafeStringify } from './stringify.js'; /** * Convert a v1 UUID to a v6 UUID * * @param {string|Uint8Array} uuid - The v1 UUID to convert to v6 * @returns {string|Uint8Array} The v6 UUID as the same type as the `uuid` arg * (string or Uint8Array) */ export default function v1ToV6(uuid: string): string; export default function v1ToV6(uuid: Uint8Array): Uint8Array; export default function v1ToV6(uuid: string | Uint8Array): UUIDTypes { const v1Bytes = typeof uuid === 'string' ? parse(uuid) : uuid; const v6Bytes = _v1ToV6(v1Bytes); return typeof uuid === 'string' ? unsafeStringify(v6Bytes) : v6Bytes; } // Do the field transformation needed for v1 -> v6 function _v1ToV6(v1Bytes: Uint8Array) { return Uint8Array.of( ((v1Bytes[6] & 0x0f) << 4) | ((v1Bytes[7] >> 4) & 0x0f), ((v1Bytes[7] & 0x0f) << 4) | ((v1Bytes[4] & 0xf0) >> 4), ((v1Bytes[4] & 0x0f) << 4) | ((v1Bytes[5] & 0xf0) >> 4), ((v1Bytes[5] & 0x0f) << 4) | ((v1Bytes[0] & 0xf0) >> 4), ((v1Bytes[0] & 0x0f) << 4) | ((v1Bytes[1] & 0xf0) >> 4), ((v1Bytes[1] & 0x0f) << 4) | ((v1Bytes[2] & 0xf0) >> 4), 0x60 | (v1Bytes[2] & 0x0f), v1Bytes[3], v1Bytes[8], v1Bytes[9], v1Bytes[10], v1Bytes[11], v1Bytes[12], v1Bytes[13], v1Bytes[14], v1Bytes[15] ); } ================================================ FILE: src/v3.ts ================================================ import { UUIDTypes } from './types.js'; import md5 from './md5.js'; import v35, { DNS, URL } from './v35.js'; export { DNS, URL } from './v35.js'; function v3( value: string | Uint8Array, namespace: UUIDTypes, buf?: undefined, offset?: number ): string; function v3( value: string | Uint8Array, namespace: UUIDTypes, buf: TBuf, offset?: number ): TBuf; function v3( value: string | Uint8Array, namespace: UUIDTypes, buf?: TBuf, offset?: number ): UUIDTypes { return v35(0x30, md5, value, namespace, buf, offset); } v3.DNS = DNS; v3.URL = URL; export default v3; ================================================ FILE: src/v35.ts ================================================ import { UUIDTypes } from './types.js'; import parse from './parse.js'; import { unsafeStringify } from './stringify.js'; export function stringToBytes(str: string) { // TODO: Use TextEncoder (see https://stackoverflow.com/a/48762658/109538) str = unescape(encodeURIComponent(str)); const bytes = new Uint8Array(str.length); for (let i = 0; i < str.length; ++i) { bytes[i] = str.charCodeAt(i); } return bytes; } export const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; export const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; type HashFunction = (bytes: Uint8Array) => Uint8Array; export default function v35( version: 0x30 | 0x50, hash: HashFunction, value: string | Uint8Array, namespace: UUIDTypes, buf?: TBuf, offset?: number ): UUIDTypes { const valueBytes: Uint8Array = typeof value === 'string' ? stringToBytes(value) : value; const namespaceBytes: Uint8Array = typeof namespace === 'string' ? parse(namespace) : namespace; if (typeof namespace === 'string') { namespace = parse(namespace); } if (namespace?.length !== 16) { throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); } // Compute hash of namespace and value, Per 4.3 // Future: Use spread syntax when supported on all platforms, e.g. `bytes = // hashfunc([...namespace, ... value])` let bytes = new Uint8Array(16 + valueBytes.length); bytes.set(namespaceBytes); bytes.set(valueBytes, namespaceBytes.length); bytes = hash(bytes); bytes[6] = (bytes[6] & 0x0f) | version; bytes[8] = (bytes[8] & 0x3f) | 0x80; if (buf) { offset = offset || 0; for (let i = 0; i < 16; ++i) { buf[offset + i] = bytes[i]; } return buf; } return unsafeStringify(bytes); } ================================================ FILE: src/v4.ts ================================================ import native from './native.js'; import rng from './rng.js'; import { unsafeStringify } from './stringify.js'; import { UUIDTypes, Version4Options } from './types.js'; function _v4( options?: Version4Options, buf?: TBuf, offset?: number ): UUIDTypes { options = options || {}; const rnds = options.random ?? options.rng?.() ?? rng(); if (rnds.length < 16) { throw new Error('Random bytes length must be >= 16'); } // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = (rnds[6] & 0x0f) | 0x40; rnds[8] = (rnds[8] & 0x3f) | 0x80; // Copy bytes to buffer, if provided if (buf) { offset = offset || 0; if (offset < 0 || offset + 16 > buf.length) { throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); } for (let i = 0; i < 16; ++i) { buf[offset + i] = rnds[i]; } return buf; } return unsafeStringify(rnds); } function v4(options?: Version4Options, buf?: undefined, offset?: number): string; function v4( options: Version4Options | undefined, buf: TBuf, offset?: number ): TBuf; function v4( options?: Version4Options, buf?: TBuf, offset?: number ): UUIDTypes { if (native.randomUUID && !buf && !options) { return native.randomUUID(); } // Putting tail-code that could just go inline here in a separate function // allows for compiler optimizations that dramatically improve performance. // // REF: https://github.com/uuidjs/uuid/issues/892 return _v4(options, buf, offset); } export default v4; ================================================ FILE: src/v5.ts ================================================ import { UUIDTypes } from './types.js'; import sha1 from './sha1.js'; import v35, { DNS, URL } from './v35.js'; export { DNS, URL } from './v35.js'; function v5( value: string | Uint8Array, namespace: UUIDTypes, buf?: undefined, offset?: number ): string; function v5( value: string | Uint8Array, namespace: UUIDTypes, buf: TBuf, offset?: number ): TBuf; function v5( value: string | Uint8Array, namespace: UUIDTypes, buf?: TBuf, offset?: number ): UUIDTypes { return v35(0x50, sha1, value, namespace, buf, offset); } v5.DNS = DNS; v5.URL = URL; export default v5; ================================================ FILE: src/v6.ts ================================================ import { UUIDTypes, Version6Options } from './types.js'; import { unsafeStringify } from './stringify.js'; import v1 from './v1.js'; import v1ToV6 from './v1ToV6.js'; function v6(options?: Version6Options, buf?: undefined, offset?: number): string; function v6( options: Version6Options | undefined, buf: TBuf, offset?: number ): TBuf; function v6( options?: Version6Options, buf?: TBuf, offset?: number ): UUIDTypes { options ??= {}; offset ??= 0; // v6 is v1 with different field layout, so we start with a v1 UUID, albeit // with slightly different behavior around how the clock_seq and node fields // are randomized, which is why we call v1 with _v6: true. let bytes = v1({ ...options, _v6: true }, new Uint8Array(16)); // Reorder the fields to v6 layout. bytes = v1ToV6(bytes); // Return as a byte array if requested if (buf) { for (let i = 0; i < 16; i++) { buf[offset + i] = bytes[i]; } return buf; } return unsafeStringify(bytes); } export default v6; ================================================ FILE: src/v6ToV1.ts ================================================ import { UUIDTypes } from './types.js'; import parse from './parse.js'; import { unsafeStringify } from './stringify.js'; /** * Convert a v6 UUID to a v1 UUID * * @param {string|Uint8Array} uuid - The v6 UUID to convert to v6 * @returns {string|Uint8Array} The v1 UUID as the same type as the `uuid` arg * (string or Uint8Array) */ export default function v6ToV1(uuid: string): string; export default function v6ToV1(uuid: Uint8Array): Uint8Array; export default function v6ToV1(uuid: UUIDTypes): UUIDTypes { const v6Bytes = typeof uuid === 'string' ? parse(uuid) : uuid; const v1Bytes = _v6ToV1(v6Bytes); return typeof uuid === 'string' ? unsafeStringify(v1Bytes) : v1Bytes; } // Do the field transformation needed for v6 -> v1 function _v6ToV1(v6Bytes: Uint8Array) { return Uint8Array.of( ((v6Bytes[3] & 0x0f) << 4) | ((v6Bytes[4] >> 4) & 0x0f), ((v6Bytes[4] & 0x0f) << 4) | ((v6Bytes[5] & 0xf0) >> 4), ((v6Bytes[5] & 0x0f) << 4) | (v6Bytes[6] & 0x0f), v6Bytes[7], ((v6Bytes[1] & 0x0f) << 4) | ((v6Bytes[2] & 0xf0) >> 4), ((v6Bytes[2] & 0x0f) << 4) | ((v6Bytes[3] & 0xf0) >> 4), 0x10 | ((v6Bytes[0] & 0xf0) >> 4), ((v6Bytes[0] & 0x0f) << 4) | ((v6Bytes[1] & 0xf0) >> 4), v6Bytes[8], v6Bytes[9], v6Bytes[10], v6Bytes[11], v6Bytes[12], v6Bytes[13], v6Bytes[14], v6Bytes[15] ); } ================================================ FILE: src/v7.ts ================================================ import rng from './rng.js'; import { unsafeStringify } from './stringify.js'; import { UUIDTypes, Version7Options } from './types.js'; type V7State = { msecs?: number; // time, milliseconds seq?: number; // sequence number (32-bits) }; const _state: V7State = {}; function v7(options?: Version7Options, buf?: undefined, offset?: number): string; function v7( options: Version7Options | undefined, buf: TBuf, offset?: number ): TBuf; function v7( options?: Version7Options, buf?: TBuf, offset?: number ): UUIDTypes { let bytes: Uint8Array; if (options) { // With options: Make UUID independent of internal state bytes = v7Bytes( options.random ?? options.rng?.() ?? rng(), options.msecs, options.seq, buf, offset ); } else { // No options: Use internal state const now = Date.now(); const rnds = rng(); updateV7State(_state, now, rnds); bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset); } return buf ?? unsafeStringify(bytes); } // (Private!) Do not use. This method is only exported for testing purposes // and may change without notice. export function updateV7State(state: V7State, now: number, rnds: Uint8Array) { state.msecs ??= -Infinity; state.seq ??= 0; if (now > state.msecs) { // Time has moved on! Pick a new random sequence number state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; state.msecs = now; } else { // Bump sequence counter w/ 32-bit rollover state.seq = (state.seq + 1) | 0; // In case of rollover, bump timestamp to preserve monotonicity. This is // allowed by the RFC and should self-correct as the system clock catches // up. See https://www.rfc-editor.org/rfc/rfc9562.html#section-6.2-9.4 if (state.seq === 0) { state.msecs++; } } return state; } function v7Bytes(rnds: Uint8Array, msecs?: number, seq?: number, buf?: Uint8Array, offset = 0) { if (rnds.length < 16) { throw new Error('Random bytes length must be >= 16'); } if (!buf) { buf = new Uint8Array(16); offset = 0; } else { if (offset < 0 || offset + 16 > buf.length) { throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); } } // Defaults msecs ??= Date.now(); seq ??= ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; // byte 0-5: timestamp (48 bits) buf[offset++] = (msecs / 0x10000000000) & 0xff; buf[offset++] = (msecs / 0x100000000) & 0xff; buf[offset++] = (msecs / 0x1000000) & 0xff; buf[offset++] = (msecs / 0x10000) & 0xff; buf[offset++] = (msecs / 0x100) & 0xff; buf[offset++] = msecs & 0xff; // byte 6: `version` (4 bits) | sequence bits 28-31 (4 bits) buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f); // byte 7: sequence bits 20-27 (8 bits) buf[offset++] = (seq >>> 20) & 0xff; // byte 8: `variant` (2 bits) | sequence bits 14-19 (6 bits) buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f); // byte 9: sequence bits 6-13 (8 bits) buf[offset++] = (seq >>> 6) & 0xff; // byte 10: sequence bits 0-5 (6 bits) | random (2 bits) buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03); // bytes 11-15: random (40 bits) buf[offset++] = rnds[11]; buf[offset++] = rnds[12]; buf[offset++] = rnds[13]; buf[offset++] = rnds[14]; buf[offset++] = rnds[15]; return buf; } export default v7; ================================================ FILE: src/validate.ts ================================================ import REGEX from './regex.js'; function validate(uuid: unknown) { return typeof uuid === 'string' && REGEX.test(uuid); } export default validate; ================================================ FILE: src/version.ts ================================================ import validate from './validate.js'; function version(uuid: string) { if (!validate(uuid)) { throw TypeError('Invalid UUID'); } return parseInt(uuid.slice(14, 15), 16); } export default version; ================================================ FILE: test/browser/browser.spec.js ================================================ /* global browser:false, $:false, $$:false */ const v1Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; const v4Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; const v6Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-6[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; const v7Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; const V1_ID = 'f1207660-21d2-11ef-8c4f-419efbd44d48'; const V6_ID = '1ef21d2f-1207-6660-8c4f-419efbd44d48'; const v1 = (result) => expect(result).toMatch(v1Regex); const v4 = (result) => expect(result).toMatch(v4Regex); const v6 = (result) => expect(result).toMatch(v6Regex); const v7 = (result) => expect(result).toMatch(v7Regex); const v3dns = (result) => expect(result).toBe('9125a8dc-52ee-365b-a5aa-81b0b3681cf6'); const v3url = (result) => expect(result).toBe('c6235813-3ba4-3801-ae84-e0a6ebb7d138'); const v3custom = (result) => expect(result).toBe('f5a52d34-dcd7-30f7-b581-0112fab43d0c'); const v5dns = (result) => expect(result).toBe('fdda765f-fc57-5604-a269-52a7df8164ec'); const v5url = (result) => expect(result).toBe('3bbcee75-cecc-5b56-8031-b6641c1ed1f1'); const v5custom = (result) => expect(result).toBe('c49c5142-4d9a-5940-a926-612ede0ec632'); const v1ToV6 = (result) => expect(result).toBe(V6_ID); const v6ToV1 = (result) => expect(result).toBe(V1_ID); const nil = (result) => expect(result).toBe('00000000-0000-0000-0000-000000000000'); const max = (result) => expect(result).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff'); const parse = (result) => expect(result).toEqual('85,35,141,21,201,38,69,152,180,157,207,78,145,59,161,60'); const stringify = (result) => expect(result).toBe('55238d15-c926-4598-b49d-cf4e913ba13c'); const validate = (result) => expect(result).toBe('true'); const version = (result) => expect(result).toBe('4'); const expectations = { 'uuidv1()': v1, 'uuidv4()': v4, 'uuidv7()': v7, 'uuidv3() DNS': v3dns, 'uuidv3() URL': v3url, 'uuidv3() MY_NAMESPACE': v3custom, 'uuidv5() DNS': v5dns, 'uuidv5() URL': v5url, 'uuidv5() MY_NAMESPACE': v5custom, 'uuidv6()': v6, 'uuidv1ToV6()': v1ToV6, 'uuidv6ToV1()': v6ToV1, NIL_UUID: nil, MAX_UUID: max, 'uuidParse()': parse, 'uuidStringify()': stringify, 'uuidValidate()': validate, 'uuidVersion()': version, 'uuid.v1()': v1, 'uuid.v4()': v4, 'uuid.v7()': v7, 'uuid.v3() DNS': v3dns, 'uuid.v3() URL': v3url, 'uuid.v3() MY_NAMESPACE': v3custom, 'uuid.v5() DNS': v5dns, 'uuid.v5() URL': v5url, 'uuid.v5() MY_NAMESPACE': v5custom, 'uuid.v6()': v6, 'uuid.v1ToV6()': v1ToV6, 'uuid.v6ToV1()': v6ToV1, 'uuid.NIL': nil, 'uuid.MAX': max, 'uuid.parse()': parse, 'uuid.stringify()': stringify, 'uuid.validate()': validate, 'uuid.version()': version, }; const expectationTitles = Object.keys(expectations); const PORT = 9000; describe('BrowserStack Local Testing', () => { async function testExpectations(path, titleFilter) { const url = `http://127.0.0.1:${PORT}/${path}`; await browser.url(url); await browser.waitUntil(async () => $('#done').isExisting(), 30000); const elements = await $$('.test_result'); // Unfortunately the WebDriver API is not thread safe and we cannot use Promise.all() to // query it in parallel: // https://github.com/SeleniumHQ/selenium/issues/422#issuecomment-90629726 const titles = []; for (let i = 0; i < elements.length; ++i) { const element = elements[i]; const titleEl = await element.$('dt'); const title = await titleEl.getText(); const resultEl = await element.$('dd'); const result = await resultEl.getText(); if (!expectations[title]) { throw new Error(`Unexpected title: ${title}`); } expectations[title](result); titles.push(title); } // Confirm the expected titles are all present const expectedTitles = expectationTitles.filter(titleFilter); expect(titles.length).toEqual(expectedTitles.length); expect(titles.sort()).toEqual(expectedTitles.sort()); } describe('webpack', () => { it('renders all', async () => testExpectations('browser-webpack/example-all.html', () => true)); it('renders v1 only', async () => testExpectations('browser-webpack/example-v1.html', (title) => title.includes('uuidv1()'))); it('renders v4 only', async () => testExpectations('browser-webpack/example-v4.html', (title) => title.includes('uuidv4()'))); }); describe('rollup', () => { it('renders all', async () => testExpectations('browser-rollup/example-all.html', () => true)); it('renders v1 only', async () => testExpectations('browser-rollup/example-v1.html', (title) => title.includes('uuidv1()'))); it('renders v4 only', async () => testExpectations('browser-rollup/example-v4.html', (title) => title.includes('uuidv4('))); }); }); ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "declaration": true, "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", "removeComments": true, "skipLibCheck": true, "strict": true, "target": "ES2022" }, "exclude": ["dist", "examples"] } ================================================ FILE: wdio.conf.js ================================================ const PORT = 9000; const PROJECT = process.env.GITHUB_REPOSITORY || 'node-uuid'; const GITHUB_SHA = process.env.GITHUB_SHA || ''; const GITHUB_REF = process.env.GITHUB_REF || ''; const BUILD = GITHUB_SHA || GITHUB_REF ? `${GITHUB_REF} ${GITHUB_SHA}` : 'manual build'; const commonCapabilities = { projectName: PROJECT, buildName: BUILD, sessionName: 'browser test', resolution: '1024x768', }; const capabilities = [ // Chrome Latest { browserName: 'Chrome', browserVersion: 'latest', 'bstack:options': { ...commonCapabilities, os: 'Windows', osVersion: '11', }, }, // Firefox Latest { browserName: 'Firefox', browserVersion: 'latest', 'bstack:options': { ...commonCapabilities, os: 'Windows', osVersion: '11', }, }, // Edge Latest { browserName: 'Edge', browserVersion: 'latest', 'bstack:options': { ...commonCapabilities, os: 'Windows', osVersion: '11', }, }, // Safari Latest { browserName: 'Safari', browserVersion: 'latest', 'bstack:options': { ...commonCapabilities, os: 'OS X', osVersion: 'Monterey', }, }, ]; export const config = { specs: ['./test/browser/browser.spec.js'], user: process.env.BROWSERSTACK_USER, key: process.env.BROWSERSTACK_ACCESS_KEY, services: [ [ 'static-server', { folders: [{ mount: '/', path: './examples' }], port: PORT, }, ], [ 'browserstack', { browserstackLocal: true, }, ], ], runner: 'local', maxInstances: 5, capabilities, logLevel: 'warn', bail: 1, waitforTimeout: 10000, connectionRetryTimeout: 90000, connectionRetryCount: 3, framework: 'jasmine', jasmineOpts: { defaultTimeoutInterval: 120000, }, reporters: ['spec'], };