nanoid 1.3.0 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +25 -25
- package/async/index.browser.js +5 -1
- package/async/index.js +19 -12
- package/index.browser.js +5 -1
- package/index.js +16 -2
- package/non-secure.js +1 -1
- package/package.json +6 -1
- package/url.js +2 -2
package/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
# Change Log
|
2
2
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
3
3
|
|
4
|
+
## 1.3.4
|
5
|
+
* Reduce `non-secure` size.
|
6
|
+
* Add `async` callback type check.
|
7
|
+
|
8
|
+
## 1.3.3
|
9
|
+
* Fix `nanoid/async` performance regression.
|
10
|
+
* Fix old Node.js `not seeded` issue in synchronous version too.
|
11
|
+
|
12
|
+
## 1.3.2
|
13
|
+
* Fix random generator `not seeded` issue of old Node.js.
|
14
|
+
|
15
|
+
## 1.3.1
|
16
|
+
* Reduce library size.
|
17
|
+
|
4
18
|
## 1.3
|
5
19
|
* Add `nanoid/async/format` and `nanoid/async/generate`.
|
6
20
|
* Improve synchronous API performance.
|
package/README.md
CHANGED
@@ -5,14 +5,13 @@
|
|
5
5
|
|
6
6
|
A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
|
7
7
|
|
8
|
-
**
|
9
|
-
and tests distribution of symbols.
|
10
|
-
|
11
|
-
**Small.** 143 bytes (minified and gzipped). No dependencies.
|
8
|
+
* **Small.** 142 bytes (minified and gzipped). No dependencies.
|
12
9
|
It uses [Size Limit] to control size.
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
* **Safe.** It uses cryptographically strong random APIs
|
11
|
+
and tests distribution of symbols.
|
12
|
+
* **Fast.** It’s 16% faster than UUID.
|
13
|
+
* **Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_~`).
|
14
|
+
So ID size was reduced from 36 to 21 symbols.
|
16
15
|
|
17
16
|
```js
|
18
17
|
var nanoid = require('nanoid')
|
@@ -39,14 +38,14 @@ The generator supports Node.js, React Native, and [all browsers].
|
|
39
38
|
### Unpredictability
|
40
39
|
|
41
40
|
Instead of using the unsafe `Math.random()`, Nano ID uses the `crypto` module
|
42
|
-
in Node.js and the Web Crypto API in browsers.
|
41
|
+
in Node.js and the Web Crypto API in browsers. These modules use unpredictable
|
43
42
|
hardware random generator.
|
44
43
|
|
45
44
|
|
46
45
|
### Uniformity
|
47
46
|
|
48
47
|
`random % alphabet` is a popular mistake to make when coding an ID generator.
|
49
|
-
The spread will not be even; there will
|
48
|
+
The spread will not be even; there will be a lower chance for some symbols
|
50
49
|
to appear compared to others—so it will reduce the number of tries
|
51
50
|
when brute-forcing.
|
52
51
|
|
@@ -63,7 +62,7 @@ Nano ID uses a [better algorithm] and is tested for uniformity.
|
|
63
62
|
|
64
63
|
Nano ID is quite comparable to UUID v4 (random-based).
|
65
64
|
It has a similar number of random bits in the ID
|
66
|
-
(126 in Nano ID and
|
65
|
+
(126 in Nano ID and 122 in UUID), so it has a similar collision probability:
|
67
66
|
|
68
67
|
> For there to be a one in a billion chance of duplication,
|
69
68
|
> 103 trillion version 4 IDs must be generated.
|
@@ -73,7 +72,7 @@ There are two main differences between Nano ID and UUID v4:
|
|
73
72
|
1. Nano ID uses a bigger alphabet, so a similar number of random bits
|
74
73
|
are packed in just 21 symbols instead of 36.
|
75
74
|
2. Nano ID code is 3 times less than `uuid/v4` package:
|
76
|
-
|
75
|
+
142 bytes instead of 435.
|
77
76
|
|
78
77
|
|
79
78
|
## Benchmark
|
@@ -102,7 +101,7 @@ rndm 2,544,612 ops/sec
|
|
102
101
|
### Normal
|
103
102
|
|
104
103
|
The main module uses URL-friendly symbols (`A-Za-z0-9_~`) and returns an ID
|
105
|
-
with 21 characters (to have a collision
|
104
|
+
with 21 characters (to have a collision probability similar to UUID v4).
|
106
105
|
|
107
106
|
```js
|
108
107
|
const nanoid = require('nanoid')
|
@@ -113,13 +112,13 @@ Symbols `-,.()` are not encoded in the URL. If used at the end of a link
|
|
113
112
|
they could be identified as a punctuation symbol.
|
114
113
|
|
115
114
|
If you want to reduce ID length (and increase collisions probability),
|
116
|
-
you can pass the length as
|
115
|
+
you can pass the length as an argument.
|
117
116
|
|
118
117
|
```js
|
119
118
|
nanoid(10) //=> "IRFa~VaY2b"
|
120
119
|
```
|
121
120
|
|
122
|
-
Don’t forget to check safety of your ID length
|
121
|
+
Don’t forget to check the safety of your ID length
|
123
122
|
in our [ID collision probability] calculator.
|
124
123
|
|
125
124
|
[ID collision probability]: https://zelark.github.io/nano-id-cc/
|
@@ -128,7 +127,7 @@ in our [ID collision probability] calculator.
|
|
128
127
|
### React Native
|
129
128
|
|
130
129
|
To generate secure random IDs in React Native, you must use
|
131
|
-
[a native random generator]
|
130
|
+
[a native random generator] and asynchronous API:
|
132
131
|
|
133
132
|
```js
|
134
133
|
const generateSecureRandom = require('react-native-securerandom').generateSecureRandom
|
@@ -162,9 +161,10 @@ model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
|
|
162
161
|
## Async
|
163
162
|
|
164
163
|
To generate hardware random bytes, CPU will collect electromagnetic noise.
|
165
|
-
During
|
166
|
-
|
167
|
-
|
164
|
+
During the collection, CPU doesn’t work.
|
165
|
+
|
166
|
+
If we will use asynchronous API for random generator,
|
167
|
+
another code could be executed during the entropy collection.
|
168
168
|
|
169
169
|
```js
|
170
170
|
const nanoid = require('nanoid/async')
|
@@ -174,11 +174,11 @@ async function createUser () {
|
|
174
174
|
}
|
175
175
|
```
|
176
176
|
|
177
|
-
Unfortunately, you will not have any benefits in browser, since Web Crypto API
|
177
|
+
Unfortunately, you will not have any benefits in a browser, since Web Crypto API
|
178
178
|
doesn’t have asynchronous API.
|
179
179
|
|
180
180
|
|
181
|
-
|
181
|
+
## Custom Alphabet or Length
|
182
182
|
|
183
183
|
If you want to change the ID's alphabet or length
|
184
184
|
you can use the low-level `generate` module.
|
@@ -188,9 +188,9 @@ const generate = require('nanoid/generate')
|
|
188
188
|
model.id = generate('1234567890abcdef', 10) //=> "4f90d13a42"
|
189
189
|
```
|
190
190
|
|
191
|
-
Check safety of your custom alphabet and ID length
|
191
|
+
Check the safety of your custom alphabet and ID length
|
192
192
|
in our [ID collision probability] calculator.
|
193
|
-
You
|
193
|
+
You can find popular alphabets in [`nanoid-dictionary`].
|
194
194
|
|
195
195
|
Alphabet must contain 256 symbols or less.
|
196
196
|
Otherwise, the generator will not be secure.
|
@@ -208,10 +208,10 @@ async function createUser () {
|
|
208
208
|
[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
|
209
209
|
|
210
210
|
|
211
|
-
|
211
|
+
## Custom Random Bytes Generator
|
212
212
|
|
213
213
|
You can replace the default safe random generator using the `format` module.
|
214
|
-
For instance, to
|
214
|
+
For instance, to use a seed-based generator.
|
215
215
|
|
216
216
|
```js
|
217
217
|
const format = require('nanoid/format')
|
@@ -284,6 +284,6 @@ async function createUser () {
|
|
284
284
|
* [Rust](https://github.com/nikolay-govorov/nanoid)
|
285
285
|
* [Swift](https://github.com/antiflasher/NanoID)
|
286
286
|
|
287
|
-
Also, [CLI tool] is available to generate IDs from command line.
|
287
|
+
Also, [CLI tool] is available to generate IDs from a command line.
|
288
288
|
|
289
289
|
[CLI tool]: https://github.com/twhitbeck/nanoid-cli
|
package/async/index.browser.js
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
var crypto = self.crypto || self.msCrypto
|
2
2
|
|
3
|
-
|
3
|
+
/*
|
4
|
+
* This alphabet uses a-z A-Z 0-9 _~ symbols.
|
5
|
+
* Symbols order was changed for better gzip compression.
|
6
|
+
*/
|
7
|
+
var url = 'ModuleSymbhasOwnPr0123456789ABCDEFGHIJKLNQRTUVWXYZ_cfgijkpqtvxz~'
|
4
8
|
|
5
9
|
module.exports = function (size) {
|
6
10
|
size = size || 21
|
package/async/index.js
CHANGED
@@ -31,12 +31,12 @@ if (crypto.randomFill) {
|
|
31
31
|
* @name async
|
32
32
|
* @function
|
33
33
|
*/
|
34
|
-
module.exports = function (size, callback) {
|
34
|
+
module.exports = function (size, callback, attempt) {
|
35
35
|
size = size || 21
|
36
36
|
|
37
37
|
if (!callback) {
|
38
38
|
if (typeof Promise !== 'function') {
|
39
|
-
throw new
|
39
|
+
throw new TypeError('Function callback is required')
|
40
40
|
}
|
41
41
|
return new Promise(function (resolve, reject) {
|
42
42
|
module.exports(size, function (error, id) {
|
@@ -47,18 +47,25 @@ module.exports = function (size, callback) {
|
|
47
47
|
}
|
48
48
|
})
|
49
49
|
})
|
50
|
+
} else if (typeof callback !== 'function') {
|
51
|
+
throw new TypeError('Callback is not a function')
|
50
52
|
}
|
51
53
|
|
52
|
-
random(size, function (
|
53
|
-
if (
|
54
|
-
|
54
|
+
random(size, function (err, bytes) {
|
55
|
+
if (err) {
|
56
|
+
if (typeof attempt === 'undefined') attempt = 3
|
57
|
+
attempt -= 1
|
58
|
+
if (attempt === 0) {
|
59
|
+
callback(err)
|
60
|
+
} else {
|
61
|
+
setTimeout(module.exports.bind(null, size, callback, attempt), 10)
|
62
|
+
}
|
63
|
+
} else {
|
64
|
+
var id = ''
|
65
|
+
while (0 < size--) {
|
66
|
+
id += url[bytes[size] & 63]
|
67
|
+
}
|
68
|
+
callback(null, id)
|
55
69
|
}
|
56
|
-
|
57
|
-
var id = ''
|
58
|
-
while (0 < size--) {
|
59
|
-
id += url[bytes[size] & 63]
|
60
|
-
}
|
61
|
-
|
62
|
-
callback(null, id)
|
63
70
|
})
|
64
71
|
}
|
package/index.browser.js
CHANGED
@@ -9,7 +9,11 @@ if (process.env.NODE_ENV !== 'production') {
|
|
9
9
|
|
10
10
|
var crypto = self.crypto || self.msCrypto
|
11
11
|
|
12
|
-
|
12
|
+
/*
|
13
|
+
* This alphabet uses a-z A-Z 0-9 _~ symbols.
|
14
|
+
* Symbols order was changed for better gzip compression.
|
15
|
+
*/
|
16
|
+
var url = 'Uint8ArdomValuesObj012345679BCDEFGHIJKLMNPQRSTWXYZ_cfghkpqvwxyz~'
|
13
17
|
|
14
18
|
module.exports = function (size) {
|
15
19
|
size = size || 21
|
package/index.js
CHANGED
@@ -18,12 +18,26 @@ var url = require('./url')
|
|
18
18
|
* @name nanoid
|
19
19
|
* @function
|
20
20
|
*/
|
21
|
-
module.exports = function (size) {
|
21
|
+
module.exports = function (size, attempt) {
|
22
22
|
size = size || 21
|
23
|
+
|
24
|
+
var bytes
|
25
|
+
try {
|
26
|
+
bytes = random(size)
|
27
|
+
} catch (e) {
|
28
|
+
if (typeof attempt === 'undefined') attempt = 3
|
29
|
+
attempt -= 1
|
30
|
+
if (attempt === 0) {
|
31
|
+
throw e
|
32
|
+
} else {
|
33
|
+
return module.exports(size, attempt)
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
23
37
|
var id = ''
|
24
|
-
var bytes = random(size)
|
25
38
|
while (0 < size--) {
|
26
39
|
id += url[bytes[size] & 63]
|
27
40
|
}
|
41
|
+
|
28
42
|
return id
|
29
43
|
}
|
package/non-secure.js
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nanoid",
|
3
|
-
"version": "1.3.
|
3
|
+
"version": "1.3.4",
|
4
4
|
"description": "A tiny (143 bytes), secure URL-friendly unique string ID generator",
|
5
5
|
"keywords": [
|
6
6
|
"uuid",
|
@@ -16,5 +16,10 @@
|
|
16
16
|
"./random.js": "./random.browser.js",
|
17
17
|
"./async/index.js": "./async/index.browser.js",
|
18
18
|
"./async/random.js": "./async/random.browser.js"
|
19
|
+
},
|
20
|
+
"husky": {
|
21
|
+
"hooks": {
|
22
|
+
"pre-commit": "lint-staged"
|
23
|
+
}
|
19
24
|
}
|
20
25
|
}
|
package/url.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
* URL safe symbols.
|
3
3
|
*
|
4
4
|
* This alphabet uses a-z A-Z 0-9 _~ symbols.
|
5
|
-
*
|
5
|
+
* Symbols order was changed for better gzip compression.
|
6
6
|
*
|
7
7
|
* @name url
|
8
8
|
* @type {string}
|
@@ -12,4 +12,4 @@
|
|
12
12
|
* generate(url, 10) //=> "Uakgb_J5m9"
|
13
13
|
*/
|
14
14
|
module.exports =
|
15
|
-
'
|
15
|
+
'SymboljecthasOwnPr0123456789ABCDEFGHIJKLMNQRTUVWXYZ_dfgikpquvxz~'
|