nanoid 1.0.7 → 1.2.1
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 +17 -0
- package/README.md +72 -26
- package/async.browser.js +13 -0
- package/async.js +54 -0
- package/format.js +5 -3
- package/generate.js +1 -1
- package/index.browser.js +9 -0
- package/index.js +1 -1
- package/non-secure.js +28 -0
- package/package.json +5 -47
- package/url.js +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
# Change Log
|
2
2
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
3
3
|
|
4
|
+
## 1.2.1
|
5
|
+
* Fix old Node.js support.
|
6
|
+
|
7
|
+
## 1.2
|
8
|
+
* Add `nanoid/async`.
|
9
|
+
* Fix `nanoid/non-secure` JSDoc.
|
10
|
+
* Add Chinese documentation (by Wenliang Dai).
|
11
|
+
* Speed up and reduce size of `nanoid/non-secure` (by Ori Livni).
|
12
|
+
|
13
|
+
## 1.1.1
|
14
|
+
* Improve performance and reduce size of non-secure ID generator.
|
15
|
+
|
16
|
+
## 1.1
|
17
|
+
* Add non-secure ID generator.
|
18
|
+
* Suggest to use non-secure ID generator for React Native developers.
|
19
|
+
* Reduce size.
|
20
|
+
|
4
21
|
## 1.0.7
|
5
22
|
* Fix documentation.
|
6
23
|
|
package/README.md
CHANGED
@@ -3,23 +3,23 @@
|
|
3
3
|
<img src="https://ai.github.io/nanoid/logo.svg" align="right"
|
4
4
|
alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
|
5
5
|
|
6
|
-
A tiny, secure, URL-friendly, unique
|
6
|
+
A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
|
7
7
|
|
8
8
|
**Safe.** It uses cryptographically strong random APIs
|
9
|
-
and
|
9
|
+
and tests distribution of symbols.
|
10
10
|
|
11
|
-
**Small.**
|
12
|
-
It uses [Size Limit] to
|
11
|
+
**Small.** 145 bytes (minified and gzipped). No dependencies.
|
12
|
+
It uses [Size Limit] to control size.
|
13
13
|
|
14
|
-
**Compact.** It uses a
|
15
|
-
As
|
14
|
+
**Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_~`).
|
15
|
+
As result it could reduce ID size from 36 to 21 symbols.
|
16
16
|
|
17
17
|
```js
|
18
18
|
var nanoid = require('nanoid')
|
19
19
|
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B~myT"
|
20
20
|
```
|
21
21
|
|
22
|
-
The
|
22
|
+
The generator supports Node.js, React Native, and [all browsers].
|
23
23
|
|
24
24
|
[all browsers]: http://caniuse.com/#feat=getrandomvalues
|
25
25
|
[Size Limit]: https://github.com/ai/size-limit
|
@@ -50,7 +50,7 @@ The spread will not be even; there will be a lower chance for some symbols
|
|
50
50
|
to appear compared to others—so it will reduce the number of tries
|
51
51
|
when brute-forcing.
|
52
52
|
|
53
|
-
Nano ID uses a [better algorithm] and is tested for uniformity
|
53
|
+
Nano ID uses a [better algorithm] and is tested for uniformity.
|
54
54
|
|
55
55
|
<img src="img/distribution.png" alt="Nano ID uniformity"
|
56
56
|
width="340" height="135">
|
@@ -73,17 +73,26 @@ There are two main differences between Nano ID and UUID v4:
|
|
73
73
|
1. Nano ID uses a bigger alphabet, so a similar number of random bits
|
74
74
|
are packed in just 21 symbols instead of 36.
|
75
75
|
2. Nano ID code is 3 times less than `uuid/v4` package:
|
76
|
-
|
76
|
+
145 bytes instead of 435.
|
77
77
|
|
78
78
|
|
79
79
|
## Benchmark
|
80
80
|
|
81
81
|
```
|
82
|
-
$ ./benchmark
|
83
|
-
nanoid
|
84
|
-
nanoid/generate
|
85
|
-
|
86
|
-
|
82
|
+
$ ./test/benchmark
|
83
|
+
nanoid 354,201 ops/sec
|
84
|
+
nanoid/generate 348,467 ops/sec
|
85
|
+
uid.sync 325,347 ops/sec
|
86
|
+
uuid/v4 322,328 ops/sec
|
87
|
+
shortid 33,277 ops/sec
|
88
|
+
|
89
|
+
Async:
|
90
|
+
uid 71,998 ops/sec
|
91
|
+
nanoid/async 72,836 ops/sec
|
92
|
+
|
93
|
+
Non-secure:
|
94
|
+
rndm 2,495,324 ops/sec
|
95
|
+
nanoid/non-secure 2,746,033 ops/sec
|
87
96
|
```
|
88
97
|
|
89
98
|
|
@@ -95,7 +104,7 @@ The main module uses URL-friendly symbols (`A-Za-z0-9_~`) and returns an ID
|
|
95
104
|
with 21 characters (to have a collision probability similar to UUID v4).
|
96
105
|
|
97
106
|
```js
|
98
|
-
|
107
|
+
const nanoid = require('nanoid')
|
99
108
|
model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
|
100
109
|
```
|
101
110
|
|
@@ -103,7 +112,7 @@ Symbols `-,.()` are not encoded in the URL. If used at the end of a link
|
|
103
112
|
they could be identified as a punctuation symbol.
|
104
113
|
|
105
114
|
If you want to reduce ID length (and increase collisions probability),
|
106
|
-
you can pass the length as an argument
|
115
|
+
you can pass the length as an argument.
|
107
116
|
|
108
117
|
```js
|
109
118
|
nanoid(10) //=> "IRFa~VaY2b"
|
@@ -112,7 +121,41 @@ nanoid(10) //=> "IRFa~VaY2b"
|
|
112
121
|
Don’t forget to check safety of your ID length
|
113
122
|
in our [ID collision probability] calculator.
|
114
123
|
|
115
|
-
[ID collision probability]: https://
|
124
|
+
[ID collision probability]: https://zelark.github.io/nano-id-cc/
|
125
|
+
|
126
|
+
|
127
|
+
### React Native and Web Workers
|
128
|
+
|
129
|
+
React Native and Web Worker don’t have access to secure random generator.
|
130
|
+
|
131
|
+
Security is important in ID, when ID should be unpredictable. For instance,
|
132
|
+
in “access by URL” link generation.
|
133
|
+
|
134
|
+
If you don’t need unpredictable IDs, but you need React Native
|
135
|
+
or Web Workers support, you can use non‑secure ID generator.
|
136
|
+
|
137
|
+
```js
|
138
|
+
const nanoid = require('nanoid/non-secure')
|
139
|
+
model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
|
140
|
+
```
|
141
|
+
|
142
|
+
|
143
|
+
## Async
|
144
|
+
|
145
|
+
To generate hardware random bytes, CPU will collect electromagnetic noise.
|
146
|
+
During the collection, CPU doesn’t work. So if we will use asynchronous API
|
147
|
+
for hardware random generator, your other code could be executed during
|
148
|
+
the entropy collection.
|
149
|
+
|
150
|
+
```js
|
151
|
+
const nanoid = require('nanoid/async')
|
152
|
+
nanoid.then(id => {
|
153
|
+
model.id = id
|
154
|
+
})
|
155
|
+
```
|
156
|
+
|
157
|
+
Unfortunately, you will not have any benefits in browser, since Web Crypto API
|
158
|
+
doesn’t have asynchronous API.
|
116
159
|
|
117
160
|
|
118
161
|
### Custom Alphabet or Length
|
@@ -121,18 +164,17 @@ If you want to change the ID's alphabet or length
|
|
121
164
|
you can use the low-level `generate` module.
|
122
165
|
|
123
166
|
```js
|
124
|
-
|
167
|
+
const generate = require('nanoid/generate')
|
125
168
|
model.id = generate('1234567890abcdef', 10) //=> "4f90d13a42"
|
126
169
|
```
|
127
170
|
|
128
171
|
Check safety of your custom alphabet and ID length
|
129
172
|
in our [ID collision probability] calculator.
|
173
|
+
You can find popular alphabets in [`nanoid-dictionary`].
|
130
174
|
|
131
175
|
Alphabet must contain 256 symbols or less.
|
132
176
|
Otherwise, the generator will not be secure.
|
133
177
|
|
134
|
-
You can find popular alphabets in [`nanoid-dictionary`].
|
135
|
-
|
136
178
|
[ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/
|
137
179
|
[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
|
138
180
|
|
@@ -143,11 +185,13 @@ You can replace the default safe random generator using the `format` module.
|
|
143
185
|
For instance, to use a seed-based generator.
|
144
186
|
|
145
187
|
```js
|
146
|
-
|
188
|
+
const format = require('nanoid/format')
|
147
189
|
|
148
190
|
function random (size) {
|
149
|
-
|
150
|
-
for (
|
191
|
+
const result = []
|
192
|
+
for (let i = 0; i < size; i++) {
|
193
|
+
result.push(randomByte())
|
194
|
+
}
|
151
195
|
return result
|
152
196
|
}
|
153
197
|
|
@@ -158,10 +202,10 @@ format(random, "abcdef", 10) //=> "fbaefaadeb"
|
|
158
202
|
with random numbers.
|
159
203
|
|
160
204
|
If you want to use the same URL-friendly symbols with `format`,
|
161
|
-
you can get the default alphabet from the `url`
|
205
|
+
you can get the default alphabet from the `url` file.
|
162
206
|
|
163
207
|
```js
|
164
|
-
|
208
|
+
const url = require('nanoid/url')
|
165
209
|
format(random, url, 10) //=> "93ce_Ltuub"
|
166
210
|
```
|
167
211
|
|
@@ -171,10 +215,12 @@ format(random, url, 10) //=> "93ce_Ltuub"
|
|
171
215
|
* [ID size calculator] to choice smaller ID size depends on your case.
|
172
216
|
* [`nanoid-dictionary`] with popular alphabets to use with `nanoid/generate`.
|
173
217
|
* [`nanoid-cli`] to generate ID from CLI.
|
218
|
+
* [`nanoid-good`] to be sure that your ID doesn't contain any obscene words.
|
174
219
|
|
175
220
|
[`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
|
176
|
-
[ID size calculator]: https://
|
221
|
+
[ID size calculator]: https://zelark.github.io/nano-id-cc/
|
177
222
|
[`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli
|
223
|
+
[`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good
|
178
224
|
|
179
225
|
|
180
226
|
## Other Programming Languages
|
package/async.browser.js
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
var crypto = self.crypto || self.msCrypto
|
2
|
+
|
3
|
+
var url = '_~getRandomVcryp0123456789bfhijklqsuvwxzABCDEFGHIJKLMNOPQSTUWXYZ'
|
4
|
+
|
5
|
+
module.exports = function (size) {
|
6
|
+
size = size || 21
|
7
|
+
var id = ''
|
8
|
+
var bytes = crypto.getRandomValues(new Uint8Array(size))
|
9
|
+
while (0 < size--) {
|
10
|
+
id += url[bytes[size] & 63]
|
11
|
+
}
|
12
|
+
return Promise.resolve(id)
|
13
|
+
}
|
package/async.js
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
var crypto = require('crypto')
|
2
|
+
|
3
|
+
var url = require('./url')
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Generate secure URL-friendly unique ID. Non-blocking version.
|
7
|
+
*
|
8
|
+
* By default, ID will have 21 symbols to have a collision probability similar
|
9
|
+
* to UUID v4.
|
10
|
+
*
|
11
|
+
* @param {number} [size=21] The number of symbols in ID.
|
12
|
+
* @param {function} callback for environments without `Promise`.
|
13
|
+
*
|
14
|
+
* @return {Promise} Promise with random string.
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* const nanoidAsync = require('nanoid/async')
|
18
|
+
* nanoidAsync.then(id => {
|
19
|
+
* model.id = id
|
20
|
+
* })
|
21
|
+
*
|
22
|
+
* @name async
|
23
|
+
* @function
|
24
|
+
*/
|
25
|
+
module.exports = function (size, callback) {
|
26
|
+
size = size || 21
|
27
|
+
if (callback) {
|
28
|
+
crypto.randomBytes(size, function (err, bytes) {
|
29
|
+
if (err) {
|
30
|
+
callback(err)
|
31
|
+
} else {
|
32
|
+
var id = ''
|
33
|
+
while (0 < size--) {
|
34
|
+
id += url[bytes[size] & 63]
|
35
|
+
}
|
36
|
+
callback(null, id)
|
37
|
+
}
|
38
|
+
})
|
39
|
+
} else {
|
40
|
+
return new Promise(function (resolve, reject) {
|
41
|
+
crypto.randomBytes(size, function (err, bytes) {
|
42
|
+
if (err) {
|
43
|
+
reject(err)
|
44
|
+
} else {
|
45
|
+
var id = ''
|
46
|
+
while (0 < size--) {
|
47
|
+
id += url[bytes[size] & 63]
|
48
|
+
}
|
49
|
+
resolve(id)
|
50
|
+
}
|
51
|
+
})
|
52
|
+
})
|
53
|
+
}
|
54
|
+
}
|
package/format.js
CHANGED
@@ -11,11 +11,13 @@
|
|
11
11
|
* @return {string} Random string.
|
12
12
|
*
|
13
13
|
* @example
|
14
|
-
*
|
14
|
+
* const format = require('nanoid/format')
|
15
15
|
*
|
16
16
|
* function random (size) {
|
17
|
-
*
|
18
|
-
* for (
|
17
|
+
* const result = []
|
18
|
+
* for (let i = 0; i < size; i++) {
|
19
|
+
* result.push(randomByte())
|
20
|
+
* }
|
19
21
|
* return result
|
20
22
|
* }
|
21
23
|
*
|
package/generate.js
CHANGED
@@ -13,7 +13,7 @@ var format = require('./format')
|
|
13
13
|
* @return {string} Unique ID.
|
14
14
|
*
|
15
15
|
* @example
|
16
|
-
*
|
16
|
+
* const generate = require('nanoid/generate')
|
17
17
|
* model.id = generate('0123456789абвгдеё', 5) //=> "8ё56а"
|
18
18
|
*
|
19
19
|
* @name generate
|
package/index.browser.js
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
if (process.env.NODE_ENV !== 'production') {
|
2
|
+
if (typeof self === 'undefined' || (!self.crypto && !self.msCrypto)) {
|
3
|
+
throw new Error(
|
4
|
+
'Your browser does not have secure random generator. ' +
|
5
|
+
'If you don’t need unpredictable IDs, you can use nanoid/non-secure.'
|
6
|
+
)
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
1
10
|
var crypto = self.crypto || self.msCrypto
|
2
11
|
|
3
12
|
var url = '_~getRandomVcryp0123456789bfhijklqsuvwxzABCDEFGHIJKLMNOPQSTUWXYZ'
|
package/index.js
CHANGED
package/non-secure.js
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
var url = '_~getRandomVcryp0123456789bfhijklqsuvwxzABCDEFGHIJKLMNOPQSTUWXYZ'
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Generate URL-friendly unique ID. This method use non-secure predictable
|
5
|
+
* random generator.
|
6
|
+
*
|
7
|
+
* By default, ID will have 21 symbols to have a collision probability similar
|
8
|
+
* to UUID v4.
|
9
|
+
*
|
10
|
+
* @param {number} [size=21] The number of symbols in ID.
|
11
|
+
*
|
12
|
+
* @return {string} Random string.
|
13
|
+
*
|
14
|
+
* @example
|
15
|
+
* const nanoid = require('nanoid/non-secure')
|
16
|
+
* model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqL"
|
17
|
+
*
|
18
|
+
* @name nonSecure
|
19
|
+
* @function
|
20
|
+
*/
|
21
|
+
module.exports = function (size) {
|
22
|
+
size = size || 21
|
23
|
+
var id = ''
|
24
|
+
while (0 < size--) {
|
25
|
+
id += url[Math.random() * 63 | 0]
|
26
|
+
}
|
27
|
+
return id
|
28
|
+
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "nanoid",
|
3
|
-
"version": "1.
|
4
|
-
"description": "A tiny (
|
3
|
+
"version": "1.2.1",
|
4
|
+
"description": "A tiny (145 bytes), secure URL-friendly unique string ID generator",
|
5
5
|
"keywords": [
|
6
6
|
"uuid",
|
7
7
|
"random",
|
@@ -13,49 +13,7 @@
|
|
13
13
|
"repository": "ai/nanoid",
|
14
14
|
"browser": {
|
15
15
|
"./random.js": "./random.browser.js",
|
16
|
-
"./index.js": "./index.browser.js"
|
17
|
-
|
18
|
-
|
19
|
-
"benchmark": "^2.1.4",
|
20
|
-
"chalk": "^2.4.1",
|
21
|
-
"docdash": "^0.4.0",
|
22
|
-
"eslint": "^5.0.1",
|
23
|
-
"eslint-ci": "^0.1.1",
|
24
|
-
"eslint-config-logux": "^23.0.2",
|
25
|
-
"eslint-config-standard": "^11.0.0",
|
26
|
-
"eslint-plugin-es5": "^1.3.1",
|
27
|
-
"eslint-plugin-import": "^2.13.0",
|
28
|
-
"eslint-plugin-jest": "^21.17.0",
|
29
|
-
"eslint-plugin-node": "^6.0.1",
|
30
|
-
"eslint-plugin-promise": "^3.8.0",
|
31
|
-
"eslint-plugin-security": "^1.4.0",
|
32
|
-
"eslint-plugin-standard": "^3.1.0",
|
33
|
-
"html-webpack-plugin": "^3.2.0",
|
34
|
-
"jest": "^23.3.0",
|
35
|
-
"jsdoc": "^3.5.5",
|
36
|
-
"lint-staged": "^7.2.0",
|
37
|
-
"microtime": "^2.1.8",
|
38
|
-
"pre-commit": "^1.2.2",
|
39
|
-
"rimraf": "^2.6.2",
|
40
|
-
"shortid": "^2.2.9",
|
41
|
-
"size-limit": "^0.18.3",
|
42
|
-
"svgo": "^1.0.5",
|
43
|
-
"uuid": "^3.3.2",
|
44
|
-
"webpack": "^4.15.1",
|
45
|
-
"webpack-cli": "^3.0.8",
|
46
|
-
"webpack-dev-server": "^3.1.4",
|
47
|
-
"yaspeller-ci": "^1.0.0"
|
48
|
-
},
|
49
|
-
"scripts": {
|
50
|
-
"lint-staged": "lint-staged",
|
51
|
-
"spellcheck": "yarn docs && yaspeller-ci *.md docs/*.html",
|
52
|
-
"clean": "rimraf docs/ coverage/",
|
53
|
-
"docs": "jsdoc --configure .jsdocrc *.js",
|
54
|
-
"lint": "eslint-ci *.js test/*.js",
|
55
|
-
"test": "jest --coverage && yarn lint && size-limit && yarn spellcheck",
|
56
|
-
"start": "webpack-dev-server --config test/demo/webpack.config"
|
57
|
-
},
|
58
|
-
"pre-commit": [
|
59
|
-
"lint-staged"
|
60
|
-
]
|
16
|
+
"./index.js": "./index.browser.js",
|
17
|
+
"./async.js": "./async.browser.js"
|
18
|
+
}
|
61
19
|
}
|