npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ralalabs/rid

v1.0.1

Published

Fast deterministic reversible ID encoding for numbers and strings using AES-128-CTR with base62 output

Readme

@ralalabs/rid

Fast, deterministic, reversible ID encoding for Node.js and edge runtimes.

@ralalabs/rid turns internal IDs into short opaque tokens and decodes them back with the same secret key. It supports both numeric IDs and string IDs works in Node.js and Cloudflare Workers, and keeps the API intentionally small.

Features

  • fast encode and decode for hot-path usage
  • supports both number and string IDs
  • works across runtimes: Node.js, browsers with WebCrypto, Cloudflare Workers, and other edge runtimes
  • deterministic output for the same input and key
  • short URL-safe base62 tokens
  • optional prefixes such as media-, season-, or episode-
  • same high-level API for encode and decode
  • small surface area with stricter typed helpers available when needed

Install

npm install @ralalabs/rid
# or
pnpm add @ralalabs/rid

Quick start

import { createCodec, generateKey } from '@ralalabs/rid';

const key = process.env.RID_KEY;

const codec = createCodec({
  key,
  prefix: 'media',
  // default separator is '-'
});

const rid = await codec.encode('kv:ro');
const value = await codec.decode(rid);

console.log(rid);
console.log(value);

encode() and decode() are the default high-level methods. They accept both number and string IDs and return the original value type on decode.

Prefixes

Prefixes let you namespace tokens by domain or entity type.

const mediaCodec = createCodec({ key: RID_KEY, prefix: 'media' });
const userCodec = createCodec({ key: RID_KEY, prefix: 'user' });

await mediaCodec.encodeNumber(1); // media-...
await userCodec.encodeNumber(1); // user-...

Prefix validation is enforced on decode.

Custom separators are also supported. Use non-alphanumeric separators only, such as -, _, :, ::, or ~. This keeps prefix parsing unambiguous because the token body is base62.

API

createCodec(options)

Creates a codec instance.

Options

| Option | Type | Required | Description | | ----------- | ---------------------- | -------- | ------------------------------------------------------------------------------ | | key | string \| Uint8Array | yes | 128-bit key as a 32-char hex string or 16-byte array | | prefix | string | no | optional token namespace, for example med | | separator | string | no | separator used after prefix, default -. Must not contain letters or numbers. |

Codec methods

| Method | Returns | Notes | | --------------------- | ---------------------------------- | ----------------------------------------------------------- | | encode(value) | Promise<string> | accepts number or string | | decode(token) | Promise<number \| string> | returns the original ID type | | encodeNumber(value) | Promise<string> | strict numeric helper | | decodeNumber(token) | Promise<number> | strict numeric helper; throws if token contains a string ID | | encodeString(value) | Promise<string> | strict string helper | | decodeString(token) | Promise<string> | strict string helper; throws if token contains a numeric ID | | encodeBatch(values) | Promise<string[]> | batch encode | | decodeBatch(tokens) | Promise<Array<number \| string>> | batch decode |

generateKey()

Returns a random 128-bit key as a lowercase 32-character hex string.

import { generateKey } from '@ralalabs/rid';

const key = await generateKey();

RidError

All package validation and decode failures throw RidError.

ID support

Numbers

  • non-negative integers only
  • maximum value: Number.MAX_SAFE_INTEGER

Strings

  • UTF-8 strings are supported
  • maximum encoded string size: 65535 bytes before encryption
  • suitable for IDs such as media:x:y, user:abc, show:season:1

Security notes

This package is meant for opaque reversible IDs. It helps hide internal identifiers from public URLs and APIs, but it is not an authorization mechanism.

Important properties:

  • deterministic by design
  • same key + same ID always produces the same token
  • no MAC or authenticity guarantee
  • malformed tokens are rejected through structural validation after decode
  • tampered tokens usually fail validation, but this package should not be treated as a cryptographic integrity layer

Use it when you want:

  • opaque public route IDs
  • reversible IDs across services
  • one secret key shared between Node.js and edge runtimes

Do not use it as your only control for:

  • access control
  • anti-tampering guarantees
  • high-assurance cryptographic protocols

Runtime support

| Runtime | Backend | | ------------------ | ------------- | | Node.js 18+ | node:crypto | | Cloudflare Workers | WebCrypto | | Deno | WebCrypto | | Modern browsers | WebCrypto |

Performance notes

The package is built for hot-path use:

  • small API surface
  • cached crypto adapter selection
  • cached imported WebCrypto keys
  • no JSON serialization in the encoded payload
  • deterministic output means token length reflects payload size
  • compact binary payload before base62 conversion

For the best type safety and clarity in application code, prefer encodeNumber / decodeNumber and encodeString / decodeString when the ID shape is known.

License

MIT