nanoid 1.3.4 → 2.0.3

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,6 +1,20 @@
1
1
  # Change Log
2
2
  This project adheres to [Semantic Versioning](http://semver.org/).
3
3
 
4
+ ## 2.0.3
5
+ * Fix freeze on string in ID length.
6
+
7
+ ## 2.0.2
8
+ * Improve docs (by Sylvanus Kateile and Mark Stosberg).
9
+
10
+ ## 2.0.1
11
+ * Reduce npm package size.
12
+ * Mark package as not having side effects (by @xiaody).
13
+
14
+ ## 2.0
15
+ * Use `-` instead of `~` in default alphabet to by file name safe.
16
+ * Add `nanoid/non-secure/generate`.
17
+
4
18
  ## 1.3.4
5
19
  * Reduce `non-secure` size.
6
20
  * Add `async` callback type check.
package/README.md CHANGED
@@ -5,17 +5,17 @@
5
5
 
6
6
  A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
7
7
 
8
- * **Small.** 142 bytes (minified and gzipped). No dependencies.
9
- It uses [Size Limit] to control size.
8
+ * **Small.** 141 bytes (minified and gzipped). No dependencies.
9
+ [Size Limit] controls the size.
10
10
  * **Safe.** It uses cryptographically strong random APIs
11
11
  and tests distribution of symbols.
12
12
  * **Fast.** It’s 16% faster than UUID.
13
- * **Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_~`).
13
+ * **Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`).
14
14
  So ID size was reduced from 36 to 21 symbols.
15
15
 
16
16
  ```js
17
17
  var nanoid = require('nanoid')
18
- model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B~myT"
18
+ model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
19
19
  ```
20
20
 
21
21
  The generator supports Node.js, React Native, and [all browsers].
@@ -29,6 +29,47 @@ The generator supports Node.js, React Native, and [all browsers].
29
29
  </a>
30
30
 
31
31
 
32
+ ## Comparison with UUID
33
+
34
+ Nano ID is quite comparable to UUID v4 (random-based).
35
+ It has a similar number of random bits in the ID
36
+ (126 in Nano ID and 122 in UUID), so it has a similar collision probability:
37
+
38
+ > For there to be a one in a billion chance of duplication,
39
+ > 103 trillion version 4 IDs must be generated.
40
+
41
+ There are three main differences between Nano ID and UUID v4:
42
+
43
+ 1. Nano ID uses a bigger alphabet, so a similar number of random bits
44
+ are packed in just 21 symbols instead of 36.
45
+ 2. Nano ID code is 3 times less than `uuid/v4` package:
46
+ 141 bytes instead of 435.
47
+ 3. Because of memory allocation tricks, Nano ID 16% faster than UUID.
48
+
49
+
50
+ ## Benchmark
51
+
52
+ ```rust
53
+ $ ./test/benchmark
54
+ nanoid 693,132 ops/sec
55
+ nanoid/generate 624,291 ops/sec
56
+ uid.sync 487,706 ops/sec
57
+ uuid/v4 471,299 ops/sec
58
+ secure-random-string 448,386 ops/sec
59
+ shortid 66,809 ops/sec
60
+
61
+ Async:
62
+ nanoid/async 105,024 ops/sec
63
+ nanoid/async/generate 106,682 ops/sec
64
+ secure-random-string 94,217 ops/sec
65
+ uid 92,026 ops/sec
66
+
67
+ Non-secure:
68
+ nanoid/non-secure 2,555,814 ops/sec
69
+ rndm 2,413,565 ops/sec
70
+ ```
71
+
72
+
32
73
  ## Security
33
74
 
34
75
  *See a good article about random generators theory:
@@ -58,64 +99,56 @@ Nano ID uses a [better algorithm] and is tested for uniformity.
58
99
  [better algorithm]: https://github.com/ai/nanoid/blob/master/format.js
59
100
 
60
101
 
61
- ## Comparison with UUID
62
-
63
- Nano ID is quite comparable to UUID v4 (random-based).
64
- It has a similar number of random bits in the ID
65
- (126 in Nano ID and 122 in UUID), so it has a similar collision probability:
66
-
67
- > For there to be a one in a billion chance of duplication,
68
- > 103 trillion version 4 IDs must be generated.
102
+ ## Tools
69
103
 
