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 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
- Very small secure URL-friendly unique ID generator.
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-strong random APIs
11
- and tests symbols distribution.
10
+ **Safe.** It uses cryptographically strong random APIs
11
+ and guarantees a proper distribution of symbols.
12
12
 
13
- **Small.** Only 258 bytes (minified and gzipped). Zero-dependency.
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 have same uniqueness in 22 symbols instead of 36.
17
+ and has the same number of unique options in just 22 symbols instead of 36.
17
18
 
18
- Generator supports Node.js and [all browsers] from IE 11.
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
- *Good article about random generators theory:
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
- Nano ID doesn’t use unsafe `Math.random()`. It use `crypto` module in Node.js
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 in ID generator. Change to get some
40
- symbols will be lower and it will reduce amount of guesses in bruteforcing.
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 use [better algorithm] and test uniformity:
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
- Main module uses URL-friendly symbols (`A-Za-z0-9_~`) and return ID
54
- with 22 characters (to have same uniqueness as UUID).
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 they could
62
- be detected as punctuation.
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 you can use low-level `generate`
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
- If you want to use same URL-friendly symbols and just change length,
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 generators by `format` module.
85
- It could be useful if you need seed-based generator.
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 of random numbers.
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 step = Math.ceil(310 / alphabet.length * size)
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 (id.length !== size) {
32
- bytes = random(step)
33
- for (var i = 0; i < bytes.length; i++) {
34
- byte = bytes[i]
35
- if (byte < alphabet.length) {
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) break
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 generate = require('./generate')
2
- var url = require('./url')
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
- * @return {string} Random string with 22 URL-friendly symbols.
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
- return generate(url, 22)
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.1.0",
4
- "description": "Very small secure URL-friendly unique ID generator",
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.4.0",
20
- "eslint-config-logux": "^16.0.0",
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": "^20.0.3",
25
- "eslint-plugin-node": "^5.1.1",
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": "^20.0.4",
31
- "jsdoc": "^3.5.4",
32
- "lint-staged": "^4.0.2",
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
- "size-limit": "^0.8.0",
35
- "webpack-dev-server": "^2.6.1",
36
- "yaspeller-ci": "^0.6.0"
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 && size-limit",
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": "260 B"
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
@@ -1,5 +1 @@
1
- var randomBytes = require('crypto').randomBytes
2
-
3
- module.exports = function (bytes) {
4
- return randomBytes(bytes)
5
- }
1
+ module.exports = require('crypto').randomBytes