/** * @module nexid/types/xid * * XID core type definitions. * * ARCHITECTURE: * This module defines the fundamental type-level representation of XIDs * using TypeScript's type system. It employs advanced TypeScript techniques * like branded types and nominal typing to ensure type safety when working * with XIDs, preventing accidental misuse of generic arrays or strings * where XIDs are expected. */ /** * Branded type helper that creates a nominal type from a base type. * Uses a string literal tag to ensure structurally identical base types * (e.g. two Brand variants) are not interchangeable. */ type Brand = Readonly & { readonly __brand: Tag; }; /** * XID binary representation - a branded 12-byte Uint8Array. * This provides compile-time and runtime immutability guarantees. */ type XIDBytes = Brand; /** * XID string representation - a branded 20-character string. * Ensures only properly formatted XID strings are accepted by functions * expecting this type. */ type XIDString = Brand; /** * @module nexid/core/xid * * Core XID immutable value type and operations. * * ARCHITECTURE: * This module provides the fundamental XID implementation - globally unique, * lexicographically sortable identifiers with a rich functional API. Each XID * consists of 12 bytes (96 bits) with the following structure: * * ╔═══════════════════════════════════════════════════════════════╗ * ║0 3║4 6║7 8║9 11║ * ║--- 4 bytes ---║--- 3 bytes ---║--- 2 bytes ---║--- 3 bytes ---║ * ║═══════════════════════════════════════════════════════════════║ * ║ time ║ machine ID ║ process ID ║ counter ║ * ╚═══════════════════════════════════════════════════════════════╝ * * DESIGN PRINCIPLES: * - Immutability: all XID values and operations are immutable * - Functional composition: pure operations on value objects * - Type safety: comprehensive type definitions with exhaustive checks * * SECURITY: * - Copy-on-read for component extraction to prevent tampering * - Strict validation for all inputs * - No mutation methods provided on XID instances */ /** * Immutable XID class representing a globally unique identifier. * * An XID is a 12-byte value with a specific structure that ensures * both uniqueness and lexicographical sortability. XIDs can be * serialized to a compact 20-character URL-safe string representation. */ declare class XID { readonly bytes: XIDBytes; /** * Private constructor to ensure XIDs are only created through factory methods. * This enforces proper validation of all XID instances. * * @param bytes - The underlying byte array for the XID * @private */ private constructor(); /** * Creates an XID from a raw byte array. * * @param bytes - The 12-byte array to create the ID from * @returns A new XID instance * @throws Error if the input is not a valid 12-byte Uint8Array */ static fromBytes(bytes: Uint8Array): XID; /** * Parses an XID from its 20-character string representation. * * @param str - The string to parse (expected to be 20 characters in base32-hex format) * @returns A new XID instance * @throws Error if the input string is invalid or malformed */ static fromString(str: string): XID; /** * Creates a nil (zero) XID, useful as a default value or placeholder. * * @returns A nil XID (all bytes set to zero) */ static nilID(): XID; /** * Extracts the timestamp portion of the XID as a JavaScript Date object. * * @returns A Date object representing when the ID was created */ get time(): Date; /** * Extracts the machine identifier component from the XID. * This is a 3-byte value derived from platform-specific identifiers. * * @returns A copy of the 3-byte machine ID portion */ get machineId(): Uint8Array; /** * Extracts the process ID component from the XID. * This is a 2-byte value of the process that generated the ID. * * @returns A number representing the process ID */ get processId(): number; /** * Extracts the counter component from the XID. * This is a 3-byte value that increments for each ID generated by the same * process, ensuring uniqueness even when multiple IDs are generated in the same second. * * @returns A number representing the counter value */ get counter(): number; /** * Converts the XID to its 20-character base32-hex string representation. * This string is URL-safe, compact, and maintains lexicographical ordering. * * @returns A 20-character string representation of the XID */ toString(): XIDString; /** * Returns the string representation for JSON serialization. * Ensures `JSON.stringify(xid)` produces the base32-hex string, not the raw bytes. */ toJSON(): XIDString; /** * Checks if this XID is a nil (zero) ID. * A nil ID has all bytes set to zero and is typically used as a placeholder or default value. * * @returns True if this is a nil ID, false otherwise */ isNil(): boolean; /** * Checks if this XID is equal to another XID. * Two XIDs are equal if they contain the same bytes in the same order. * * @param other - Second XID to compare * @returns True if the XIDs contain identical bytes, false otherwise */ equals(other: XID): boolean; /** * Compares the current XID with another, lexicographically. * Since the timestamp is the first component, this also sorts chronologically. * * @param other - Second XID to compare * @returns Negative number if a is smaller (older), 0 if equal, positive if a is greater (newer) */ compare(other: XID): number; } /** * @module nexid/env/registry * * Environment features registry and resolution system. * * ARCHITECTURE: * This module implements a capability-based environment abstraction layer * that enables the library to adapt to different JavaScript runtimes while * providing a consistent API. The registry: * * 1. Defines the core capabilities required by the ID generator * 2. Manages the validation and fallback mechanisms for these capabilities * 3. Implements a resolution system with caching for performance * * This abstraction allows the core library code to remain platform-agnostic * while still utilizing environment-specific optimizations when available. */ /** * Core capabilities required by the XID generator. * Each capability is implemented differently based on the runtime environment. */ type FeatureSet = { /** Generates cryptographically secure random bytes */ RandomBytes: (size: number) => Uint8Array; /** Provides a stable machine/device identifier */ MachineId: () => string; /** Provides a process-specific identifier */ ProcessId: () => number; }; /** * @module nexid/types/xid-generator * * XID Generator type definitions. * * ARCHITECTURE: * This module defines the public interface and configuration options for * the XID generator. It establishes the contract between the application code * and the generator, providing type safety and documentation for the generator's * capabilities and configuration options. */ declare namespace Generator { /** * Public API for the XID generator. * This interface defines the operations available after initialization. */ export interface API { /** The hashed machine ID bytes used by this generator instance (hex-encoded) */ readonly machineId: string; /** The process ID used by this generator instance */ readonly processId: number; /** True if any security-critical feature is using an insecure fallback */ readonly degraded: boolean; /** * Generates a new XID with the specified timestamp or current time. * * @param timestamp - Optional date to use instead of current time * @returns A new XID object */ newId(timestamp?: Date): XID; /** * Generates a new XID string directly, bypassing object creation. * This is approximately 30% faster than newId() when only the string * representation is needed. * * @returns A string representation of a new XID */ fastId(): XIDString; } /** * Configuration options for the XID generator. * These options allow customizing the generator's behavior. */ export type Options = Partial<{ /** Custom random bytes source */ randomBytes: FeatureSet['RandomBytes']; /** Custom machine identifier string */ machineId: string; /** Custom process identifier number */ processId: number; /** * Allow insecure fallbacks for security-critical features. * When false (default), initialization throws if CSPRNG * cannot be resolved. */ allowInsecure: boolean; /** * Enable filtering of generated IDs that contain offensive word substrings. * When enabled, the generator retries (incrementing the counter) until the * filter passes or maxFilterAttempts is exhausted. * * Uses a curated built-in blocklist of 57 universally offensive English * terms that can be formed from the base32-hex alphabet (0-9, a-v). * * @default false */ filterOffensiveWords: boolean; /** * Additional offensive words to block alongside the built-in blocklist. * Only takes effect when `filterOffensiveWords` is `true`. * * Words are lowercased and regex-escaped internally. Only words * representable in the base32-hex alphabet (0-9, a-v) will ever * match generated IDs. */ offensiveWords: readonly string[]; /** * Maximum attempts to generate a clean ID when the offensive word filter * is enabled. Each attempt consumes one counter value. If the budget is * exhausted, the last generated ID is returned regardless (best-effort). * * A value of 0 returns the first generated ID unchecked. To disable * filtering entirely, set `filterOffensiveWords: false` instead. * * Only takes effect when `filterOffensiveWords` is `true`. * Clamped to 0–100. * * @default 10 */ maxFilterAttempts: number; }>; } type initNeXID = (options?: Generator.Options) => Generator.API; type ResolvedEnvironment = { init: initNeXID; }; /** * Built-in blocklist of offensive words (3+ chars) that can be formed * from the base32-hex alphabet (0-9, a-v only). * * Curation criteria: * - Only characters representable in the encoding alphabet (0-9, a-v) * - 3+ characters to avoid excessive false positives * - Universally offensive English terms */ declare const BLOCKED_WORDS: readonly string[]; export { BLOCKED_WORDS as B, Generator as G, type ResolvedEnvironment as R, XID as X, type XIDBytes as a, type XIDString as b, type initNeXID as i };