Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/theedoran/uuidv7-js
UUIDv7 generator library for JavaScript, RFC 9562 compliant. Supports encoding/decoding UUIDs to custom alphabets.
https://github.com/theedoran/uuidv7-js
id id-gen rfc-9562 uuid uuidv7
Last synced: 11 days ago
JSON representation
UUIDv7 generator library for JavaScript, RFC 9562 compliant. Supports encoding/decoding UUIDs to custom alphabets.
- Host: GitHub
- URL: https://github.com/theedoran/uuidv7-js
- Owner: TheEdoRan
- License: mit
- Created: 2024-04-25T22:47:43.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2024-07-04T23:26:53.000Z (4 months ago)
- Last Synced: 2024-10-13T04:35:46.975Z (about 1 month ago)
- Topics: id, id-gen, rfc-9562, uuid, uuidv7
- Language: TypeScript
- Homepage: https://npmjs.com/uuidv7-js
- Size: 96.7 KB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# [uuidv7-js](https://github.com/TheEdoRan/uuidv7-js)
UUIDv7 generator library for JavaScript, [RFC 9562](https://datatracker.ietf.org/doc/html/rfc9562) compliant. Supports encoding/decoding UUIDs to custom alphabets.
## Installation
```sh
npm i uuidv7-js
```## Usage
```typescript
import { UUIDv7, uuidv7, encodeUUIDv7, decodeUUIDv7 } from "uuidv7-js";// Initialize a new UUIDv7 generator.
// You can pass a custom encoding alphabet here.
const uuid = new UUIDv7();const id = uuid.gen(); // 018ef3e8-90e2-7be4-b4ea-4be3bf8803b7
const encoded = uuid.encode(id); // CANANjseoigQthQMd1VwC
const decoded = uuid.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
```typescript
const uuid = new UUIDv7(opts?: { encodeAlphabet?: string })
```Creates a new `UUIDv7` instance. By default it uses the [Base58](https://www.cs.utexas.edu/users/moore/acl2/manuals/current/manual/index-seo.php/BITCOIN_____A2BASE58-CHARACTERS_A2) alphabet to `encode` and `decode` UUIDs, but you can pass a custom alphabet (16-64 characters).
### Instance methods
#### `gen`
```typescript
gen(customTimestamp?: number) => string
```Generates a new UUIDv7. You can provide a custom timestamp to be used instead of the current one.
#### `genMany`
```typescript
genMany(amount: number, customTimestamp?: number) => string[]
```Generates a custom amount of UUIDv7s. You can provide a custom timestamp to be used instead of the current one.
#### `encode`
```typescript
encode(id: string) => string
```Encodes a UUIDv7 using the alphabet passed to the constructor or the default one.
#### `decode`
```typescript
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`
```typescript
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`
```typescript
UUIDv7.isValid(id: string) => boolean
```Checks if the UUIDv7 is valid.
#### `UUIDv7.timestamp`
```typescript
UUIDv7.timestamp(id: string) => number | null
```Returns the timestamp part of the UUIDv7. If the UUIDv7 is not valid, `null` is returned.
#### `UUIDv7.date`
```typescript
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 name | Instance method | Description |
| --------------------- | --------------- | --------------------------------------------------------------------------------------------- |
| `uuidv7` | `gen` | Generates a new UUIDv7. |
| `encodeUUIDv7` | `encode` | Encodes a UUIDv7 with the default Base58 alphabet. |
| `decodeUUIDv7` | `decode` | Decodes an encoded UUIDv7 from Base58 alphabet. Returns null if the encoded ID is invalid. |
| `decodeOrThrowUUIDv7` | `decodeOrThrow` | Decodes an encoded UUIDv7 from Base58 alphabet. Throws an error if the encoded ID is invalid. |## Implementation details
This library implements the [RFC 9562](https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-7) spec to generate UUIDv7s:
- if the current timestamp is ahead of the last stored one, it generates new `rand_a` and `rand_b` parts;
- if the current timestamp is behind the last stored one, it waits for the next valid timestamp to return a UUIDv7 with newly generated `rand_a` and `rand_b` parts;
- if the current timestamp is the same as the last stored one:
- it uses `rand_b` and then `rand_a` as randomly seeded counters, in that order. `rand_b` is the primary counter, and `rand_a` is used as the secondary one, when `rand_b` overflows its 62 bits (rare case). When used as a counter, `rand_b` increments its previous random value by a random integer between 1 and 4,294,967,296 (2^32), and `rand_a` increments its previous random value by 1, while generating a new `rand_b` part.
- if both counters overflow their bit sizes, the generation function waits for the next millisecond to return a UUIDv7 with newly generated random parts.This approach follows the [method 2](https://datatracker.ietf.org/doc/html/rfc9562#monotonicity_counters) of the "Monotonicity and Counters" section of the spec. It guarantees monotonicity and uniqueness per instance, and always keeps timestamp the same as `Date.now()` value.
If you provide a custom timestamp, it will be used instead of the current one. Generation works differently in this case:
- if the custom timestamp is different from the last custom stored one, it generates new `rand_a` and `rand_b` parts;
- if the custom timestamp is the same as the last custom stored one, it uses `rand_b` and then `rand_a` as randomly seeded counters, in that order, just like the normal generation method. If both `rand_a` and `rand_b` overflow, though, the generator creates new `rand_a` and `rand_b` parts. This breaks monotonicity per instance with custom timestamp, but ensures that a valid UUIDv7 is always returned. Keep in mind that this is an extremely rare case and should really never happen.## Field and Bit Layout
This is the UUIDv7 Field and Bit Layout, took from the spec 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](https://datatracker.ietf.org/doc/html/rfc9562#timestamp_considerations). Occupies bits 0 through 47 (octets 0-5).
#### ver
The 4 bit version field as defined by [Section 4.2](https://datatracker.ietf.org/doc/html/rfc9562#version_field), 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.9](https://datatracker.ietf.org/doc/html/rfc9562#unguessability) and/or optional constructs to guarantee additional monotonicity as per [Section 6.2](https://datatracker.ietf.org/doc/html/rfc9562#monotonicity_counters). Occupies bits 52 through 63 (octets 6-7).
#### var
The 2 bit variant field as defined by [Section 4.1](https://datatracker.ietf.org/doc/html/rfc9562#variant_field), 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.9](https://datatracker.ietf.org/doc/html/rfc9562#unguessability) and/or an optional counter to guarantee additional monotonicity as per [Section 6.2](https://datatracker.ietf.org/doc/html/rfc9562#monotonicity_counters). Occupies bits 66 through 127 (octets 8-15).
## Feedback
If you found a bug in the implementation, please open a new [issue](https://github.com/TheEdoRan/uuidv7-js/issues/new).
## Alternatives
- [uuidv7](https://www.npmjs.com/package/uuidv7) by [LiosK](https://github.com/LiosK)
## License
This project is licensed under the MIT License.