nanoid
Advanced tools
Comparing version 2.1.9 to 2.1.10
@@ -0,3 +1,25 @@ | ||
// This file replaces `async/format.js` in bundlers like webpack or Rollup, | ||
// according to `browser` config in `package.json`. | ||
module.exports = function (random, alphabet, size) { | ||
var mask = (2 << 31 - Math.clz32((alphabet.length - 1) | 1)) - 1 | ||
// We can’t use bytes bigger than the alphabet. To make bytes values closer | ||
// to the alphabet, we apply bitmask on them. We look for the closest | ||
// `2 ** x - 1` number, which will be bigger than alphabet size. If we have | ||
// 30 symbols in the alphabet, we will take 31 (00011111). | ||
// We do not use faster Math.clz32, because it is not available in browsers. | ||
var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1 | ||
// Bitmask is not a perfect solution (in our example it will pass 31 bytes, | ||
// which is bigger than the alphabet). As a result, we will need more bytes, | ||
// than ID size, because we will refuse bytes bigger than the alphabet. | ||
// Every hardware random generator call is costly, | ||
// because we need to wait for entropy collection. This is why often it will | ||
// be faster to ask for few extra bytes in advance, to avoid additional calls. | ||
// Here we calculate how many random bytes should we call in advance. | ||
// It depends on ID length, mask / alphabet size and magic number 1.6 | ||
// (which was selected according benchmarks). | ||
// -~f => Math.ceil(f) if n is float number | ||
// -~i => i + 1 if n is integer number | ||
var step = -~(1.6 * mask * size / alphabet.length) | ||
@@ -7,5 +29,9 @@ | ||
return random(step).then(function (bytes) { | ||
// Compact alternative for `for (var i = 0; i < step; i++)` | ||
var i = step | ||
while (i--) { | ||
// If random byte is bigger than alphabet even after bitmask, | ||
// we refuse it by `|| ''`. | ||
id += alphabet[bytes[i] & mask] || '' | ||
// More compact than `id.length + 1 === size` | ||
if (id.length === +size) return id | ||
@@ -12,0 +38,0 @@ } |
@@ -32,3 +32,18 @@ /** | ||
module.exports = function (random, alphabet, size) { | ||
var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1 | ||
// We can’t use bytes bigger than the alphabet. To make bytes values closer | ||
// to the alphabet, we apply bitmask on them. We look for the closest | ||
// `2 ** x - 1` number, which will be bigger than alphabet size. If we have | ||
// 30 symbols in the alphabet, we will take 31 (00011111). | ||
var mask = (2 << 31 - Math.clz32((alphabet.length - 1) | 1)) - 1 | ||
// Bitmask is not a perfect solution (in our example it will pass 31 bytes, | ||
// which is bigger than the alphabet). As a result, we will need more bytes, | ||
// than ID size, because we will refuse bytes bigger than the alphabet. | ||
// Every hardware random generator call is costly, | ||
// because we need to wait for entropy collection. This is why often it will | ||
// be faster to ask for few extra bytes in advance, to avoid additional calls. | ||
// Here we calculate how many random bytes should we call in advance. | ||
// It depends on ID length, mask / alphabet size and magic number 1.6 | ||
// (which was selected according benchmarks). | ||
var step = Math.ceil(1.6 * mask * size / alphabet.length) | ||
@@ -38,5 +53,9 @@ | ||
return random(step).then(function (bytes) { | ||
// Compact alternative for `for (var i = 0; i < step; i++)` | ||
var i = step | ||
while (i--) { | ||
// If random byte is bigger than alphabet even after bitmask, | ||
// we refuse it by `|| ''`. | ||
id += alphabet[bytes[i] & mask] || '' | ||
// More compact than `id.length + 1 === size` | ||
if (id.length === +size) return id | ||
@@ -43,0 +62,0 @@ } |
@@ -0,9 +1,29 @@ | ||
// This file replaces `async/index.js` in bundlers like webpack or Rollup, | ||
// according to `browser` config in `package.json`. | ||
var crypto = self.crypto || self.msCrypto | ||
/* | ||
* This alphabet uses a-z A-Z 0-9 _- symbols. | ||
* Symbols order was changed for better gzip compression. | ||
*/ | ||
var url = 'IUint8Ar21ModulvezGFYPCJ7_p0V4XSymbLBNH6fTqQ35xD9ZREghasOw-cjkWK' | ||
// This alphabet uses a-z A-Z 0-9 _- symbols. | ||
// Despite the fact the source code is quite long, its entropy | ||
// is low and there are lots of duplicates - just what compressors | ||
// like GZIP and Brotli likes the best. | ||
var i | ||
var url = '_-' + String.fromCharCode( | ||
// ASCII codes for 0...9 | ||
i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for A...Z | ||
i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for a...z | ||
i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1 | ||
) | ||
module.exports = function (size) { | ||
@@ -13,3 +33,8 @@ size = size || 21 | ||
var bytes = crypto.getRandomValues(new Uint8Array(size)) | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. | ||
// This mask reduces random byte 0-255 to 0-63 values. | ||
// There is no need in `|| ''` and `* 1.6` hacks in here, | ||
// because bitmask trim bytes exact to alphabet size. | ||
id += url[bytes[size] & 63] | ||
@@ -16,0 +41,0 @@ } |
@@ -27,3 +27,8 @@ var random = require('./random') | ||
var id = '' | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. | ||
// This mask reduces random byte 0-255 to 0-63 values. | ||
// There is no need in `|| ''` and `* 1.6` hacks in here, | ||
// because bitmask trim bytes exact to alphabet size. | ||
id += url[bytes[size] & 63] | ||
@@ -30,0 +35,0 @@ } |
@@ -0,1 +1,4 @@ | ||
// This file replaces `async/random.js` in bundlers like webpack or Rollup, | ||
// according to `browser` config in `package.json`. | ||
var crypto = self.crypto || self.msCrypto | ||
@@ -2,0 +5,0 @@ |
var crypto = require('crypto') | ||
if (crypto.randomFill) { | ||
// `crypto.randomFill()` is a little fatser than `crypto.randomBytes()`, | ||
// because we can use faster `Buffer.allocUnsafe()`. | ||
module.exports = function (bytes) { | ||
return new Promise(function (resolve, reject) { | ||
// `Buffer.allocUnsafe()` faster because it don’t clean memory. | ||
// We do not need it, since we will fill memory with new bytes anyway. | ||
crypto.randomFill(Buffer.allocUnsafe(bytes), function (err, buf) { | ||
@@ -7,0 +11,0 @@ if (err) { |
# Change Log | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
## 2.1.10 | ||
* Reduce size by 10% (by Anton Khlynovskiy). | ||
## 2.1.9 | ||
@@ -5,0 +8,0 @@ * Reduce `format` and `async/format` size (by Dair Aidarkhanov). |
@@ -0,3 +1,25 @@ | ||
// This file replaces `format.js` in bundlers like webpack or Rollup, | ||
// according to `browser` config in `package.json`. | ||
module.exports = function (random, alphabet, size) { | ||
// We can’t use bytes bigger than the alphabet. To make bytes values closer | ||
// to the alphabet, we apply bitmask on them. We look for the closest | ||
// `2 ** x - 1` number, which will be bigger than alphabet size. If we have | ||
// 30 symbols in the alphabet, we will take 31 (00011111). | ||
// We do not use faster Math.clz32, because it is not available in browsers. | ||
var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1 | ||
// Bitmask is not a perfect solution (in our example it will pass 31 bytes, | ||
// which is bigger than the alphabet). As a result, we will need more bytes, | ||
// than ID size, because we will refuse bytes bigger than the alphabet. | ||
// Every hardware random generator call is costly, | ||
// because we need to wait for entropy collection. This is why often it will | ||
// be faster to ask for few extra bytes in advance, to avoid additional calls. | ||
// Here we calculate how many random bytes should we call in advance. | ||
// It depends on ID length, mask / alphabet size and magic number 1.6 | ||
// (which was selected according benchmarks). | ||
// -~f => Math.ceil(f) if n is float number | ||
// -~i => i + 1 if n is integer number | ||
var step = -~(1.6 * mask * size / alphabet.length) | ||
@@ -7,6 +29,10 @@ var id = '' | ||
while (true) { | ||
var bytes = random(step) | ||
// Compact alternative for `for (var i = 0; i < step; i++)` | ||
var i = step | ||
var bytes = random(i) | ||
while (i--) { | ||
// If random byte is bigger than alphabet even after bitmask, | ||
// we refuse it by `|| ''`. | ||
id += alphabet[bytes[i] & mask] || '' | ||
// More compact than `id.length + 1 === size` | ||
if (id.length === +size) return id | ||
@@ -13,0 +39,0 @@ } |
@@ -30,3 +30,18 @@ /** | ||
module.exports = function (random, alphabet, size) { | ||
// We can’t use bytes bigger than the alphabet. To make bytes values closer | ||
// to the alphabet, we apply bitmask on them. We look for the closest | ||
// `2 ** x - 1` number, which will be bigger than alphabet size. If we have | ||
// 30 symbols in the alphabet, we will take 31 (00011111). | ||
var mask = (2 << 31 - Math.clz32((alphabet.length - 1) | 1)) - 1 | ||
// Bitmask is not a perfect solution (in our example it will pass 31 bytes, | ||
// which is bigger than the alphabet). As a result, we will need more bytes, | ||
// than ID size, because we will refuse bytes bigger than the alphabet. | ||
// Every hardware random generator call is costly, | ||
// because we need to wait for entropy collection. This is why often it will | ||
// be faster to ask for few extra bytes in advance, to avoid additional calls. | ||
// Here we calculate how many random bytes should we call in advance. | ||
// It depends on ID length, mask / alphabet size and magic number 1.6 | ||
// (which was selected according benchmarks). | ||
var step = Math.ceil(1.6 * mask * size / alphabet.length) | ||
@@ -36,6 +51,10 @@ var id = '' | ||
while (true) { | ||
var bytes = random(step) | ||
// Compact alternative for `for (var i = 0; i < step; i++)` | ||
var i = step | ||
var bytes = random(i) | ||
while (i--) { | ||
// If random byte is bigger than alphabet even after bitmask, | ||
// we refuse it by `|| ''`. | ||
id += alphabet[bytes[i] & mask] || '' | ||
// More compact than `id.length + 1 === size` | ||
if (id.length === +size) return id | ||
@@ -42,0 +61,0 @@ } |
@@ -0,2 +1,6 @@ | ||
// This file replaces `index.js` in bundlers like webpack or Rollup, | ||
// according to `browser` config in `package.json`. | ||
if (process.env.NODE_ENV !== 'production') { | ||
// All bundlers will remove this block in production bundle | ||
if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { | ||
@@ -19,8 +23,25 @@ throw new Error( | ||
/* | ||
* This alphabet uses a-z A-Z 0-9 _- symbols. | ||
* Symbols order was changed for better gzip compression. | ||
*/ | ||
var url = 'QLUint8ARdomValuesObj0h6345-79BCrypgJzHKTNYDSMkXPZ_FfG1WcqvwxEI2' | ||
// This alphabet uses a-z A-Z 0-9 _- symbols. | ||
// Despite the fact the source code is quite long, its entropy | ||
// is low and there are lots of duplicates - just what compressors | ||
// like GZIP and Brotli likes the best. | ||
var i | ||
var url = '_-' + String.fromCharCode( | ||
// ASCII codes for 0...9 | ||
i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for A...Z | ||
i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for a...z | ||
i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1 | ||
) | ||
module.exports = function (size) { | ||
@@ -30,3 +51,8 @@ size = size || 21 | ||
var bytes = crypto.getRandomValues(new Uint8Array(size)) | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. | ||
// This mask reduces random byte 0-255 to 0-63 values. | ||
// There is no need in `|| ''` and `* 1.6` hacks in here, | ||
// because bitmask trim bytes exact to alphabet size. | ||
id += url[bytes[size] & 63] | ||
@@ -33,0 +59,0 @@ } |
@@ -25,3 +25,8 @@ var random = require('./random') | ||
var id = '' | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. | ||
// This mask reduces random byte 0-255 to 0-63 values. | ||
// There is no need in `|| ''` and `* 1.6` hacks in here, | ||
// because bitmask trim bytes exact to alphabet size. | ||
id += url[bytes[size] & 63] | ||
@@ -28,0 +33,0 @@ } |
@@ -20,3 +20,5 @@ /** | ||
var id = '' | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// `| 0` is compact and faster alternative for `Math.floor()` | ||
id += alphabet[Math.random() * alphabet.length | 0] | ||
@@ -23,0 +25,0 @@ } |
@@ -1,3 +0,24 @@ | ||
var url = 'sOwnPropMN49CEiq-hXvHJdSymlFURTag61GQfuD8YIWz2Zk5xKB7LV30_Abject' | ||
// This alphabet uses a-z A-Z 0-9 _- symbols. | ||
// Despite the fact the source code is quite long, its entropy | ||
// is low and there are lots of duplicates - just what compressors | ||
// like GZIP and Brotli likes the best. | ||
var i | ||
var url = '_-' + String.fromCharCode( | ||
// ASCII codes for 0...9 | ||
i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for A...Z | ||
i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for a...z | ||
i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1 | ||
) | ||
/** | ||
@@ -21,3 +42,5 @@ * Generate URL-friendly unique ID. This method use non-secure predictable | ||
var id = '' | ||
// Compact alternative for `for (var i = 0; i < size; i++)` | ||
while (size--) { | ||
// `| 0` is compact and faster alternative for `Math.floor()` | ||
id += url[Math.random() * 64 | 0] | ||
@@ -24,0 +47,0 @@ } |
{ | ||
"name": "nanoid", | ||
"version": "2.1.9", | ||
"description": "A tiny (137 bytes), secure URL-friendly unique string ID generator", | ||
"version": "2.1.10", | ||
"description": "A tiny (127 bytes), secure URL-friendly unique string ID generator", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "uuid", |
var crypto = require('crypto') | ||
if (crypto.randomFillSync) { | ||
// We reuse buffers with the same size to avoid memory fragmentations | ||
// for better performance | ||
var buffers = { } | ||
@@ -8,2 +10,4 @@ module.exports = function (bytes) { | ||
if (!buffer) { | ||
// `Buffer.allocUnsafe()` faster because it don’t clean memory. | ||
// We do not need it, since we will fill memory with new bytes anyway. | ||
buffer = Buffer.allocUnsafe(bytes) | ||
@@ -10,0 +14,0 @@ if (bytes <= 255) buffers[bytes] = buffer |
@@ -8,3 +8,3 @@ # Nano ID | ||
* **Small.** 137 bytes (minified and gzipped). No dependencies. | ||
* **Small.** 127 bytes (minified and gzipped). No dependencies. | ||
[Size Limit] controls the size. | ||
@@ -66,4 +66,4 @@ * **Safe.** It uses cryptographically strong random APIs. | ||
are packed in just 21 symbols instead of 36. | ||
2. Nano ID code is 3 times less than `uuid/v4` package: | ||
137 bytes instead of 435. | ||
2. Nano ID code is 4 times less than `uuid/v4` package: | ||
127 bytes instead of 435. | ||
3. Because of memory allocation tricks, Nano ID is 16% faster than UUID. | ||
@@ -70,0 +70,0 @@ |
29
url.js
@@ -0,7 +1,11 @@ | ||
// This alphabet uses a-z A-Z 0-9 _- symbols. | ||
// Despite the fact the source code is quite long, its entropy | ||
// is low and there are lots of duplicates - just what compressors | ||
// like GZIP and Brotli likes the best. | ||
var i | ||
/** | ||
* URL safe symbols. | ||
* | ||
* This alphabet uses a-z A-Z 0-9 _- symbols. | ||
* Symbols order was changed for better gzip compression. | ||
* | ||
* @name url | ||
@@ -14,3 +18,18 @@ * @type {string} | ||
*/ | ||
module.exports = | ||
'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW' | ||
module.exports = '_-' + String.fromCharCode( | ||
// ASCII codes for 0...9 | ||
i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for A...Z | ||
i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, | ||
// ASCII codes for a...z | ||
i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, | ||
i += 1, i += 1 | ||
) |
36993
577