nanoid 0.1.0 → 0.2.2
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 +15 -0
- package/README.md +74 -27
- package/format.js +8 -10
- package/index.js +17 -5
- package/package.json +25 -14
- package/random.js +1 -5
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Change Log
|
2
2
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
3
3
|
|
4
|
+
## 0.2.2
|
5
|
+
* Reduce `nanoid/generate` size (by Anton Khlynovskiy).
|
6
|
+
* Speed up Node.js random generator.
|
7
|
+
|
8
|
+
## 0.2.1
|
9
|
+
* Fix documentation (by Piper Chester).
|
10
|
+
|
11
|
+
## 0.2
|
12
|
+
* Add `size` argument to `nanoid()`.
|
13
|
+
* Improve performance by 50%.
|
14
|
+
* Reduce library size by 26% (by Vsevolod Rodionov and Oleg Mokhov).
|
15
|
+
|
16
|
+
## 0.1.1
|
17
|
+
* Reduce library size by 5%.
|
18
|
+
|
4
19
|
## 0.1
|
5
20
|
* Initial release.
|
package/README.md
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
# Nano ID
|
2
2
|
|
3
|
-
|
3
|
+
A tiny, secure URL-friendly unique string ID generator for JavaScript.
|
4
4
|
|
5
5
|
```js
|
6
6
|
var nanoid = require('nanoid')
|
7
7
|
model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
|
8
8
|
```
|
9
9
|
|
10
|
-
**Safe.** It uses cryptographically
|
11
|
-
and
|
10
|
+
**Safe.** It uses cryptographically strong random APIs
|
11
|
+
and guarantees a proper distribution of symbols.
|
12
12
|
|
13
|
-
**Small.** Only
|
13
|
+
**Small.** Only 179 bytes (minified and gzipped). No dependencies.
|
14
|
+
It uses [Size Limit] to control size.
|
14
15
|
|
15
16
|
**Compact.** It uses more symbols than UUID (`A-Za-z0-9_~`)
|
16
|
-
and
|
17
|
+
and has the same number of unique options in just 22 symbols instead of 36.
|
17
18
|
|
18
|
-
|
19
|
+
The generator supports Node.js and [all browsers] starting from IE 11.
|
19
20
|
|
20
21
|
[all browsers]: http://caniuse.com/#feat=getrandomvalues
|
22
|
+
[Size Limit]: https://github.com/ai/size-limit
|
21
23
|
|
22
24
|
<a href="https://evilmartians.com/?utm_source=nanoid">
|
23
25
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
|
@@ -26,63 +28,92 @@ Generator supports Node.js and [all browsers] from IE 11.
|
|
26
28
|
|
27
29
|
## Security
|
28
30
|
|
29
|
-
*
|
31
|
+
*See a good article about random generators theory:
|
30
32
|
[Secure random values (in Node.js)]*
|
31
33
|
|
32
34
|
### Unpredictability
|
33
35
|
|
34
|
-
|
36
|
+
Instead of unsafe `Math.random()` Nano ID uses `crypto` module in Node.js
|
35
37
|
and Web Crypto API in browsers.
|
36
38
|
|
37
39
|
### Uniformity
|
38
40
|
|
39
|
-
`random % alphabet` is a popular mistake
|
40
|
-
|
41
|
+
`random % alphabet` is a popular mistake to make when coding an ID generator.
|
42
|
+
The spread will not be even; there will be a lower chance for some symbols
|
43
|
+
to appear compared to others—so it will reduce the number of tries
|
44
|
+
when brute-forcing.
|
41
45
|
|
42
|
-
Nano ID
|
46
|
+
Nano ID uses a [better algorithm] and tests uniformity:
|
43
47
|
|
44
48
|
<img src="distribution.png" alt="Nano ID uniformity" width="340" height="135">
|
45
49
|
|
46
50
|
[Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba
|
47
51
|
[better algorithm]: https://github.com/ai/nanoid/blob/master/format.js
|
48
52
|
|
53
|
+
## Comparison with UUID
|
54
|
+
|
55
|
+
Nano ID is similar to UUID v4 (random-based). It uses the same number
|
56
|
+
of random bits in ID, so it has the same collision probability:
|
57
|
+
|
58
|
+
> For there to be a one in a billion chance of duplication,
|
59
|
+
> 103 trillion version 4 IDs must be generated.
|
60
|
+
|
61
|
+
There are only 2 differences between Nano ID and UUID v4:
|
62
|
+
|
63
|
+
1. Nano ID uses a bigger alphabet for ID, so the same random bits
|
64
|
+
are packed in just 22 symbols instead of 36.
|
65
|
+
2. Nano ID code is 2 times smaller in size than `uuid/v4` package:
|
66
|
+
179 bytes instead of 435.
|
67
|
+
|
68
|
+
## Benchmark
|
69
|
+
|
70
|
+
```
|
71
|
+
$ ./benchmark
|
72
|
+
nanoid 375,840 ops/sec
|
73
|
+
nanoid/generate 268,747 ops/sec
|
74
|
+
uuid/v4 374,767 ops/sec
|
75
|
+
shortid 41,260 ops/sec
|
76
|
+
```
|
77
|
+
|
78
|
+
|
49
79
|
## Usage
|
50
80
|
|
51
81
|
### Normal
|
52
82
|
|
53
|
-
|
54
|
-
with 22 characters (to have same
|
83
|
+
The main module uses URL-friendly symbols (`A-Za-z0-9_~`) and returns an ID
|
84
|
+
with 22 characters (to have the same collisions probability as UUID v4).
|
55
85
|
|
56
86
|
```js
|
57
87
|
var nanoid = require('nanoid')
|
58
88
|
model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
|
59
89
|
```
|
60
90
|
|
61
|
-
Symbols `-,.()` are not encoded in URL, but in the end of link
|
62
|
-
be
|
91
|
+
Symbols `-,.()` are not encoded in URL, but in the end of a link
|
92
|
+
they could be identified as a punctuation symbol.
|
93
|
+
|
94
|
+
If you want to reduce ID length (and increase collisions probability),
|
95
|
+
you can pass length as argument:
|
96
|
+
|
97
|
+
```js
|
98
|
+
nanoid(10) //=> "IRFa~VaY2b"
|
99
|
+
```
|
63
100
|
|
64
101
|
### Custom Alphabet or Length
|
65
102
|
|
66
|
-
If you want to change ID alphabet or length
|
67
|
-
module.
|
103
|
+
If you want to change the ID alphabet or the length
|
104
|
+
you can use low-level `generate` module.
|
68
105
|
|
69
106
|
```js
|
70
107
|
var generate = require('nanoid/generate')
|
71
108
|
model.id = generate('1234567890abcdef', 10) //=> "4f90d13a42"
|
72
109
|
```
|
73
110
|
|
74
|
-
|
75
|
-
you can get default alphabet from `url` module:
|
76
|
-
|
77
|
-
```js
|
78
|
-
var url = require('nanoid/url')
|
79
|
-
model.id = generate(url, 10) //=> "Uakgb_J5m9"
|
80
|
-
```
|
111
|
+
Alphabet must contain less than 256 symbols.
|
81
112
|
|
82
113
|
### Custom Random Bytes Generator
|
83
114
|
|
84
|
-
You can replace default safe random
|
85
|
-
|
115
|
+
You can replace the default safe random generator using the `format` module.
|
116
|
+
For instance, to use seed-based generator.
|
86
117
|
|
87
118
|
```js
|
88
119
|
var format = require('nanoid/format')
|
@@ -96,4 +127,20 @@ function random (size) {
|
|
96
127
|
format(random, "abcdef", 10) //=> "fbaefaadeb"
|
97
128
|
```
|
98
129
|
|
99
|
-
`random` callback must accept array size and return array
|
130
|
+
`random` callback must accept the array size and return an array
|
131
|
+
with random numbers.
|
132
|
+
|
133
|
+
If you want to use the same URL-friendly symbols with `format`,
|
134
|
+
you can get default alphabet from the `url` module:
|
135
|
+
|
136
|
+
```js
|
137
|
+
var url = require('nanoid/url')
|
138
|
+
format(random, url, 10) //=> "93ce_Ltuub"
|
139
|
+
```
|
140
|
+
|
141
|
+
## Other Programming Languages
|
142
|
+
|
143
|
+
* [Go](https://github.com/matoous/go-nanoid)
|
144
|
+
* [PHP](https://github.com/hidehalo/nanoid-php)
|
145
|
+
* [Python](https://github.com/puyuan/py-nanoid)
|
146
|
+
* [Ruby](https://github.com/radeno/nanoid.rb)
|
package/format.js
CHANGED
@@ -24,22 +24,20 @@
|
|
24
24
|
* @name format
|
25
25
|
*/
|
26
26
|
module.exports = function (random, alphabet, size) {
|
27
|
-
var
|
27
|
+
var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1
|
28
|
+
var step = Math.ceil(1.6 * mask * size / alphabet.length)
|
28
29
|
|
29
|
-
var bytes, byte
|
30
30
|
var id = ''
|
31
|
-
while (
|
32
|
-
bytes = random(step)
|
33
|
-
for (var i = 0; i <
|
34
|
-
byte = bytes[i]
|
35
|
-
if (byte
|
31
|
+
while (true) {
|
32
|
+
var bytes = random(step)
|
33
|
+
for (var i = 0; i < step; i++) {
|
34
|
+
var byte = bytes[i] & mask
|
35
|
+
if (alphabet[byte]) {
|
36
36
|
id += alphabet[byte]
|
37
|
-
if (id.length === size)
|
37
|
+
if (id.length === size) return id
|
38
38
|
}
|
39
39
|
}
|
40
40
|
}
|
41
|
-
|
42
|
-
return id
|
43
41
|
}
|
44
42
|
|
45
43
|
/**
|
package/index.js
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
var
|
2
|
-
|
1
|
+
var random = require('./random')
|
2
|
+
|
3
|
+
var url = '_~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
3
4
|
|
4
5
|
/**
|
5
6
|
* Generate secure URL-friendly unique ID.
|
6
7
|
*
|
7
|
-
*
|
8
|
+
* By default, ID will have 22 symbols to have same collisions probability
|
9
|
+
* as UUID v4.
|
10
|
+
*
|
11
|
+
* @param {number} [size=22] The number of symbols in ID.
|
12
|
+
*
|
13
|
+
* @return {string} Random string.
|
8
14
|
*
|
9
15
|
* @example
|
10
16
|
* var nanoid = require('nanoid')
|
@@ -12,6 +18,12 @@ var url = require('./url')
|
|
12
18
|
*
|
13
19
|
* @name nanoid
|
14
20
|
*/
|
15
|
-
module.exports = function () {
|
16
|
-
|
21
|
+
module.exports = function (size) {
|
22
|
+
size = size || 22
|
23
|
+
var id = ''
|
24
|
+
var bytes = random(size)
|
25
|
+
for (var i = 0; i < size; i++) {
|
26
|
+
id += url[bytes[i] & 63]
|
27
|
+
}
|
28
|
+
return id
|
17
29
|
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "nanoid",
|
3
|
-
"version": "0.
|
4
|
-
"description": "
|
3
|
+
"version": "0.2.2",
|
4
|
+
"description": "A tiny (179 bytes), secure URL-friendly unique string ID generator",
|
5
5
|
"keywords": [
|
6
6
|
"uuid",
|
7
7
|
"random",
|
@@ -15,32 +15,39 @@
|
|
15
15
|
"./random.js": "./random-browser.js"
|
16
16
|
},
|
17
17
|
"devDependencies": {
|
18
|
+
"benchmark": "^2.1.4",
|
19
|
+
"chalk": "^2.1.0",
|
18
20
|
"docdash": "^0.4.0",
|
19
|
-
"eslint": "^4.
|
20
|
-
"eslint-config-logux": "^16.
|
21
|
+
"eslint": "^4.8.0",
|
22
|
+
"eslint-config-logux": "^16.2.0",
|
21
23
|
"eslint-config-standard": "^10.2.1",
|
22
24
|
"eslint-plugin-es5": "^1.1.0",
|
23
25
|
"eslint-plugin-import": "^2.7.0",
|
24
|
-
"eslint-plugin-jest": "^
|
25
|
-
"eslint-plugin-node": "^5.
|
26
|
+
"eslint-plugin-jest": "^21.2.0",
|
27
|
+
"eslint-plugin-node": "^5.2.0",
|
26
28
|
"eslint-plugin-promise": "^3.5.0",
|
27
29
|
"eslint-plugin-security": "^1.4.0",
|
28
30
|
"eslint-plugin-standard": "^3.0.1",
|
29
31
|
"html-webpack-plugin": "^2.30.1",
|
30
|
-
"jest": "^
|
31
|
-
"jsdoc": "^3.5.
|
32
|
-
"lint-staged": "^4.
|
32
|
+
"jest": "^21.2.1",
|
33
|
+
"jsdoc": "^3.5.5",
|
34
|
+
"lint-staged": "^4.2.3",
|
35
|
+
"microtime": "^2.1.6",
|
33
36
|
"pre-commit": "^1.2.2",
|
34
|
-
"
|
35
|
-
"
|
36
|
-
"
|
37
|
+
"rimraf": "^2.6.2",
|
38
|
+
"shortid": "^2.2.8",
|
39
|
+
"size-limit": "^0.11.6",
|
40
|
+
"uuid": "^3.1.0",
|
41
|
+
"webpack-dev-server": "^2.9.1",
|
42
|
+
"yaspeller-ci": "^0.7.0"
|
37
43
|
},
|
38
44
|
"scripts": {
|
39
45
|
"lint-staged": "lint-staged",
|
40
46
|
"spellcheck": "yarn docs && yaspeller-ci *.md docs/*.html",
|
47
|
+
"clean": "rimraf docs/ coverage/",
|
41
48
|
"docs": "jsdoc --configure .jsdocrc *.js",
|
42
49
|
"lint": "eslint *.js test/*.js",
|
43
|
-
"test": "jest --coverage && yarn lint && yarn spellcheck
|
50
|
+
"test": "jest --coverage && yarn lint && size-limit && yarn spellcheck",
|
44
51
|
"demo": "webpack-dev-server --config test/demo/webpack.config"
|
45
52
|
},
|
46
53
|
"jest": {
|
@@ -56,7 +63,11 @@
|
|
56
63
|
"size-limit": [
|
57
64
|
{
|
58
65
|
"path": "index.js",
|
59
|
-
"limit": "
|
66
|
+
"limit": "179 B"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"path": "generate.js",
|
70
|
+
"limit": "184 B"
|
60
71
|
}
|
61
72
|
],
|
62
73
|
"lint-staged": {
|
package/random.js
CHANGED