70
- There are two main differences between Nano ID and UUID v4:
104
+ * [ID size calculator] to choice smaller ID size depends on your case.
105
+ * [`nanoid-dictionary`] with popular alphabets to use with `nanoid/generate`.
106
+ * [`nanoid-cli`] to generate ID from CLI.
107
+ * [`nanoid-good`] to be sure that your ID doesn't contain any obscene words.
71
108
 
72
- 1. Nano ID uses a bigger alphabet, so a similar number of random bits
73
- are packed in just 21 symbols instead of 36.
74
- 2. Nano ID code is 3 times less than `uuid/v4` package:
75
- 142 bytes instead of 435.
109
+ [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
110
+ [ID size calculator]: https://zelark.github.io/nano-id-cc/
111
+ [`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli
112
+ [`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good
76
113
 
77
114
 
78
- ## Benchmark
115
+ ## Other Programming Languages
79
116
 
80
- ```rust
81
- $ ./test/benchmark
82
- nanoid 413,579 ops/sec
83
- nanoid/generate 401,349 ops/sec
84
- uid.sync 354,882 ops/sec
85
- uuid/v4 353,836 ops/sec
86
- shortid 39,152 ops/sec
117
+ * [C#](https://github.com/codeyu/nanoid-net)
118
+ * [Clojure and ClojureScript](https://github.com/zelark/nano-id)
119
+ * [Crystal](https://github.com/mamantoha/nanoid.cr)
120
+ * [Dart](https://github.com/pd4d10/nanoid)
121
+ * [Go](https://github.com/matoous/go-nanoid)
122
+ * [Elixir](https://github.com/railsmechanic/nanoid)
123
+ * [Haskell](https://github.com/4e6/nanoid-hs)
124
+ * [Java](https://github.com/aventrix/jnanoid)
125
+ * [Nim](https://github.com/icyphox/nanoid.nim)
126
+ * [PHP](https://github.com/hidehalo/nanoid-php)
127
+ * [Python](https://github.com/puyuan/py-nanoid) with [dictionaries](https://github.com/aidarkhanov/py-nanoid-dictionary)
128
+ * [Ruby](https://github.com/radeno/nanoid.rb)
129
+ * [Rust](https://github.com/nikolay-govorov/nanoid)
130
+ * [Swift](https://github.com/antiflasher/NanoID)
87
131
 
88
- Async:
89
- nanoid/async 85,168 ops/sec
90
- nanoid/async/generate 81,037 ops/sec
91
- uid 78,426 ops/sec
132
+ Also, [CLI tool] is available to generate IDs from a command line.
92
133
 
93
- Non-secure:
94
- nanoid/non-secure 2,718,186 ops/sec
95
- rndm 2,544,612 ops/sec
96
- ```
134
+ [CLI tool]: https://github.com/twhitbeck/nanoid-cli
97
135
 
98
136
 
99
137
  ## Usage
100
138
 
101
- ### Normal
102
-
103
- The main module uses URL-friendly symbols (`A-Za-z0-9_~`) and returns an ID
139
+ The main module uses URL-friendly symbols (`A-Za-z0-9_-`) and returns an ID
104
140
  with 21 characters (to have a collision probability similar to UUID v4).
105
141
 
106
142
  ```js
107
143
  const nanoid = require('nanoid')
108
- model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
144
+ model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
109
145
  ```
110
146
 
111
- Symbols `-,.()` are not encoded in the URL. If used at the end of a link
112
- they could be identified as a punctuation symbol.
113
-
114
147
  If you want to reduce ID length (and increase collisions probability),
115
148
  you can pass the length as an argument.
116
149
 
117
150
  ```js
118
- nanoid(10) //=> "IRFa~VaY2b"
151
+ nanoid(10) //=> "IRFa-VaY2b"
119
152
  ```
120
153
 
121
154
  Don’t forget to check the safety of your ID length
@@ -123,6 +156,30 @@ in our [ID collision probability] calculator.
123
156
 
124
157
  [ID collision probability]: https://zelark.github.io/nano-id-cc/
125
158
 
159
+ ### React
160
+
161
+ **Do not** use a nanoid for `key` prop. In React `key` should be consistence
162
+ between renders. This is bad code:
163
+
164
+ ```jsx
165
+ <Item key={nanoid()} /> /* DON’T DO IT */
166
+ ```
167
+
168
+ This is good code. Note, that we added `"input"` string in front of `id`,
169
+ because Nano ID could be started from number. HTML ID can’t be started
170
+ from the number.
171
+
172
+ ```jsx
173
+ id = 'input' + nanoid()
174
+
175
+ render () {
176
+ return <>
177
+ <label htmlFor={this.id}>Label text</label>
178
+ <input id={this.id} type="text"/>
179
+ </>;
180
+ }
181
+ }
182
+ ```
126
183
 
127
184
  ### React Native
128
185
 
@@ -142,6 +199,18 @@ async function createUser () {
142
199
  [a native random generator]: https://github.com/rh389/react-native-securerandom
143
200
 
144
201
 
202
+ ### Mongoose
203
+
204
+ ```js
205
+ const mySchema = new Schema({
206
+ _id: {
207
+ type: String,
208
+ default: () => nanoid(10)
209
+ }
210
+ })
211
+ ```
212
+
213
+
145
214
  ### Web Workers
146
215
 
147
216
  Web Workers don’t have access to a secure random generator.
@@ -154,11 +223,11 @@ you can use non‑secure ID generator.
154
223
 
155
224
  ```js
156
225
  const nanoid = require('nanoid/non-secure')
157
- model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqLJ"
226
+ model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
158
227
  ```
159
228
 
160
229
 
161
- ## Async
230
+ ### Async
162
231
 
163
232
  To generate hardware random bytes, CPU will collect electromagnetic noise.
164
233
  During the collection, CPU doesn’t work.
@@ -178,7 +247,7 @@ Unfortunately, you will not have any benefits in a browser, since Web Crypto A
178
247
  doesn’t have asynchronous API.
179
248
 
180
249
 
181
- ## Custom Alphabet or Length
250
+ ### Custom Alphabet or Length
182
251
 
183
252
  If you want to change the ID's alphabet or length
184
253
  you can use the low-level `generate` module.
@@ -195,7 +264,7 @@ You can find popular alphabets in [`nanoid-dictionary`].
195
264
  Alphabet must contain 256 symbols or less.
196
265
  Otherwise, the generator will not be secure.
197
266
 
198
- Asynchronous API is also available:
267
+ Asynchronous and non-secure API is also available:
199
268
 
200
269
  ```js
201
270
  const generate = require('nanoid/async/generate')
@@ -204,11 +273,17 @@ async function createUser () {
204
273
  }
205
274
  ```
206
275
 
276
+ ```js
277
+ const generate = require('nanoid/non-secure/generate')
278
+
279
+ user.id = generate('1234567890abcdef', 10)
280
+ ```
281
+
207
282
  [ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/
208
283
  [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
209
284
 
210
285
 
211
- ## Custom Random Bytes Generator
286
+ ### Custom Random Bytes Generator
212
287
 
213
288
  You can replace the default safe random generator using the `format` module.
214
289
  For instance, to use a seed-based generator.
@@ -252,38 +327,3 @@ async function createUser () {
252
327
  user.id = await format(random, url, 10)
253
328
  }
254
329
  ```
255
-
256
-
257
- ## Tools
258
-
259
- * [ID size calculator] to choice smaller ID size depends on your case.
260
- * [`nanoid-dictionary`] with popular alphabets to use with `nanoid/generate`.
261
- * [`nanoid-cli`] to generate ID from CLI.
262
- * [`nanoid-good`] to be sure that your ID doesn't contain any obscene words.
263
-
264
- [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
265
- [ID size calculator]: https://zelark.github.io/nano-id-cc/
266
- [`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli
267
- [`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good
268
-
269
-
270
- ## Other Programming Languages
271
-
272
- * [C#](https://github.com/codeyu/nanoid-net)
273
- * [Clojure and ClojureScript](https://github.com/zelark/nano-id)
274
- * [Crystal](https://github.com/mamantoha/nanoid.cr)
275
- * [Dart](https://github.com/pd4d10/nanoid)
276
- * [Go](https://github.com/matoous/go-nanoid)
277
- * [Elixir](https://github.com/railsmechanic/nanoid)
278
- * [Haskell](https://github.com/4e6/nanoid-hs)
279
- * [Java](https://github.com/aventrix/jnanoid)
280
- * [Nim](https://github.com/icyphox/nanoid.nim)
281
- * [PHP](https://github.com/hidehalo/nanoid-php)
282
- * [Python](https://github.com/puyuan/py-nanoid)
283
- * [Ruby](https://github.com/radeno/nanoid.rb)
284
- * [Rust](https://github.com/nikolay-govorov/nanoid)
285
- * [Swift](https://github.com/antiflasher/NanoID)
286
-
287
- Also, [CLI tool] is available to generate IDs from a command line.
288
-
289
- [CLI tool]: https://github.com/twhitbeck/nanoid-cli
package/async/format.js CHANGED
@@ -31,6 +31,7 @@
31
31
  module.exports = function (random, alphabet, size) {
32
32
  var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1
33
33
  var step = Math.ceil(1.6 * mask * size / alphabet.length)
34
+ size = +size
34
35
 
35
36
  function tick (id) {
36
37
  return random(step).then(function (bytes) {
@@ -1,10 +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.
4
+ * This alphabet uses a-z A-Z 0-9 _- symbols.
5
5
  * Symbols order was changed for better gzip compression.
6
6
  */
7
- var url = 'ModuleSymbhasOwnPr0123456789ABCDEFGHIJKLNQRTUVWXYZ_cfgijkpqtvxz~'
7
+ var url = 'Uint8ArModuleSymbhasOw-012345679BCDEFGHIJKLNPQRTVWXYZ_cfgjkpqvxz'
8
8
 
9
9
  module.exports = function (size) {
10
10
  size = size || 21
package/async/index.js CHANGED
@@ -1,16 +1,6 @@
1
- var crypto = require('crypto')
2
-
1
+ var random = require('./random')
3
2
  var url = require('../url')
4
3
 
5
- var random
6
- if (crypto.randomFill) {
7
- random = function (bytes, callback) {
8
- return crypto.randomFill(Buffer.allocUnsafe(bytes), callback)
9
- }
10
- } else {
11
- random = crypto.randomBytes
12
- }
13
-
14
4
  /**
15
5
  * Generate secure URL-friendly unique ID. Non-blocking version.
16
6
  *
@@ -18,7 +8,6 @@ if (crypto.randomFill) {
18
8
  * to UUID v4.
19
9
  *
20
10
  * @param {number} [size=21] The number of symbols in ID.
21
- * @param {function} [callback] for environments without `Promise`.
22
11
  *
23
12
  * @return {Promise} Promise with random string.
24
13
  *
@@ -31,41 +20,13 @@ if (crypto.randomFill) {
31
20
  * @name async
32
21
  * @function
33
22
  */
34
- module.exports = function (size, callback, attempt) {
23
+ module.exports = function (size) {
35
24
  size = size || 21
36
-
37
- if (!callback) {
38
- if (typeof Promise !== 'function') {
39
- throw new TypeError('Function callback is required')
40
- }
41
- return new Promise(function (resolve, reject) {
42
- module.exports(size, function (error, id) {
43
- if (error) {
44
- reject(error)
45
- } else {
46
- resolve(id)
47
- }
48
- })
49
- })
50
- } else if (typeof callback !== 'function') {
51
- throw new TypeError('Callback is not a function')
52
- }
53
-
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)
25
+ return random(size).then(function (bytes) {
26
+ var id = ''
27
+ while (0 < size--) {
28
+ id += url[bytes[size] & 63]
69
29
  }
30
+ return id
70
31
  })
71
32
  }
package/format.js CHANGED
@@ -29,6 +29,7 @@
29
29
  module.exports = function (random, alphabet, size) {
30
30
  var mask = (2 << Math.log(alphabet.length - 1) / Math.LN2) - 1
31
31
  var step = Math.ceil(1.6 * mask * size / alphabet.length)
32
+ size = +size
32
33
 
33
34
  var id = ''
34
35
  while (true) {
package/index.browser.js CHANGED
@@ -10,10 +10,10 @@ if (process.env.NODE_ENV !== 'production') {
10
10
  var crypto = self.crypto || self.msCrypto
11
11
 
12
12
  /*
13
- * This alphabet uses a-z A-Z 0-9 _~ symbols.
13
+ * This alphabet uses a-z A-Z 0-9 _- symbols.
14
14
  * Symbols order was changed for better gzip compression.
15
15
  */
16
- var url = 'Uint8ArdomValuesObj012345679BCDEFGHIJKLMNPQRSTWXYZ_cfghkpqvwxyz~'
16
+ var url = 'Uint8ArdomValuesObj012345679BCDEFGHIJKLMNPQRSTWXYZ_cfghkpqvwxyz-'
17
17
 
18
18
  module.exports = function (size) {
19
19
  size = size || 21
package/index.js CHANGED
@@ -13,31 +13,17 @@ var url = require('./url')
13
13
  *
14
14
  * @example
15
15
  * const nanoid = require('nanoid')
16
- * model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqL"
16
+ * model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
17
17
  *
18
18
  * @name nanoid
19
19
  * @function
20
20
  */
21
- module.exports = function (size, attempt) {
21
+ module.exports = function (size) {
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
+ var bytes = random(size)
37
24
  var id = ''
38
25
  while (0 < size--) {
39
26
  id += url[bytes[size] & 63]
40
27
  }
41
-
42
28
  return id
43
29
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generate URL-friendly unique ID. This method use non-secure predictable
3
+ * random generator.
4
+ *
5
+ * By default, ID will have 21 symbols to have a collision probability similar
6
+ * to UUID v4.
7
+ *
8
+ * @param {string} alphabet Symbols to be used in ID.
9
+ * @param {number} [size=21] The number of symbols in ID.
10
+ *
11
+ * @return {string} Random string.
12
+ *
13
+ * @example
14
+ * const nanoid = require('nanoid/non-secure')
15
+ * model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
16
+ *
17
+ * @name nonSecure
18
+ * @function
19
+ */
20
+ module.exports = function (alphabet, size) {
21
+ size = size || 21
22
+ var id = ''
23
+ while (0 < size--) {
24
+ id += alphabet[Math.random() * alphabet.length | 0]
25
+ }
26
+ return id
27
+ }
@@ -1,4 +1,4 @@
1
- var url = 'bjectxporhasOwnP0123456789ABCDEFGHIJKLMNQRSTUVWXYZ_dfgiklmquvyz~'
1
+ var url = 'bjectSymhasOwnProp-0123456789ABCDEFGHIJKLMNQRTUVWXYZ_dfgiklquvxz'
2
2
 
3
3
  /**
4
4
  * Generate URL-friendly unique ID. This method use non-secure predictable
@@ -13,7 +13,7 @@ var url = 'bjectxporhasOwnP0123456789ABCDEFGHIJKLMNQRSTUVWXYZ_dfgiklmquvyz~'
13
13
  *
14
14
  * @example
15
15
  * const nanoid = require('nanoid/non-secure')
16
- * model.id = nanoid() //=> "Uakgb_J5m9g~0JDMbcJqL"
16
+ * model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
17
17
  *
18
18
  * @name nonSecure
19
19
  * @function
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nanoid",
3
- "version": "1.3.4",
4
- "description": "A tiny (143 bytes), secure URL-friendly unique string ID generator",
3
+ "version": "2.0.3",
4
+ "description": "A tiny (141 bytes), secure URL-friendly unique string ID generator",
5
5
  "keywords": [
6
6
  "uuid",
7
7
  "random",
@@ -17,9 +17,5 @@
17
17
  "./async/index.js": "./async/index.browser.js",
18
18
  "./async/random.js": "./async/random.browser.js"
19
19
  },
20
- "husky": {
21
- "hooks": {
22
- "pre-commit": "lint-staged"
23
- }
24
- }
20
+ "sideEffects": false
25
21
  }
package/url.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * URL safe symbols.
3
3
  *
4
- * This alphabet uses a-z A-Z 0-9 _~ symbols.
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
@@ -12,4 +12,4 @@
12
12
  * generate(url, 10) //=> "Uakgb_J5m9"
13
13
  */
14
14
  module.exports =
15
- 'SymboljecthasOwnPr0123456789ABCDEFGHIJKLMNQRTUVWXYZ_dfgikpquvxz~'
15
+ 'ModuleSymbhasOwnPr-0123456789ABCDEFGHIJKLNQRTUVWXYZ_cfgijkpqtvxz'