1.0.3 • Published 2 months ago

idseven v1.0.3

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

idseven

UUIDv7 generator library for Node.js.

Installation

npm i idseven

Usage

import { UUIDv7, uuidv7, encodeUUIDv7, decodeUUIDv7 } from "idseven";

// Initialize a new UUIDv7 generator.
// You can pass a custom encoding alphabet here.
const uuidv7 = new UUIDv7();

const id = uuidv7.gen(); // 018ef3e8-90e2-7be4-b4ea-4be3bf8803b7
const encoded = uuidv7.encode(id); // CANANjseoigQthQMd1VwC
const decoded = uuidv7.decode(encoded); // 018ef3e8-90e2-7be4-b4ea-4be3bf8803b7
const isValid = UUIDv7.isValid(id); // true
const timestamp = UUIDv7.timestamp(id); // 1713489088738
const date = UUIDv7.date(id); // 2024-04-19T01:11:28.738Z

// You can also use convenient function aliases if you don't need to use a custom alphabet.
const id = uuidv7(); // 018ef3e8-90e2-7be4-b4ea-4be3bf8803b7
const encoded = encodeUUIDv7(id); // CANANjseoigQthQMd1VwC
const decoded = decodeUUIDv7(encoded); // // 018ef3e8-90e2-7be4-b4ea-4be3bf8803b7

Create a new instance

new UUIDv7(opts?: { encodeAlphabet: string })

Creates a new UUIDv7 instance. By default it uses the Base58 alphabet to encode and decode UUIDs, but you can pass a custom alphabet (16-64 characters).

Instance methods

gen

gen() => string

Generates a new UUIDv7.

genMany

genMany(amount: number) => string

Generates a custom amount of UUIDv7s.

encode

encode(id: string) => string

Encodes a UUIDv7 using the alphabet passed to the constructor or the default one.

decode

decode(encodedId: string) => string | null

Decodes an encoded UUIDv7 using the alphabet passed to the constuctor or the default one. If the UUIDv7 is not valid, null is returned.

decodeOrThrow

decodeOrThrow(encodedId: string) => string

Decodes an encoded UUIDv7 using the alphabet passed to the constuctor or the default one. If the UUIDv7 is not valid, an error is thrown.

Static methods

UUIDv7.isValid

UUIDv7.isValid(id: string) => boolean

Checks if the UUIDv7 is valid.

UUIDv7.timestamp

UUIDv7.timestamp(id: string) => number | null

Returns the timestamp part of the UUIDv7. If the UUIDv7 is not valid, null is returned.

UUIDv7.date

UUIDv7.date(id: string) => Date | null

Returns the timestamp part of the UUIDv7 converted to Date. If the UUIDv7 is not valid, null is returned.

Function aliases

The library provides a few function aliases for convenience. You can use them without creating a new UUIDv7 instance:

Function nameInstance methodDescription
uuidv7genGenerates a new UUIDv7.
encodeUUIDv7encodeEncodes an UUIDv7 with the default Base58 alphabet.
decodeUUIDv7decodeDecodes an encoded UUIDv7 from Base58 alphabet. Returns null if the encoded ID is invalid.
decodeOrThrowUUIDv7decodeOrThrowDecodes an encoded UUIDv7 from Base58 alphabet. Throws an error if the encoded ID is invalid.

Implementation details

This library follows the draft-ietf-uuidrev-rfc4122bis-11 draft to generate UUIDv7s.

It uses rand_b, then rand_a, and finally unix_ts_ms as counters, in that order. rand_b is the primary one, rand_a is the secondary counter when rand_b overflows its 62 bits (rare case), and unix_ts_ms is the third counter (*) in the very rare case that both rand_b and rand_a overflows their 62 bits. This is the method 2 of the "Monotonicity and Counters" section of the draft.

(*) UUIDs are generated using by default Date.now() for the timestamp part. In the very rare case that an overflow occurred for both rand_b and rand_a counters in previously generated UUID(s), the timestamp is shifted forward to guarantee monotonicity. Then, when a new UUID is generated, if the current timestamp is greater than the previous one, the new one with Date.now() is used instead, going back to the default generation behavior. In short (and in practice), don't rely on the timestamp part of the UUIDv7 to check when a record was inserted in the database, because it may be wrong. Instead, use a created_at column like you do with other primary key types.

Field and Bit Layout

This is the UUIDv7 Field and Bit Layout, took from the draft linked above:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           unix_ts_ms                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |       rand_a          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Description

unix_ts_ms

48 bit big-endian unsigned number of Unix epoch timestamp in milliseconds as per Section 6.1. Occupies bits 0 through 47 (octets 0-5).

ver

The 4 bit version field as defined by Section 4.2, set to 0b0111 (7). Occupies bits 48 through 51 of octet 6.

rand_a

12 bits pseudo-random data to provide uniqueness as per Section 6.8 and/or optional constructs to guarantee additional monotonicity as per Section 6.2. Occupies bits 52 through 63 (octets 6-7).

var

The 2 bit variant field as defined by Section 4.1, set to 0b10. Occupies bits 64 and 65 of octet 8.

rand_b

The final 62 bits of pseudo-random data to provide uniqueness as per Section 6.8 and/or an optional counter to guarantee additional monotonicity as per Section 6.2. Occupies bits 66 through 127 (octets 8-15).

Feedback

If you found a bug in the implementation, please open a new issue.

License

This project is licensed under the MIT License.

1.0.3

2 months ago

1.0.2

2 months ago

1.0.1

2 months ago

1.0.0

2 months ago