UNPKG

nehoid

Version:

NehoID is a high-performance TypeScript library designed for generating, validating, and managing unique identifiers in enterprise-grade applications.

1,465 lines (1,460 loc) 64.8 kB
import { StruLink } from 'strulink'; /** * Supported encoding types for data transformation. * * These encoding schemes provide various methods for transforming strings, * including standard encodings, cryptographic preparations, and specialized formats. * Each type corresponds to a specific encoding algorithm with different properties * such as reversibility, URL-safety, and security characteristics. */ type ENC_TYPE = Parameters<typeof StruLink.encode>[1]; /** * Core encoding utilities for data transformation and compression. * * The Encoder class provides a comprehensive set of encoding and decoding methods * supporting multiple algorithms including base64, hex, ROT13, compression schemes, * and specialized encodings. It serves as the foundation for NehoID's transformation * capabilities and supports both synchronous and asynchronous operations. * * @example * ```typescript * // Basic encoding and decoding * const encoded = await Encoder.encode('hello world', 'base64'); * const decoded = Encoder.decode(encoded, 'base64'); * * // Multiple encodings in sequence * const multiEncoded = await Encoder.encode('data', ['base64', 'hex']); * const multiDecoded = Encoder.decode(multiEncoded, ['hex', 'base64']); * * // Compression * const compressed = Encoder.compress('long text to compress', 'gzip'); * const decompressed = Encoder.decompress(compressed, 'gzip'); * ``` */ declare class Encoder { /** * Encode a string using one or more encoding schemes asynchronously. * * Applies encoding transformations in sequence, where each encoding * is applied to the result of the previous encoding. This allows for * complex encoding pipelines to be built programmatically. * * @param input - The string to encode * @param encodings - Single encoding type or array of encoding types to apply in sequence * @returns Promise that resolves to the encoded string * * @example * ```typescript * // Single encoding * const base64Result = await Encoder.encode('hello', 'base64'); * // Output: 'aGVsbG8=' * * // Multiple encodings * const result = await Encoder.encode('data', ['base64', 'hex']); * // Applies base64 first, then hex to the result * * // URL-safe encoding * const urlSafe = await Encoder.encode('user input', 'urlSafeBase64'); * ``` */ static encode(input: string, encodings: ENC_TYPE | ENC_TYPE[]): Promise<string>; /** * Decode a string using one or more decoding schemes. * * Reverses encoding transformations by applying decodings in reverse order. * Supports both manual specification of decoding types and automatic detection. * * @param input - The encoded string to decode * @param encodings - Single decoding type or array of decoding types to apply in reverse order * @param opt - Optional decoding configuration * @param opt.autoDetect - Whether to attempt automatic encoding detection (experimental) * @returns The decoded string * * @example * ```typescript * // Single decoding * const original = Encoder.decode('aGVsbG8=', 'base64'); * // Output: 'hello' * * // Multiple decodings (reverse order) * const result = Encoder.decode(encodedData, ['hex', 'base64']); * // Decodes hex first, then base64 * * // With auto-detection * const decoded = Encoder.decode(encodedStr, 'base64', { autoDetect: true }); * ``` */ static decode(input: string, encodings: ENC_TYPE | ENC_TYPE[], opt?: { autoDetect?: boolean; }): string; /** * Compress a string using LZ77 or GZIP-style compression. * * Reduces the size of input strings using dictionary-based compression algorithms. * LZ77 uses sliding window compression, while GZIP uses LZW-style dictionary compression. * Both methods are lossless and can be reversed using the decompress method. * * @param input - The string to compress * @param method - Compression algorithm to use ('lz77' or 'gzip') * @returns The compressed and base64-encoded string * * @example * ```typescript * // LZ77 compression (good for repetitive data) * const compressed = Encoder.compress('abababababab', 'lz77'); * const decompressed = Encoder.decompress(compressed, 'lz77'); * * // GZIP compression (good for large texts) * const text = 'A very long string with lots of repetition and patterns...'; * const gzipped = Encoder.compress(text, 'gzip'); * const original = Encoder.decompress(gzipped, 'gzip'); * * // Measure compression ratio * const ratio = gzipped.length / text.length; * console.log(`Compression ratio: ${ratio.toFixed(2)}`); * ``` */ static compress(input: string, method: "lz77" | "gzip"): string; /** * Decompress a string that was compressed using the compress method. * * Reverses the compression applied by the compress method, restoring the * original string. Supports both LZ77 and GZIP decompression algorithms. * * @param input - The compressed string to decompress * @param method - Decompression algorithm to use ('lz77' or 'gzip') * @returns The decompressed original string * * @example * ```typescript * // Round-trip compression * const original = 'This is a long string with repetitive patterns...'; * const compressed = Encoder.compress(original, 'lz77'); * const decompressed = Encoder.decompress(compressed, 'lz77'); * // decompressed === original * * // Error handling * try { * const result = Encoder.decompress('invalid-compressed-data', 'gzip'); * } catch (error) { * console.error('Decompression failed:', error); * } * * // Check decompression success * const result = Encoder.decompress(compressedData, 'lz77'); * if (!result) { * console.error('Decompression returned empty result'); * } * ``` */ static decompress(input: string, method: "lz77" | "gzip"): string; } /** * Configuration options for ID generation. * * Controls every aspect of how an ID is generated — from its size and encoding * to advanced features like expiration, checksums, sequential numbering, and * metadata embedding. All properties are optional; omitting them applies sensible defaults. * * @example Basic usage * ```typescript * const opts: IdGeneratorOptions = { * size: 16, * prefix: 'usr_', * encoding: 'base62', * includeTimestamp: true, * }; * ``` * * @example Preset format shortcut * ```typescript * const opts: IdGeneratorOptions = { format: 'uuid' }; * ``` * * @example URL-safe ID with high entropy * ```typescript * const opts: IdGeneratorOptions = { * size: 32, * randomness: 'crypto', * quality: { urlSafe: true, minEntropy: 'high', avoidPatterns: true }, * }; * ``` * * @example Pattern-based ID (e.g. licence plate) * ```typescript * const opts: IdGeneratorOptions = { pattern: 'AA-9999' }; * // Possible output: "CA-4821" * ``` * * @example Expiring token with checksum * ```typescript * const opts: IdGeneratorOptions = { * expiresIn: 60 * 60 * 1000, // 1 hour in ms * includeChecksum: true, * domain: 'auth', * version: 2, * }; * ``` */ interface IdGeneratorOptions { /** Desired total length of the generated ID (excluding affixes). */ size?: number; /** * Number of segments when generating a multi-part ID. * Each segment is separated by {@link separator}. * * @default 1 * @example * ```typescript * // With segments: 2 and separator: '-' → "aB3x-K9mZ" * { segments: 2, separator: '-', size: 4 } * ``` */ segments?: number; /** * Separator character inserted between each segment. * * @default '-' * @example { segments: 3, separator: '_' } // "abc_def_ghi" */ separator?: string; /** * Encoding scheme(s) to apply during generation. * Pass a single value or an array to chain multiple encodings. * * @example Single encoding * ```typescript * { encoding: 'base62' } * ``` * @example Chained encodings * ```typescript * { encoding: ['base62', 'hex'] } * ``` */ encoding?: ENC_TYPE | ENC_TYPE[]; /** * Custom character alphabet used as the source pool for generation. * Overrides any alphabet implied by {@link encoding} or {@link charset}. * * @example * ```typescript * { alphabet: '0123456789abcdef' } // hexadecimal only * ``` */ alphabet?: string; /** * Compression algorithm applied to the raw bytes before encoding. * * - `'none'` — no compression (default) * - `'lz77'` — fast, lightweight compression * - `'gzip'` — standard gzip compression * * @default 'none' */ compression?: "none" | "lz77" | "gzip"; /** * When `true`, the ID can be decoded back to its original form. * Requires a reversible encoding scheme (e.g. Base64, Base62). * * @default false */ reversible?: boolean; /** * Static string prepended to the generated ID. * * @example * ```typescript * { prefix: 'usr_' } // "usr_aB3xK9mZ" * ``` */ prefix?: string; /** * Shortcut to apply a well-known ID format. * When set, format-specific defaults (size, alphabet, timestamp) are applied automatically. * * | Value | Length | Notes | * |------------|--------|-----------------------------------------| * | `'uuid'` | 36 | RFC 4122, hyphen-separated | * | `'nanoid'` | 21 | URL-safe, uses `size` override if set | * | `'cuid'` | 25 | Collision-resistant, prefixed with `c` | * | `'ksuid'` | 27 | K-Sortable, timestamp-prefixed | * | `'xid'` | 20 | Mongo-compatible, base32-encoded | * | `'pushid'` | 20 | Firebase-style, time-ordered | * * @example * ```typescript * NehoID.generate({ format: 'ksuid' }); * // Output: "0ujzPyRiIAffKhBux4PvQdDqMHY" * ``` */ format?: "uuid" | "nanoid" | "cuid" | "ksuid" | "xid" | "pushid"; /** * When `true`, a Unix millisecond timestamp is embedded in the ID, * enabling chronological sorting. * * @default false */ includeTimestamp?: boolean; /** * Embeds an expiration deadline in the ID as `_exp{epoch_ms}`. * The value is a TTL expressed in **milliseconds** from the moment of generation. * * @example * ```typescript * { expiresIn: 24 * 60 * 60 * 1000 } // expires in 24 h * // Output: "aB3xK9mZ_exp1710000000000" * ``` */ expiresIn?: number; /** * Version tag prepended to the ID as `v{n}_`. * Accepts a number (auto-prefixed with `v`) or a custom string. * * @example * ```typescript * { version: 2 } // "v2_aB3xK9mZ" * { version: 'beta' } // "beta_aB3xK9mZ" * ``` */ version?: number | string; /** * Domain or service identifier prepended as a namespace: `{domain}_{id}`. * Useful for distinguishing IDs across microservices. * * @example * ```typescript * { domain: 'payments' } // "payments_aB3xK9mZ" * ``` */ domain?: string; /** * Fine-grained control over which character categories are included. * Each boolean flag defaults to `true` unless explicitly set to `false`. * * @example Numbers only * ```typescript * { charset: { numbers: true, lowercase: false, uppercase: false } } * ``` * @example Exclude ambiguous characters * ```typescript * { charset: { exclude: ['0', 'O', 'l', 'I'] } } * ``` */ charset?: { /** Include digits `0–9`. @default true */ numbers?: boolean; /** Include lowercase letters `a–z`. @default true */ lowercase?: boolean; /** Include uppercase letters `A–Z`. @default true */ uppercase?: boolean; /** Include printable special characters (`!@#$%^&*…`). @default false */ special?: boolean; /** Characters to remove from the final pool, applied after all inclusions. */ exclude?: string[]; }; /** * Case transformation applied to the final ID string. * * | Value | Description | Example | * |------------|------------------------------------------|------------------| * | `'lower'` | All lowercase | `"abc123def"` | * | `'upper'` | All uppercase | `"ABC123DEF"` | * | `'mixed'` | Random per-character casing | `"AbC1d2EF"` | * | `'camel'` | camelCase (first word lowercase) | `"myOrderId"` | * | `'pascal'` | PascalCase (every word capitalised) | `"MyOrderId"` | * | `'snake'` | snake_case (words joined with `_`) | `"my_order_id"` | */ case?: "lower" | "upper" | "mixed" | "camel" | "pascal" | "snake"; /** * Source of randomness used during generation. * * - `'fast'` — `Math.random()`, fastest but not cryptographically secure. * - `'crypto'` — `crypto.getRandomValues()`, cryptographically secure. * - `'secure'` — Additional entropy hardening on top of crypto. * * @default 'fast' */ randomness?: "fast" | "crypto" | "secure"; /** * Quality constraints applied after generation. * * @example * ```typescript * { * quality: { * minEntropy: 'high', * avoidPatterns: true, * urlSafe: true, * } * } * ``` */ quality?: { /** * Minimum Shannon entropy level required. * IDs that do not meet this threshold are regenerated. * * - `'low'` — ≥ 2 bits/char * - `'medium'` — ≥ 3.5 bits/char * - `'high'` — ≥ 5 bits/char */ minEntropy?: "low" | "medium" | "high"; /** Reject IDs that contain common sequences (`123`, `aaa`, etc.). @default false */ avoidPatterns?: boolean; /** Restrict output to characters safe for use in URLs without encoding. @default false */ urlSafe?: boolean; }; /** * Template string where each placeholder is replaced by a random character. * * | Placeholder | Replaced with | * |-------------|----------------------| * | `X` | Uppercase letter A–Z | * | `A` | Uppercase letter A–Z | * | `a` | Lowercase letter a–z | * | `9` | Digit 0–9 | * | Other chars | Kept as-is | * * @example * ```typescript * { pattern: 'XXX-999' } // e.g. "BKT-472" * { pattern: 'AA-9999' } // e.g. "CA-1834" (licence-plate style) * ``` */ pattern?: string; /** * Emit deterministic sequential IDs scoped to a named context. * Useful as a distributed-safe replacement for database auto-increment. * * @example * ```typescript * { sequential: { context: 'invoices', start: 1000, padLength: 6 } } * // Output: "invoices001000" * ``` */ sequential?: { /** Named scope that isolates the counter from other sequences. */ context: string; /** Initial counter value. @default 1 */ start?: number; /** Zero-pad the counter to this many digits. @default 0 (no padding) */ padLength?: number; }; /** * When `true`, a short DJB2 checksum is appended as `_{checksum}`. * Use {@link NehoID.validate} to verify integrity later. * * @default false * @example * ```typescript * { includeChecksum: true } * // Output: "aB3xK9mZ_3f2a" * ``` */ includeChecksum?: boolean; /** * Arbitrary key-value pairs serialised as Base64 JSON and appended as `_meta{data}`. * Keep payloads small — large objects significantly inflate ID length. * * @example * ```typescript * { metadata: { env: 'prod', source: 'api' } } * // Output: "aB3xK9mZ_meta eyJlbnYiOiJwcm9kIn0=" * ``` */ metadata?: Record<string, unknown>; } /** * Strategy configuration for collision-resistant ID generation. * * When generating IDs that must be unique within an external store (e.g. a database), * use this interface with {@link NehoID.safe} to automatically retry on collision. * * @example Exponential back-off with database check * ```typescript * const id = await NehoID.safe({ * name: 'user-id-check', * maxAttempts: 10, * backoffType: 'exponential', * checkFunction: async (candidate) => { * const exists = await db.users.exists({ id: candidate }); * return !exists; // return true → candidate is unique and accepted * }, * }); * ``` */ interface CollisionStrategy { /** Human-readable name for logging and debugging purposes. */ name: string; /** * Maximum number of generation attempts before throwing an error. * Raise this value when collision probability is high. * * @minimum 1 * @example 50 */ maxAttempts: number; /** * Retry delay strategy applied between consecutive attempts. * * - `'linear'` — constant delay between retries. * - `'exponential'` — delay doubles with each attempt (recommended). */ backoffType: "linear" | "exponential"; /** * Async predicate that returns `true` when the candidate ID is unique * and safe to use, or `false` to trigger another attempt. * * @param id - The candidate ID to validate. * @returns `Promise<boolean>` — `true` if unique, `false` if collision. * * @example * ```typescript * checkFunction: async (id) => !(await redis.exists(`session:${id}`)) * ``` */ checkFunction: (id: string) => Promise<boolean>; } /** * Options for generating IDs that embed environmental context. * * Useful for tracing, analytics, and fraud detection — each flag adds a * fingerprint segment derived from the current runtime environment. * * > ⚠️ **Privacy notice**: Enabling `includeLocation` or `includeDevice` may * > collect personally identifiable information. Ensure compliance with * > applicable privacy regulations (GDPR, CCPA, etc.) before enabling these flags. * * @example * ```typescript * const id = NehoID.contextual({ * includeDevice: true, * includeTimezone: true, * userBehavior: 'checkout', * }); * ``` */ interface ContextOptions { /** Embed a device fingerprint (OS, CPU, memory) in the ID. @default false */ includeDevice?: boolean; /** Embed the IANA timezone string (e.g. `"Europe/Paris"`). @default false */ includeTimezone?: boolean; /** Embed a hash of the browser user-agent string. @default false */ includeBrowser?: boolean; /** Embed screen resolution and colour depth. @default false */ includeScreen?: boolean; /** * Embed a coarse geolocation hash. * Requires user permission and `navigator.geolocation` availability. * * @default false */ includeLocation?: boolean; /** * Custom string describing the current user interaction (e.g. `'login'`, `'purchase'`). * Hashed and embedded as a short segment. * * @example 'add-to-cart' */ userBehavior?: string; } /** * Configuration for generating human-readable, structured semantic IDs. * * Semantic IDs encode business context directly in the identifier, making * them self-documenting while remaining unique. * * @example * ```typescript * const id = NehoID.semantic({ * prefix: 'ORD', * region: 'EU-WEST', * department: 'SALES', * year: 2025, * customSegments: { channel: 'web' }, * }); * // Possible output: "ORD-EU-WEST-SALES-2025-web-x7k2" * ``` */ interface SemanticOptions { /** Static business prefix (e.g. `'ORD'`, `'INV'`, `'TKT'`). */ prefix?: string; /** * Geographic region code embedded in the ID. * * @example 'US-WEST' | 'EU-CENTRAL' | 'APAC' */ region?: string; /** * Organisational unit or department code. * * @example 'SALES' | 'OPS' | 'ENG' */ department?: string; /** * Four-digit year component for temporal organisation. * * @example 2025 */ year?: number; /** * Additional domain-specific segments as key-value pairs. * Each entry is appended in insertion order. * * @example { channel: 'mobile', tier: 'premium' } */ customSegments?: Record<string, string | number>; } /** * Options for generating multiple IDs in a single operation. * * @example Standard batch * ```typescript * const ids = NehoID.batch({ count: 50, format: 'uuid', ensureUnique: true }); * ``` * * @example High-throughput parallel batch * ```typescript * const ids = NehoID.batch({ count: 10_000, format: 'nano', parallel: true }); * ``` */ interface BatchOptions { /** * Number of IDs to produce. * * @minimum 1 */ count: number; /** * ID format applied uniformly across the batch. * * | Value | Description | * |--------------|------------------------------------| * | `'standard'` | Default NehoID format | * | `'nano'` | NanoID-compatible, 21 chars | * | `'short'` | Short alphanumeric, 8 chars | * | `'uuid'` | RFC 4122 UUID, 36 chars | * * @default 'standard' */ format?: "standard" | "nano" | "short" | "uuid"; /** * Generate IDs in parallel using worker threads when available. * Significantly improves throughput for large batches (> 1 000 IDs). * * @default false */ parallel?: boolean; /** * Deduplicate the output so every ID in the batch is distinct. * Slightly reduces throughput for very large batches. * * @default true */ ensureUnique?: boolean; } /** * Options controlling what aspects of an ID are validated. * * @example Full validation * ```typescript * const valid = NehoID.validate(id, { * checkFormat: true, * checkCollisions: true, * repairCorrupted: false, * }); * ``` */ interface ValidationOptions { /** * Verify that the ID conforms to its declared format (length, alphabet, prefix, checksum). * * @default true */ checkFormat?: boolean; /** * Check whether the ID already exists in the configured store. * Requires a collision back-end to be registered via `NehoID.configure()`. * * @default false */ checkCollisions?: boolean; /** * Attempt to recover a structurally damaged ID (e.g. truncated, bad checksum). * Returns the repaired string if possible; `false` otherwise. * * @default false */ repairCorrupted?: boolean; } /** * Detailed quality assessment of a generated ID. * * Returned by {@link NehoID.healthCheck}. A score of `1.0` represents a * cryptographically ideal ID; `0.0` represents a trivially guessable one. * * @example * ```typescript * const health = NehoID.healthCheck('usr_aB3xK9mZ'); * // { * // score: 0.91, * // entropy: 'high', * // predictability: 'low', * // recommendations: [], * // } * ``` */ interface HealthScore { /** * Overall quality score in the range `[0.0, 1.0]`. * Higher values indicate better randomness and uniqueness guarantees. */ score: number; /** * Shannon entropy classification of the ID's character distribution. * * - `'low'` — < 2 bits/char, easily guessable. * - `'medium'` — 2–4 bits/char, moderate security. * - `'high'` — > 4 bits/char, suitable for security tokens. */ entropy: "low" | "medium" | "high"; /** * Likelihood that the ID could be predicted or enumerated by an attacker. * * - `'high'` — sequential or pattern-based, avoid for sensitive use-cases. * - `'medium'` — some structure present. * - `'low'` — effectively random. */ predictability: "low" | "medium" | "high"; /** * Actionable suggestions for improving ID quality. * Empty array when no improvements are needed. * * @example ["Increase size to at least 16", "Use 'crypto' randomness source"] */ recommendations: string[]; } /** * Runtime performance and health statistics for the ID generation system. * * Populated by the internal {@link Monitor} after {@link NehoID.startMonitoring} is called. * * @example * ```typescript * NehoID.startMonitoring(); * // ... run workload ... * const stats = NehoID.getStats(); * console.log(`Generated: ${stats.generated} | Avg: ${stats.averageGenerationTime}`); * ``` */ interface Stats { /** Total number of IDs successfully generated during the monitoring session. */ generated: number; /** * Number of collision events detected. * A non-zero value indicates ID space exhaustion or a low-quality generator config. */ collisions: number; /** * Human-readable average generation latency (e.g. `"0.043 ms"`). * Computed as a rolling mean over all generation calls. */ averageGenerationTime: string; /** * Current heap memory consumed by internal caches and counters (e.g. `"4.2 MB"`). */ memoryUsage: string; /** * Chi-squared distribution quality score in `[0.0, 1.0]`. * Values close to `1.0` indicate a uniform ID distribution (ideal). * Values below `0.7` may indicate a biased generator. */ distributionScore: number; } /** * Configuration for bulk-migrating IDs between formats. * * Use this with {@link NehoID.migrate} to convert legacy IDs (e.g. plain UUIDs) * to a richer NehoID format without losing referential integrity. * * @example Migrate a list of UUIDs to NehoID format * ```typescript * const newIds = await NehoID.migrate({ * from: 'uuid', * to: 'nehoid', * preserveOrder: true, * batchSize: 500, * ids: legacyUuids, * }); * ``` * * @example Migrate the first 1 000 records from a store * ```typescript * const newIds = await NehoID.migrate({ * from: 'legacy-numeric', * to: 'ksuid', * count: 1000, * batchSize: 100, * }); * ``` */ interface MigrationOptions { /** Format identifier of the source IDs (e.g. `'uuid'`, `'legacy-numeric'`). */ from: string; /** Format identifier for the output IDs (e.g. `'nehoid'`, `'ksuid'`). */ to: string; /** * Preserve the original chronological ordering of IDs in the output array. * When `false`, output order is not guaranteed (may be faster). * * @default true */ preserveOrder?: boolean; /** * Number of IDs processed per internal batch to limit memory pressure. * Tune this based on available heap and source record size. * * @default 100 * @minimum 1 */ batchSize?: number; /** * Explicit list of source IDs to migrate. * When provided, takes precedence over {@link count}. */ ids?: string[]; /** * Maximum number of IDs to migrate from the configured source store. * Ignored when {@link ids} is provided. */ count?: number; } /** * Options for generating IDs that are valid across multiple platforms and languages. * * Different runtimes impose constraints on string length, character sets, and * integer overflow. This interface ensures the output ID satisfies all target platforms. * * @example * ```typescript * const id = NehoID.compatible({ * platform: ['javascript', 'python', 'go'], * format: 'alphanumeric', * length: 16, * }); * ``` */ interface CompatibilityOptions { /** * Target platforms the ID must be usable on without transformation. * The generator applies the most restrictive constraint set across all listed platforms. * * | Platform | Key constraints | * |----------------|------------------------------------------------| * | `'javascript'` | UTF-16, `Number.MAX_SAFE_INTEGER` limit | * | `'python'` | UTF-8, arbitrary precision integers | * | `'go'` | UTF-8, fixed-size integer types | */ platform: Array<"javascript" | "python" | "go">; /** * Named character set or format the ID must conform to. * * @example 'alphanumeric' | 'hex' | 'base62' | 'uuid' */ format: string; /** * Exact character length of the generated ID. * * @minimum 1 * @example 16 */ length: number; } /** * Specialized ID generators for NehoID * Implements hierarchical, temporal, and sequential ID generation */ declare class Specialized { /** * Generates a hierarchical ID with parent-child relationships * @param parent Optional parent ID to create a child under * @param level Hierarchy level (defaults to 1 if no parent, otherwise parent level + 1) * @param separator Character to separate hierarchy levels * @returns A hierarchical ID */ static hierarchical(options?: { parent?: string; level?: number; separator?: string; }): string; /** * Generates a time-ordered ID for chronological sorting * @param precision Time precision ('ms', 's', 'm', 'h', 'd') * @param suffix Whether to add a random suffix for uniqueness * @returns A temporal ID with timestamp */ static temporal(options?: { precision?: 'ms' | 's' | 'm' | 'h' | 'd'; suffix?: boolean; format?: 'hex' | 'dec' | 'b36'; }): string; /** * Generates a sequential ID suitable for database use * @param prefix Optional prefix for the ID * @param counter Current counter value * @param padLength Length to pad the counter to * @returns A sequential ID */ static sequential(options: { prefix?: string; counter: number; padLength?: number; suffix?: boolean; }): string; /** * Generates a temporal ID from a specific timestamp * @param timestamp Unix timestamp in milliseconds * @param precision Time precision ('ms', 's', 'm', 'h', 'd') * @param suffix Whether to add a random suffix for uniqueness * @param format Timestamp format ('hex' | 'dec' | 'b36') * @returns A temporal ID with the specified timestamp */ static fromTemporal(timestamp: number, options?: { precision?: 'ms' | 's' | 'm' | 'h' | 'd'; suffix?: boolean; format?: 'hex' | 'dec' | 'b36'; }): string; /** * Extracts timestamp from a temporal ID * @param temporalId The temporal ID to extract timestamp from * @param precision Time precision used in the temporal ID ('ms', 's', 'm', 'h', 'd') * @param format Timestamp format used in the temporal ID ('hex' | 'dec' | 'b36') * @returns Unix timestamp in milliseconds * @throws Error if the temporal ID format is invalid */ static fromTemporalToTimestamp(temporalId: string, options?: { precision?: 'ms' | 's' | 'm' | 'h' | 'd'; format?: 'hex' | 'dec' | 'b36'; }): number; } /** * Specialized ID generation methods for advanced use cases. * * This module provides generators for hierarchical relationships, time-ordered IDs, * and sequential identifiers. These specialized generators are designed for specific * architectural patterns and data modeling requirements. */ declare class SpecializedGenerators { /** * Generates a hierarchical ID with parent-child relationships. * * Creates IDs that encode hierarchical structures, making it easy to query * and navigate tree-like data relationships. The ID format supports efficient * ancestor and descendant queries in databases. * * @param options - Configuration options for hierarchical generation * @returns A hierarchical ID string with encoded relationship information * * @example * ```typescript * // Basic hierarchical ID * const rootId = SpecializedGenerators.hierarchical(); * * // Child ID with parent reference * const childId = SpecializedGenerators.hierarchical({ * parentId: rootId, * level: 1 * }); * * // Deep hierarchy * const grandchildId = SpecializedGenerators.hierarchical({ * parentId: childId, * level: 2, * maxDepth: 5 * }); * ``` * * @example * ```typescript * // Database queries with hierarchical IDs * // Find all descendants of a node * const descendants = await db.collection.find({ * hierarchicalId: { $regex: `^${parentId}` } * }); * * // Find direct children * const children = await db.collection.find({ * parentId: parentId * }); * ``` */ static hierarchical(options?: Record<string, any>): string; /** * Generates a time-ordered ID for chronological sorting and pagination. * * Creates IDs that sort chronologically by embedding timestamp information. * This enables efficient time-based queries and pagination without requiring * separate timestamp columns. * * @param options - Configuration options for temporal generation * @returns A temporal ID string with embedded timestamp for natural sorting * * @example * ```typescript * // Basic temporal ID (current timestamp) * const eventId = SpecializedGenerators.temporal(); * * // Custom timestamp * const pastEventId = SpecializedGenerators.temporal({ * timestamp: new Date('2023-01-01').getTime() * }); * * // High precision temporal ID * const preciseId = SpecializedGenerators.temporal({ * precision: 'nanoseconds', * includeRandom: true * }); * ``` * * @example * ```typescript * // Time-based pagination * const recentEvents = await db.collection.find({ * temporalId: { $gt: lastEventId } * }).sort({ temporalId: 1 }).limit(50); * * // Events from specific time range * const startTime = SpecializedGenerators.temporal({ * timestamp: Date.now() - (24 * 60 * 60 * 1000) // 24 hours ago * }); * const todaysEvents = await db.collection.find({ * temporalId: { $gte: startTime } * }); * ``` */ static temporal(...options: Parameters<typeof Specialized.temporal>): string; /** * Generates a sequential ID suitable for database primary keys. * * Creates human-readable sequential identifiers that can replace auto-incrementing * integers in databases. Supports prefixes, padding, and custom formatting * for business logic requirements. * * @param options - Configuration options for sequential generation * @returns A formatted sequential ID string * * @example * ```typescript * // Simple sequential ID * const id = SpecializedGenerators.sequential({ * counter: 1001 * }); * // Output: '1001' * * // With prefix and padding * const orderId = SpecializedGenerators.sequential({ * prefix: 'ORD', * counter: 42, * padLength: 6 * }); * // Output: 'ORD000042' * * // With suffix * const invoiceId = SpecializedGenerators.sequential({ * prefix: 'INV', * counter: 123, * suffix: true * }); * // Output: 'INV123' * ``` * * @example * ```typescript * // Database schema with sequential IDs * const userSchema = new mongoose.Schema({ * _id: { * type: String, * default: () => SpecializedGenerators.sequential({ * prefix: 'USR', * counter: await getNextUserCounter() * }) * }, * name: String * }); * ``` */ /** * Generates a temporal ID from a timestamp. * * Converts a Unix timestamp into a temporal ID that can be used for * chronological sorting and time-based queries. The temporal ID format * includes encoded timestamp information for efficient database indexing. * * @param timestamp - Unix timestamp in milliseconds * @returns A temporal ID string containing the encoded timestamp * * @example * ```typescript * // Generate temporal ID from current time * const temporalId = SpecializedGenerators.fromTemporal(Date.now()); * * // Generate temporal ID from specific date * const pastTemporalId = SpecializedGenerators.fromTemporal( * new Date('2023-01-01').getTime() * ); * * // Use in database queries * const recentEvents = await db.collection.find({ * temporalId: { $gte: SpecializedGenerators.fromTemporal(Date.now() - 86400000) } * }); * ``` */ static fromTemporal(timestamp: number, options?: Parameters<typeof Specialized.fromTemporal>[1]): string; /** * Extracts timestamp from a temporal ID. * * Reverses the temporal ID generation process to recover the original * Unix timestamp. This is useful for converting temporal IDs back to * human-readable dates or for time-based calculations. * * @param temporalId - Temporal ID string to extract timestamp from * @returns Unix timestamp in milliseconds * @throws {Error} If the temporal ID format is invalid * * @example * ```typescript * // Extract timestamp from temporal ID * const temporalId = SpecializedGenerators.fromTemporal(Date.now()); * const timestamp = SpecializedGenerators.fromTemporalToTimestamp(temporalId); * * // Convert back to Date object * const date = new Date(timestamp); * console.log(date.toISOString()); * * // Calculate time differences * const age = Date.now() - timestamp; * const hoursOld = age / (1000 * 60 * 60); * ``` * * @example * ```typescript * // Error handling * try { * const timestamp = SpecializedGenerators.fromTemporalToTimestamp('invalid-id'); * } catch (error) { * console.error('Invalid temporal ID format'); * } * ``` */ static fromTemporalToTimestamp(temporalId: string, options?: Parameters<typeof Specialized.fromTemporalToTimestamp>[1]): number; static sequential(options: { prefix?: string; counter: number; padLength?: number; suffix?: boolean; }): string; } /** * Central facade for all ID generation, validation, monitoring, and migration * operations provided by the NehoID library. * * Every public method is **static** — no instantiation required. Internally the * class delegates to specialised sub-modules ({@link Generator}, {@link Validators}, * {@link Monitor}, {@link Advanced}, etc.) and adds orchestration, option * pre-processing, and monitoring instrumentation on top. * * --- * * ### Quick-start * * ```typescript * import { NehoID } from 'nehoid'; * * // ── Simple generation ────────────────────────────────────────────────────── * const id = NehoID.generate(); // default settings * const uuid = NehoID.generate({ format: 'uuid' }); // RFC 4122 UUID * const nano = NehoID.nanoid(16); // NanoID, length 16 * const hex = NehoID.hex(32); // 32-char hex string * * // ── Collision-safe async generation ─────────────────────────────────────── * const safeId = await NehoID.safe({ * name: 'user-id', * maxAttempts: 10, * backoffType: 'exponential', * checkFunction: async (candidate) => !(await db.exists(candidate)), * }); * * // ── Bulk generation ──────────────────────────────────────────────────────── * const ids = NehoID.batch({ count: 500, format: 'uuid', ensureUnique: true }); * * // ── Validation ───────────────────────────────────────────────────────────── * const ok = NehoID.validate(id); * const health = NehoID.healthCheck(id); * * // ── Monitoring ───────────────────────────────────────────────────────────── * NehoID.startMonitoring(); * const stats = NehoID.getStats(); * NehoID.stopMonitoring(); * ``` */ declare class NehoID { private constructor(); /** * Replaces pattern placeholders with random characters. * * Recognised placeholders: * - `X` / `A` → random uppercase letter (A–Z) * - `a` → random lowercase letter (a–z) * - `9` → random digit (0–9) * * All other characters are kept verbatim. * * @param pattern - Template string (e.g. `'XXX-999'`). * @returns Resolved pattern string (e.g. `'BKT-472'`). */ private static generateFromPattern; /** * Derives an alphabet string from a {@link IdGeneratorOptions.charset} descriptor. * * @param charset - Charset descriptor from caller options. * @returns Combined alphabet string, or `undefined` if the descriptor is empty. */ private static buildAlphabetFromCharset; /** * Applies format-specific defaults for preset format shortcuts. * * Mutates `processedOptions` in place and may return early with a fully * formed ID for formats that have their own dedicated generators. * * @param format - The requested preset format. * @param originalOptions - The raw caller options (read-only). * @param processedOptions - Options object being built for the core generator. * @returns An early-exit ID string for `'uuid'` and `'nanoid'`, or `undefined`. */ private static applyFormatPreset; /** * Applies a case transformation to an ID string. * * @param id - The raw ID string. * @param caseMode - Desired case transformation. * @returns Transformed string. */ private static applyCase; /** * Generates a unique ID with optional configuration. * * This is the primary entry point for ID generation. It supports preset format * shortcuts, fine-grained character control, case transformations, expiration * timestamps, versioning, domains, sequential numbering, pattern templates, * metadata embedding, and checksum appending — all composable in a single call. * * > **Performance note**: For bulk generation prefer {@link NehoID.batch}, which * > avoids per-call monitoring overhead and can run in parallel. * * @param options - Generation options. All properties are optional. * @returns A newly generated unique ID string. * * @throws {RangeError} If `options.size` is defined and less than 1. * @throws {TypeError} If `options.sequential.padLength` is negative. * * @example Preset formats * ```typescript * NehoID.generate({ format: 'uuid' }); // "550e8400-e29b-41d4-a716-446655440000" * NehoID.generate({ format: 'nanoid' }); // "V1StGXR8_Z5jdHi6B-myT" * NehoID.generate({ format: 'ksuid' }); // "0ujzPyRiIAffKhBux4PvQdDqMHY" * ``` * * @example Custom size, segments & separator * ```typescript * NehoID.generate({ size: 4, segments: 3, separator: '.' }); * // "aB3x.K9mZ.tR8q" * ``` * * @example Prefix, case & charset control * ```typescript * NehoID.generate({ * prefix: 'USR', * case: 'lower', * charset: { numbers: true, uppercase: false } * }); * // "usr_3f2a9c1b" * ``` * * @example Pattern template * ```typescript * NehoID.generate({ pattern: 'AA-9999' }); // "CA-1834" * NehoID.generate({ pattern: 'XXX-XXX' }); // "BKT-ZMP" * ``` * * @example Compression & Encoding * ```typescript * NehoID.generate({ * encoding: 'base64', * compression: 'lz77' * }); * ``` * * @example Expiring security token * ```typescript * NehoID.generate({ * size: 32, * randomness: 'crypto', * expiresIn: 15 * 60 * 1000, // 15 minutes * domain: 'auth', * includeChecksum: true, * }); * ``` * * @example Sequential order IDs * ```typescript * NehoID.generate({ * sequential: { context: 'orders', start: 1000, padLength: 6 }, * }); * // "orders001000" * ``` * * @example Embedded metadata * ```typescript * NehoID.generate({ * metadata: { env: 'prod', source: 'api-v3' }, * includeTimestamp: true, * }); * ``` */ static generate(options?: Partial<IdGeneratorOptions>): string; /** * Generates a collision-safe ID by validating each candidate against an * external uniqueness predicate before returning it. * * The method retries up to {@link CollisionStrategy.maxAttempts} times with * the configured back-off strategy. If all attempts fail, it throws an error * and increments the collision counter in {@link Monitor}. * * @param options - Collision strategy including the async uniqueness check. * @returns A promise that resolves to a guaranteed-unique ID string. * @throws {Error} When `maxAttempts` is exhausted without finding a unique ID. * * @example Database uniqueness check * ```typescript * const id = await NehoID.safe({ * name: 'order-id-check', * maxAttempts: 10, * backoffType: 'exponential', * checkFunction: async (candidate) => { * return !(await db.orders.exists({ id: candidate })); * }, * }); * ``` * * @example Redis cache token * ```typescript * const token = await NehoID.safe({ * name: 'session-token', * maxAttempts: 5, * backoffType: 'linear', * checkFunction: async (t) => !(await redis.exists(`sess:${t}`)), * }); * ``` */ static safe(options: CollisionStrategy): Promise<string>; /** * Generates a RFC 4122 v4 UUID. * * @returns A hyphen-separated UUID string (36 characters). * * @example * ```typescript * NehoID.uuid(); // "550e8400-e29b-41d4-a716-446655440000" * ``` */ static uuid(): string; /** * Generates a NanoID using URL-safe characters. * * NanoIDs are compact, URL-safe, and statistically collision-resistant. * The default length of 21 chars provides ~126 bits of entropy. * * @param length - Character length of the output. @default 21 * @returns A NanoID string. * * @example * ```typescript * NehoID.nanoid(); // "V1StGXR8_Z5jdHi6B-myT" (21 chars) * NehoID.nanoid(10); // "IRFa-VaY2b" (10 chars) * ``` */ static nanoid(length?: number): string; /** * Generates a short, compact alphanumeric ID. * * Useful for human-readable references (order numbers, share codes, etc.) * where brevity matters more than maximum entropy. * * @param length - Character length of the output. @default 8 * @returns A short alphanumeric string. * * @example * ```typescript * NehoID.short(); // "aB3xK9mZ" (8 chars) * NehoID.short(12); // "aB3xK9mZtR8q" * ``` */ static short(length?: number): string; /** * Generates a random hexadecimal string. * * @param length - Character length of the output. @default 16 * @returns A lowercase hexadecimal string. * * @example * ```typescript * NehoID.hex(); // "3f2a9c1b4e7d8f0a" (16 chars) * NehoID.hex(32); // "3f2a9c1b4e7d8f0a1c3e5b7d9f2a4c6e" * ``` */ static hex(length?: number): string; /** * Generates a hierarchical ID encoding a parent-child relationship. * * Hierarchical IDs preserve the ancestry chain in the identifier itself, * enabling efficient tree traversal without additional database joins. * * @param options - Hierarchical generation options. * @returns A hierarchical ID string with encoded relationship segments. * * @example * ```typescript * const child = NehoID.hierarchical({ parentId: 'root-abc123', depth: 2 }); * // "root-abc123.L2.xK9m" * ``` */ static hierarchical(options?: Record<string, unknown>): string; /** * Generates a time-ordered ID suitable for chronological sorting. * * Temporal IDs embed a timestamp prefix so that lexicographic order matches * insertion order — ideal for event logs, message queues, and time-series data. * * @param options - Temporal generation options (precision, random suffix, etc.). * @returns A temporal ID string with an embedded timestamp prefix. * * @example * ```typescript * const id = NehoID.temporal({ precision: 'milliseconds', suffix: true }); * // "01HX3KBPM4-aB3x" * ``` */ static temporal(...options: Parameters<typeof SpecializedGenerators.temporal>): string; /** * Converts a Unix timestamp (milliseconds) into a temporal ID. * * Allows back-dated or future-dated IDs to be generated from arbitrary * epoch values without going through the standard clock. * * @param timestamp - Unix epoch in milliseconds. * @returns A temporal ID string derived from the given timestamp. * @throws {RangeError} If `timestamp` is negative. * * @example * ```typescript * NehoID.fromTemporal(Date.now()); // current-time