├── .github └── dependabot.yml ├── .gitignore ├── .taskcluster.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package.json ├── src ├── index.d.ts ├── index.js └── slugid.js ├── test └── slugid_test.js └── yarn.lock /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "monthly" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.taskcluster.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | policy: 3 | pullRequests: public 4 | tasks: 5 | $let: 6 | head_rev: 7 | $if: tasks_for == "github-pull-request" 8 | then: ${event.pull_request.head.sha} 9 | else: ${event.after} 10 | repository: 11 | $if: tasks_for == "github-pull-request" 12 | then: ${event.pull_request.head.repo.html_url} 13 | else: ${event.repository.html_url} 14 | environments: 15 | - image: node:18 16 | description: Run tests with node v18 17 | command: yarn test 18 | - image: node:latest 19 | description: Run tests with latest node 20 | command: yarn test 21 | - image: node:latest 22 | description: Run tests with latest node without Buffer 23 | command: yarn run test-nobuffer 24 | in: 25 | $if: tasks_for == "github-pull-request" && event["action"] in ["opened","reopened","synchronize"] 26 | then: 27 | $map: {$eval: environments} 28 | each(env): 29 | taskId: {$eval: as_slugid(env.image + ":tests")} 30 | deadline: 31 | $fromNow: 1 day 32 | taskQueueId: proj-taskcluster/ci 33 | metadata: 34 | name: ${env.image} tests 35 | description: ${env.description} 36 | owner: ${event.sender.login}@users.noreply.github.com 37 | source: ${event.repository.url} 38 | payload: 39 | maxRunTime: 3600 40 | image: ${env.image} 41 | command: 42 | - /bin/bash 43 | - '--login' 44 | - '-c' 45 | - >- 46 | set -o xtrace && 47 | git --version && 48 | node -v && 49 | yarn -v && 50 | git clone --no-progress ${repository} repo && 51 | cd repo && 52 | git config advice.detachedHead false && 53 | git checkout --no-progress ${head_rev} && 54 | yarn install && 55 | ${env.command} 56 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog for slugid 2 | 3 | ## v3.1.0 (2022-09-05) 4 | 5 | * Buffer usage is [optional](https://github.com/taskcluster/slugid/pull/24) for browsers 6 | 7 | ## v3.0.0 (2021-08-06) 8 | 9 | * Drop support for node 4 (Node v6.17.1 is the earliest tested release) 10 | * Add support for node 12, 14, and 16 11 | * Remove unmaintained [uuid-parse](https://www.npmjs.com/package/uuid-parse) 12 | * Update to [uuid](https://www.npmjs.com/package/uuid) 8.3.2, which now 13 | includes UUID parsing functions (again) 14 | * Use ``Buffer.from(bytes)`` instead of the 15 | [insecure](https://nodejs.org/en/docs/guides/buffer-constructor-deprecation/) 16 | ``new Buffer(bytes)`` 17 | * Switch from TravisCI to Taskcluster for testing pull requests 18 | * Add Code of Conduct, Contributing Guide, and Changelog 19 | 20 | ## v2.0.0 (2018-05-07) 21 | 22 | * Drop support for node 0.10, 0.11 23 | * Add support for node 4, 6, 8, and 10 24 | * Update to [uuid](https://www.npmjs.com/package/uuid) 3.2.1 25 | * Add [uuid-parse](https://www.npmjs.com/package/uuid-parse) 1.0.0 to parse 26 | UUIDs (instead of ``uuid``) 27 | 28 | ## v1.1.0 (2015-08-27) 29 | 30 | * Add `slugid.nice()`, which ensures the first letter of the slug begins with a 31 | letter, allowing it to be used in more contexts 32 | * Update to [uuid](https://www.npmjs.com/package/uuid) 2.0.1 33 | 34 | ## v1.0.3 (2014-10-06) 35 | 36 | * Remove extra files not needed for the browser variant built with Browserify 37 | 38 | ## v1.0.2 (2014-08-19) 39 | 40 | * Add a variant that runs in a browser using [Browserify](https://browserify.org/) 5.9.1 41 | 42 | ## v1.0.1 (2014-03-28) 43 | 44 | * Add ``index.js`` with proper exports. 45 | 46 | ## v1.0.0 (2014-03-27) 47 | 48 | * Initial release of code ported from Taskcluster 49 | 50 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Participation Guidelines 2 | 3 | This repository is governed by Mozilla's code of conduct and etiquette guidelines. 4 | For more details, please read the 5 | [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). 6 | 7 | ## How to Report 8 | For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. 9 | 10 | 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We welcome pull requests from everyone. We do expect everyone to adhere to the [Mozilla Community Participation Guidelines][participation]. 4 | 5 | If you're trying to figure out what to work on, here are some places to find suitable projects: 6 | * [Good first bugs][goodfirstbug]: these are scoped to make it easy for first-time contributors to get their feet wet with Taskcluster code. 7 | * [Mentored bugs][bugsahoy]: these are slightly more involved projects that may require insight or guidance from someone on the Taskcluster team. 8 | * [Full list of open issues][issues]: everything else 9 | 10 | If the project you're interested in working on isn't covered by a bug or issue, or you're unsure about how to proceed on an existing issue, it's a good idea to talk to someone on the Taskcluster team before you go too far down a particular path. You can find us in the #taskcluster channel on [Mozilla's IRC server][irc] to discuss. You can also simply add a comment to the issue or bug. 11 | 12 | Once you've found an issue to work on and written a patch, submit a pull request. Some things that will increase the chance that your pull request is accepted: 13 | 14 | * Follow our [best practices][bestpractices]. 15 | * This includes [writing or updating tests][testing]. 16 | * Write a [good commit message][commit]. 17 | 18 | Welcome to the team! 19 | 20 | [participation]: https://www.mozilla.org/en-US/about/governance/policies/participation/ 21 | [issues]: ../../issues 22 | [bugsahoy]: https://www.joshmatthews.net/bugsahoy/?taskcluster=1 23 | [goodfirstbug]: http://www.joshmatthews.net/bugsahoy/?taskcluster=1&simple=1 24 | [irc]: https://wiki.mozilla.org/IRC 25 | [bestpractices]: https://docs.taskcluster.net/docs/manual/design/devel/best-practices 26 | [testing]: https://docs.taskcluster.net/docs/manual/design/devel/best-practices/testing 27 | [commit]: https://docs.taskcluster.net/docs/manual/design/devel/best-practices/commits 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jonas Finnemann Jensen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # slugid - Compressed UUIDs for Node.js 4 | 5 | A node.js module for generating v4 UUIDs and encoding them into 22 character 6 | URL-safe base64 slug representation (see [RFC 4648 sec. 7 | 5](http://tools.ietf.org/html/rfc4648#section-5)). 8 | 9 | Slugs are url-safe base64 encoded v4 uuids, stripped of base64 `=` padding. 10 | They are generated with the [uuid package](https://www.npmjs.com/package/uuid) which 11 | is careful to use a cryptographically strong random number generator on platforms 12 | that make one available. 13 | 14 | There are two methods for generating slugs - `slugid.v4()` and `slugid.nice()`. 15 | 16 | The `slugid.v4()` method returns a slug from a randomly generated v4 uuid. The 17 | `slugid.nice()` method returns a v4 slug which conforms to a set of "nice" 18 | properties. At the moment the only "nice" property is that the slug starts with 19 | [A-Za-f], which in turn implies that the first (most significant) but of its 20 | associated uuid is set to 0. 21 | 22 | The purpose of the `slugid.nice()` method is to support having slugids which 23 | can be used in more contexts safely. Regular slugids can safely be used in 24 | urls, and for example in AMQP routing keys. However, slugs beginning with `-` 25 | may cause problems when used as command line parameters. 26 | 27 | In contrast, slugids generated by the `slugid.nice()` method can safely be used 28 | as command line parameters. This comes at a cost to entropy (121 bits vs 122 29 | bits for regular v4 slugs). 30 | 31 | Slug consumers should consider carefully which of these two slug generation 32 | methods to call. Is it more important to have maximum entropy, or to have 33 | slugids that do not need special treatment when used as command line 34 | parameters? This is especially important if you are providing a service which 35 | supplies slugs to unexpecting tool developers downstream, who may not realise 36 | the risks of using your regular v4 slugs as command line parameters, especially 37 | since this would arise only as an intermittent issue (one time in 64). 38 | 39 | Generated slugs take the form `[A-Za-z0-9_-]{22}`, or more precisely: 40 | 41 | * `slugid.v4()` slugs conform to 42 | `[A-Za-z0-9_-]{8}[Q-T][A-Za-z0-9_-][CGKOSWaeimquy26-][A-Za-z0-9_-]{10}[AQgw]` 43 | 44 | * `slugid.nice()` slugs conform to 45 | `[A-Za-f][A-Za-z0-9_-]{7}[Q-T][A-Za-z0-9_-][CGKOSWaeimquy26-][A-Za-z0-9_-]{10}[AQgw]` 46 | 47 | RFC 4122 defines the setting of 6 bits of the v4 UUID which determines these 48 | regular expressions. 49 | 50 | ```js 51 | const slugid = require('slugid'); 52 | 53 | // Generate "nice" URL-safe base64 encoded UUID version 4 (random) 54 | const slug = slugid.nice(); // a8_YezW8T7e1jLxG7evy-A 55 | ``` 56 | 57 | Encode / Decode 58 | --------------- 59 | ```js 60 | const slugid = require('slugid'); 61 | 62 | // Generate URL-safe base64 encoded UUID version 4 (random) 63 | const slug = slugid.v4(); 64 | 65 | // Get UUID on the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx 66 | const uuid = slugid.decode(slug); 67 | 68 | // Compress to slug again 69 | assert(slug == slugid.encode(uuid)); 70 | ``` 71 | 72 | License 73 | ------- 74 | The `slugid` library is released on the MIT license, see the `LICENSE` for 75 | complete license. 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slugid", 3 | "version": "5.0.1", 4 | "author": "Jonas Finnemann Jensen ", 5 | "description": "URL-safe base64 UUID encoder for generating 22 character slugs", 6 | "license": "MIT", 7 | "main": "./src/index.js", 8 | "files": [ 9 | "src" 10 | ], 11 | "scripts": { 12 | "test": "mocha", 13 | "test-nobuffer": "NO_BUFFER=1 yarn test" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/taskcluster/slugid.git" 18 | }, 19 | "types": "./src/index.d.ts", 20 | "bugs": { 21 | "url": "https://github.com/taskcluster/slugid/issues" 22 | }, 23 | "engines": { 24 | "node": ">=18" 25 | }, 26 | "dependencies": { 27 | "uuid": "^9.0.0" 28 | }, 29 | "devDependencies": { 30 | "mocha": "^10.2.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | export function decode(slug: string): string; 2 | export function encode(uuid: string): string; 3 | export function v4(): string; 4 | export function nice(): string; 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jonas Finnemann Jensen 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | module.exports = require('./slugid'); 24 | -------------------------------------------------------------------------------- /src/slugid.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jonas Finnemann Jensen 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | const uuid = require('uuid'); 24 | 25 | /** @type {(bytes: Uint8Array) => string} */ 26 | const toBase64 = (() => { 27 | if (typeof Buffer !== 'undefined') { 28 | return (bytes) => Buffer.from(bytes).toString('base64'); 29 | } 30 | return (bytes) => btoa(String.fromCharCode(...bytes)); 31 | })(); 32 | 33 | /** @type {(base64: string) => Uint8Array | Buffer} */ 34 | const fromBase64 = (() => { 35 | if (typeof Buffer !== 'undefined') { 36 | return (base64) => Buffer.from(base64, 'base64'); 37 | } 38 | return (base64) => Uint8Array.from(atob(base64), c => c.charCodeAt(0)); 39 | })(); 40 | 41 | /** 42 | * Returns the given uuid as a 22 character slug. This can be a regular v4 43 | * slug or a "nice" slug. 44 | */ 45 | exports.encode = function(uuid_) { 46 | const bytes = uuid.parse(uuid_); 47 | const base64 = toBase64(bytes); 48 | const slug = base64 49 | .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) 50 | .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) 51 | .substring(0, 22); // Drop '==' padding 52 | return slug; 53 | }; 54 | 55 | /** 56 | * Returns the uuid represented by the given v4 or "nice" slug 57 | */ 58 | exports.decode = function(slug) { 59 | const base64 = slug 60 | .replace(/-/g, '+') 61 | .replace(/_/g, '/') 62 | + '=='; 63 | return uuid.stringify(fromBase64(base64)); 64 | }; 65 | 66 | /** 67 | * Returns a randomly generated uuid v4 compliant slug 68 | */ 69 | exports.v4 = function() { 70 | const bytes = uuid.v4(null, new Uint8Array(16)); 71 | const base64 = toBase64(bytes); 72 | const slug = base64 73 | .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) 74 | .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) 75 | .substring(0, 22); // Drop '==' padding 76 | return slug; 77 | }; 78 | 79 | /** 80 | * Returns a randomly generated uuid v4 compliant slug which conforms to a set 81 | * of "nice" properties, at the cost of some entropy. Currently this means one 82 | * extra fixed bit (the first bit of the uuid is set to 0) which guarantees the 83 | * slug will begin with [A-Za-f]. For example such slugs don't require special 84 | * handling when used as command line parameters (whereas non-nice slugs may 85 | * start with `-` which can confuse command line tools). 86 | * 87 | * Potentially other "nice" properties may be added in future to further 88 | * restrict the range of potential uuids that may be generated. 89 | */ 90 | exports.nice = function() { 91 | const bytes = uuid.v4(null, new Uint8Array(16)); 92 | bytes[0] = bytes[0] & 0x7f; // unset first bit to ensure [A-Za-f] first char 93 | const base64 = toBase64(bytes); 94 | const slug = base64 95 | .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) 96 | .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) 97 | .substring(0, 22); // Drop '==' padding 98 | return slug; 99 | }; 100 | -------------------------------------------------------------------------------- /test/slugid_test.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Jonas Finnemann Jensen 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | // Allows the tests to be run in environments with and without `Buffer`. 24 | if (process.env.NO_BUFFER === "1") { 25 | delete global.Buffer; 26 | console.log('\x1b[33m' + 'Removed `Buffer` from globalThis.' + '\x1b[0m'); 27 | } 28 | 29 | const assert = require('assert'); 30 | const slugid = require('../src/slugid'); 31 | const uuidv4 = require('uuid').v4; 32 | 33 | describe('slugid', function () { 34 | describe('encode', function () { 35 | /** 36 | * Test that we can correctly encode a "non-nice" uuid (with first bit set) to 37 | * its known slug. The specific uuid was chosen since it has a slug which 38 | * contains both `-` and `_` characters. 39 | */ 40 | it('should correctly encode a "non-nce" uuid', function () { 41 | // 10000000010011110011111111001000110111111100101101001011000001101000100111111011101011101111101011010101111000011000011101010100.... 42 | // <8 ><0 ><4 ><3 ><8 ><4 ><0 ><6 ><8 ><9 ><5 ><1 ><8 ><7 ><5 ><4 > 43 | // < g >< E >< 8 >< _ >< y >< N >< _ >< L >< S >< w >< a >< J >< - >< 6 >< 7 >< 6 >< 1 >< e >< G >< H >< V >< A > 44 | const uuid_ = '804f3fc8-dfcb-4b06-89fb-aefad5e18754'; 45 | const expectedSlug = "gE8_yN_LSwaJ-6761eGHVA"; 46 | 47 | // Encode 48 | const actualSlug = slugid.encode(uuid_); 49 | 50 | // Test that it encoded correctly 51 | assert(expectedSlug == actualSlug, "UUID not correctly encoded into slug: '" + expectedSlug + "' != '" + actualSlug + "'"); 52 | }); 53 | }); 54 | 55 | describe('decode', function () { 56 | /** 57 | * Test that we can decode a "non-nice" slug (first bit of uuid is set) that 58 | * begins with `-` 59 | */ 60 | it('should correctly decode a "non-nice" slug', function () { 61 | // 11111011111011111011111011111011111011111011111001000011111011111011111111111111111111111111111111111111111111111111111111111101.... 62 | // <4 ><3 > 63 | // < - >< - >< - >< - >< - >< - >< - >< - >< Q >< - >< - >< - >< _ >< _ >< _ >< _ >< _ >< _ >< _ >< _ >< _ >< Q > 64 | const slug = '--------Q--__________Q'; 65 | const expectedUuid = "fbefbefb-efbe-43ef-bfff-fffffffffffd"; 66 | 67 | // Decode 68 | const actualUuid = slugid.decode(slug); 69 | 70 | // Test that it is decoded correctly 71 | assert(expectedUuid == actualUuid, "Slug not correctly decoded into uuid: '" + expectedUuid + "' != '" + actualUuid + "'"); 72 | }); 73 | }); 74 | 75 | describe('encode and decode', function () { 76 | /** 77 | * Test that 100 v4 uuids are unchanged after encoding and then decoding them 78 | */ 79 | it('should correctly encode and decode 100 v4 uuids', function () { 80 | for (let i = 0; i < 100; i++) { 81 | // Generate uuid 82 | const uuid_ = uuidv4(); 83 | 84 | // Encode 85 | const slug = slugid.encode(uuid_); 86 | 87 | // Test that decode uuid matches original 88 | assert(slugid.decode(slug) == uuid_, "Encode and decode isn't identity"); 89 | }; 90 | }); 91 | 92 | /** 93 | * Test that 100 v4 slugs are unchanged after decoding and then encoding them. 94 | */ 95 | it('should correctly decode and encode 100 v4 slugs', function () { 96 | for (let i = 0; i < 100; i++) { 97 | // Generate slug 98 | const slug1 = slugid.v4(); 99 | 100 | // Decode 101 | const uuid_ = slugid.decode(slug1); 102 | 103 | // Encode 104 | const slug2 = slugid.encode(uuid_); 105 | 106 | // Test that decode uuid matches original 107 | assert(slug1 == slug2, "Decode and encode isn't identity"); 108 | }; 109 | }); 110 | }); 111 | 112 | describe('spread', function () { 113 | /** 114 | * Test: Make sure that all allowed characters can appear in all allowed 115 | * positions within the "nice" slug. In this test we generate over a thousand 116 | * slugids, and make sure that every possible allowed character per position 117 | * appears at least once in the sample of all slugids generated. We also make 118 | * sure that no other characters appear in positions in which they are not 119 | * allowed. 120 | * 121 | * base 64 encoding char -> value: 122 | * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_ 123 | * 0 1 2 3 4 5 6 124 | * 0123456789012345678901234567890123456789012345678901234567890123 125 | * 126 | * e.g. from this we can see 'j' represents 35 in base64 127 | * 128 | * The following comments show the 128 bits of the v4 uuid in binary, hex and 129 | * base 64 encodings. The 6 fixed bits (`0`/`1`) according to RFC 4122, plus 130 | * the first (most significant) fixed bit (`0`) are shown among the 121 131 | * arbitrary value bits (`.`/`x`). The `x` means the same as `.` but just 132 | * highlights which bits are grouped together for the respective encoding. 133 | * 134 | * schema: 135 | * <..........time_low............><...time_mid...><.....................node.....................> 136 | * 137 | * bin: 0xxx............................................0100............10xx............................................................ 138 | * hex: $A <01><02><03><04><05><06><07><08><09><10><11> 4 <13><14><15> $B <17><18><19><20><21><22><23><24><25><26><27><28><29><30><31> 139 | * 140 | * => $A in {0, 1, 2, 3, 4, 5, 6, 7} (0b0xxx) 141 | * => $B in {8, 9, A, B} (0b10xx) 142 | * 143 | * bin: 0xxxxx..........................................0100xx......xxxx10............................................................xx0000 144 | * b64: $C < 01 >< 02 >< 03 >< 04 >< 05 >< 06 >< 07 > $D < 09 > $E < 11 >< 12 >< 13 >< 14 >< 15 >< 16 >< 17 >< 18 >< 19 >< 20 > $F 145 | * 146 | * => $C in {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f} (0b0xxxxx) 147 | * => $D in {Q, R, S, T} (0b0100xx) 148 | * => $E in {C, G, K, O, S, W, a, e, i, m, q, u, y, 2, 6, -} (0bxxxx10) 149 | * => $F in {A, Q, g, w} (0bxx0000) 150 | */ 151 | it('should have allowed characters in all allowed positions within the "nice" slug', function () { 152 | const charsAll = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".split('').sort().join(''); 153 | // 0 - 31: 0b0xxxxx 154 | const charsC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef".split('').sort().join(''); 155 | // 16, 17, 18, 19: 0b0100xx 156 | const charsD = "QRST".split('').sort().join(''); 157 | // 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62: 0bxxxx10 158 | const charsE = "CGKOSWaeimquy26-".split('').sort().join(''); 159 | // 0, 16, 32, 48: 0bxx0000 160 | const charsF = "AQgw".split('').sort().join(''); 161 | const expected = [charsC, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsD, charsAll, charsE, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsF]; 162 | spreadTest( 163 | function() { 164 | return slugid.nice(); 165 | }, 166 | expected 167 | ); 168 | }); 169 | 170 | /** 171 | * This test is the same as niceSpreadTest but for slugid.v4() rather than 172 | * slugid.nice(). The only difference is that a v4() slug can start with any of 173 | * the base64 characters since the first six bits of the uuid are random. 174 | */ 175 | it('should have allowed characters in all allowed positions within the "v4" slug', function () { 176 | const charsAll = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".split('').sort().join(''); 177 | // 16, 17, 18, 19: 0b0100xx 178 | const charsD = "QRST".split('').sort().join(''); 179 | // 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62: 0bxxxx10 180 | const charsE = "CGKOSWaeimquy26-".split('').sort().join(''); 181 | // 0, 16, 32, 48: 0bxx0000 182 | const charsF = "AQgw".split('').sort().join(''); 183 | const expected = [charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsD, charsAll, charsE, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsAll, charsF]; 184 | spreadTest( 185 | function() { 186 | return slugid.v4(); 187 | }, 188 | expected 189 | ); 190 | }); 191 | }); 192 | }); 193 | 194 | /** 195 | * `spreadTest` runs a test against the `generator` function, to check that 196 | * when calling it 64*40 times, the range of characters per string position it 197 | * returns matches the array `expected`, where each entry in `expected` is a 198 | * string of all possible characters that should appear in that position in the 199 | * string, at least once in the sample of 64*40 responses from the `generator` 200 | * function */ 201 | function spreadTest(generator, expected) { 202 | // k records which characters were found at which positions. It has one entry 203 | // per slugid character, therefore 22 entries. Each entry is an object with 204 | // a property for each character found, where the value of that property is 205 | // the number of times that character appeared at that position in the slugid 206 | // in the large sample of slugids generated in this test. 207 | let k = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]; 208 | 209 | // Generate a large sample of slugids, and record what characters appeared 210 | // where... A monte-carlo test has demonstrated that with 64 * 20 211 | // iterations, no failure occurred in 1000 simulations, so 64 * 40 should be 212 | // suitably large to rule out false positives. 213 | for (let i = 0; i < 64 * 40; i++) { 214 | let slug = generator(); 215 | for (let j = 0; j < slug.length; j++) { 216 | if (k[j][slug.charAt(j)] === undefined) { 217 | k[j][slug.charAt(j)] = 1 218 | } else { 219 | k[j][slug.charAt(j)]++; 220 | } 221 | } 222 | } 223 | 224 | // Compose results into an array `actual`, for comparison with `expected` 225 | let actual = []; 226 | for (let j = 0; j < k.length; j++) { 227 | const a = Object.keys(k[j]) 228 | actual[j] = "" 229 | for (const el of a) { 230 | if (k[j][el] > 0) { 231 | actual[j] += el 232 | } 233 | } 234 | // sort for easy comparison 235 | actual[j] = actual[j].split('').sort().join(''); 236 | } 237 | 238 | assert(arraysEqual(expected, actual), "In a large sample of generated slugids, the range of characters found per character position in the sample did not match expected results.\n\nExpected: " + expected + "\n\nActual: " + actual); 239 | } 240 | 241 | /** 242 | * `arraysEqual` checks arrays `a` and `b` for equality 243 | */ 244 | function arraysEqual(a, b) { 245 | if (a === b) return true; 246 | if (a == null || b == null) return false; 247 | if (a.length != b.length) return false; 248 | for (let i = 0; i < a.length; ++i) { 249 | if (a[i] !== b[i]) return false; 250 | } 251 | return true; 252 | } 253 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ansi-colors@4.1.1: 6 | version "4.1.1" 7 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 8 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 9 | 10 | ansi-regex@^5.0.1: 11 | version "5.0.1" 12 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 13 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 14 | 15 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 16 | version "4.3.0" 17 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 18 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 19 | dependencies: 20 | color-convert "^2.0.1" 21 | 22 | anymatch@~3.1.2: 23 | version "3.1.3" 24 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 25 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 26 | dependencies: 27 | normalize-path "^3.0.0" 28 | picomatch "^2.0.4" 29 | 30 | argparse@^2.0.1: 31 | version "2.0.1" 32 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 33 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 34 | 35 | balanced-match@^1.0.0: 36 | version "1.0.2" 37 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 38 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 39 | 40 | binary-extensions@^2.0.0: 41 | version "2.2.0" 42 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 43 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 44 | 45 | brace-expansion@^2.0.1: 46 | version "2.0.1" 47 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 48 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 49 | dependencies: 50 | balanced-match "^1.0.0" 51 | 52 | braces@~3.0.2: 53 | version "3.0.3" 54 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 55 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 56 | dependencies: 57 | fill-range "^7.1.1" 58 | 59 | browser-stdout@1.3.1: 60 | version "1.3.1" 61 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 62 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 63 | 64 | camelcase@^6.0.0: 65 | version "6.3.0" 66 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 67 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 68 | 69 | chalk@^4.1.0: 70 | version "4.1.2" 71 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 72 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 73 | dependencies: 74 | ansi-styles "^4.1.0" 75 | supports-color "^7.1.0" 76 | 77 | chokidar@3.5.3: 78 | version "3.5.3" 79 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 80 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 81 | dependencies: 82 | anymatch "~3.1.2" 83 | braces "~3.0.2" 84 | glob-parent "~5.1.2" 85 | is-binary-path "~2.1.0" 86 | is-glob "~4.0.1" 87 | normalize-path "~3.0.0" 88 | readdirp "~3.6.0" 89 | optionalDependencies: 90 | fsevents "~2.3.2" 91 | 92 | cliui@^7.0.2: 93 | version "7.0.4" 94 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 95 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 96 | dependencies: 97 | string-width "^4.2.0" 98 | strip-ansi "^6.0.0" 99 | wrap-ansi "^7.0.0" 100 | 101 | color-convert@^2.0.1: 102 | version "2.0.1" 103 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 104 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 105 | dependencies: 106 | color-name "~1.1.4" 107 | 108 | color-name@~1.1.4: 109 | version "1.1.4" 110 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 111 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 112 | 113 | debug@4.3.4: 114 | version "4.3.4" 115 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 116 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 117 | dependencies: 118 | ms "2.1.2" 119 | 120 | decamelize@^4.0.0: 121 | version "4.0.0" 122 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 123 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 124 | 125 | diff@5.0.0: 126 | version "5.0.0" 127 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 128 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 129 | 130 | emoji-regex@^8.0.0: 131 | version "8.0.0" 132 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 133 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 134 | 135 | escalade@^3.1.1: 136 | version "3.1.1" 137 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 138 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 139 | 140 | escape-string-regexp@4.0.0: 141 | version "4.0.0" 142 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 143 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 144 | 145 | fill-range@^7.1.1: 146 | version "7.1.1" 147 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 148 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 149 | dependencies: 150 | to-regex-range "^5.0.1" 151 | 152 | find-up@5.0.0: 153 | version "5.0.0" 154 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 155 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 156 | dependencies: 157 | locate-path "^6.0.0" 158 | path-exists "^4.0.0" 159 | 160 | flat@^5.0.2: 161 | version "5.0.2" 162 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 163 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 164 | 165 | fs.realpath@^1.0.0: 166 | version "1.0.0" 167 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 168 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 169 | 170 | fsevents@~2.3.2: 171 | version "2.3.2" 172 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 173 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 174 | 175 | get-caller-file@^2.0.5: 176 | version "2.0.5" 177 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 178 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 179 | 180 | glob-parent@~5.1.2: 181 | version "5.1.2" 182 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 183 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 184 | dependencies: 185 | is-glob "^4.0.1" 186 | 187 | glob@8.1.0: 188 | version "8.1.0" 189 | resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" 190 | integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== 191 | dependencies: 192 | fs.realpath "^1.0.0" 193 | inflight "^1.0.4" 194 | inherits "2" 195 | minimatch "^5.0.1" 196 | once "^1.3.0" 197 | 198 | has-flag@^4.0.0: 199 | version "4.0.0" 200 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 201 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 202 | 203 | he@1.2.0: 204 | version "1.2.0" 205 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 206 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 207 | 208 | inflight@^1.0.4: 209 | version "1.0.6" 210 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 211 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 212 | dependencies: 213 | once "^1.3.0" 214 | wrappy "1" 215 | 216 | inherits@2: 217 | version "2.0.4" 218 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 219 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 220 | 221 | is-binary-path@~2.1.0: 222 | version "2.1.0" 223 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 224 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 225 | dependencies: 226 | binary-extensions "^2.0.0" 227 | 228 | is-extglob@^2.1.1: 229 | version "2.1.1" 230 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 231 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 232 | 233 | is-fullwidth-code-point@^3.0.0: 234 | version "3.0.0" 235 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 236 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 237 | 238 | is-glob@^4.0.1, is-glob@~4.0.1: 239 | version "4.0.3" 240 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 241 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 242 | dependencies: 243 | is-extglob "^2.1.1" 244 | 245 | is-number@^7.0.0: 246 | version "7.0.0" 247 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 248 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 249 | 250 | is-plain-obj@^2.1.0: 251 | version "2.1.0" 252 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 253 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 254 | 255 | is-unicode-supported@^0.1.0: 256 | version "0.1.0" 257 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 258 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 259 | 260 | js-yaml@4.1.0: 261 | version "4.1.0" 262 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 263 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 264 | dependencies: 265 | argparse "^2.0.1" 266 | 267 | locate-path@^6.0.0: 268 | version "6.0.0" 269 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 270 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 271 | dependencies: 272 | p-locate "^5.0.0" 273 | 274 | log-symbols@4.1.0: 275 | version "4.1.0" 276 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 277 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 278 | dependencies: 279 | chalk "^4.1.0" 280 | is-unicode-supported "^0.1.0" 281 | 282 | minimatch@5.0.1: 283 | version "5.0.1" 284 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" 285 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== 286 | dependencies: 287 | brace-expansion "^2.0.1" 288 | 289 | minimatch@^5.0.1: 290 | version "5.1.6" 291 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 292 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 293 | dependencies: 294 | brace-expansion "^2.0.1" 295 | 296 | mocha@^10.2.0: 297 | version "10.4.0" 298 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" 299 | integrity sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA== 300 | dependencies: 301 | ansi-colors "4.1.1" 302 | browser-stdout "1.3.1" 303 | chokidar "3.5.3" 304 | debug "4.3.4" 305 | diff "5.0.0" 306 | escape-string-regexp "4.0.0" 307 | find-up "5.0.0" 308 | glob "8.1.0" 309 | he "1.2.0" 310 | js-yaml "4.1.0" 311 | log-symbols "4.1.0" 312 | minimatch "5.0.1" 313 | ms "2.1.3" 314 | serialize-javascript "6.0.0" 315 | strip-json-comments "3.1.1" 316 | supports-color "8.1.1" 317 | workerpool "6.2.1" 318 | yargs "16.2.0" 319 | yargs-parser "20.2.4" 320 | yargs-unparser "2.0.0" 321 | 322 | ms@2.1.2: 323 | version "2.1.2" 324 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 325 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 326 | 327 | ms@2.1.3: 328 | version "2.1.3" 329 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 330 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 331 | 332 | normalize-path@^3.0.0, normalize-path@~3.0.0: 333 | version "3.0.0" 334 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 335 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 336 | 337 | once@^1.3.0: 338 | version "1.4.0" 339 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 340 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 341 | dependencies: 342 | wrappy "1" 343 | 344 | p-limit@^3.0.2: 345 | version "3.1.0" 346 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 347 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 348 | dependencies: 349 | yocto-queue "^0.1.0" 350 | 351 | p-locate@^5.0.0: 352 | version "5.0.0" 353 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 354 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 355 | dependencies: 356 | p-limit "^3.0.2" 357 | 358 | path-exists@^4.0.0: 359 | version "4.0.0" 360 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 361 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 362 | 363 | picomatch@^2.0.4, picomatch@^2.2.1: 364 | version "2.3.1" 365 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 366 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 367 | 368 | randombytes@^2.1.0: 369 | version "2.1.0" 370 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 371 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 372 | dependencies: 373 | safe-buffer "^5.1.0" 374 | 375 | readdirp@~3.6.0: 376 | version "3.6.0" 377 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 378 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 379 | dependencies: 380 | picomatch "^2.2.1" 381 | 382 | require-directory@^2.1.1: 383 | version "2.1.1" 384 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 385 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 386 | 387 | safe-buffer@^5.1.0: 388 | version "5.2.1" 389 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 390 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 391 | 392 | serialize-javascript@6.0.0: 393 | version "6.0.0" 394 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 395 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 396 | dependencies: 397 | randombytes "^2.1.0" 398 | 399 | string-width@^4.1.0, string-width@^4.2.0: 400 | version "4.2.3" 401 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 402 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 403 | dependencies: 404 | emoji-regex "^8.0.0" 405 | is-fullwidth-code-point "^3.0.0" 406 | strip-ansi "^6.0.1" 407 | 408 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 409 | version "6.0.1" 410 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 411 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 412 | dependencies: 413 | ansi-regex "^5.0.1" 414 | 415 | strip-json-comments@3.1.1: 416 | version "3.1.1" 417 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 418 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 419 | 420 | supports-color@8.1.1: 421 | version "8.1.1" 422 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 423 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 424 | dependencies: 425 | has-flag "^4.0.0" 426 | 427 | supports-color@^7.1.0: 428 | version "7.2.0" 429 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 430 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 431 | dependencies: 432 | has-flag "^4.0.0" 433 | 434 | to-regex-range@^5.0.1: 435 | version "5.0.1" 436 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 437 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 438 | dependencies: 439 | is-number "^7.0.0" 440 | 441 | uuid@^9.0.0: 442 | version "9.0.1" 443 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" 444 | integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== 445 | 446 | workerpool@6.2.1: 447 | version "6.2.1" 448 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" 449 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== 450 | 451 | wrap-ansi@^7.0.0: 452 | version "7.0.0" 453 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 454 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 455 | dependencies: 456 | ansi-styles "^4.0.0" 457 | string-width "^4.1.0" 458 | strip-ansi "^6.0.0" 459 | 460 | wrappy@1: 461 | version "1.0.2" 462 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 463 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 464 | 465 | y18n@^5.0.5: 466 | version "5.0.8" 467 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 468 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 469 | 470 | yargs-parser@20.2.4: 471 | version "20.2.4" 472 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 473 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 474 | 475 | yargs-parser@^20.2.2: 476 | version "20.2.9" 477 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 478 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 479 | 480 | yargs-unparser@2.0.0: 481 | version "2.0.0" 482 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 483 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 484 | dependencies: 485 | camelcase "^6.0.0" 486 | decamelize "^4.0.0" 487 | flat "^5.0.2" 488 | is-plain-obj "^2.1.0" 489 | 490 | yargs@16.2.0: 491 | version "16.2.0" 492 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 493 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 494 | dependencies: 495 | cliui "^7.0.2" 496 | escalade "^3.1.1" 497 | get-caller-file "^2.0.5" 498 | require-directory "^2.1.1" 499 | string-width "^4.2.0" 500 | y18n "^5.0.5" 501 | yargs-parser "^20.2.2" 502 | 503 | yocto-queue@^0.1.0: 504 | version "0.1.0" 505 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 506 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 507 | --------------------------------------------------------------------------------