Rando

Copied to Clipboard!
Copied to Clipboard!
Copied to Clipboard!
Copied to Clipboard!

Rando is a library for generating identifiers. IDs are random and universally unique by default. Options can be modified to fit a wide variety of requirements. In a node environment, randomness is provided by the node:crypto module. In a browser environment, randomness is provided by the Web Crypto API.

Install

npm i @balancer-team/rando

Usage

Import the rando class and create an instance. The instance generates IDs with the generate() method.

import { Rando } from '@balancer-team/rando'

const rando = new Rando()
rando.generate() // => "Jb46bM8xM3mhDLnpQrwNvN"

Customizing the Length

If you want a longer random string, for example if you want extra security for an API key, it's easy to modify the length. The example below generates a 46-character ID with over 256 bits of entropy:

const rando = new Rando({ length: 46 })
rando.generate() //=> "X5533mwXPH6V2nMN5548t1vkFVN4RTJqM89JNQcbVjmt1G"

Sortable IDs

Rando can generate sortable IDs where the beginning of the ID is an encoded timestamp using the given alphabet. Rando will evaluate the alphabet length and automatically determine how many characters are required to encode a timestamp at millisecond precision. The length must be sufficient for millisecond precision. Refer to the table below for guidance on the length needed to support a given year with a given alphabet base.

const rando = new Rando({ sortable: true })
rando.generate()

// Output:
//
// "13DNYFr2DBJvhWfWCs58Nb"
//  |------||------------|
//  Sortable    Random
//  Segment     Segment

Sortable IDs can be decoded to return a date. Note that the instance doing the decoding must have the same options as the instance that generated it.

rando.getDate('13DNYFr2DBJvhWfWCs58Nb').toISOString() //=> "2025-02-25T13:11:45.061Z"

All Options

Rando instances can be extensively customized to generate the perfect identifier for your requirements. Here's the type definition of all available options, with details below:

type RandoOptions = {
  alphabet?: string
  length?: number
  sortable?: boolean
  supportDate?: Date
}
PropertyDefaultDescription
alphabetBASE_50A string of characters to use to generate your IDs. Each character must be unique. The default base 50 alphabet excludes vowels and ambiguous characters.
length22The length of the ID. By default, the length is 22 which provides 124 bits of entropy, slightly more than a UUIDv4.
sortablefalseMakes the ID sortable when set to true. The leading characters encode a timestamp at millisecond precision.
supportDate'4000'Allows you to specify a target date for the sortable segment. See below for additional details.

Special Considerations for Sortable IDs

The length and base of the alphabet together determine how long the sortable segment must be for millisecond precision. If the length is too short, Rando will throw an error when instantiated. The supportDate property allows you to specify a target date for the sortable segment to support. The sortable segment will be left-padded to support the target date with a consistent overall length.

Note that making an ID sortable will reduce the number of random characters in the ID. If you console.log the instance, you will see several helpful properties such as randomBits that can help you determine whether or not the ID meets your requirements.

const rando = new Rando({ sortable: true })

// Output:
//
// Rando {
//   alphabet: '123456789BCDFGHJKLMNPQRSTVWXYZbcdfghjkmnpqrstvwxyz',
//   length: 22,
//   randomLength: 13,
//   base: 50,
//   randomBits: 73.37013046707142,
//   randomLimit: 1.2207031249999986e+22,
//   sortable: true,
//   supportDate: 4000-01-01T00:00:00.000Z,
//   sortableLength: 9,
//   sortableLimit: +063862-01-25T10:13:20.000Z
// }

Presets

Rando comes with a few presets to make it easy to generate IDs for common use cases.

import { rando, sorto, locker, sesame, pinto } from '@balancer-team/rando/presets'

rando.generate() //=> "7kFD8XHYp1JdXXzYsxRvXT"
sorto.generate() //=> "13DNYDsRBvc6TQ2HwHh1GW"
locker.generate() //=> "5Myvnv4BQm7rDhz3zntYGMXf9Srr71z7wFwF1SSYMQVvQQ"
sesame.generate() //=> "E@MvHJG4JbA$o{8ll0AK"
pinto.generate() //=> "368230"
  • rando Default, like a compact UUIDv4.
  • sorto Sortable string followed by a random string, like a compact UUIDv7.
  • locker Long string with over 256 bits of entropy, suitable for API keys.
  • sesame Secure password with over 128 bits of entropy.
  • pinto Numerical 6-digit pin for verification codes.

Guidance for Sortable IDs

The following table is a guide for the length needed to support at least the year 3000 with a given alphabet base.

BaseLengthMax Year
2464199
3294144
4234199
5204992
6185188
7179341
81610889
9158494
10145138
111414003
12135360
131311567
141327121
15126081
161210889
171220432
18114006
19115661
20118459
211113069
221120486
231132163
241150190
25104992
26106443
27108494
281011356
291015301
301020681
311027942
321037648
331050503
341067387
3594467
3695188
3796088
3897205
3998584
40910277
41912344
42914856
43917896
44921557
45925948
46931193
47937433
48944832
49953572
50963862
51975936
52990061
539106535
5484261
5584623
5685034
5785501
5886028
5986622
6087292
6188044
6288888
6389833
64810889