5.0.6 • Published 9 months ago

@balancer-team/rando v5.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Rando

Rando is a tool for generating identifiers. By default, rando() generates a cryptographically random, universally unique ID. Options can be modified to fit a wide variety of requirements.

Install

npm i @balancer-team/rando

Usage

Import the rando class and create an instance. The instance generates IDs with the generate() method. By default, IDs are 22 characters long, use a base 58 alphabet, and have 128 bits of entropy. The default settings provide a good balance of entropy, human-readability, and URL safety.

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

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

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 44-character ID with over 256 bits of entropy:

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

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. If the length isn't sufficient for millisecond precision, the precision will be reduced as needed.

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

// Output:
//
// "1nN6oZkdAnxQck8bPqUCzG"
//  |------||------------|
//  Sortable    Random
//  Segment     Segment

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

rando.getDate('1nN6oZkdAnxQck8bPqUCzG').toISOString() //=> 2024-09-21T17:38:44.418Z

Signed IDs

You can add a signature to the end of an ID to verify its authenticity. This is useful for preventing tampering with the ID and stopping brute-force attempts at guessing IDs, since verification can be handled by your server instead of your database. The signature is generated using the HMAC algorithm with the SHA-256 hash function. The signature is encoded using the same alphabet as the random segment, and the length of the signature will vary depending on the base of the alphabet. Longer alphabets will result in shorter signatures.

// Generate the ID and sign it
const rando = new Rando({ secret: 'secret' }) // Use a secure secret, of course
const id = rando.generate() //=> "2VRw9zT8EHVFdxnzSXremp"
const signed = rando.sign(id) //=> "2VRw9zT8EHVFdxnzSXrempDPvgBzGv9RiGbLnUnQ8X2qPGbuYUzH1exnSnfKFVWrXM"

// Verify the signature
const verified = rando.verify(signed) //=> "2VRw9zT8EHVFdxnzSXremp"

// Handling the result
if (verified) {
  console.log(verified) //=> "2VRw9zT8EHVFdxnzSXremp"
} else {
  console.log(verified) //=> null
}

The verify method will return the original ID if the signature is valid, or null if the signature is invalid.

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
  secret?: string
}
PropertyDefaultDescription
alphabetBASE_58A string of characters to use to generate your IDs. By default, the base 58 alphabet is used for a good balance of human-readability, URL safety, and entropy.
length22The length of the ID. By default, the length is 22 which provides 128 bits of entropy with a base 58 alphabet.
sortablefalseMakes the ID sortable. With the default base 58 alphabet, the first 8 characters are used to encode a timestamp at millisecond precision.
supportDate3000-01-01Allows you to specify a target date for the sortable segment to support. See below for additional details.
secretundefinedProvide a secret for the sign and verify methods. The secret property can be changed after the instance is created, allowing you to set secrets even on presets. A good signing secret should be at least 32 characters long.

Special Considerations for Sortable IDs

The length and base of the alphabet together determine how long the sortable segment must be to support millisecond precision. If the length isn't long enough to support millisecond precision, the timestamp precision will be reduced as needed. 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 as needed.

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

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

//=> Output
// Rando {
//   alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
//   length: 22,
//   randomLength: 14,
//   base: 58,
//   randomBits: 82.01173393178601,
//   randomLimit: 4.875194084160305e+24,
//   sortable: true,
//   supportDate: 3000-01-01T05:00:00.000Z,
//   sortableLength: 8,
//   sortableLimit: 6028-02-27T14:15:18.016Z,
//   sortableTrim: 0,
//   sortableResolution: '1 millisecond',
//   sortableFullLength: 8,
//   signatureFullLength: 44,
//   secret: 'secret'
// }

Presets

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

import { rando, particle, locker, pinto, slug } from '@balancer-team/rando/presets'

rando.generate() //=> "ogm3Yzf4NnSKJsDnL8ma8X"
particle.generate() //=> "1nMK3pu9oQ8ff2jVutn5PR"
locker.generate() //=> "KExaEVwFiZ5XL7339yjauuW2VAD2BrzBP5BPT8GWXbtX"
pinto.generate() //=> "368230"
slug.generate() //=> "gD75nv"
  • rando Default settings with over 128 bits of entropy, like a compact UUIDv4.
  • particle Sortable ID with over 80 bits of entropy, like a compact UUIDv7.
  • locker Long string with over 256 bits of entropy, suitable for API keys.
  • pinto Numerical 6-digit pin for email or phone verification.
  • slug Short, no vowels, over 32 bits of entropy.

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. The table assumes that the timestamp supports millisecond precision.

BaseLengthMax Year
2453084
3294144
4234199
5204992
6185188
7163023
8153084
9158494
10145138
11133063
12135360
131311567
14123766
15126081
161210889
17113056
18114006
19115661
20118459
211113069
221120486
23103282
24103979
25104992
26106443
27108494
281011356
291015301
301020681
311027942
3293084
3393440
3493894
3594467
3695188
3796088
3897205
3998584
40910277
41912344
42914856
43917896
44921557
45925948
46931193
47937433
48944832
4983023
5083207
5183420
5283664
5383942
5484261
5584623
5685034
5785501
5886028
5986622
6087292
6188044
6288888
6389833
64810889
5.0.6

9 months ago

5.0.5

9 months ago

5.0.4

9 months ago

5.0.3

9 months ago

5.0.2

9 months ago

5.0.1

9 months ago

5.0.0

9 months ago

4.0.5

10 months ago

4.0.4

10 months ago

4.0.3

10 months ago

4.0.2

10 months ago

4.0.1

10 months ago

4.0.0

10 months ago

3.3.4

10 months ago

3.3.3

10 months ago

3.3.2

10 months ago

3.3.1

10 months ago

3.3.0

10 months ago

3.2.3

10 months ago

3.2.2

10 months ago

3.2.1

10 months ago

3.2.0

10 months ago

3.1.8

10 months ago

3.1.7

10 months ago

3.1.6

10 months ago

3.1.5

10 months ago

3.1.4

10 months ago

3.1.3

10 months ago

3.1.2

10 months ago

3.1.1

10 months ago

3.1.0

10 months ago

3.0.9

10 months ago

3.0.8

10 months ago

3.0.7

10 months ago

3.0.6

10 months ago

3.0.5

10 months ago

3.0.4

10 months ago

3.0.3

10 months ago

3.0.2

10 months ago

3.0.1

10 months ago

2.0.0

10 months ago

1.0.2

10 months ago

1.0.1

10 months ago