| let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes)) | ||
| let customAlphabet = (alphabet, defaultSize = 21) => { | ||
| // First, a bitmask is necessary to generate the ID. The bitmask makes bytes | ||
| // values closer to the alphabet size. The bitmask calculates the closest | ||
| // `2^31 - 1` number, which exceeds the alphabet size. | ||
| // For example, the bitmask for the alphabet size 30 is 31 (00011111). | ||
| // `Math.clz32` is not used, because it is not available in browsers. | ||
| let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1 | ||
| // Though, the bitmask solution is not perfect since the bytes exceeding | ||
| // the alphabet size are refused. Therefore, to reliably generate the ID, | ||
| // the random bytes redundancy has to be satisfied. | ||
| // Note: every hardware random generator call is performance expensive, | ||
| // because the system call for entropy collection takes a lot of time. | ||
| // So, to avoid additional system calls, extra bytes are requested in advance. | ||
| // Next, a step determines how many random bytes to generate. | ||
| // The number of random bytes gets decided upon the ID size, mask, | ||
| // alphabet size, and magic number 1.6 (using 1.6 peaks at performance | ||
| // according to benchmarks). | ||
| // `-~f => Math.ceil(f)` if f is a float | ||
| // `-~i => i + 1` if i is an integer | ||
| let step = -~((1.6 * mask * defaultSize) / alphabet.length) | ||
| return async (size = defaultSize) => { | ||
@@ -31,6 +9,4 @@ let id = '' | ||
| let bytes = crypto.getRandomValues(new Uint8Array(step)) | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let i = step | 0 | ||
| while (i--) { | ||
| // Adding `|| ''` refuses a random byte that exceeds the alphabet size. | ||
| id += alphabet[bytes[i] & mask] || '' | ||
@@ -42,20 +18,10 @@ if (id.length === size) return id | ||
| } | ||
| let nanoid = async (size = 21) => { | ||
| let id = '' | ||
| let bytes = crypto.getRandomValues(new Uint8Array((size |= 0))) | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| while (size--) { | ||
| // It is incorrect to use bytes exceeding the alphabet size. | ||
| // The following mask reduces the random byte in the 0-255 value | ||
| // range to the 0-63 value range. Therefore, adding hacks, such | ||
| // as empty string fallback or magic numbers, is unneccessary because | ||
| // the bitmask trims bytes down to the alphabet size. | ||
| let byte = bytes[size] & 63 | ||
| if (byte < 36) { | ||
| // `0-9a-z` | ||
| id += byte.toString(36) | ||
| } else if (byte < 62) { | ||
| // `A-Z` | ||
| id += (byte - 26).toString(36).toUpperCase() | ||
@@ -70,3 +36,2 @@ } else if (byte < 63) { | ||
| } | ||
| export { nanoid, customAlphabet, random } |
+0
-36
| import crypto from 'crypto' | ||
| import { urlAlphabet } from '../url-alphabet/index.js' | ||
| // `crypto.randomFill()` is a little faster than `crypto.randomBytes()`, | ||
| // because it is possible to use in combination with `Buffer.allocUnsafe()`. | ||
| let random = bytes => | ||
| new Promise((resolve, reject) => { | ||
| // `Buffer.allocUnsafe()` is faster because it doesn’t flush the memory. | ||
| // Memory flushing is unnecessary since the buffer allocation itself resets | ||
| // the memory with the new bytes. | ||
| crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => { | ||
@@ -20,29 +13,9 @@ if (err) { | ||
| }) | ||
| let customAlphabet = (alphabet, defaultSize = 21) => { | ||
| // First, a bitmask is necessary to generate the ID. The bitmask makes bytes | ||
| // values closer to the alphabet size. The bitmask calculates the closest | ||
| // `2^31 - 1` number, which exceeds the alphabet size. | ||
| // For example, the bitmask for the alphabet size 30 is 31 (00011111). | ||
| let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1 | ||
| // Though, the bitmask solution is not perfect since the bytes exceeding | ||
| // the alphabet size are refused. Therefore, to reliably generate the ID, | ||
| // the random bytes redundancy has to be satisfied. | ||
| // Note: every hardware random generator call is performance expensive, | ||
| // because the system call for entropy collection takes a lot of time. | ||
| // So, to avoid additional system calls, extra bytes are requested in advance. | ||
| // Next, a step determines how many random bytes to generate. | ||
| // The number of random bytes gets decided upon the ID size, mask, | ||
| // alphabet size, and magic number 1.6 (using 1.6 peaks at performance | ||
| // according to benchmarks). | ||
| let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length) | ||
| let tick = (id, size = defaultSize) => | ||
| random(step).then(bytes => { | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let i = step | ||
| while (i--) { | ||
| // Adding `|| ''` refuses a random byte that exceeds the alphabet size. | ||
| id += alphabet[bytes[i] & mask] || '' | ||
@@ -53,16 +26,8 @@ if (id.length >= size) return id | ||
| }) | ||
| return size => tick('', size) | ||
| } | ||
| let nanoid = (size = 21) => | ||
| random((size |= 0)).then(bytes => { | ||
| let id = '' | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| while (size--) { | ||
| // It is incorrect to use bytes exceeding the alphabet size. | ||
| // The following mask reduces the random byte in the 0-255 value | ||
| // range to the 0-63 value range. Therefore, adding hacks, such | ||
| // as empty string fallback or magic numbers, is unneccessary because | ||
| // the bitmask trims bytes down to the alphabet size. | ||
| id += urlAlphabet[bytes[size] & 63] | ||
@@ -72,3 +37,2 @@ } | ||
| }) | ||
| export { nanoid, customAlphabet, random } |
| import { getRandomBytesAsync } from 'expo-random' | ||
| import { urlAlphabet } from '../url-alphabet/index.js' | ||
| let random = getRandomBytesAsync | ||
| let customAlphabet = (alphabet, defaultSize = 21) => { | ||
| // First, a bitmask is necessary to generate the ID. The bitmask makes bytes | ||
| // values closer to the alphabet size. The bitmask calculates the closest | ||
| // `2^31 - 1` number, which exceeds the alphabet size. | ||
| // For example, the bitmask for the alphabet size 30 is 31 (00011111). | ||
| let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1 | ||
| // Though, the bitmask solution is not perfect since the bytes exceeding | ||
| // the alphabet size are refused. Therefore, to reliably generate the ID, | ||
| // the random bytes redundancy has to be satisfied. | ||
| // Note: every hardware random generator call is performance expensive, | ||
| // because the system call for entropy collection takes a lot of time. | ||
| // So, to avoid additional system calls, extra bytes are requested in advance. | ||
| // Next, a step determines how many random bytes to generate. | ||
| // The number of random bytes gets decided upon the ID size, mask, | ||
| // alphabet size, and magic number 1.6 (using 1.6 peaks at performance | ||
| // according to benchmarks). | ||
| let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length) | ||
| let tick = (id, size = defaultSize) => | ||
| random(step).then(bytes => { | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let i = step | ||
| while (i--) { | ||
| // Adding `|| ''` refuses a random byte that exceeds the alphabet size. | ||
| id += alphabet[bytes[i] & mask] || '' | ||
@@ -38,16 +16,8 @@ if (id.length >= size) return id | ||
| }) | ||
| return size => tick('', size) | ||
| } | ||
| let nanoid = (size = 21) => | ||
| random((size |= 0)).then(bytes => { | ||
| let id = '' | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| while (size--) { | ||
| // It is incorrect to use bytes exceeding the alphabet size. | ||
| // The following mask reduces the random byte in the 0-255 value | ||
| // range to the 0-63 value range. Therefore, adding hacks, such | ||
| // as empty string fallback or magic numbers, is unneccessary because | ||
| // the bitmask trims bytes down to the alphabet size. | ||
| id += urlAlphabet[bytes[size] & 63] | ||
@@ -57,3 +27,2 @@ } | ||
| }) | ||
| export { nanoid, customAlphabet, random } |
+0
-38
@@ -1,32 +0,6 @@ | ||
| // This file replaces `index.js` in bundlers like webpack or Rollup, | ||
| // according to `browser` config in `package.json`. | ||
| import { urlAlphabet } from './url-alphabet/index.js' | ||
| let random = bytes => crypto.getRandomValues(new Uint8Array(bytes)) | ||
| let customRandom = (alphabet, defaultSize, getRandom) => { | ||
| // First, a bitmask is necessary to generate the ID. The bitmask makes bytes | ||
| // values closer to the alphabet size. The bitmask calculates the closest | ||
| // `2^31 - 1` number, which exceeds the alphabet size. | ||
| // For example, the bitmask for the alphabet size 30 is 31 (00011111). | ||
| // `Math.clz32` is not used, because it is not available in browsers. | ||
| let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1 | ||
| // Though, the bitmask solution is not perfect since the bytes exceeding | ||
| // the alphabet size are refused. Therefore, to reliably generate the ID, | ||
| // the random bytes redundancy has to be satisfied. | ||
| // Note: every hardware random generator call is performance expensive, | ||
| // because the system call for entropy collection takes a lot of time. | ||
| // So, to avoid additional system calls, extra bytes are requested in advance. | ||
| // Next, a step determines how many random bytes to generate. | ||
| // The number of random bytes gets decided upon the ID size, mask, | ||
| // alphabet size, and magic number 1.6 (using 1.6 peaks at performance | ||
| // according to benchmarks). | ||
| // `-~f => Math.ceil(f)` if f is a float | ||
| // `-~i => i + 1` if i is an integer | ||
| let step = -~((1.6 * mask * defaultSize) / alphabet.length) | ||
| return (size = defaultSize) => { | ||
@@ -36,6 +10,4 @@ let id = '' | ||
| let bytes = getRandom(step) | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let j = step | 0 | ||
| while (j--) { | ||
| // Adding `|| ''` refuses a random byte that exceeds the alphabet size. | ||
| id += alphabet[bytes[j] & mask] || '' | ||
@@ -47,19 +19,10 @@ if (id.length === size) return id | ||
| } | ||
| let customAlphabet = (alphabet, size = 21) => | ||
| customRandom(alphabet, size, random) | ||
| let nanoid = (size = 21) => | ||
| crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => { | ||
| // It is incorrect to use bytes exceeding the alphabet size. | ||
| // The following mask reduces the random byte in the 0-255 value | ||
| // range to the 0-63 value range. Therefore, adding hacks, such | ||
| // as empty string fallback or magic numbers, is unneccessary because | ||
| // the bitmask trims bytes down to the alphabet size. | ||
| byte &= 63 | ||
| if (byte < 36) { | ||
| // `0-9a-z` | ||
| id += byte.toString(36) | ||
| } else if (byte < 62) { | ||
| // `A-Z` | ||
| id += (byte - 26).toString(36).toUpperCase() | ||
@@ -73,3 +36,2 @@ } else if (byte > 62) { | ||
| }, '') | ||
| export { nanoid, customAlphabet, customRandom, urlAlphabet, random } |
+0
-40
| import crypto from 'crypto' | ||
| import { urlAlphabet } from './url-alphabet/index.js' | ||
| // It is best to make fewer, larger requests to the crypto module to | ||
| // avoid system call overhead. So, random numbers are generated in a | ||
| // pool. The pool is a Buffer that is larger than the initial random | ||
| // request size by this multiplier. The pool is enlarged if subsequent | ||
| // requests exceed the maximum buffer size. | ||
| const POOL_SIZE_MULTIPLIER = 128 | ||
| let pool, poolOffset | ||
| let fillPool = bytes => { | ||
@@ -24,29 +16,9 @@ if (!pool || pool.length < bytes) { | ||
| } | ||
| let random = bytes => { | ||
| // `|=` convert `bytes` to number to prevent `valueOf` abusing and pool pollution | ||
| fillPool((bytes |= 0)) | ||
| return pool.subarray(poolOffset - bytes, poolOffset) | ||
| } | ||
| let customRandom = (alphabet, defaultSize, getRandom) => { | ||
| // First, a bitmask is necessary to generate the ID. The bitmask makes bytes | ||
| // values closer to the alphabet size. The bitmask calculates the closest | ||
| // `2^31 - 1` number, which exceeds the alphabet size. | ||
| // For example, the bitmask for the alphabet size 30 is 31 (00011111). | ||
| let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1 | ||
| // Though, the bitmask solution is not perfect since the bytes exceeding | ||
| // the alphabet size are refused. Therefore, to reliably generate the ID, | ||
| // the random bytes redundancy has to be satisfied. | ||
| // Note: every hardware random generator call is performance expensive, | ||
| // because the system call for entropy collection takes a lot of time. | ||
| // So, to avoid additional system calls, extra bytes are requested in advance. | ||
| // Next, a step determines how many random bytes to generate. | ||
| // The number of random bytes gets decided upon the ID size, mask, | ||
| // alphabet size, and magic number 1.6 (using 1.6 peaks at performance | ||
| // according to benchmarks). | ||
| let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length) | ||
| return (size = defaultSize) => { | ||
@@ -56,6 +28,4 @@ let id = '' | ||
| let bytes = getRandom(step) | ||
| // A compact alternative for `for (let i = 0; i < step; i++)`. | ||
| let i = step | ||
| while (i--) { | ||
| // Adding `|| ''` refuses a random byte that exceeds the alphabet size. | ||
| id += alphabet[bytes[i] & mask] || '' | ||
@@ -67,17 +37,8 @@ if (id.length === size) return id | ||
| } | ||
| let customAlphabet = (alphabet, size = 21) => | ||
| customRandom(alphabet, size, random) | ||
| let nanoid = (size = 21) => { | ||
| // `|=` convert `size` to number to prevent `valueOf` abusing and pool pollution | ||
| fillPool((size |= 0)) | ||
| let id = '' | ||
| // We are reading directly from the random pool to avoid creating new array | ||
| for (let i = poolOffset - size; i < poolOffset; i++) { | ||
| // It is incorrect to use bytes exceeding the alphabet size. | ||
| // The following mask reduces the random byte in the 0-255 value | ||
| // range to the 0-63 value range. Therefore, adding hacks, such | ||
| // as empty string fallback or magic numbers, is unneccessary because | ||
| // the bitmask trims bytes down to the alphabet size. | ||
| id += urlAlphabet[pool[i] & 63] | ||
@@ -87,3 +48,2 @@ } | ||
| } | ||
| export { nanoid, customAlphabet, customRandom, urlAlphabet, random } |
+0
-13
@@ -1,17 +0,8 @@ | ||
| // This alphabet uses `A-Za-z0-9_-` symbols. | ||
| // The order of characters is optimized for better gzip and brotli compression. | ||
| // References to the same file (works both for gzip and brotli): | ||
| // `'use`, `andom`, and `rict'` | ||
| // References to the brotli default dictionary: | ||
| // `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf` | ||
| let urlAlphabet = | ||
| 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict' | ||
| let customAlphabet = (alphabet, defaultSize = 21) => { | ||
| return (size = defaultSize) => { | ||
| let id = '' | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let i = size | 0 | ||
| while (i--) { | ||
| // `| 0` is more compact and faster than `Math.floor()`. | ||
| id += alphabet[(Math.random() * alphabet.length) | 0] | ||
@@ -22,9 +13,6 @@ } | ||
| } | ||
| let nanoid = (size = 21) => { | ||
| let id = '' | ||
| // A compact alternative for `for (var i = 0; i < step; i++)`. | ||
| let i = size | 0 | ||
| while (i--) { | ||
| // `| 0` is more compact and faster than `Math.floor()`. | ||
| id += urlAlphabet[(Math.random() * 64) | 0] | ||
@@ -34,3 +22,2 @@ } | ||
| } | ||
| export { nanoid, customAlphabet } |
+3
-2
| { | ||
| "name": "nanoid", | ||
| "version": "3.3.10", | ||
| "version": "3.3.11", | ||
| "description": "A tiny (116 bytes), secure URL-friendly unique string ID generator", | ||
@@ -38,2 +38,3 @@ "keywords": [ | ||
| ".": { | ||
| "react-native": "./index.browser.js", | ||
| "browser": "./index.browser.js", | ||
@@ -89,2 +90,2 @@ "require": { | ||
| } | ||
| } | ||
| } |
+2
-517
@@ -38,518 +38,3 @@ # Nano ID | ||
| ## Table of Contents | ||
| * [Comparison with UUID](#comparison-with-uuid) | ||
| * [Benchmark](#benchmark) | ||
| * [Security](#security) | ||
| * [API](#api) | ||
| * [Blocking](#blocking) | ||
| * [Async](#async) | ||
| * [Non-Secure](#non-secure) | ||
| * [Custom Alphabet or Size](#custom-alphabet-or-size) | ||
| * [Custom Random Bytes Generator](#custom-random-bytes-generator) | ||
| * [Usage](#usage) | ||
| * [IE](#ie) | ||
| * [React](#react) | ||
| * [React Native](#react-native) | ||
| * [Rollup](#rollup) | ||
| * [PouchDB and CouchDB](#pouchdb-and-couchdb) | ||
| * [Mongoose](#mongoose) | ||
| * [Web Workers](#web-workers) | ||
| * [CLI](#cli) | ||
| * [Other Programming Languages](#other-programming-languages) | ||
| * [Tools](#tools) | ||
| ## Comparison with UUID | ||
| Nano ID is quite comparable to UUID v4 (random-based). | ||
| It has a similar number of random bits in the ID | ||
| (126 in Nano ID and 122 in UUID), so it has a similar collision probability: | ||
| > For there to be a one in a billion chance of duplication, | ||
| > 103 trillion version 4 IDs must be generated. | ||
| There are three main differences between Nano ID and UUID v4: | ||
| 1. Nano ID uses a bigger alphabet, so a similar number of random bits | ||
| are packed in just 21 symbols instead of 36. | ||
| 2. Nano ID code is **4 times less** than `uuid/v4` package: | ||
| 130 bytes instead of 483. | ||
| 3. Because of memory allocation tricks, Nano ID is **2 times** faster than UUID. | ||
| ## Benchmark | ||
| ```rust | ||
| $ node ./test/benchmark.js | ||
| crypto.randomUUID 25,603,857 ops/sec | ||
| @napi-rs/uuid 9,973,819 ops/sec | ||
| uid/secure 8,234,798 ops/sec | ||
| @lukeed/uuid 7,464,706 ops/sec | ||
| nanoid 5,616,592 ops/sec | ||
| customAlphabet 3,115,207 ops/sec | ||
| uuid v4 1,535,753 ops/sec | ||
| secure-random-string 388,226 ops/sec | ||
| uid-safe.sync 363,489 ops/sec | ||
| cuid 187,343 ops/sec | ||
| shortid 45,758 ops/sec | ||
| Async: | ||
| nanoid/async 96,094 ops/sec | ||
| async customAlphabet 97,184 ops/sec | ||
| async secure-random-string 92,794 ops/sec | ||
| uid-safe 90,684 ops/sec | ||
| Non-secure: | ||
| uid 67,376,692 ops/sec | ||
| nanoid/non-secure 2,849,639 ops/sec | ||
| rndm 2,674,806 ops/sec | ||
| ``` | ||
| Test configuration: ThinkPad X1 Carbon Gen 9, Fedora 34, Node.js 16.10. | ||
| ## Security | ||
| *See a good article about random generators theory: | ||
| [Secure random values (in Node.js)]* | ||
| * **Unpredictability.** Instead of using the unsafe `Math.random()`, Nano ID | ||
| uses the `crypto` module in Node.js and the Web Crypto API in browsers. | ||
| These modules use unpredictable hardware random generator. | ||
| * **Uniformity.** `random % alphabet` is a popular mistake to make when coding | ||
| an ID generator. The distribution will not be even; there will be a lower | ||
| chance for some symbols to appear compared to others. So, it will reduce | ||
| the number of tries when brute-forcing. Nano ID uses a [better algorithm] | ||
| and is tested for uniformity. | ||
| <img src="img/distribution.png" alt="Nano ID uniformity" | ||
| width="340" height="135"> | ||
| * **Well-documented:** all Nano ID hacks are documented. See comments | ||
| in [the source]. | ||
| * **Vulnerabilities:** to report a security vulnerability, please use | ||
| the [Tidelift security contact](https://tidelift.com/security). | ||
| Tidelift will coordinate the fix and disclosure. | ||
| [Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba | ||
| [better algorithm]: https://github.com/ai/nanoid/blob/main/index.js | ||
| [the source]: https://github.com/ai/nanoid/blob/main/index.js | ||
| ## Install | ||
| ```bash | ||
| npm install --save nanoid | ||
| ``` | ||
| For quick hacks, you can load Nano ID from CDN. Though, it is not recommended | ||
| to be used in production because of the lower loading performance. | ||
| ```js | ||
| import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js' | ||
| ``` | ||
| Nano ID provides ES modules. You do not need to do anything to use Nano ID | ||
| as ESM in webpack, Rollup, Parcel, or Node.js. | ||
| ```js | ||
| import { nanoid } from 'nanoid' | ||
| ``` | ||
| In Node.js you can use CommonJS import: | ||
| ```js | ||
| const { nanoid } = require('nanoid') | ||
| ``` | ||
| ## API | ||
| Nano ID has 3 APIs: normal (blocking), asynchronous, and non-secure. | ||
| By default, Nano ID uses URL-friendly symbols (`A-Za-z0-9_-`) and returns an ID | ||
| with 21 characters (to have a collision probability similar to UUID v4). | ||
| ### Blocking | ||
| The safe and easiest way to use Nano ID. | ||
| In rare cases could block CPU from other work while noise collection | ||
| for hardware random generator. | ||
| ```js | ||
| import { nanoid } from 'nanoid' | ||
| model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" | ||
| ``` | ||
| If you want to reduce the ID size (and increase collisions probability), | ||
| you can pass the size as an argument. | ||
| ```js | ||
| nanoid(10) //=> "IRFa-VaY2b" | ||
| ``` | ||
| Don’t forget to check the safety of your ID size | ||
| in our [ID collision probability] calculator. | ||
| You can also use a [custom alphabet](#custom-alphabet-or-size) | ||
| or a [random generator](#custom-random-bytes-generator). | ||
| [ID collision probability]: https://zelark.github.io/nano-id-cc/ | ||
| ### Async | ||
| To generate hardware random bytes, CPU collects electromagnetic noise. | ||
| For most cases, entropy will be already collected. | ||
| In the synchronous API during the noise collection, the CPU is busy and | ||
| cannot do anything useful (for instance, process another HTTP request). | ||
| Using the asynchronous API of Nano ID, another code can run during | ||
| the entropy collection. | ||
| ```js | ||
| import { nanoid } from 'nanoid/async' | ||
| async function createUser () { | ||
| user.id = await nanoid() | ||
| } | ||
| ``` | ||
| Read more about entropy collection in [`crypto.randomBytes`] docs. | ||
| Unfortunately, you will lose Web Crypto API advantages in a browser | ||
| if you use the asynchronous API. So, currently, in the browser, you are limited | ||
| with either security (`nanoid`), asynchronous behavior (`nanoid/async`), | ||
| or non-secure behavior (`nanoid/non-secure`) that will be explained | ||
| in the next part of the documentation. | ||
| [`crypto.randomBytes`]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback | ||
| ### Non-Secure | ||
| By default, Nano ID uses hardware random bytes generation for security | ||
| and low collision probability. If you are not so concerned with security, | ||
| you can use the faster non-secure generator. | ||
| ```js | ||
| import { nanoid } from 'nanoid/non-secure' | ||
| const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ" | ||
| ``` | ||
| ### Custom Alphabet or Size | ||
| `customAlphabet` allows you to create `nanoid` with your own alphabet | ||
| and ID size. | ||
| ```js | ||
| import { customAlphabet } from 'nanoid' | ||
| const nanoid = customAlphabet('1234567890abcdef', 10) | ||
| model.id = nanoid() //=> "4f90d13a42" | ||
| ``` | ||
| ```js | ||
| import { customAlphabet } from 'nanoid/async' | ||
| const nanoid = customAlphabet('1234567890abcdef', 10) | ||
| async function createUser () { | ||
| user.id = await nanoid() | ||
| } | ||
| ``` | ||
| ```js | ||
| import { customAlphabet } from 'nanoid/non-secure' | ||
| const nanoid = customAlphabet('1234567890abcdef', 10) | ||
| user.id = nanoid() | ||
| ``` | ||
| Check the safety of your custom alphabet and ID size in our | ||
| [ID collision probability] calculator. For more alphabets, check out the options | ||
| in [`nanoid-dictionary`]. | ||
| Alphabet must contain 256 symbols or less. | ||
| Otherwise, the security of the internal generator algorithm is not guaranteed. | ||
| In addition to setting a default size, you can change the ID size when calling | ||
| the function: | ||
| ```js | ||
| import { customAlphabet } from 'nanoid' | ||
| const nanoid = customAlphabet('1234567890abcdef', 10) | ||
| model.id = nanoid(5) //=> "f01a2" | ||
| ``` | ||
| [ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/ | ||
| [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary | ||
| ### Custom Random Bytes Generator | ||
| `customRandom` allows you to create a `nanoid` and replace alphabet | ||
| and the default random bytes generator. | ||
| In this example, a seed-based generator is used: | ||
| ```js | ||
| import { customRandom } from 'nanoid' | ||
| const rng = seedrandom(seed) | ||
| const nanoid = customRandom('abcdef', 10, size => { | ||
| return (new Uint8Array(size)).map(() => 256 * rng()) | ||
| }) | ||
| nanoid() //=> "fbaefaadeb" | ||
| ``` | ||
| `random` callback must accept the array size and return an array | ||
| with random numbers. | ||
| If you want to use the same URL-friendly symbols with `customRandom`, | ||
| you can get the default alphabet using the `urlAlphabet`. | ||
| ```js | ||
| const { customRandom, urlAlphabet } = require('nanoid') | ||
| const nanoid = customRandom(urlAlphabet, 10, random) | ||
| ``` | ||
| Asynchronous and non-secure APIs are not available for `customRandom`. | ||
| Note, that between Nano ID versions we may change random generator | ||
| call sequence. If you are using seed-based generators, we do not guarantee | ||
| the same result. | ||
| ## Usage | ||
| ### IE | ||
| If you support IE, you need to [transpile `node_modules`] by Babel | ||
| and add `crypto` alias. Moreover, `UInt8Array` in IE actually | ||
| is not an array and to cope with it, you have to convert it to an array | ||
| manually: | ||
| ```js | ||
| // polyfills.js | ||
| if (!window.crypto && window.msCrypto) { | ||
| window.crypto = window.msCrypto | ||
| const getRandomValuesDef = window.crypto.getRandomValues | ||
| window.crypto.getRandomValues = function (array) { | ||
| const values = getRandomValuesDef.call(window.crypto, array) | ||
| const result = [] | ||
| for (let i = 0; i < array.length; i++) { | ||
| result[i] = values[i]; | ||
| } | ||
| return result | ||
| }; | ||
| } | ||
| ``` | ||
| ```js | ||
| import './polyfills.js' | ||
| import { nanoid } from 'nanoid' | ||
| ``` | ||
| [transpile `node_modules`]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/ | ||
| ### React | ||
| There’s no correct way to use Nano ID for React `key` prop | ||
| since it should be consistent among renders. | ||
| ```jsx | ||
| function Todos({todos}) { | ||
| return ( | ||
| <ul> | ||
| {todos.map(todo => ( | ||
| <li key={nanoid()}> /* DON’T DO IT */ | ||
| {todo.text} | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| ) | ||
| } | ||
| ``` | ||
| You should rather try to reach for stable ID inside your list item. | ||
| ```jsx | ||
| const todoItems = todos.map((todo) => | ||
| <li key={todo.id}> | ||
| {todo.text} | ||
| </li> | ||
| ) | ||
| ``` | ||
| In case you don’t have stable IDs you'd rather use index as `key` | ||
| instead of `nanoid()`: | ||
| ```jsx | ||
| const todoItems = todos.map((text, index) => | ||
| <li key={index}> /* Still not recommended but preferred over nanoid(). | ||
| Only do this if items have no stable IDs. */ | ||
| {text} | ||
| </li> | ||
| ) | ||
| ``` | ||
| ### React Native | ||
| React Native does not have built-in random generator. The following polyfill | ||
| works for plain React Native and Expo starting with `39.x`. | ||
| 1. Check [`react-native-get-random-values`] docs and install it. | ||
| 2. Import it before Nano ID. | ||
| ```js | ||
| import 'react-native-get-random-values' | ||
| import { nanoid } from 'nanoid' | ||
| ``` | ||
| [`react-native-get-random-values`]: https://github.com/LinusU/react-native-get-random-values | ||
| ### Rollup | ||
| For Rollup you will need [`@rollup/plugin-node-resolve`] to bundle browser version | ||
| of this library.: | ||
| ```js | ||
| plugins: [ | ||
| nodeResolve({ | ||
| browser: true | ||
| }) | ||
| ] | ||
| ``` | ||
| [`@rollup/plugin-node-resolve`]: https://github.com/rollup/plugins/tree/master/packages/node-resolve | ||
| ### PouchDB and CouchDB | ||
| In PouchDB and CouchDB, IDs can’t start with an underscore `_`. | ||
| A prefix is required to prevent this issue, as Nano ID might use a `_` | ||
| at the start of the ID by default. | ||
| Override the default ID with the following option: | ||
| ```js | ||
| db.put({ | ||
| _id: 'id' + nanoid(), | ||
| … | ||
| }) | ||
| ``` | ||
| ### Mongoose | ||
| ```js | ||
| const mySchema = new Schema({ | ||
| _id: { | ||
| type: String, | ||
| default: () => nanoid() | ||
| } | ||
| }) | ||
| ``` | ||
| ### Web Workers | ||
| Web Workers do not have access to a secure random generator. | ||
| Security is important in IDs when IDs should be unpredictable. | ||
| For instance, in "access by URL" link generation. | ||
| If you do not need unpredictable IDs, but you need to use Web Workers, | ||
| you can use the non‑secure ID generator. | ||
| ```js | ||
| import { nanoid } from 'nanoid/non-secure' | ||
| nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ" | ||
| ``` | ||
| Note: non-secure IDs are more prone to collision attacks. | ||
| ### CLI | ||
| You can get unique ID in terminal by calling `npx nanoid`. You need only | ||
| Node.js in the system. You do not need Nano ID to be installed anywhere. | ||
| ```sh | ||
| $ npx nanoid | ||
| npx: installed 1 in 0.63s | ||
| LZfXLFzPPR4NNrgjlWDxn | ||
| ``` | ||
| Size of generated ID can be specified with `--size` (or `-s`) option: | ||
| ```sh | ||
| $ npx nanoid --size 10 | ||
| L3til0JS4z | ||
| ``` | ||
| Custom alphabet can be specified with `--alphabet` (or `-a`) option | ||
| (note that in this case `--size` is required): | ||
| ```sh | ||
| $ npx nanoid --alphabet abc --size 15 | ||
| bccbcabaabaccab | ||
| ``` | ||
| ### Other Programming Languages | ||
| Nano ID was ported to many languages. You can use these ports to have | ||
| the same ID generator on the client and server side. | ||
| * [C#](https://github.com/codeyu/nanoid-net) | ||
| * [C++](https://github.com/mcmikecreations/nanoid_cpp) | ||
| * [Clojure and ClojureScript](https://github.com/zelark/nano-id) | ||
| * [ColdFusion/CFML](https://github.com/JamoCA/cfml-nanoid) | ||
| * [Crystal](https://github.com/mamantoha/nanoid.cr) | ||
| * [Dart & Flutter](https://github.com/pd4d10/nanoid-dart) | ||
| * [Deno](https://github.com/ianfabs/nanoid) | ||
| * [Go](https://github.com/matoous/go-nanoid) | ||
| * [Elixir](https://github.com/railsmechanic/nanoid) | ||
| * [Haskell](https://github.com/MichelBoucey/NanoID) | ||
| * [Janet](https://sr.ht/~statianzo/janet-nanoid/) | ||
| * [Java](https://github.com/aventrix/jnanoid) | ||
| * [Nim](https://github.com/icyphox/nanoid.nim) | ||
| * [OCaml](https://github.com/routineco/ocaml-nanoid) | ||
| * [Perl](https://github.com/tkzwtks/Nanoid-perl) | ||
| * [PHP](https://github.com/hidehalo/nanoid-php) | ||
| * [Python](https://github.com/puyuan/py-nanoid) | ||
| with [dictionaries](https://pypi.org/project/nanoid-dictionary) | ||
| * [Postgres Extension](https://github.com/spa5k/uids-postgres) | ||
| * [R](https://github.com/hrbrmstr/nanoid) (with dictionaries) | ||
| * [Ruby](https://github.com/radeno/nanoid.rb) | ||
| * [Rust](https://github.com/nikolay-govorov/nanoid) | ||
| * [Swift](https://github.com/antiflasher/NanoID) | ||
| * [Unison](https://share.unison-lang.org/latest/namespaces/hojberg/nanoid) | ||
| * [V](https://github.com/invipal/nanoid) | ||
| * [Zig](https://github.com/SasLuca/zig-nanoid) | ||
| For other environments, [CLI] is available to generate IDs from a command line. | ||
| [CLI]: #cli | ||
| ## Tools | ||
| * [ID size calculator] shows collision probability when adjusting | ||
| the ID alphabet or size. | ||
| * [`nanoid-dictionary`] with popular alphabets to use with [`customAlphabet`]. | ||
| * [`nanoid-good`] to be sure that your ID doesn’t contain any obscene words. | ||
| [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary | ||
| [ID size calculator]: https://zelark.github.io/nano-id-cc/ | ||
| [`customAlphabet`]: #custom-alphabet-or-size | ||
| [`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good | ||
| ## Docs | ||
| Read full docs **[here](https://github.com/ai/nanoid#readme)**. |
@@ -1,7 +0,3 @@ | ||
| // This alphabet uses `A-Za-z0-9_-` symbols. | ||
| // The order of characters is optimized for better gzip and brotli compression. | ||
| // Same as in non-secure/index.js | ||
| let urlAlphabet = | ||
| 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict' | ||
| export { urlAlphabet } |
32583
-42.41%713
-17%40
-92.79%