Skip to content
mdhthahmdPublic

About

Sqids (pronounced "squids") generates short, unique, URL-safe IDs from numbers. This implementation follows the Sqids specification and adds opt-in BigInt support for the full unsigned 64-bit integer range.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Sqids

Sqids JavaScript (with BigInt support)

release workflow GitHub stars MIT license

Node.js 18 or newer TypeScript 7 pnpm 11

Vitest 4 Biome 2 Commitlint 21 tsdown 0.22 semantic-release 25

Husky 9 lint-staged 17 publint 0.3 Are the Types Wrong 0.18 GitHub Actions

Sqids (pronounced "squids") generates short, unique, URL-safe IDs from numbers. This implementation follows the Sqids specification and adds opt-in BigInt support for the full unsigned 64-bit integer range.

πŸ“š Table of contents

✨ Features

  • πŸ”’ Multiple numbers β€” encode one or more non-negative numbers into one ID
  • πŸ’ͺ BigInt support β€” use the full unsigned 64-bit integer range
  • ⚑ Quick decoding β€” decode IDs back into their original values
  • πŸ”€ Randomized output β€” sequential inputs produce nonconsecutive IDs
  • πŸ“ ID padding β€” configure a minimum ID length
  • πŸ”€ Custom alphabets β€” control the characters used to generate IDs
  • πŸ›‘οΈ Blocklists β€” regenerate IDs containing blocked words
  • πŸ”— URL safe β€” use generated IDs safely in URLs
  • 🌍 Portable β€” Sqids supports 40+ programming languages

🎯 Use cases

Sqids works well for:

  • Public URL identifiers and link shorteners
  • Internal identifiers such as event or object references
  • Reversible database lookups by numeric primary key

Warning

Sqids is not encryption. Anyone can decode an ID, so do not use it for secrets or to hide sensitive information.

πŸ“¦ Installation

Requires Node.js 18 or newer.

Using pnpm:

pnpm add @mdhthahmd/sqids

Using npm:

npm install @mdhthahmd/sqids

Using Yarn:

yarn add @mdhthahmd/sqids

πŸš€ Quick start

import Sqids from "@mdhthahmd/sqids";

const sqids = new Sqids();
const id = sqids.encode([1, 2, 3]); // "86Rf07"
const numbers = sqids.decode(id); // [1, 2, 3]

Note

Because of the algorithm's design, multiple IDs can decode to the same sequence of numbers. If IDs must be canonical, re-encode the decoded numbers and verify that the generated ID matches.

πŸ’ͺ BigInt support

Enable BigInt mode when values may exceed Number.MAX_SAFE_INTEGER. BigInt mode accepts values from 0n through 2n ** 64n - 1n and returns bigint[] when decoding.

import Sqids from "@mdhthahmd/sqids";

const sqids = new Sqids({ mode: "bigint" });
const values = [0n, 9_007_199_254_740_992n, 18_446_744_073_709_551_615n];

const id = sqids.encode(values);
const decoded = sqids.decode(id);

console.log(decoded); // [0n, 9007199254740992n, 18446744073709551615n]

Number mode and BigInt mode generate the same ID for values within the safe-integer range:

new Sqids().encode([1, 2, 3]) ===
  new Sqids({ mode: "bigint" }).encode([1n, 2n, 3n]); // true

βš™οΈ Configuration

Minimum ID length

import Sqids from "@mdhthahmd/sqids";

const sqids = new Sqids({
  minLength: 10,
});

const id = sqids.encode([1, 2, 3]); // "86Rf07xd4z"
const numbers = sqids.decode(id); // [1, 2, 3]

Custom alphabet

import Sqids from "@mdhthahmd/sqids";

const sqids = new Sqids({
  alphabet: "FxnXM1kBN6cuhsAvjW3Co7l2RePyY8DwaU04Tzt9fHQrqSVKdpimLGIJOgb5ZE",
});

const id = sqids.encode([1, 2, 3]); // "B4aajs"
const numbers = sqids.decode(id); // [1, 2, 3]

Custom blocklist

import Sqids from "@mdhthahmd/sqids";

const sqids = new Sqids({
  blocklist: new Set(["86Rf07"]),
});

const id = sqids.encode([1, 2, 3]); // "se8ojk"
const numbers = sqids.decode(id); // [1, 2, 3]

Error handling

All validation and encoding failures throw SqidsError, which extends the built-in Error class.

import Sqids, { SqidsError } from "@mdhthahmd/sqids";

try {
  new Sqids().encode([-1]);
} catch (error) {
  if (error instanceof SqidsError) {
    console.error(error.message);
  }
}

πŸ§ͺ Example APIs

The workspace includes two consumer applications that use the published @mdhthahmd/sqids package:

  • examples/hono-api β€” Node.js ESM API on port 3000
  • examples/nestjs-api β€” NestJS CommonJS API on port 3001

Start both APIs in watch mode:

pnpm dev:examples

For manual testing, open bruno/requests/api as a collection in Bruno and select the hono or nestjs environment. Run each folder's encode request before its decode request.

πŸ› οΈ Development

Dev Container

The recommended setup is the repository's Dev Container. It provides Node.js 24.19, pnpm 11.22, GitHub CLI, Biome, Vitest Explorer, Bruno, and the configured coding-agent tools.

  1. Install Docker and a Dev Container-compatible editor, such as VS Code with the Dev Containers extension.
  2. Clone the repository and open it in VS Code.
  3. Run Dev Containers: Reopen in Container from the command palette.
  4. Wait for pnpm install --frozen-lockfile to finish automatically.
  5. Run pnpm test:all to verify the workspace.

To apply changes made to .devcontainer/devcontainer.json, run Dev Containers: Rebuild Container.

Local setup

Install Node.js 24.19 and pnpm 11.22, then run:

pnpm install --frozen-lockfile
pnpm test:all

Workspace layout

Path Purpose
lib Published Sqids package, source, tests, and benchmarks
examples/hono-api ESM consumer example
examples/nestjs-api CommonJS consumer example
bruno/requests/api Bruno collection for both example APIs

Commands

Command Description
pnpm build Build the library and all example applications
pnpm dev:lib Rebuild the library in watch mode
pnpm dev:examples Start both example APIs in watch mode
pnpm test:all Build, type-check, test, and run Biome CI checks
pnpm test:coverage Run the library tests with coverage
pnpm test:package Validate the packed npm package and its types
pnpm benchmark Run the library's Vitest benchmarks
pnpm check Format and lint the entire repository with Biome
pnpm clean Remove generated workspace build output

The benchmark suite covers number and BigInt operations, verified round trips, UUID-shaped batch inputs, construction, padding, custom alphabets, and blocklist retries.

🚒 Release workflow

Semantic-release owns package versions, tags, changelog entries, and publication. Use Conventional Commit messages on next; fix: creates a patch prerelease and feat: creates a minor prerelease.

Promote next to main using exactly one of these strategies:

  • Regular merge: preserve the original commits and use a non-releasing merge message such as chore: merge next into main. Semantic-release analyzes the preserved fix: and feat: commits.
  • Squash merge: use one Conventional Commit PR title, such as fix: validate package inputs. The squash commit replaces the original commits, so its title determines the stable release.

Do not squash and then merge the same changes again. Do not use fix: or feat: for a regular merge commit when the preserved commits already contain those types; doing so duplicates the release note. After a stable release, update the local main and next branches independently before starting the next prerelease.

πŸ“„ License

MIT

About

Sqids (pronounced "squids") generates short, unique, URL-safe IDs from numbers. This implementation follows the Sqids specification and adds opt-in BigInt support for the full unsigned 64-bit integer range.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages