[d24f17c] | 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).
|
---|