ulidx

ULID generator for NodeJS and the browser

README

ulidx


ULID generator for NodeJS and the browser


ULID generator library, based off of the original ulid for NodeJS and the browser. ULIDs are Universally Unique Lexicographically Sortable Identifiers. This library adheres to this specification.

The original ulid is no longer maintained, and has several outstanding compatibility-related issues that were never addressed. This library aims to address those and remain compatible in a larger range of environments.


Installation


Install using npm by running: npm install ulidx --save.

ulidx provides types and is written entirely in Typescript. It provides both ESM and CommonJS outputs.

Usage


Import ulid to generate new ULIDs:

  1. ```typescript
  2. import { ulid } from "ulidx";

  3. ulid(); // 01F7DKCVCVDZN1Z5Q4FWANHHCC
  4. ```

Time seed


You can also provide a time seed which will consistently give you the same string for the time component.

This is useful for migrating to ulid.


  1. ```typescript
  2. ulid(1469918176385); // 01ARYZ6S41TSV4RRFFQ69G5FAV
  3. ```

Monotonic ULID factory


To generate monotonically increasing ULIDs, create a monotonic counter using the factory:

  1. ```typescript
  2. import { monotonicFactory } from "ulidx";

  3. const ulid = monotonicFactory();

  4. // Strict ordering for the same timestamp, by incrementing the least-significant random bit by 1
  5. ulid(150000); // 000XAL6S41ACTAV9WEVGEMMVR8
  6. ulid(150000); // 000XAL6S41ACTAV9WEVGEMMVR9
  7. ulid(150000); // 000XAL6S41ACTAV9WEVGEMMVRA
  8. ulid(150000); // 000XAL6S41ACTAV9WEVGEMMVRB
  9. ulid(150000); // 000XAL6S41ACTAV9WEVGEMMVRC

  10. // Even if a lower timestamp is passed (or generated), it will preserve sort order
  11. ulid(100000); // 000XAL6S41ACTAV9WEVGEMMVRD
  12. ```

Decode ULID Time


Import decodeTime to extract the timestamp embedded in a ULID:

  1. ```typescript
  2. import { decodeTime } from "ulidx";

  3. // Extract milliseconds since UNIX Epoch from ULID
  4. decodeTime("01ARYZ6S41TSV4RRFFQ69G5FAV"); // 1469918176385
  5. ```

Validate ULID


Import isValid to check if a string is a valid ULID:

  1. ```typescript
  2. import { isValid } from "ulidx";

  3. isValid("01ARYZ6S41TSV4RRFFQ69G5FAV"); // true
  4. isValid("01ARYZ6S41TSV4RRFFQ69G5FA"); // false
  5. ```

Crockford's Base32 (Typos tolerance and Hyphened ULIDs)


Import fixULIDBase32 to fix typos and remove hyphens in a ULID:

  1. ```typescript
  2. import { fixULIDBase32 } from "ulidx";

  3. fixULIDBase32("oLARYZ6-S41TSV4RRF-FQ69G5FAV"); // 01ARYZ6S41TSV4RRFFQ69G5FAV
  4. ```

Pseudo-Random Number Generation (PRNG)


ulidx will attempt to locate a suitable cryptographically-secure random number generator in the environment where it's loaded. On NodeJS this will be crypto.randomBytes and in the browser it will be crypto.getRandomValues.

Math.random() is not supported: The environment _must_ have a suitable crypto random number generator.

Compatibility


ulidx is compatible with the following environments:

NodeJS 16 and up
   Node REPL
Browsers with working crypto / msCrypto libraries
   Web workers
React-Native ¹
Edge compute
   Cloudflare Workers ²
   Vercel Edge

¹ React-Native is supported if crypto.getRandomValues() is polyfilled. [react-native-get-random-values](https://github.com/LinusU/react-native-get-random-values) is one such library that should work well with ulidx. It should be imported before ulidx is used.

² ulidx is not _fully_ compatible with Cloudflare Workers due to their problematic stance on getting the current time. It is recommended to only use monotonic factories in this runtime.

Browser


ulidx provides browser bundles in both ESM and CommonJS varieties. Importing should be automatic, but you can import them directly:

dist/browser/index.js - Browser ESM build
dist/browser/index.cjs - Browser CommonJS build

Unlike version 1.x, these browser builds cannot simply be injected into the browser. They must be included in a build system of some kind, like Rollup or Webpack.

Note that you can use the Node-based builds in the browser if you use such an aforementioned tool, but you will need to stub node:crypto to do so. Consider the following example in Webpack using a plugin:

  1. ```javascript
  2. {
  3.     // ...

  4.     plugins: [
  5.         new NormalModuleReplacementPlugin(/node:/, (resource) => {
  6.             resource.request = resource.request.replace(/^node:/, "");
  7.         })
  8.     ]

  9.     // ...
  10. }
  11. ```