1 | # Short Unique ID (UUID) Generating Library
|
---|
2 | 
|
---|
3 | [](https://npm.runkit.com/short-unique-id)
|
---|
4 | [](https://npmjs.com/package/short-unique-id)
|
---|
5 | [](https://www.jsdelivr.com/package/npm/short-unique-id)
|
---|
6 |
|
---|
7 | <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
---|
8 | [](#contributors)
|
---|
9 | <!-- ALL-CONTRIBUTORS-BADGE:END -->
|
---|
10 |
|
---|
11 | ---
|
---|
12 |
|
---|
13 | Tiny (6.7kB minified) no-dependency library for generating random or sequential UUID of any length
|
---|
14 | with exceptionally minuscule probabilies of duplicate IDs.
|
---|
15 |
|
---|
16 | ```ts
|
---|
17 | const uid = new ShortUniqueId({ length: 10 });
|
---|
18 | uid.rnd(); // p0ZoB1FwH6
|
---|
19 | uid.rnd(); // mSjGCTfn8w
|
---|
20 | uid.rnd(); // yt4Xx5nHMB
|
---|
21 | // ...
|
---|
22 |
|
---|
23 | // or
|
---|
24 |
|
---|
25 | const { randomUUID } = new ShortUniqueId({ length: 10 });
|
---|
26 | randomUUID(); // e8Civ0HoDy
|
---|
27 | randomUUID(); // iPjiGoHXAK
|
---|
28 | randomUUID(); // n528gSMwTN
|
---|
29 | // ...
|
---|
30 | ```
|
---|
31 |
|
---|
32 | For example, using the default dictionary of numbers and letters (lower and upper case):
|
---|
33 |
|
---|
34 | ```ts
|
---|
35 | 0,1,2,3,4,5,6,7,8,9,
|
---|
36 | a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
|
---|
37 | A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
|
---|
38 | ```
|
---|
39 |
|
---|
40 | - if you generate a unique ID of 16 characters (half of the standard UUID of 32 characters)
|
---|
41 | - generating 100 unique IDs **per second**
|
---|
42 |
|
---|
43 | #### It would take **~10 thousand years** to have a 1% probability of at least one collision!
|
---|
44 |
|
---|
45 | To put this into perspective:
|
---|
46 |
|
---|
47 | - 73 years is the (global) average life expectancy of a human being
|
---|
48 | - 120 years ago no human ever had set foot on either of the Earth's poles
|
---|
49 | - 480 years ago Nicolaus Copernicus was still working on his theory of the Earth revolving around the Sun
|
---|
50 | - 1000 years ago there was no such thing as government-issued paper money (and wouldn't be for about a century)
|
---|
51 | - 5000 years ago the global population of humans was under 50 million (right now Mexico has a population of 127 million)
|
---|
52 |
|
---|
53 | You can calculate duplicate/collision probabilities using the included functions:
|
---|
54 |
|
---|
55 | - [availableUUIDs()](https://shortunique.id/classes/default.html#availableuuids)
|
---|
56 | - [approxMaxBeforeCollision()](https://shortunique.id/classes/default.html#approxmaxbeforecollision)
|
---|
57 | - [collisionProbability()](https://shortunique.id/classes/default.html#collisionprobability)
|
---|
58 |
|
---|
59 | _NOTE: 👆 On these links you will also find explanations for the math used within the functions._
|
---|
60 |
|
---|
61 | ---
|
---|
62 |
|
---|
63 | ## Open source notice
|
---|
64 |
|
---|
65 | This project is part of the [Open Collective](https://opencollective.com/simplyhexagonal) project [Simply Hexagonal](https://simplyhexagonal.org)
|
---|
66 | and is open to updates by its users, we ensure that PRs are relevant to the community.
|
---|
67 | In other words, if you find a bug or want a new feature, please help us by becoming one of the
|
---|
68 | [contributors](#contributors-) ✌️ ! See the [contributing section](#contributing).
|
---|
69 |
|
---|
70 | ## Like this module? ❤
|
---|
71 |
|
---|
72 | Please consider:
|
---|
73 |
|
---|
74 | - [Buying me a coffee](https://www.buymeacoffee.com/jeanlescure) ☕
|
---|
75 | - Supporting me on [Patreon](https://www.patreon.com/jeanlescure) 🏆
|
---|
76 | - Starring this repo on [Github](https://github.com/jeanlescure/short-unique-id) 🌟
|
---|
77 |
|
---|
78 | ## 📣 v5 Notice
|
---|
79 |
|
---|
80 | In order to improve security compliance we have removed the ability to use a ShortUniqueId as a
|
---|
81 | function, i.e. `const uid = new ShortUniqueId(); uid();` is no longer supported.
|
---|
82 |
|
---|
83 | If you plan to upgrade to v5 make sure to refactor `uid();` to `uid.rnd();` in your code beforehand.
|
---|
84 |
|
---|
85 | For more information regarding this decision you can view [issue #53](https://github.com/simplyhexagonal/short-unique-id/issues/53).
|
---|
86 |
|
---|
87 | ### Features
|
---|
88 |
|
---|
89 | The ability to generate UUIDs that contain a timestamp which can be extracted:
|
---|
90 |
|
---|
91 | ```js
|
---|
92 | // js/ts
|
---|
93 |
|
---|
94 | const uid = new ShortUniqueId();
|
---|
95 |
|
---|
96 | const uidWithTimestamp = uid.stamp(32);
|
---|
97 | console.log(uidWithTimestamp);
|
---|
98 | // GDa608f973aRCHLXQYPTbKDbjDeVsSb3
|
---|
99 |
|
---|
100 | const recoveredTimestamp = uid.parseStamp(uidWithTimestamp);
|
---|
101 | console.log(recoveredTimestamp);
|
---|
102 | // 2021-05-03T06:24:58.000Z
|
---|
103 | ```
|
---|
104 |
|
---|
105 | ```bash
|
---|
106 | # cli
|
---|
107 |
|
---|
108 | $ suid -s -l 42
|
---|
109 |
|
---|
110 | lW611f30a2ky4276g3l8N7nBHI5AQ5rCiwYzU47HP2
|
---|
111 |
|
---|
112 | $ suid -p lW611f30a2ky4276g3l8N7nBHI5AQ5rCiwYzU47HP2
|
---|
113 |
|
---|
114 | 2021-08-20T04:33:38.000Z
|
---|
115 | ```
|
---|
116 |
|
---|
117 | Default dictionaries (generated on the spot to reduce memory footprint and
|
---|
118 | avoid dictionary injection vulnerabilities):
|
---|
119 |
|
---|
120 | - number
|
---|
121 | - alpha
|
---|
122 | - alpha_lower
|
---|
123 | - alpha_upper
|
---|
124 | - **alphanum** _(default when no dictionary is provided to `new ShortUniqueId()`)_
|
---|
125 | - alphanum_lower
|
---|
126 | - alphanum_upper
|
---|
127 | - hex
|
---|
128 |
|
---|
129 | ```js
|
---|
130 | // instantiate using one of the default dictionary strings
|
---|
131 | const uid = new ShortUniqueId({
|
---|
132 | dictionary: 'hex',
|
---|
133 | });
|
---|
134 |
|
---|
135 | console.log(uid.dict.join());
|
---|
136 | // 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
|
---|
137 |
|
---|
138 | // or change the dictionary after instantiation
|
---|
139 | uid.setDictionary('alpha_upper');
|
---|
140 |
|
---|
141 | console.log(uid.dict.join());
|
---|
142 | // A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
|
---|
143 | ```
|
---|
144 |
|
---|
145 | Ability to use custom formatting.
|
---|
146 |
|
---|
147 | Where `$r` is random UUID, `$s` is sequential UUID, and `$t` is timestamp UUID:
|
---|
148 |
|
---|
149 | ```js
|
---|
150 | const timestamp = new Date('2023-01-29T03:21:21.000Z');
|
---|
151 | const result = uid.formattedUUID('Time: $t0 ID: $s2-$r4', timestamp); // timestamp is optional
|
---|
152 |
|
---|
153 | console.log(result);
|
---|
154 | // Time: 63d5e631 ID: 0b-aaab
|
---|
155 | ```
|
---|
156 |
|
---|
157 | ### Use in CLI
|
---|
158 |
|
---|
159 | ```sh
|
---|
160 | $ npm install --global short-unique-id
|
---|
161 |
|
---|
162 | $ suid -h
|
---|
163 |
|
---|
164 | # Usage:
|
---|
165 | # node short-unique-id [OPTION]
|
---|
166 | #
|
---|
167 | # Options:
|
---|
168 | # -l, --length=ARG character length of the uid to generate.
|
---|
169 | # -s, --stamp include timestamp in uid (must be used with --length (-l) of 10 or more).
|
---|
170 | # -t, --timestamp=ARG custom timestamp to parse (must be used along with -s, --stamp, -f, or --format).
|
---|
171 | # -f, --format=ARG string representing custom format to generate id with.
|
---|
172 | # -p, --parse=ARG extract timestamp from stamped uid (ARG).
|
---|
173 | # -d, --dictionaryJson=ARG json file with dictionary array.
|
---|
174 | # -h, --help display this help
|
---|
175 | ```
|
---|
176 |
|
---|
177 | ### Use as module
|
---|
178 |
|
---|
179 | Add to your project:
|
---|
180 |
|
---|
181 | ```js
|
---|
182 | // ES6 / TypeScript Import
|
---|
183 | import ShortUniqueId from 'short-unique-id';
|
---|
184 |
|
---|
185 | // Node.js require
|
---|
186 | const ShortUniqueId = require('short-unique-id');
|
---|
187 |
|
---|
188 | // Deno (web module) Import
|
---|
189 | import ShortUniqueId from 'https://esm.sh/short-unique-id';
|
---|
190 | ```
|
---|
191 |
|
---|
192 | Instantiate and use:
|
---|
193 |
|
---|
194 | ```js
|
---|
195 | //Instantiate
|
---|
196 | const uid = new ShortUniqueId();
|
---|
197 |
|
---|
198 | // Random UUID
|
---|
199 | console.log(uid.rnd());
|
---|
200 |
|
---|
201 | // Sequential UUID
|
---|
202 | console.log(uid.seq());
|
---|
203 | ```
|
---|
204 |
|
---|
205 | alternatively using destructuring assignment:
|
---|
206 |
|
---|
207 | ```js
|
---|
208 | // Instantiate and destructure (long method name recommended for code readability)
|
---|
209 | const { randomUUID, sequentialUUID } = new ShortUniqueId();
|
---|
210 |
|
---|
211 | // Random UUID
|
---|
212 | console.log(randomUUID());
|
---|
213 |
|
---|
214 | // Sequential UUID
|
---|
215 | console.log(sequentialUUID());
|
---|
216 | ```
|
---|
217 |
|
---|
218 | _NOTE:_ we made sure to use `bind()` on all ShortUniqueId methods to ensure that any options
|
---|
219 | passed when creating the instance will be respected by the destructured methods.
|
---|
220 |
|
---|
221 | ### Use in browser
|
---|
222 |
|
---|
223 | ```html
|
---|
224 | <!-- Add source (minified 4.6kB) -->
|
---|
225 | <script src="https://cdn.jsdelivr.net/npm/short-unique-id@latest/dist/short-unique-id.min.js"></script>
|
---|
226 |
|
---|
227 | <!-- Usage -->
|
---|
228 | <script>
|
---|
229 | // Instantiate
|
---|
230 | var uid = new ShortUniqueId();
|
---|
231 |
|
---|
232 | // Random UUID
|
---|
233 | document.write(uid.rnd());
|
---|
234 |
|
---|
235 | // Sequential UUID
|
---|
236 | document.write(uid.seq());
|
---|
237 | </script>
|
---|
238 | ```
|
---|
239 |
|
---|
240 | ### Options
|
---|
241 |
|
---|
242 | Options can be passed when instantiating `uid`:
|
---|
243 |
|
---|
244 | ```js
|
---|
245 | const options = { ... };
|
---|
246 |
|
---|
247 | const uid = new ShortUniqueId(options);
|
---|
248 | ```
|
---|
249 |
|
---|
250 | For more information take a look at the [docs](https://shortunique.id/interfaces/shortuniqueidoptions.html).
|
---|
251 |
|
---|
252 | ## Available for
|
---|
253 |
|
---|
254 | - [Node.js (npm)](https://www.npmjs.com/package/short-unique-id)
|
---|
255 | - [Deno](https://esm.sh/short-unique-id)
|
---|
256 | - [Browsers](https://www.jsdelivr.com/package/npm/short-unique-id?path=dist)
|
---|
257 |
|
---|
258 | ## Documentation with Online Short UUID Generator
|
---|
259 |
|
---|
260 | You can find the docs and online generator at:
|
---|
261 |
|
---|
262 | <a target="_blank" href="https://shortunique.id">https://shortunique.id</a>
|
---|
263 |
|
---|
264 | ## What is the probability of generating the same id again?
|
---|
265 |
|
---|
266 | This largely depends on the given dictionary and the selected UUID length.
|
---|
267 |
|
---|
268 | Out of the box this library provides a shuffled dictionary of digits from
|
---|
269 | 0 to 9, as well as the alphabet from a to z both in UPPER and lower case,
|
---|
270 | with a default UUID length of 6. That gives you a total of 56,800,235,584
|
---|
271 | possible UUIDs.
|
---|
272 |
|
---|
273 | So, given the previous values, the probability of generating a duplicate
|
---|
274 | in 1,000,000 rounds is ~0.00000002, or about 1 in 50,000,000.
|
---|
275 |
|
---|
276 | If you change the dictionary and/or the UUID length then we have provided
|
---|
277 | the function `collisionProbability()` function to calculate the probability
|
---|
278 | of hitting a duplicate in a given number of rounds (a collision) and the
|
---|
279 | function `uniqueness()` which provides a score (from 0 to 1) to rate the
|
---|
280 | "quality" of the combination of given dictionary and UUID length (the closer
|
---|
281 | to 1, higher the uniqueness and thus better the quality).
|
---|
282 |
|
---|
283 | To find out more about the math behind these functions please refer to the
|
---|
284 | <a target="_blank" href="https://shortunique.id/classes/default.html#collisionprobability">API Reference</a>.
|
---|
285 |
|
---|
286 | ## Acknowledgement and platform support
|
---|
287 |
|
---|
288 | This repo and npm package started as a straight up manual transpilation to ES6 of the [short-uid](https://github.com/serendipious/nodejs-short-uid) npm package by [Ankit Kuwadekar](https://github.com/serendipious/).
|
---|
289 |
|
---|
290 | 
|
---|
291 | 
|
---|
292 |
|
---|
293 | Since this package is now reporting 200k+ npm weekly downloads and 16M+ weekly cdn hits,
|
---|
294 | we've gone ahead and re-written the whole of it in TypeScript and made sure to package
|
---|
295 | dist modules compatible with Deno, Node.js and all major Browsers.
|
---|
296 |
|
---|
297 | ## Sponsors
|
---|
298 |
|
---|
299 | - [Clever Synapse](https://cleversynapse.com)
|
---|
300 |
|
---|
301 | ## Development
|
---|
302 |
|
---|
303 | Clone this repo:
|
---|
304 |
|
---|
305 | ```sh
|
---|
306 | # SSH
|
---|
307 | git clone git@github.com:jeanlescure/short-unique-id.git
|
---|
308 |
|
---|
309 | # HTTPS
|
---|
310 | git clone https://github.com/jeanlescure/short-unique-id.git
|
---|
311 | ```
|
---|
312 |
|
---|
313 | Tests run using:
|
---|
314 |
|
---|
315 | ```
|
---|
316 | pnpm test
|
---|
317 | ```
|
---|
318 |
|
---|
319 | ## Build
|
---|
320 |
|
---|
321 | In order to publish the latest changes you must build the distribution files:
|
---|
322 |
|
---|
323 | ```
|
---|
324 | pnpm build
|
---|
325 | ```
|
---|
326 |
|
---|
327 | Then commit all changes and run the release script:
|
---|
328 |
|
---|
329 | ```
|
---|
330 | pnpm release
|
---|
331 | ```
|
---|
332 |
|
---|
333 | ## Contributing
|
---|
334 |
|
---|
335 | Yes, thank you! This plugin is community-driven, most of its features are from different authors.
|
---|
336 | Please update the docs and tests and add your name to the `package.json` file.
|
---|
337 |
|
---|
338 | ## Contributors ✨
|
---|
339 |
|
---|
340 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
---|
341 |
|
---|
342 | <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
---|
343 | <!-- prettier-ignore-start -->
|
---|
344 | <!-- markdownlint-disable -->
|
---|
345 | <table>
|
---|
346 | <tr>
|
---|
347 | <td align="center"><a href="https://github.com/serendipious"><img src="https://shortunique.id/assets/contributors/serendipious.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/commits?author=serendipious" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
348 | <td align="center"><a href="https://jeanlescure.cr"><img src="https://shortunique.id/assets/contributors/jeanlescure.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="#maintenance-jeanlescure" title="Maintenance">🚧</a> <a href="https://github.com/jeanlescure/short-unique-id/commits?author=jeanlescure" title="Code">💻</a> <a href="https://github.com/jeanlescure/short-unique-id/commits?author=jeanlescure" title="Documentation">📖</a> <a href="https://github.com/jeanlescure/short-unique-id/commits?author=jeanlescure" title="Tests">⚠️</a></td></tr></tbody></table></td>
|
---|
349 | <td align="center"><a href="https://dianalu.design"><img src="https://shortunique.id/assets/contributors/dilescure.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short_uuid/commits?author=DiLescure" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
350 | <td align="center"><a href="https://github.com/EmerLM"><img src="https://shortunique.id/assets/contributors/emerlm.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short_uuid/commits?author=EmerLM" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
351 | </tr>
|
---|
352 | <tr>
|
---|
353 | <td align="center"><a href="https://github.com/angelnath26"><img src="https://shortunique.id/assets/contributors/angelnath26.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short_uuid/commits?author=angelnath26" title="Code">💻</a> <a href="https://github.com/jeanlescure/short_uuid/pulls?q=is%3Apr+reviewed-by%3Aangelnath26" title="Reviewed Pull Requests">👀</a></td></tr></tbody></table></td>
|
---|
354 | <td align="center"><a href="https://twitter.com/jeffturcotte"><img src="https://shortunique.id/assets/contributors/jeffturcotte.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/commits?author=jeffturcotte" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
355 | <td align="center"><a href="https://github.com/neversun"><img src="https://shortunique.id/assets/contributors/neversun.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/commits?author=neversun" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
356 | <td align="center"><a href="https://github.com/ekelvin"><img src="https://shortunique.id/assets/contributors/ekelvin.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/issues/19" title="Ideas, Planning, & Feedback">🤔</a></td></tr></tbody></table></td>
|
---|
357 | </tr>
|
---|
358 | <tr>
|
---|
359 | <td align="center"><a href="https://github.com/anthony-arnold"><img src="https://shortunique.id/assets/contributors/anthony-arnold.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/issues/35" title="Security">🛡️</a></td></tr></tbody></table></td>
|
---|
360 | <td align="center"><a href="https://github.com/ColdtQ"><img src="https://shortunique.id/assets/contributors/coldtq.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/pull/46" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
361 | <td align="center"><a href="https://github.com/char0n"><img src="https://shortunique.id/assets/contributors/char0n.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/pull/48" title="Code">💻</a></td></tr></tbody></table></td>
|
---|
362 | <td align="center"><a href="https://github.com/mybuddymichael"><img src="https://shortunique.id/assets/contributors/mybuddymichael.svg" /></a><table><tbody><tr><td width="150" align="center"><a href="https://github.com/jeanlescure/short-unique-id/issues/47" title="Documentation">📖</a></td></tr></tbody></table></td>
|
---|
363 | </tr>
|
---|
364 | </table>
|
---|
365 |
|
---|
366 | <!-- markdownlint-enable -->
|
---|
367 | <!-- prettier-ignore-end -->
|
---|
368 | <!-- ALL-CONTRIBUTORS-LIST:END -->
|
---|
369 |
|
---|
370 | ## License
|
---|
371 |
|
---|
372 | Copyright (c) 2018-2023 [Short Unique ID Contributors](https://github.com/jeanlescure/short-unique-id/#contributors-).<br/>
|
---|
373 | Licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
|
---|