🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

uniku

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

uniku - npm Package Compare versions

Comparing version
0.4.3
to
0.5.0
+67
build/errors-Da-8dh4J.d.mts
import { n as IdGenerator } from "./generators-BfJLt7Qf.mjs";
//#region src/errors.d.ts
/**
* The canonical, ordered list of machine-readable error codes emitted by
* uniku's public API.
*
* Codes describe the failure independently of an ID format. Use an error's
* `strategy` field when the generator that raised it matters.
*/
declare const ERROR_CODES: readonly ["TIMESTAMP_OUT_OF_RANGE", "CONFLICTING_OPTIONS", "COUNTER_OUT_OF_RANGE", "NODE_OUT_OF_RANGE", "NODE_BITS_OUT_OF_RANGE", "EPOCH_INVALID", "PROCESS_ID_OUT_OF_RANGE", "MACHINE_ID_BYTES_TOO_SHORT", "RANDOM_BYTES_TOO_SHORT", "RANDOM_OVERFLOW", "LENGTH_OUT_OF_RANGE", "ALPHABET_OUT_OF_RANGE", "ALPHABET_INVALID_CHAR", "ALPHABET_DUPLICATE", "PREFIX_TOO_LONG", "PREFIX_INVALID_CHAR", "PREFIX_INVALID_BOUNDARY", "UUID_NOT_V7", "BYTES_INVALID_LENGTH", "BUFFER_OUT_OF_BOUNDS", "INVALID_CHAR", "INVALID_LENGTH", "INVALID_FORMAT", "NON_CANONICAL", "VALUE_OUT_OF_RANGE"];
/**
* A machine-readable error code emitted by uniku, derived from
* {@link ERROR_CODES}.
*/
type ErrorCode = (typeof ERROR_CODES)[number];
/**
* Extra context carried by every uniku error.
*/
type UniqueIdErrorOptions = {
/**
* The ID strategy whose public boundary raised the error.
* Error codes are strategy-agnostic (e.g. `TIMESTAMP_OUT_OF_RANGE`), so this
* field attributes the failure to the generator that produced it.
*/
readonly strategy?: IdGenerator;
};
/**
* Base error for all uniku errors.
* Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`),
* `code` for machine-readable error identification, and `strategy` to attribute
* unified codes to the ID generator that raised them.
*/
declare abstract class UniqueIdError extends Error {
abstract readonly _tag: string;
abstract readonly code: ErrorCode;
/** The ID strategy whose public boundary raised the error. */
readonly strategy?: IdGenerator;
constructor(message: string, options?: UniqueIdErrorOptions);
}
/**
* Thrown when generator arguments are invalid (bad size, alphabet, length, timestamp, version).
*/
declare class InvalidInputError extends UniqueIdError {
readonly code: ErrorCode;
readonly _tag = "InvalidInputError";
constructor(code: ErrorCode, message: string, options?: UniqueIdErrorOptions);
}
/**
* Thrown when parsing/decoding an ID string that has invalid format or characters.
*/
declare class ParseError extends UniqueIdError {
readonly code: ErrorCode;
readonly _tag = "ParseError";
constructor(code: ErrorCode, message: string, options?: UniqueIdErrorOptions);
}
/**
* Thrown when a byte array or buffer is too short or an offset is out of bounds.
*/
declare class BufferError extends UniqueIdError {
readonly code: ErrorCode;
readonly _tag = "BufferError";
constructor(code: ErrorCode, message: string, options?: UniqueIdErrorOptions);
}
//#endregion
export { ParseError as a, InvalidInputError as i, ERROR_CODES as n, UniqueIdError as o, ErrorCode as r, UniqueIdErrorOptions as s, BufferError as t };
//# sourceMappingURL=errors-Da-8dh4J.d.mts.map
{"version":3,"file":"errors-Da-8dh4J.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;;AAWA;;;;AAyBE;cAzBW,WAAA;;;;AAgCmB;KAApB,SAAA,WAAoB,WAAA;;;;KAKpB,oBAAA;EAeZ;;;;;EAAA,SATW,QAAA,GAAW,WAAA;AAAA;;;;;;;uBASA,aAAA,SAAsB,KAAA;EAAA,kBACxB,IAAA;EAAA,kBACA,IAAA,EAAM,SAAA;;WAGf,QAAA,GAAW,WAAA;EAEpB,WAAA,CAAY,OAAA,UAAiB,OAAA,GAAU,oBAAA;AAAA;AAAA;AAUzC;;AAVyC,cAU5B,iBAAA,SAA0B,aAAA;EAAA,SAInC,IAAA,EAAe,SAAA;EAAA,SAHR,IAAA;EAET,WAAA,CACE,IAAA,EAAe,SAAA,EACf,OAAA,UACA,OAAA,GAAU,oBAAA;AAAA;;;;cASD,UAAA,SAAmB,aAAA;EAAA,SAI5B,IAAA,EAAe,SAAA;EAAA,SAHR,IAAA;EAET,WAAA,CACE,IAAA,EAAe,SAAA,EACf,OAAA,UACA,OAAA,GAAU,oBAAA;AAAA;;;;cASD,WAAA,SAAoB,aAAA;EAAA,SAI7B,IAAA,EAAe,SAAA;EAAA,SAHR,IAAA;EAET,WAAA,CACE,IAAA,EAAe,SAAA,EACf,OAAA,UACA,OAAA,GAAU,oBAAA;AAAA"}
//#region src/generators.d.ts
/**
* The canonical, ordered list of ID generators supported by uniku.
*
* This is the single source of truth for the set of supported ID generators.
* Tools that need to enumerate or validate ID generators (for example,
* `@uniku/cli`'s `--type` flag) should derive from this array rather than
* hand-copying the union.
*/
declare const ID_GENERATORS: readonly ["uuid", "ulid", "typeid", "nanoid", "cuid", "ksuid", "objectid", "tsid", "xid"];
/**
* The union of ID generators supported by uniku, derived from {@link ID_GENERATORS}.
*/
type IdGenerator = (typeof ID_GENERATORS)[number];
//#endregion
export { IdGenerator as n, ID_GENERATORS as t };
//# sourceMappingURL=generators-BfJLt7Qf.d.mts.map
{"version":3,"file":"generators-BfJLt7Qf.d.mts","names":[],"sources":["../src/generators.ts"],"mappings":";;AAWA;;;;AAAuG;AAKvG;;cALa,aAAA;;AAKqB;;KAAtB,WAAA,WAAsB,aAAA"}
import{t as e}from"./validation-CTNpXm94.mjs";import{InvalidInputError as t}from"./errors.mjs";function n(n,r,i,a){let{msecs:o,secs:s}=n;if(o!==void 0&&s!==void 0)throw new t(`CONFLICTING_OPTIONS`,"Pass only one of `msecs` or `secs`, not both",{strategy:a});if(o!==void 0){let n=r*1e3,s=i*1e3+999;if(!e(o,n,s))throw new t(`TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between ${n} and ${s} milliseconds`,{strategy:a});return Math.floor(o/1e3)}if(s!==void 0){if(!e(s,r,i))throw new t(`TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between ${r} and ${i} seconds`,{strategy:a});return s}}export{n as t};
//# sourceMappingURL=timestamp-ChrSuQCR.mjs.map
{"version":3,"file":"timestamp-ChrSuQCR.mjs","names":[],"sources":["../src/common/timestamp.ts"],"sourcesContent":["import { InvalidInputError } from '../errors'\nimport type { IdGenerator } from '../generators'\nimport { isIntegerInRange } from './validation'\n\n/**\n * Timestamp options accepted by second-precision generators (ksuid, objectid,\n * xid) during the pre-v1 transition to unified millisecond inputs.\n */\nexport type TimestampSecsOptions = {\n /**\n * Timestamp in milliseconds since the Unix epoch.\n * The generator stores whole seconds, so sub-second precision is truncated.\n */\n msecs?: number\n /**\n * Timestamp in seconds since the Unix epoch.\n *\n * @deprecated Use `msecs` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n secs?: number\n}\n\n/**\n * Resolve caller-provided timestamp options to whole seconds since the Unix\n * epoch, or `undefined` when neither option was supplied.\n *\n * `msecs` is the unified input and is truncated to whole seconds; `secs` is\n * the deprecated pre-v1 alias. Passing both is an error.\n *\n * TODO(v1-rc): drop the `secs` branch once the alias is removed.\n */\nexport function resolveTimestampSecs(\n options: TimestampSecsOptions,\n minSecs: number,\n maxSecs: number,\n strategy: IdGenerator,\n): number | undefined {\n const { msecs, secs } = options\n\n if (msecs !== undefined && secs !== undefined) {\n throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `msecs` or `secs`, not both', { strategy })\n }\n\n if (msecs !== undefined) {\n const minMsecs = minSecs * 1000\n const maxMsecs = maxSecs * 1000 + 999\n if (!isIntegerInRange(msecs, minMsecs, maxMsecs)) {\n throw new InvalidInputError(\n 'TIMESTAMP_OUT_OF_RANGE',\n `Timestamp must be an integer between ${minMsecs} and ${maxMsecs} milliseconds`,\n { strategy },\n )\n }\n return Math.floor(msecs / 1000)\n }\n\n if (secs !== undefined) {\n if (!isIntegerInRange(secs, minSecs, maxSecs)) {\n throw new InvalidInputError(\n 'TIMESTAMP_OUT_OF_RANGE',\n `Timestamp must be an integer between ${minSecs} and ${maxSecs} seconds`,\n { strategy },\n )\n }\n return secs\n }\n\n return undefined\n}\n"],"mappings":"+FAgCA,SAAgB,EACd,EACA,EACA,EACA,EACoB,CACpB,GAAM,CAAE,QAAO,QAAS,EAExB,GAAI,IAAU,IAAA,IAAa,IAAS,IAAA,GAClC,MAAM,IAAI,EAAkB,sBAAuB,+CAAgD,CAAE,UAAS,CAAC,EAGjH,GAAI,IAAU,IAAA,GAAW,CACvB,IAAM,EAAW,EAAU,IACrB,EAAW,EAAU,IAAO,IAClC,GAAI,CAAC,EAAiB,EAAO,EAAU,CAAQ,EAC7C,MAAM,IAAI,EACR,yBACA,wCAAwC,EAAS,OAAO,EAAS,eACjE,CAAE,UAAS,CACb,EAEF,OAAO,KAAK,MAAM,EAAQ,GAAI,CAChC,CAEA,GAAI,IAAS,IAAA,GAAW,CACtB,GAAI,CAAC,EAAiB,EAAM,EAAS,CAAO,EAC1C,MAAM,IAAI,EACR,yBACA,wCAAwC,EAAQ,OAAO,EAAQ,UAC/D,CAAE,UAAS,CACb,EAEF,OAAO,CACT,CAGF"}
import{BufferError as e,ParseError as t}from"./errors.mjs";function n(e){return e>=48&&e<=57?e-48:e>=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:-1}const r=[0,0,1,1,2,2,3,3,-1,4,4,5,5,-1,6,6,7,7,-1,8,8,9,9,-1,10,10,11,11,12,12,13,13,14,14,15,15],i=[!0,!1,!0,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!0,!1,!0,!1,!0,!1,!0,!1],a=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,`0`));function o(t){if(t.length!==16)throw new e(`BYTES_INVALID_LENGTH`,`UUID bytes must be exactly 16 bytes, got ${t.length}`,{strategy:`uuid`});return s(t)}function s(e){return a[e[0]]+a[e[1]]+a[e[2]]+a[e[3]]+`-`+a[e[4]]+a[e[5]]+`-`+a[e[6]]+a[e[7]]+`-`+a[e[8]]+a[e[9]]+`-`+a[e[10]]+a[e[11]]+a[e[12]]+a[e[13]]+a[e[14]]+a[e[15]]}function c(e){if(e.length!==36)throw new t(`INVALID_LENGTH`,`UUID string must be 36 characters, got ${e.length}`,{strategy:`uuid`});if(e[8]!==`-`||e[13]!==`-`||e[18]!==`-`||e[23]!==`-`)throw new t(`INVALID_FORMAT`,`UUID string has invalid separators at positions 8, 13, 18, 23. Received: "${e}"`,{strategy:`uuid`});let a=new Uint8Array(16);for(let o=0;o<36;o+=1){let s=r[o];if(s===-1)continue;let c=n(e.charCodeAt(o));if(c===-1)throw new t(`INVALID_CHAR`,`UUID string contains invalid hex character at position ${o}`,{strategy:`uuid`});i[o]?a[s]=c<<4:a[s]|=c}return a}export{s as n,c as r,o as t};
//# sourceMappingURL=uuid-BPebYihz.mjs.map
{"version":3,"file":"uuid-BPebYihz.mjs","names":[],"sources":["../src/uuid/common/hex.ts","../src/uuid/common/uuid.ts"],"sourcesContent":["// ASCII code ranges for hex character validation\nconst ASCII_0 = 48 // '0'\nconst ASCII_9 = 57 // '9'\nconst ASCII_A = 65 // 'A'\nconst ASCII_F = 70 // 'F'\nconst ASCII_a = 97 // 'a'\nconst ASCII_f = 102 // 'f'\n\n/**\n * Convert a hex character ASCII code to its numeric value (0-15).\n * Returns -1 for invalid hex characters.\n */\nexport function hexValue(code: number): number {\n if (code >= ASCII_0 && code <= ASCII_9) {\n return code - ASCII_0\n }\n if (code >= ASCII_A && code <= ASCII_F) {\n return code - ASCII_A + 10\n }\n if (code >= ASCII_a && code <= ASCII_f) {\n return code - ASCII_a + 10\n }\n return -1 // Invalid hex character\n}\n","import { BufferError, ParseError } from '../../errors'\nimport { hexValue } from './hex'\n\nconst UUID_BYTE_LENGTH = 16\nconst UUID_STRING_LENGTH = 36\n\n// Mapping from UUID string position to byte index.\n// -1 indicates a dash position that should be skipped.\n// This avoids intermediate string allocations during parsing.\nconst UUID_CHAR_TO_BYTE: number[] = [\n 0,\n 0,\n 1,\n 1,\n 2,\n 2,\n 3,\n 3, // chars 0-7 → bytes 0-3\n -1, // char 8 is '-'\n 4,\n 4,\n 5,\n 5, // chars 9-12 → bytes 4-5\n -1, // char 13 is '-'\n 6,\n 6,\n 7,\n 7, // chars 14-17 → bytes 6-7\n -1, // char 18 is '-'\n 8,\n 8,\n 9,\n 9, // chars 19-22 → bytes 8-9\n -1, // char 23 is '-'\n 10,\n 10,\n 11,\n 11,\n 12,\n 12,\n 13,\n 13,\n 14,\n 14,\n 15,\n 15, // chars 24-35 → bytes 10-15\n]\n\n// Whether each position is the high nibble (true) or low nibble (false)\nconst UUID_CHAR_IS_HIGH: boolean[] = [\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false, // chars 0-7\n false, // dash (ignored)\n true,\n false,\n true,\n false, // chars 9-12\n false, // dash\n true,\n false,\n true,\n false, // chars 14-17\n false, // dash\n true,\n false,\n true,\n false, // chars 19-22\n false, // dash\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false, // chars 24-35\n]\n\n// Pre-computed lookup table for byte-to-hex conversion (0x00 -> \"00\", 0xff -> \"ff\")\n//\n// Note: this table must remain defined in the same module as `formatUuid`, otherwise the v8 optimizer\n// will cause a performance drop of ~36%.\nconst HEX_TABLE: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))\n\nexport function formatUuid(bytes: Uint8Array): string {\n if (bytes.length !== UUID_BYTE_LENGTH) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `UUID bytes must be exactly ${UUID_BYTE_LENGTH} bytes, got ${bytes.length}`,\n {\n strategy: 'uuid',\n },\n )\n }\n\n return formatUuidUnchecked(bytes)\n}\n\nexport function formatUuidUnchecked(bytes: Uint8Array): string {\n // Direct string concatenation - optimized for V8's string builder.\n // This approach avoids loop overhead and intermediate allocations.\n // See: https://github.com/uuidjs/uuid/pull/434\n return (\n HEX_TABLE[bytes[0]] +\n HEX_TABLE[bytes[1]] +\n HEX_TABLE[bytes[2]] +\n HEX_TABLE[bytes[3]] +\n '-' +\n HEX_TABLE[bytes[4]] +\n HEX_TABLE[bytes[5]] +\n '-' +\n HEX_TABLE[bytes[6]] +\n HEX_TABLE[bytes[7]] +\n '-' +\n HEX_TABLE[bytes[8]] +\n HEX_TABLE[bytes[9]] +\n '-' +\n HEX_TABLE[bytes[10]] +\n HEX_TABLE[bytes[11]] +\n HEX_TABLE[bytes[12]] +\n HEX_TABLE[bytes[13]] +\n HEX_TABLE[bytes[14]] +\n HEX_TABLE[bytes[15]]\n )\n}\n\nexport function parseUuid(value: string): Uint8Array {\n if (value.length !== UUID_STRING_LENGTH) {\n throw new ParseError('INVALID_LENGTH', `UUID string must be 36 characters, got ${value.length}`, {\n strategy: 'uuid',\n })\n }\n\n // Validate separator positions directly (more efficient than full loop)\n if (value[8] !== '-' || value[13] !== '-' || value[18] !== '-' || value[23] !== '-') {\n throw new ParseError(\n 'INVALID_FORMAT',\n `UUID string has invalid separators at positions 8, 13, 18, 23. Received: \"${value}\"`,\n { strategy: 'uuid' },\n )\n }\n\n // Parse bytes directly from UUID string without intermediate string allocations.\n // This avoids the 9 allocations (5 slices + 4 concatenations) of the naive approach.\n const bytes = new Uint8Array(UUID_BYTE_LENGTH)\n\n for (let i = 0; i < UUID_STRING_LENGTH; i += 1) {\n const byteIdx = UUID_CHAR_TO_BYTE[i]\n if (byteIdx === -1) continue // Skip dash positions\n\n const nibble = hexValue(value.charCodeAt(i))\n if (nibble === -1) {\n throw new ParseError('INVALID_CHAR', `UUID string contains invalid hex character at position ${i}`, {\n strategy: 'uuid',\n })\n }\n\n if (UUID_CHAR_IS_HIGH[i]) {\n bytes[byteIdx] = nibble << 4\n } else {\n bytes[byteIdx] |= nibble\n }\n }\n\n return bytes\n}\n"],"mappings":"2DAYA,SAAgB,EAAS,EAAsB,CAU7C,OATI,GAAQ,IAAW,GAAQ,GACtB,EAAO,GAEZ,GAAQ,IAAW,GAAQ,GACtB,EAAO,GAAU,GAEtB,GAAQ,IAAW,GAAQ,IACtB,EAAO,GAAU,GAEnB,EACT,CCpBA,MAMM,EAA8B,CAClC,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACF,EAGM,EAA+B,CACnC,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACF,EAMM,EAAsB,MAAM,KAAK,CAAE,OAAQ,GAAI,GAAI,EAAG,IAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,EAEjG,SAAgB,EAAW,EAA2B,CACpD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EACR,uBACA,4CAA6D,EAAM,SACnE,CACE,SAAU,MACZ,CACF,EAGF,OAAO,EAAoB,CAAK,CAClC,CAEA,SAAgB,EAAoB,EAA2B,CAI7D,OACE,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,IAEpB,CAEA,SAAgB,EAAU,EAA2B,CACnD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAW,iBAAkB,0CAA0C,EAAM,SAAU,CAC/F,SAAU,MACZ,CAAC,EAIH,GAAI,EAAM,KAAO,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,IAC9E,MAAM,IAAI,EACR,iBACA,6EAA6E,EAAM,GACnF,CAAE,SAAU,MAAO,CACrB,EAKF,IAAM,EAAQ,IAAI,WAAW,EAAgB,EAE7C,IAAK,IAAI,EAAI,EAAG,EAAI,GAAoB,GAAK,EAAG,CAC9C,IAAM,EAAU,EAAkB,GAClC,GAAI,IAAY,GAAI,SAEpB,IAAM,EAAS,EAAS,EAAM,WAAW,CAAC,CAAC,EAC3C,GAAI,IAAW,GACb,MAAM,IAAI,EAAW,eAAgB,0DAA0D,IAAK,CAClG,SAAU,MACZ,CAAC,EAGC,EAAkB,GACpB,EAAM,GAAW,GAAU,EAE3B,EAAM,IAAY,CAEtB,CAEA,OAAO,CACT"}
import { InvalidInputError } from '../errors'
import type { IdGenerator } from '../generators'
import { isIntegerInRange } from './validation'
/**
* Timestamp options accepted by second-precision generators (ksuid, objectid,
* xid) during the pre-v1 transition to unified millisecond inputs.
*/
export type TimestampSecsOptions = {
/**
* Timestamp in milliseconds since the Unix epoch.
* The generator stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number
/**
* Timestamp in seconds since the Unix epoch.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
secs?: number
}
/**
* Resolve caller-provided timestamp options to whole seconds since the Unix
* epoch, or `undefined` when neither option was supplied.
*
* `msecs` is the unified input and is truncated to whole seconds; `secs` is
* the deprecated pre-v1 alias. Passing both is an error.
*
* TODO(v1-rc): drop the `secs` branch once the alias is removed.
*/
export function resolveTimestampSecs(
options: TimestampSecsOptions,
minSecs: number,
maxSecs: number,
strategy: IdGenerator,
): number | undefined {
const { msecs, secs } = options
if (msecs !== undefined && secs !== undefined) {
throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `msecs` or `secs`, not both', { strategy })
}
if (msecs !== undefined) {
const minMsecs = minSecs * 1000
const maxMsecs = maxSecs * 1000 + 999
if (!isIntegerInRange(msecs, minMsecs, maxMsecs)) {
throw new InvalidInputError(
'TIMESTAMP_OUT_OF_RANGE',
`Timestamp must be an integer between ${minMsecs} and ${maxMsecs} milliseconds`,
{ strategy },
)
}
return Math.floor(msecs / 1000)
}
if (secs !== undefined) {
if (!isIntegerInRange(secs, minSecs, maxSecs)) {
throw new InvalidInputError(
'TIMESTAMP_OUT_OF_RANGE',
`Timestamp must be an integer between ${minSecs} and ${maxSecs} seconds`,
{ strategy },
)
}
return secs
}
return undefined
}
+1
-1

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError } from "../errors-Dgoyi-ci.mjs";
import { i as InvalidInputError, o as UniqueIdError } from "../errors-Da-8dh4J.mjs";

@@ -3,0 +3,0 @@ //#region src/cuid2/cuid2.d.ts

@@ -1,1 +0,1 @@

{"version":3,"file":"cuid2.d.mts","names":[],"sources":["../../src/cuid2/cuid2.ts"],"mappings":";;;KAIY,YAAA;;;AAAZ;;EAKE,MAAA;EAOS;;;;;AAAA;EAAT,MAAA,GAAS,UAAA;AAAA;AAAA,KAGC,KAAA;EAEC,kCAAV,OAAA,GAAU,YAAA;EAEX,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;AAAA;AAiMxB;;;;AAAoB;;;;;;;;;;;;;;;;;;;;;;;;;cAAP,KAAA,EAAO,KAAA"}
{"version":3,"file":"cuid2.d.mts","names":[],"sources":["../../src/cuid2/cuid2.ts"],"mappings":";;;KAIY,YAAA;;;AAAZ;;EAKE,MAAA;EAOS;;;;;AAAA;EAAT,MAAA,GAAS,UAAA;AAAA;AAAA,KAGC,KAAA;EAEC,kCAAV,OAAA,GAAU,YAAA;EAEX,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;AAAA;AAoMxB;;;;AAAoB;;;;;;;;;;;;;;;;;;;;;;;;;cAAP,KAAA,EAAO,KAAA"}

@@ -1,2 +0,2 @@

import{n as e}from"../random-Chp-Nkzi.mjs";import{InvalidInputError as t,UniqueIdError as n}from"../errors.mjs";import{sha3_512 as r}from"@noble/hashes/sha3.js";const i=/^[a-z][0-9a-z]+$/,a=`0123456789abcdefghijklmnopqrstuvwxyz`,o=new TextEncoder,s={counter:void 0,fingerprint:void 0};function c(){return e()%476782368}function l(e){let t=0n;for(let n of e)t=t*256n+BigInt(n);return t}function u(e){if(e===0n)return`0`;let t=[];for(;e>0n;)t.push(a[Number(e%36n)]),e/=36n;return t.reverse().join(``)}function d(e){return`abcdefghijklmnopqrstuvwxyz`[Math.floor(e()*26)]}function f(e,t){let n=Array(e);for(let r=0;r<e;r++)n[r]=a[Math.floor(t()*36)];return n.join(``)}function p(e){return r(o.encode(e))}function m(){let e=h;return u(l(p(Object.keys(globalThis).toString()+f(32,e)))).slice(1,33)}function h(){return e()/4294967296}function g(e){if(e){if(e.length===0)throw new t(`CUID2_RANDOM_BYTES_EMPTY`,`Random byte array cannot be empty`);let n=0;return()=>{let t=e[n%e.length]/256;return n+=1,t}}return h}function _(e){let n=e?.length;if(n!==void 0&&(!Number.isInteger(n)||n<2||n>32))throw new t(`CUID2_LENGTH_OUT_OF_RANGE`,`CUID2 length must be between 2 and 32. Received: ${n}`);let r=n??24,i=g(e?.random);s.counter===void 0&&(s.counter=c()),s.fingerprint===void 0&&(s.fingerprint=m());let a=d(i),o=Date.now().toString(36);s.counter+=1;let h=s.counter.toString(36);return a+u(l(p(o+f(r,i)+h+s.fingerprint))).slice(1,r)}function v(e){return typeof e==`string`&&e.length>=2&&e.length<=32&&i.test(e)}const y=Object.assign(_,{isValid:v});export{t as InvalidInputError,n as UniqueIdError,y as cuid2};
import{n as e}from"../random-Chp-Nkzi.mjs";import{InvalidInputError as t,UniqueIdError as n}from"../errors.mjs";import{sha3_512 as r}from"@noble/hashes/sha3.js";const i=/^[a-z][0-9a-z]+$/,a=`0123456789abcdefghijklmnopqrstuvwxyz`,o=new TextEncoder,s={counter:void 0,fingerprint:void 0};function c(){return e()%476782368}function l(e){let t=0n;for(let n of e)t=t*256n+BigInt(n);return t}function u(e){if(e===0n)return`0`;let t=[];for(;e>0n;)t.push(a[Number(e%36n)]),e/=36n;return t.reverse().join(``)}function d(e){return`abcdefghijklmnopqrstuvwxyz`[Math.floor(e()*26)]}function f(e,t){let n=Array(e);for(let r=0;r<e;r++)n[r]=a[Math.floor(t()*36)];return n.join(``)}function p(e){return r(o.encode(e))}function m(){let e=h;return u(l(p(Object.keys(globalThis).toString()+f(32,e)))).slice(1,33)}function h(){return e()/4294967296}function g(e){if(e){if(e.length===0)throw new t(`RANDOM_BYTES_TOO_SHORT`,`Random byte array cannot be empty`,{strategy:`cuid`});let n=0;return()=>{let t=e[n%e.length]/256;return n+=1,t}}return h}function _(e){let n=e?.length;if(n!==void 0&&(!Number.isInteger(n)||n<2||n>32))throw new t(`LENGTH_OUT_OF_RANGE`,`CUID2 length must be between 2 and 32. Received: ${n}`,{strategy:`cuid`});let r=n??24,i=g(e?.random);s.counter===void 0&&(s.counter=c()),s.fingerprint===void 0&&(s.fingerprint=m());let a=d(i),o=Date.now().toString(36);s.counter+=1;let h=s.counter.toString(36);return a+u(l(p(o+f(r,i)+h+s.fingerprint))).slice(1,r)}function v(e){return typeof e==`string`&&e.length>=2&&e.length<=32&&i.test(e)}const y=Object.assign(_,{isValid:v});export{t as InvalidInputError,n as UniqueIdError,y as cuid2};
//# sourceMappingURL=cuid2.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"cuid2.mjs","names":[],"sources":["../../src/cuid2/cuid2.ts"],"sourcesContent":["import { sha3_512 } from '@noble/hashes/sha3.js'\nimport { randomUint32 } from '../common/random'\nimport { InvalidInputError } from '../errors'\n\nexport type Cuid2Options = {\n /**\n * Length of the generated ID (2-32 characters).\n * Default: 24\n */\n length?: number\n /**\n * Custom random bytes for deterministic testing.\n * Must be at least 1 byte. For adequate entropy, use at least 16 bytes.\n * Note: The fingerprint always uses cryptographically secure random bytes,\n * regardless of this option.\n */\n random?: Uint8Array\n}\n\nexport type Cuid2 = {\n /** Generate a CUID v2 string. */\n (options?: Cuid2Options): string\n /** Return whether a value is a syntactically valid CUID v2 string. */\n isValid(id: unknown): id is string\n}\n\nconst DEFAULT_LENGTH = 24\nconst MAX_LENGTH = 32\nconst MIN_LENGTH = 2\n\n// Maximum initial counter value from cuid2 spec - provides ~29 bits of\n// initial entropy to prevent cross-process collisions at startup\nconst INITIAL_COUNT_MAX = 476782367\n\n// Validation regex: first char must be a-z, rest can be a-z or 0-9\nconst CUID2_REGEX = /^[a-z][0-9a-z]+$/\n\n// Base36 alphabet\nconst ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'\nconst LETTER_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'\n\n// Reusable TextEncoder instance (stateless, safe to share)\nconst textEncoder = new TextEncoder()\n\n/**\n * Module-level state for counter and fingerprint.\n * Counter is initialized lazily on first call to prevent unnecessary crypto operations.\n * Fingerprint is also generated lazily on first call.\n */\nconst state: { counter: number | undefined; fingerprint: string | undefined } = {\n counter: undefined,\n fingerprint: undefined,\n}\n\n/**\n * Initialize counter using crypto for consistency with other entropy sources.\n */\nfunction initializeCounter(): number {\n return randomUint32() % (INITIAL_COUNT_MAX + 1)\n}\n\n// --- Base36 utilities ---\n\nfunction bufToBigInt(buf: Uint8Array): bigint {\n let value = 0n\n for (const byte of buf) {\n value = value * 256n + BigInt(byte)\n }\n return value\n}\n\nfunction bigIntToBase36(value: bigint): string {\n if (value === 0n) return '0'\n const chars: string[] = []\n while (value > 0n) {\n chars.push(ALPHABET[Number(value % 36n)])\n value = value / 36n\n }\n return chars.reverse().join('')\n}\n\nfunction randomLetter(random: () => number): string {\n return LETTER_ALPHABET[Math.floor(random() * 26)]\n}\n\nfunction createEntropy(length: number, random: () => number): string {\n const chars = new Array<string>(length)\n for (let i = 0; i < length; i++) {\n chars[i] = ALPHABET[Math.floor(random() * 36)]\n }\n return chars.join('')\n}\n\n// --- SHA3 hash wrapper ---\n\nfunction hash(input: string): Uint8Array {\n return sha3_512(textEncoder.encode(input))\n}\n\n// --- Fingerprint generation ---\n\nconst BIG_LENGTH = 32\n\nfunction createFingerprint(): string {\n // Always use CSPRNG for fingerprint to ensure security regardless of custom random option\n const random = getCryptoRandom\n const globals = Object.keys(globalThis).toString()\n const sourceString = globals + createEntropy(BIG_LENGTH, random)\n const hashed = hash(sourceString)\n return bigIntToBase36(bufToBigInt(hashed)).slice(1, BIG_LENGTH + 1)\n}\n\n// --- Random function factory ---\n\n/**\n * Get a random number in [0, 1) using CUID2's own random pool.\n */\nfunction getCryptoRandom(): number {\n return randomUint32() / 0x100000000\n}\n\nfunction getRandomFn(random?: Uint8Array): () => number {\n if (random) {\n if (random.length === 0) {\n throw new InvalidInputError('CUID2_RANDOM_BYTES_EMPTY', 'Random byte array cannot be empty')\n }\n let index = 0\n return () => {\n const value = random[index % random.length] / 256\n index += 1\n return value\n }\n }\n return getCryptoRandom\n}\n\n// --- Main generator ---\n\nfunction cuid2Fn(options?: Cuid2Options): string {\n const requestedLength = options?.length\n\n if (\n requestedLength !== undefined &&\n (!Number.isInteger(requestedLength) || requestedLength < MIN_LENGTH || requestedLength > MAX_LENGTH)\n ) {\n throw new InvalidInputError(\n 'CUID2_LENGTH_OUT_OF_RANGE',\n `CUID2 length must be between ${MIN_LENGTH} and ${MAX_LENGTH}. Received: ${requestedLength}`,\n )\n }\n const length = requestedLength ?? DEFAULT_LENGTH\n\n const random = getRandomFn(options?.random)\n\n // Initialize counter lazily on first call\n if (state.counter === undefined) {\n state.counter = initializeCounter()\n }\n\n // Initialize fingerprint lazily on first call (always uses CSPRNG)\n if (state.fingerprint === undefined) {\n state.fingerprint = createFingerprint()\n }\n\n const firstLetter = randomLetter(random)\n const time = Date.now().toString(36)\n state.counter += 1\n const count = state.counter.toString(36)\n const salt = createEntropy(length, random)\n\n const hashInput = time + salt + count + state.fingerprint\n const hashed = hash(hashInput)\n const base36Hash = bigIntToBase36(bufToBigInt(hashed))\n\n // Drop first char of hash to avoid histogram bias, prepend random letter\n return firstLetter + base36Hash.slice(1, length)\n}\n\n// --- Validation (type guard) ---\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && id.length >= MIN_LENGTH && id.length <= MAX_LENGTH && CUID2_REGEX.test(id)\n}\n\n/**\n * Generate a CUID v2 string.\n *\n * CUID v2 is a secure, collision-resistant identifier that hashes multiple\n * entropy sources using SHA3-512. Unlike time-ordered IDs (ULID, UUID v7),\n * CUID v2 prevents enumeration attacks by making IDs non-predictable.\n *\n * Note: CUID v2 does not provide toBytes/fromBytes because it is a string-native\n * format with no canonical binary representation (unlike UUID's 16-byte format).\n *\n * @example\n * ```ts\n * import { cuid2 } from 'uniku/cuid2'\n *\n * const id = cuid2()\n * // => \"pfh0haxfpzowht3oi213cqos\"\n *\n * // Custom length\n * const shortId = cuid2({ length: 10 })\n * // => \"tz4a98xxat\"\n *\n * // Validation (type guard)\n * const maybeId: unknown = getUserInput()\n * if (cuid2.isValid(maybeId)) {\n * console.log(maybeId.length) // TypeScript knows maybeId is string\n * }\n * ```\n *\n * @deprecated Use `cuidv2` from `uniku/cuid/v2` instead. This entry point keeps\n * working unchanged, but `uniku/cuid/v2` is the canonical versioned subpath\n * (mirroring `uniku/uuid/v4` / `uniku/uuid/v7`).\n */\nexport const cuid2: Cuid2 = Object.assign(cuid2Fn, {\n isValid,\n})\n\nexport { InvalidInputError, UniqueIdError } from '../errors'\n"],"mappings":"iKA0BA,MASM,EAAc,mBAGd,EAAW,uCAIX,EAAc,IAAI,YAOlB,EAA0E,CAC9E,QAAS,IAAA,GACT,YAAa,IAAA,EACf,EAKA,SAAS,GAA4B,CACnC,OAAO,EAAa,EAAK,SAC3B,CAIA,SAAS,EAAY,EAAyB,CAC5C,IAAI,EAAQ,GACZ,IAAK,IAAM,KAAQ,EACjB,EAAQ,EAAQ,KAAO,OAAO,CAAI,EAEpC,OAAO,CACT,CAEA,SAAS,EAAe,EAAuB,CAC7C,GAAI,IAAU,GAAI,MAAO,IACzB,IAAM,EAAkB,CAAC,EACzB,KAAO,EAAQ,IACb,EAAM,KAAK,EAAS,OAAO,EAAQ,GAAG,EAAE,EACxC,GAAgB,IAElB,OAAO,EAAM,QAAQ,CAAC,CAAC,KAAK,EAAE,CAChC,CAEA,SAAS,EAAa,EAA8B,CAClD,MAAO,6BAAgB,KAAK,MAAM,EAAO,EAAI,EAAE,EACjD,CAEA,SAAS,EAAc,EAAgB,EAA8B,CACnE,IAAM,EAAY,MAAc,CAAM,EACtC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,IAC1B,EAAM,GAAK,EAAS,KAAK,MAAM,EAAO,EAAI,EAAE,GAE9C,OAAO,EAAM,KAAK,EAAE,CACtB,CAIA,SAAS,EAAK,EAA2B,CACvC,OAAO,EAAS,EAAY,OAAO,CAAK,CAAC,CAC3C,CAMA,SAAS,GAA4B,CAEnC,IAAM,EAAS,EAIf,OAAO,EAAe,EADP,EAFC,OAAO,KAAK,UAAU,CAAC,CAAC,SACb,EAAI,EAAc,GAAY,CAAM,CAExB,CAAC,CAAC,CAAC,CAAC,MAAM,EAAG,EAAc,CACpE,CAOA,SAAS,GAA0B,CACjC,OAAO,EAAa,EAAI,UAC1B,CAEA,SAAS,EAAY,EAAmC,CACtD,GAAI,EAAQ,CACV,GAAI,EAAO,SAAW,EACpB,MAAM,IAAI,EAAkB,2BAA4B,mCAAmC,EAE7F,IAAI,EAAQ,EACZ,UAAa,CACX,IAAM,EAAQ,EAAO,EAAQ,EAAO,QAAU,IAE9C,MADA,IAAS,EACF,CACT,CACF,CACA,OAAO,CACT,CAIA,SAAS,EAAQ,EAAgC,CAC/C,IAAM,EAAkB,GAAS,OAEjC,GACE,IAAoB,IAAA,KACnB,CAAC,OAAO,UAAU,CAAe,GAAK,EAAkB,GAAc,EAAkB,IAEzF,MAAM,IAAI,EACR,4BACA,oDAA2E,GAC7E,EAEF,IAAM,EAAS,GAAmB,GAE5B,EAAS,EAAY,GAAS,MAAM,EAGtC,EAAM,UAAY,IAAA,KACpB,EAAM,QAAU,EAAkB,GAIhC,EAAM,cAAgB,IAAA,KACxB,EAAM,YAAc,EAAkB,GAGxC,IAAM,EAAc,EAAa,CAAM,EACjC,EAAO,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EACnC,EAAM,SAAW,EACjB,IAAM,EAAQ,EAAM,QAAQ,SAAS,EAAE,EAQvC,OAAO,EAHY,EAAe,EADnB,EADG,EAFL,EAAc,EAAQ,CAEP,EAAI,EAAQ,EAAM,WAEK,CAAC,CAGtB,CAAC,CAAC,MAAM,EAAG,CAAM,CACjD,CAIA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAG,QAAU,GAAc,EAAG,QAAU,IAAc,EAAY,KAAK,CAAE,CAC5G,CAkCA,MAAa,EAAe,OAAO,OAAO,EAAS,CACjD,SACF,CAAC"}
{"version":3,"file":"cuid2.mjs","names":[],"sources":["../../src/cuid2/cuid2.ts"],"sourcesContent":["import { sha3_512 } from '@noble/hashes/sha3.js'\nimport { randomUint32 } from '../common/random'\nimport { InvalidInputError } from '../errors'\n\nexport type Cuid2Options = {\n /**\n * Length of the generated ID (2-32 characters).\n * Default: 24\n */\n length?: number\n /**\n * Custom random bytes for deterministic testing.\n * Must be at least 1 byte. For adequate entropy, use at least 16 bytes.\n * Note: The fingerprint always uses cryptographically secure random bytes,\n * regardless of this option.\n */\n random?: Uint8Array\n}\n\nexport type Cuid2 = {\n /** Generate a CUID v2 string. */\n (options?: Cuid2Options): string\n /** Return whether a value is a syntactically valid CUID v2 string. */\n isValid(id: unknown): id is string\n}\n\nconst DEFAULT_LENGTH = 24\nconst MAX_LENGTH = 32\nconst MIN_LENGTH = 2\n\n// Maximum initial counter value from cuid2 spec - provides ~29 bits of\n// initial entropy to prevent cross-process collisions at startup\nconst INITIAL_COUNT_MAX = 476782367\n\n// Validation regex: first char must be a-z, rest can be a-z or 0-9\nconst CUID2_REGEX = /^[a-z][0-9a-z]+$/\n\n// Base36 alphabet\nconst ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'\nconst LETTER_ALPHABET = 'abcdefghijklmnopqrstuvwxyz'\n\n// Reusable TextEncoder instance (stateless, safe to share)\nconst textEncoder = new TextEncoder()\n\n/**\n * Module-level state for counter and fingerprint.\n * Counter is initialized lazily on first call to prevent unnecessary crypto operations.\n * Fingerprint is also generated lazily on first call.\n */\nconst state: { counter: number | undefined; fingerprint: string | undefined } = {\n counter: undefined,\n fingerprint: undefined,\n}\n\n/**\n * Initialize counter using crypto for consistency with other entropy sources.\n */\nfunction initializeCounter(): number {\n return randomUint32() % (INITIAL_COUNT_MAX + 1)\n}\n\n// --- Base36 utilities ---\n\nfunction bufToBigInt(buf: Uint8Array): bigint {\n let value = 0n\n for (const byte of buf) {\n value = value * 256n + BigInt(byte)\n }\n return value\n}\n\nfunction bigIntToBase36(value: bigint): string {\n if (value === 0n) return '0'\n const chars: string[] = []\n while (value > 0n) {\n chars.push(ALPHABET[Number(value % 36n)])\n value = value / 36n\n }\n return chars.reverse().join('')\n}\n\nfunction randomLetter(random: () => number): string {\n return LETTER_ALPHABET[Math.floor(random() * 26)]\n}\n\nfunction createEntropy(length: number, random: () => number): string {\n const chars = new Array<string>(length)\n for (let i = 0; i < length; i++) {\n chars[i] = ALPHABET[Math.floor(random() * 36)]\n }\n return chars.join('')\n}\n\n// --- SHA3 hash wrapper ---\n\nfunction hash(input: string): Uint8Array {\n return sha3_512(textEncoder.encode(input))\n}\n\n// --- Fingerprint generation ---\n\nconst BIG_LENGTH = 32\n\nfunction createFingerprint(): string {\n // Always use CSPRNG for fingerprint to ensure security regardless of custom random option\n const random = getCryptoRandom\n const globals = Object.keys(globalThis).toString()\n const sourceString = globals + createEntropy(BIG_LENGTH, random)\n const hashed = hash(sourceString)\n return bigIntToBase36(bufToBigInt(hashed)).slice(1, BIG_LENGTH + 1)\n}\n\n// --- Random function factory ---\n\n/**\n * Get a random number in [0, 1) using CUID2's own random pool.\n */\nfunction getCryptoRandom(): number {\n return randomUint32() / 0x100000000\n}\n\nfunction getRandomFn(random?: Uint8Array): () => number {\n if (random) {\n if (random.length === 0) {\n throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', 'Random byte array cannot be empty', {\n strategy: 'cuid',\n })\n }\n let index = 0\n return () => {\n const value = random[index % random.length] / 256\n index += 1\n return value\n }\n }\n return getCryptoRandom\n}\n\n// --- Main generator ---\n\nfunction cuid2Fn(options?: Cuid2Options): string {\n const requestedLength = options?.length\n\n if (\n requestedLength !== undefined &&\n (!Number.isInteger(requestedLength) || requestedLength < MIN_LENGTH || requestedLength > MAX_LENGTH)\n ) {\n throw new InvalidInputError(\n 'LENGTH_OUT_OF_RANGE',\n `CUID2 length must be between ${MIN_LENGTH} and ${MAX_LENGTH}. Received: ${requestedLength}`,\n { strategy: 'cuid' },\n )\n }\n const length = requestedLength ?? DEFAULT_LENGTH\n\n const random = getRandomFn(options?.random)\n\n // Initialize counter lazily on first call\n if (state.counter === undefined) {\n state.counter = initializeCounter()\n }\n\n // Initialize fingerprint lazily on first call (always uses CSPRNG)\n if (state.fingerprint === undefined) {\n state.fingerprint = createFingerprint()\n }\n\n const firstLetter = randomLetter(random)\n const time = Date.now().toString(36)\n state.counter += 1\n const count = state.counter.toString(36)\n const salt = createEntropy(length, random)\n\n const hashInput = time + salt + count + state.fingerprint\n const hashed = hash(hashInput)\n const base36Hash = bigIntToBase36(bufToBigInt(hashed))\n\n // Drop first char of hash to avoid histogram bias, prepend random letter\n return firstLetter + base36Hash.slice(1, length)\n}\n\n// --- Validation (type guard) ---\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && id.length >= MIN_LENGTH && id.length <= MAX_LENGTH && CUID2_REGEX.test(id)\n}\n\n/**\n * Generate a CUID v2 string.\n *\n * CUID v2 is a secure, collision-resistant identifier that hashes multiple\n * entropy sources using SHA3-512. Unlike time-ordered IDs (ULID, UUID v7),\n * CUID v2 prevents enumeration attacks by making IDs non-predictable.\n *\n * Note: CUID v2 does not provide toBytes/fromBytes because it is a string-native\n * format with no canonical binary representation (unlike UUID's 16-byte format).\n *\n * @example\n * ```ts\n * import { cuid2 } from 'uniku/cuid2'\n *\n * const id = cuid2()\n * // => \"pfh0haxfpzowht3oi213cqos\"\n *\n * // Custom length\n * const shortId = cuid2({ length: 10 })\n * // => \"tz4a98xxat\"\n *\n * // Validation (type guard)\n * const maybeId: unknown = getUserInput()\n * if (cuid2.isValid(maybeId)) {\n * console.log(maybeId.length) // TypeScript knows maybeId is string\n * }\n * ```\n *\n * @deprecated Use `cuidv2` from `uniku/cuid/v2` instead. This entry point keeps\n * working unchanged, but `uniku/cuid/v2` is the canonical versioned subpath\n * (mirroring `uniku/uuid/v4` / `uniku/uuid/v7`).\n */\nexport const cuid2: Cuid2 = Object.assign(cuid2Fn, {\n isValid,\n})\n\nexport { InvalidInputError, UniqueIdError } from '../errors'\n"],"mappings":"iKA0BA,MASM,EAAc,mBAGd,EAAW,uCAIX,EAAc,IAAI,YAOlB,EAA0E,CAC9E,QAAS,IAAA,GACT,YAAa,IAAA,EACf,EAKA,SAAS,GAA4B,CACnC,OAAO,EAAa,EAAK,SAC3B,CAIA,SAAS,EAAY,EAAyB,CAC5C,IAAI,EAAQ,GACZ,IAAK,IAAM,KAAQ,EACjB,EAAQ,EAAQ,KAAO,OAAO,CAAI,EAEpC,OAAO,CACT,CAEA,SAAS,EAAe,EAAuB,CAC7C,GAAI,IAAU,GAAI,MAAO,IACzB,IAAM,EAAkB,CAAC,EACzB,KAAO,EAAQ,IACb,EAAM,KAAK,EAAS,OAAO,EAAQ,GAAG,EAAE,EACxC,GAAgB,IAElB,OAAO,EAAM,QAAQ,CAAC,CAAC,KAAK,EAAE,CAChC,CAEA,SAAS,EAAa,EAA8B,CAClD,MAAO,6BAAgB,KAAK,MAAM,EAAO,EAAI,EAAE,EACjD,CAEA,SAAS,EAAc,EAAgB,EAA8B,CACnE,IAAM,EAAY,MAAc,CAAM,EACtC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,IAC1B,EAAM,GAAK,EAAS,KAAK,MAAM,EAAO,EAAI,EAAE,GAE9C,OAAO,EAAM,KAAK,EAAE,CACtB,CAIA,SAAS,EAAK,EAA2B,CACvC,OAAO,EAAS,EAAY,OAAO,CAAK,CAAC,CAC3C,CAMA,SAAS,GAA4B,CAEnC,IAAM,EAAS,EAIf,OAAO,EAAe,EADP,EAFC,OAAO,KAAK,UAAU,CAAC,CAAC,SACb,EAAI,EAAc,GAAY,CAAM,CAExB,CAAC,CAAC,CAAC,CAAC,MAAM,EAAG,EAAc,CACpE,CAOA,SAAS,GAA0B,CACjC,OAAO,EAAa,EAAI,UAC1B,CAEA,SAAS,EAAY,EAAmC,CACtD,GAAI,EAAQ,CACV,GAAI,EAAO,SAAW,EACpB,MAAM,IAAI,EAAkB,yBAA0B,oCAAqC,CACzF,SAAU,MACZ,CAAC,EAEH,IAAI,EAAQ,EACZ,UAAa,CACX,IAAM,EAAQ,EAAO,EAAQ,EAAO,QAAU,IAE9C,MADA,IAAS,EACF,CACT,CACF,CACA,OAAO,CACT,CAIA,SAAS,EAAQ,EAAgC,CAC/C,IAAM,EAAkB,GAAS,OAEjC,GACE,IAAoB,IAAA,KACnB,CAAC,OAAO,UAAU,CAAe,GAAK,EAAkB,GAAc,EAAkB,IAEzF,MAAM,IAAI,EACR,sBACA,oDAA2E,IAC3E,CAAE,SAAU,MAAO,CACrB,EAEF,IAAM,EAAS,GAAmB,GAE5B,EAAS,EAAY,GAAS,MAAM,EAGtC,EAAM,UAAY,IAAA,KACpB,EAAM,QAAU,EAAkB,GAIhC,EAAM,cAAgB,IAAA,KACxB,EAAM,YAAc,EAAkB,GAGxC,IAAM,EAAc,EAAa,CAAM,EACjC,EAAO,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EACnC,EAAM,SAAW,EACjB,IAAM,EAAQ,EAAM,QAAQ,SAAS,EAAE,EAQvC,OAAO,EAHY,EAAe,EADnB,EADG,EAFL,EAAc,EAAQ,CAEP,EAAI,EAAQ,EAAM,WAEK,CAAC,CAGtB,CAAC,CAAC,MAAM,EAAG,CAAM,CACjD,CAIA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAG,QAAU,GAAc,EAAG,QAAU,IAAc,EAAY,KAAK,CAAE,CAC5G,CAkCA,MAAa,EAAe,OAAO,OAAO,EAAS,CACjD,SACF,CAAC"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "./errors-Dgoyi-ci.mjs";
export { BufferError, InvalidInputError, ParseError, UniqueIdError };
import { a as ParseError, i as InvalidInputError, n as ERROR_CODES, o as UniqueIdError, r as ErrorCode, s as UniqueIdErrorOptions, t as BufferError } from "./errors-Da-8dh4J.mjs";
export { BufferError, ERROR_CODES, ErrorCode, InvalidInputError, ParseError, UniqueIdError, UniqueIdErrorOptions };

@@ -1,2 +0,2 @@

var e=class extends Error{constructor(e){super(e),this.name=this.constructor.name}},t=class extends e{code;_tag=`InvalidInputError`;constructor(e,t){super(t),this.code=e}},n=class extends e{code;_tag=`ParseError`;constructor(e,t){super(t),this.code=e}},r=class extends e{code;_tag=`BufferError`;constructor(e,t){super(t),this.code=e}};export{r as BufferError,t as InvalidInputError,n as ParseError,e as UniqueIdError};
const e=[`TIMESTAMP_OUT_OF_RANGE`,`CONFLICTING_OPTIONS`,`COUNTER_OUT_OF_RANGE`,`NODE_OUT_OF_RANGE`,`NODE_BITS_OUT_OF_RANGE`,`EPOCH_INVALID`,`PROCESS_ID_OUT_OF_RANGE`,`MACHINE_ID_BYTES_TOO_SHORT`,`RANDOM_BYTES_TOO_SHORT`,`RANDOM_OVERFLOW`,`LENGTH_OUT_OF_RANGE`,`ALPHABET_OUT_OF_RANGE`,`ALPHABET_INVALID_CHAR`,`ALPHABET_DUPLICATE`,`PREFIX_TOO_LONG`,`PREFIX_INVALID_CHAR`,`PREFIX_INVALID_BOUNDARY`,`UUID_NOT_V7`,`BYTES_INVALID_LENGTH`,`BUFFER_OUT_OF_BOUNDS`,`INVALID_CHAR`,`INVALID_LENGTH`,`INVALID_FORMAT`,`NON_CANONICAL`,`VALUE_OUT_OF_RANGE`];var t=class extends Error{strategy;constructor(e,t){super(e),this.name=this.constructor.name,this.strategy=t?.strategy}},n=class extends t{code;_tag=`InvalidInputError`;constructor(e,t,n){super(t,n),this.code=e}},r=class extends t{code;_tag=`ParseError`;constructor(e,t,n){super(t,n),this.code=e}},i=class extends t{code;_tag=`BufferError`;constructor(e,t,n){super(t,n),this.code=e}};export{i as BufferError,e as ERROR_CODES,n as InvalidInputError,r as ParseError,t as UniqueIdError};
//# sourceMappingURL=errors.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base error for all uniku errors.\n * Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`)\n * and `code` for machine-readable error identification.\n */\nexport abstract class UniqueIdError extends Error {\n abstract readonly _tag: string\n abstract readonly code: string\n\n constructor(message: string) {\n super(message)\n this.name = this.constructor.name\n }\n}\n\n/**\n * Thrown when generator arguments are invalid (bad size, alphabet, length, timestamp, version).\n */\nexport class InvalidInputError extends UniqueIdError {\n readonly _tag = 'InvalidInputError' as const\n\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message)\n }\n}\n\n/**\n * Thrown when parsing/decoding an ID string that has invalid format or characters.\n */\nexport class ParseError extends UniqueIdError {\n readonly _tag = 'ParseError' as const\n\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message)\n }\n}\n\n/**\n * Thrown when a byte array or buffer is too short or an offset is out of bounds.\n */\nexport class BufferError extends UniqueIdError {\n readonly _tag = 'BufferError' as const\n\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message)\n }\n}\n"],"mappings":"AAKA,IAAsB,EAAtB,cAA4C,KAAM,CAIhD,YAAY,EAAiB,CAC3B,MAAM,CAAO,EACb,KAAK,KAAO,KAAK,YAAY,IAC/B,CACF,EAKa,EAAb,cAAuC,CAAc,CAIxC,KAHX,KAAgB,oBAEhB,YACE,EACA,EACA,CACA,MAAM,CAAO,EAHJ,KAAA,KAAA,CAIX,CACF,EAKa,EAAb,cAAgC,CAAc,CAIjC,KAHX,KAAgB,aAEhB,YACE,EACA,EACA,CACA,MAAM,CAAO,EAHJ,KAAA,KAAA,CAIX,CACF,EAKa,EAAb,cAAiC,CAAc,CAIlC,KAHX,KAAgB,cAEhB,YACE,EACA,EACA,CACA,MAAM,CAAO,EAHJ,KAAA,KAAA,CAIX,CACF"}
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import type { IdGenerator } from './generators'\n\n/**\n * The canonical, ordered list of machine-readable error codes emitted by\n * uniku's public API.\n *\n * Codes describe the failure independently of an ID format. Use an error's\n * `strategy` field when the generator that raised it matters.\n */\n// Plain `as const` keeps declaration emit compatible with\n// `isolatedDeclarations`; every member is already a string literal.\nexport const ERROR_CODES = [\n 'TIMESTAMP_OUT_OF_RANGE',\n 'CONFLICTING_OPTIONS',\n 'COUNTER_OUT_OF_RANGE',\n 'NODE_OUT_OF_RANGE',\n 'NODE_BITS_OUT_OF_RANGE',\n 'EPOCH_INVALID',\n 'PROCESS_ID_OUT_OF_RANGE',\n 'MACHINE_ID_BYTES_TOO_SHORT',\n 'RANDOM_BYTES_TOO_SHORT',\n 'RANDOM_OVERFLOW',\n 'LENGTH_OUT_OF_RANGE',\n 'ALPHABET_OUT_OF_RANGE',\n 'ALPHABET_INVALID_CHAR',\n 'ALPHABET_DUPLICATE',\n 'PREFIX_TOO_LONG',\n 'PREFIX_INVALID_CHAR',\n 'PREFIX_INVALID_BOUNDARY',\n 'UUID_NOT_V7',\n 'BYTES_INVALID_LENGTH',\n 'BUFFER_OUT_OF_BOUNDS',\n 'INVALID_CHAR',\n 'INVALID_LENGTH',\n 'INVALID_FORMAT',\n 'NON_CANONICAL',\n 'VALUE_OUT_OF_RANGE',\n] as const\n\n/**\n * A machine-readable error code emitted by uniku, derived from\n * {@link ERROR_CODES}.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[number]\n\n/**\n * Extra context carried by every uniku error.\n */\nexport type UniqueIdErrorOptions = {\n /**\n * The ID strategy whose public boundary raised the error.\n * Error codes are strategy-agnostic (e.g. `TIMESTAMP_OUT_OF_RANGE`), so this\n * field attributes the failure to the generator that produced it.\n */\n readonly strategy?: IdGenerator\n}\n\n/**\n * Base error for all uniku errors.\n * Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`),\n * `code` for machine-readable error identification, and `strategy` to attribute\n * unified codes to the ID generator that raised them.\n */\nexport abstract class UniqueIdError extends Error {\n abstract readonly _tag: string\n abstract readonly code: ErrorCode\n\n /** The ID strategy whose public boundary raised the error. */\n readonly strategy?: IdGenerator\n\n constructor(message: string, options?: UniqueIdErrorOptions) {\n super(message)\n this.name = this.constructor.name\n this.strategy = options?.strategy\n }\n}\n\n/**\n * Thrown when generator arguments are invalid (bad size, alphabet, length, timestamp, version).\n */\nexport class InvalidInputError extends UniqueIdError {\n readonly _tag = 'InvalidInputError' as const\n\n constructor(\n readonly code: ErrorCode,\n message: string,\n options?: UniqueIdErrorOptions,\n ) {\n super(message, options)\n }\n}\n\n/**\n * Thrown when parsing/decoding an ID string that has invalid format or characters.\n */\nexport class ParseError extends UniqueIdError {\n readonly _tag = 'ParseError' as const\n\n constructor(\n readonly code: ErrorCode,\n message: string,\n options?: UniqueIdErrorOptions,\n ) {\n super(message, options)\n }\n}\n\n/**\n * Thrown when a byte array or buffer is too short or an offset is out of bounds.\n */\nexport class BufferError extends UniqueIdError {\n readonly _tag = 'BufferError' as const\n\n constructor(\n readonly code: ErrorCode,\n message: string,\n options?: UniqueIdErrorOptions,\n ) {\n super(message, options)\n }\n}\n"],"mappings":"AAWA,MAAa,EAAc,CACzB,yBACA,sBACA,uBACA,oBACA,yBACA,gBACA,0BACA,6BACA,yBACA,kBACA,sBACA,wBACA,wBACA,qBACA,kBACA,sBACA,0BACA,cACA,uBACA,uBACA,eACA,iBACA,iBACA,gBACA,oBACF,EA0BA,IAAsB,EAAtB,cAA4C,KAAM,CAKhD,SAEA,YAAY,EAAiB,EAAgC,CAC3D,MAAM,CAAO,EACb,KAAK,KAAO,KAAK,YAAY,KAC7B,KAAK,SAAW,GAAS,QAC3B,CACF,EAKa,EAAb,cAAuC,CAAc,CAIxC,KAHX,KAAgB,oBAEhB,YACE,EACA,EACA,EACA,CACA,MAAM,EAAS,CAAO,EAJb,KAAA,KAAA,CAKX,CACF,EAKa,EAAb,cAAgC,CAAc,CAIjC,KAHX,KAAgB,aAEhB,YACE,EACA,EACA,EACA,CACA,MAAM,EAAS,CAAO,EAJb,KAAA,KAAA,CAKX,CACF,EAKa,EAAb,cAAiC,CAAc,CAIlC,KAHX,KAAgB,cAEhB,YACE,EACA,EACA,EACA,CACA,MAAM,EAAS,CAAO,EAJb,KAAA,KAAA,CAKX,CACF"}

@@ -1,17 +0,2 @@

//#region src/generators.d.ts
/**
* The canonical, ordered list of ID generators supported by uniku.
*
* This is the single source of truth for the set of supported ID generators.
* Tools that need to enumerate or validate ID generators (for example,
* `@uniku/cli`'s `--type` flag) should derive from this array rather than
* hand-copying the union.
*/
declare const ID_GENERATORS: readonly ["uuid", "ulid", "typeid", "nanoid", "cuid", "ksuid", "objectid", "tsid", "xid"];
/**
* The union of ID generators supported by uniku, derived from {@link ID_GENERATORS}.
*/
type IdGenerator = (typeof ID_GENERATORS)[number];
//#endregion
export { ID_GENERATORS, IdGenerator };
//# sourceMappingURL=generators.d.mts.map
import { n as IdGenerator, t as ID_GENERATORS } from "./generators-BfJLt7Qf.mjs";
export { ID_GENERATORS, IdGenerator };

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -10,6 +10,12 @@ //#region src/ksuid/ksuid.d.ts

/**
* Timestamp in seconds since Unix epoch.
* Defaults to Math.floor(Date.now() / 1000).
* KSUID natively uses second precision.
* Timestamp in milliseconds since the Unix epoch.
* Defaults to Date.now().
* KSUID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number;
/**
* Timestamp in seconds since the Unix epoch.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
secs?: number;

@@ -16,0 +22,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"file":"ksuid.d.mts","names":[],"sources":["../../src/ksuid/ksuid.ts"],"mappings":";;;KAiCY,YAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;;;;;;EAMT,IAAA;AAAA;AAAA,KAGU,KAAA;EAAA;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,YAAA,cAA0B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEtG,OAAA,GAAU,YAAA,EAAc,GAAA,cAAiB,MAAA;EAE1C,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA,WAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;cAkIW,KAAA,EAAO,KAAA"}
{"version":3,"file":"ksuid.d.mts","names":[],"sources":["../../src/ksuid/ksuid.ts"],"mappings":";;;KAkCY,YAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;;;;;;EAMT,KAAA;EAOA;AAAA;AAGF;;;EAHE,IAAA;AAAA;AAAA,KAGU,KAAA;;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,YAAA,cAA0B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEtG,OAAA,GAAU,YAAA,EAAc,GAAA,cAAiB,MAAA,oBAIzB;EAFjB,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;cA8HW,KAAA,EAAO,KAAA"}

@@ -1,2 +0,2 @@

import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t}from"../validation-CTNpXm94.mjs";import{BufferError as n,InvalidInputError as r,ParseError as i,UniqueIdError as a}from"../errors.mjs";import{n as o}from"../bytes-xqWxFYsM.mjs";const s=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`,c=62n,l=(1n<<160n)-1n,u=new Uint8Array(65536);u.fill(255);for(let e=0;e<62;e+=1)u[s.charCodeAt(e)]=e;function d(e){if(e.length<20)throw new n(`KSUID_BYTES_TOO_SHORT`,`KSUID bytes must be at least 20 bytes, got ${e.length}`);let t=0n;for(let n=0;n<20;n+=1)t=t<<8n|BigInt(e[n]);let r=``;for(;t>0n;){let e=t%c;t/=c,r=s[Number(e)]+r}return r.padStart(27,`0`)}function f(e){if(e.length!==27)throw new i(`KSUID_INVALID_LENGTH`,`KSUID string must be 27 characters, got ${e.length}`);let t=0n;for(let n=0;n<27;n+=1){let r=u[e.charCodeAt(n)];if(r===255)throw new i(`KSUID_INVALID_CHAR`,`Invalid KSUID character: ${e[n]}`);t=t*c+BigInt(r)}if(t>l)throw new i(`KSUID_OVERFLOW`,`KSUID string exceeds 160-bit range`);let n=new Uint8Array(20);for(let e=19;e>=0;--e)n[e]=Number(t&255n),t>>=8n;return n}const p=14e8,m=d(new Uint8Array(20).fill(255)),h=/^[0-9A-Za-z]{27}$/;function g(e,t,n,r){o(n,r,e);for(let e=0;e<16;e+=1)n[r+4+e]=t[e]}function _(i,a,o=0){let s=i?.random;if(s&&s.length<16)throw new r(`KSUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16 for KSUID`);let c,l=i?.secs;if(l!==void 0){if(!Number.isInteger(l)||l<p)throw new r(`KSUID_TIMESTAMP_TOO_LOW`,`Timestamp must be >= KSUID epoch`);if(l>5694967295)throw new r(`KSUID_TIMESTAMP_TOO_HIGH`,`Timestamp must be <= maximum KSUID timestamp`);c=l-p}else c=Math.floor(Date.now()/1e3)-p;let u=s??e();if(a){if(!t(a,o,20))throw new n(`KSUID_BUFFER_OUT_OF_BOUNDS`,`KSUID byte range ${o}:${o+20-1} is out of buffer bounds`);return g(c,u,a,o),a}let f=new Uint8Array(20);return g(c,u,f,0),d(f)}function v(e){return f(e)}function y(e){if(e.length!==20)throw new n(`KSUID_BYTES_INVALID_LENGTH`,`KSUID bytes must be exactly 20 bytes, got ${e.length}`);return d(e)}function b(e){let t=f(e);return(((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)+p)*1e3}function x(e){return typeof e==`string`&&e.length===27&&h.test(e)&&e<=m}const S=Object.assign(_,{toBytes:v,fromBytes:y,timestamp:b,isValid:x,NIL:`000000000000000000000000000`,MAX:m});export{n as BufferError,r as InvalidInputError,i as ParseError,a as UniqueIdError,S as ksuid};
import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t}from"../validation-CTNpXm94.mjs";import{BufferError as n,InvalidInputError as r,ParseError as i,UniqueIdError as a}from"../errors.mjs";import{n as o}from"../bytes-xqWxFYsM.mjs";import{t as s}from"../timestamp-ChrSuQCR.mjs";const c=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`,l=62n,u=(1n<<160n)-1n,d=new Uint8Array(65536);d.fill(255);for(let e=0;e<62;e+=1)d[c.charCodeAt(e)]=e;function f(e){if(e.length<20)throw new n(`BYTES_INVALID_LENGTH`,`KSUID bytes must be at least 20 bytes, got ${e.length}`,{strategy:`ksuid`});let t=0n;for(let n=0;n<20;n+=1)t=t<<8n|BigInt(e[n]);let r=``;for(;t>0n;){let e=t%l;t/=l,r=c[Number(e)]+r}return r.padStart(27,`0`)}function p(e){if(e.length!==27)throw new i(`INVALID_LENGTH`,`KSUID string must be 27 characters, got ${e.length}`,{strategy:`ksuid`});let t=0n;for(let n=0;n<27;n+=1){let r=d[e.charCodeAt(n)];if(r===255)throw new i(`INVALID_CHAR`,`Invalid KSUID character: ${e[n]}`,{strategy:`ksuid`});t=t*l+BigInt(r)}if(t>u)throw new i(`VALUE_OUT_OF_RANGE`,`KSUID string exceeds 160-bit range`,{strategy:`ksuid`});let n=new Uint8Array(20);for(let e=19;e>=0;--e)n[e]=Number(t&255n),t>>=8n;return n}const m=14e8,h=f(new Uint8Array(20).fill(255)),g=/^[0-9A-Za-z]{27}$/;function _(e,t,n,r){o(n,r,e);for(let e=0;e<16;e+=1)n[r+4+e]=t[e]}function v(i,a,o=0){let c=i?.random;if(c&&c.length<16)throw new r(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16 for KSUID`,{strategy:`ksuid`});let l,u=i===void 0?void 0:s(i,m,5694967295,`ksuid`);l=u===void 0?Math.floor(Date.now()/1e3)-m:u-m;let d=c??e();if(a){if(!t(a,o,20))throw new n(`BUFFER_OUT_OF_BOUNDS`,`KSUID byte range ${o}:${o+20-1} is out of buffer bounds`,{strategy:`ksuid`});return _(l,d,a,o),a}let p=new Uint8Array(20);return _(l,d,p,0),f(p)}function y(e){return p(e)}function b(e){if(e.length!==20)throw new n(`BYTES_INVALID_LENGTH`,`KSUID bytes must be exactly 20 bytes, got ${e.length}`,{strategy:`ksuid`});return f(e)}function x(e){let t=p(e);return(((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)+m)*1e3}function S(e){return typeof e==`string`&&e.length===27&&g.test(e)&&e<=h}const C=Object.assign(v,{toBytes:y,fromBytes:b,timestamp:x,isValid:S,NIL:`000000000000000000000000000`,MAX:h});export{n as BufferError,r as InvalidInputError,i as ParseError,a as UniqueIdError,C as ksuid};
//# sourceMappingURL=ksuid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"ksuid.mjs","names":["KSUID_BYTES","KSUID_STRING_LEN"],"sources":["../../src/ksuid/base62.ts","../../src/ksuid/ksuid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\n/**\n * Base62 encoding/decoding for KSUID.\n * Alphabet: 0-9A-Za-z (standard Base62 ordering)\n *\n * KSUID binary format: 20 bytes (160 bits)\n * - 4 bytes: timestamp (seconds since KSUID epoch)\n * - 16 bytes: payload (cryptographically random)\n *\n * String format: 27 characters of Base62\n */\n\n// Base62 alphabet: digits (0-9), uppercase (A-Z), lowercase (a-z)\nconst BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\nconst BASE = 62n\nconst MAX_KSUID_VALUE = (1n << 160n) - 1n\nconst KSUID_BYTES = 20\nconst KSUID_STRING_LEN = 27\n\n// Pre-computed decode table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 64 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\n// Note: Base62 is case-sensitive - 'A' (value 10) and 'a' (value 36) are different\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\n\nfor (let i = 0; i < BASE62_ALPHABET.length; i += 1) {\n DECODING[BASE62_ALPHABET.charCodeAt(i)] = i\n}\n\n/**\n * Encode a 20-byte KSUID to a 27-character Base62 string.\n *\n * Algorithm: Convert the 160-bit number to base 62 using BigInt.\n * V8 has highly optimized BigInt operations for this size.\n */\nexport function encodeBase62(bytes: Uint8Array): string {\n if (bytes.length < KSUID_BYTES) {\n throw new BufferError(\n 'KSUID_BYTES_TOO_SHORT',\n `KSUID bytes must be at least ${KSUID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n\n // Convert bytes to BigInt (big-endian)\n let num = 0n\n for (let i = 0; i < KSUID_BYTES; i += 1) {\n num = (num << 8n) | BigInt(bytes[i])\n }\n\n // Convert to Base62 string (build from right to left)\n // Direct string concatenation is faster than array + join in V8\n let encoded = ''\n while (num > 0n) {\n const remainder = num % BASE\n num = num / BASE\n encoded = BASE62_ALPHABET[Number(remainder)] + encoded\n }\n\n // Pad the result with the zero-character ('0') to ensure a fixed length\n return encoded.padStart(KSUID_STRING_LEN, '0')\n}\n\n/**\n * Decode a 27-character Base62 string to a 20-byte KSUID.\n *\n * Algorithm: Convert Base62 string to BigInt, then to bytes.\n * V8 has highly optimized BigInt operations.\n */\nexport function decodeBase62(str: string): Uint8Array {\n if (str.length !== KSUID_STRING_LEN) {\n throw new ParseError(\n 'KSUID_INVALID_LENGTH',\n `KSUID string must be ${KSUID_STRING_LEN} characters, got ${str.length}`,\n )\n }\n\n // Convert Base62 string to BigInt\n let num = 0n\n for (let i = 0; i < KSUID_STRING_LEN; i += 1) {\n const value = DECODING[str.charCodeAt(i)]\n if (value === 255) {\n throw new ParseError('KSUID_INVALID_CHAR', `Invalid KSUID character: ${str[i]}`)\n }\n num = num * BASE + BigInt(value)\n }\n\n if (num > MAX_KSUID_VALUE) {\n throw new ParseError('KSUID_OVERFLOW', 'KSUID string exceeds 160-bit range')\n }\n\n // Convert BigInt to bytes (big-endian)\n const bytes = new Uint8Array(KSUID_BYTES)\n for (let i = KSUID_BYTES - 1; i >= 0; i -= 1) {\n bytes[i] = Number(num & 0xffn)\n num = num >> 8n\n }\n\n return bytes\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { rng } from '../common/random'\nimport { isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeBase62, encodeBase62 } from './base62'\n\n/**\n * KSUID (K-Sortable Unique Identifier)\n *\n * A 160-bit identifier consisting of:\n * - 4 bytes: timestamp (seconds since KSUID epoch: May 13, 2014)\n * - 16 bytes: cryptographically random payload\n *\n * Encoded as a 27-character Base62 string.\n */\n\n// KSUID epoch: May 13, 2014 00:00:00 UTC (Unix timestamp in seconds)\nconst KSUID_EPOCH = 1400000000\n\nconst KSUID_BYTES = 20\nconst KSUID_STRING_LEN = 27\nconst TIMESTAMP_BYTES = 4\nconst PAYLOAD_BYTES = 16\nconst KSUID_MAX_SECS = KSUID_EPOCH + 0xffffffff\n// 2^160 - 1 in Base62 ('aWgEPTl1tmebfsQzFP4bxwgy80V'), derived from the\n// encoder so it cannot drift from the decoder's 160-bit overflow bound.\nconst KSUID_MAX_STRING = encodeBase62(new Uint8Array(KSUID_BYTES).fill(0xff))\n\n// Validation regex: 27 alphanumeric characters\n// Note: Both cases are valid Base62 characters, but they decode to different values\n// (e.g., 'A' = 10, 'a' = 36). The regex validates format, not semantic equivalence.\nconst KSUID_REGEX = /^[0-9A-Za-z]{27}$/\n\nexport type KsuidOptions = {\n /**\n * 16 bytes of random data to use for KSUID payload.\n */\n random?: Uint8Array\n /**\n * Timestamp in seconds since Unix epoch.\n * Defaults to Math.floor(Date.now() / 1000).\n * KSUID natively uses second precision.\n */\n secs?: number\n}\n\nexport type Ksuid = {\n /** Generate a time-ordered KSUID string. */\n (): string\n /** Generate a KSUID with explicit options or write its 20 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: KsuidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a KSUID string with optional timestamp or random payload bytes. */\n (options?: KsuidOptions, buf?: undefined, offset?: number): string\n /** Convert a KSUID string to its canonical 20-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 20 canonical KSUID bytes to a KSUID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid KSUID string. */\n isValid(id: unknown): id is string\n /** The nil KSUID (all zeros) */\n NIL: string\n /** The max KSUID (maximum valid value) */\n MAX: string\n}\n\n/**\n * Write already-validated KSUID fields to a buffer.\n */\nfunction writeKsuidBytesUnchecked(timestamp: number, payload: Uint8Array, buf: Uint8Array, offset: number): void {\n // Timestamp (32-bit big-endian seconds since KSUID epoch) -> bytes 0-3\n writeTimestamp32(buf, offset, timestamp)\n\n // Payload (128 bits) -> bytes 4-19\n for (let i = 0; i < PAYLOAD_BYTES; i += 1) {\n buf[offset + TIMESTAMP_BYTES + i] = payload[i]\n }\n}\n\n/*\n * Overload: no buffer => return a KSUID string.\n */\nfunction ksuidFn(options?: KsuidOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with KSUID bytes.\n */\nfunction ksuidFn<TBuf extends Uint8Array = Uint8Array>(\n options: KsuidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction ksuidFn<TBuf extends Uint8Array = Uint8Array>(options?: KsuidOptions, buf?: TBuf, offset = 0): string | TBuf {\n const random = options?.random\n if (random && random.length < PAYLOAD_BYTES) {\n throw new InvalidInputError('KSUID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16 for KSUID')\n }\n\n let timestamp: number\n const secs = options?.secs\n if (secs !== undefined) {\n if (!Number.isInteger(secs) || secs < KSUID_EPOCH) {\n throw new InvalidInputError('KSUID_TIMESTAMP_TOO_LOW', 'Timestamp must be >= KSUID epoch')\n }\n\n if (secs > KSUID_MAX_SECS) {\n throw new InvalidInputError('KSUID_TIMESTAMP_TOO_HIGH', 'Timestamp must be <= maximum KSUID timestamp')\n }\n\n timestamp = secs - KSUID_EPOCH\n } else {\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all KSUIDs generated within a single request will have the same timestamp.\n */\n timestamp = Math.floor(Date.now() / 1000) - KSUID_EPOCH\n }\n\n const payload = random ?? rng()\n\n if (buf) {\n if (!isWritableRange(buf, offset, KSUID_BYTES)) {\n throw new BufferError(\n 'KSUID_BUFFER_OUT_OF_BOUNDS',\n `KSUID byte range ${offset}:${offset + KSUID_BYTES - 1} is out of buffer bounds`,\n )\n }\n writeKsuidBytesUnchecked(timestamp, payload, buf, offset)\n return buf\n }\n\n const bytes = new Uint8Array(KSUID_BYTES)\n writeKsuidBytesUnchecked(timestamp, payload, bytes, 0)\n\n // String mode: create bytes then encode to Base62\n return encodeBase62(bytes)\n}\n\n/**\n * Convert a KSUID string to 20 bytes.\n *\n * Note: Base62 is case-sensitive. 'A' (value 10) and 'a' (value 36) decode\n * to different byte values. This function accepts both cases as valid input.\n */\nfunction toBytes(id: string): Uint8Array {\n return decodeBase62(id)\n}\n\n/**\n * Convert 20 bytes to a KSUID string.\n */\nfunction fromBytes(bytes: Uint8Array): string {\n if (bytes.length !== KSUID_BYTES) {\n throw new BufferError(\n 'KSUID_BYTES_INVALID_LENGTH',\n `KSUID bytes must be exactly ${KSUID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n return encodeBase62(bytes)\n}\n\n/**\n * Extract the timestamp from a KSUID string.\n * Returns Unix timestamp in milliseconds for API consistency with ulid/uuidv7.\n * Note: KSUID only has second precision, so the returned value will always end in 000.\n */\nfunction timestamp(id: string): number {\n const bytes = decodeBase62(id)\n // First 4 bytes are big-endian timestamp (seconds since KSUID epoch)\n const secs = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0\n // Add KSUID epoch and convert to milliseconds\n return (secs + KSUID_EPOCH) * 1000\n}\n\n/**\n * Validate a KSUID string format and 160-bit numeric range.\n */\nfunction isValid(id: unknown): id is string {\n return (\n typeof id === 'string' &&\n id.length === KSUID_STRING_LEN &&\n KSUID_REGEX.test(id) &&\n // Fixed-length Base62 strings preserve numeric order because the alphabet is ASCII-sorted.\n id <= KSUID_MAX_STRING\n )\n}\n\n/**\n * Generate a KSUID string or write the bytes into a buffer.\n * Also includes helpers to convert to and from byte arrays.\n */\nexport const ksuid: Ksuid = Object.assign(ksuidFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '000000000000000000000000000',\n MAX: KSUID_MAX_STRING,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"ksuid.mjs","names":["KSUID_BYTES","KSUID_STRING_LEN"],"sources":["../../src/ksuid/base62.ts","../../src/ksuid/ksuid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\n/**\n * Base62 encoding/decoding for KSUID.\n * Alphabet: 0-9A-Za-z (standard Base62 ordering)\n *\n * KSUID binary format: 20 bytes (160 bits)\n * - 4 bytes: timestamp (seconds since KSUID epoch)\n * - 16 bytes: payload (cryptographically random)\n *\n * String format: 27 characters of Base62\n */\n\n// Base62 alphabet: digits (0-9), uppercase (A-Z), lowercase (a-z)\nconst BASE62_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\nconst BASE = 62n\nconst MAX_KSUID_VALUE = (1n << 160n) - 1n\nconst KSUID_BYTES = 20\nconst KSUID_STRING_LEN = 27\n\n// Pre-computed decode table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 64 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\n// Note: Base62 is case-sensitive - 'A' (value 10) and 'a' (value 36) are different\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\n\nfor (let i = 0; i < BASE62_ALPHABET.length; i += 1) {\n DECODING[BASE62_ALPHABET.charCodeAt(i)] = i\n}\n\n/**\n * Encode a 20-byte KSUID to a 27-character Base62 string.\n *\n * Algorithm: Convert the 160-bit number to base 62 using BigInt.\n * V8 has highly optimized BigInt operations for this size.\n */\nexport function encodeBase62(bytes: Uint8Array): string {\n if (bytes.length < KSUID_BYTES) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `KSUID bytes must be at least ${KSUID_BYTES} bytes, got ${bytes.length}`,\n { strategy: 'ksuid' },\n )\n }\n\n // Convert bytes to BigInt (big-endian)\n let num = 0n\n for (let i = 0; i < KSUID_BYTES; i += 1) {\n num = (num << 8n) | BigInt(bytes[i])\n }\n\n // Convert to Base62 string (build from right to left)\n // Direct string concatenation is faster than array + join in V8\n let encoded = ''\n while (num > 0n) {\n const remainder = num % BASE\n num = num / BASE\n encoded = BASE62_ALPHABET[Number(remainder)] + encoded\n }\n\n // Pad the result with the zero-character ('0') to ensure a fixed length\n return encoded.padStart(KSUID_STRING_LEN, '0')\n}\n\n/**\n * Decode a 27-character Base62 string to a 20-byte KSUID.\n *\n * Algorithm: Convert Base62 string to BigInt, then to bytes.\n * V8 has highly optimized BigInt operations.\n */\nexport function decodeBase62(str: string): Uint8Array {\n if (str.length !== KSUID_STRING_LEN) {\n throw new ParseError('INVALID_LENGTH', `KSUID string must be ${KSUID_STRING_LEN} characters, got ${str.length}`, {\n strategy: 'ksuid',\n })\n }\n\n // Convert Base62 string to BigInt\n let num = 0n\n for (let i = 0; i < KSUID_STRING_LEN; i += 1) {\n const value = DECODING[str.charCodeAt(i)]\n if (value === 255) {\n throw new ParseError('INVALID_CHAR', `Invalid KSUID character: ${str[i]}`, { strategy: 'ksuid' })\n }\n num = num * BASE + BigInt(value)\n }\n\n if (num > MAX_KSUID_VALUE) {\n throw new ParseError('VALUE_OUT_OF_RANGE', 'KSUID string exceeds 160-bit range', { strategy: 'ksuid' })\n }\n\n // Convert BigInt to bytes (big-endian)\n const bytes = new Uint8Array(KSUID_BYTES)\n for (let i = KSUID_BYTES - 1; i >= 0; i -= 1) {\n bytes[i] = Number(num & 0xffn)\n num = num >> 8n\n }\n\n return bytes\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { rng } from '../common/random'\nimport { resolveTimestampSecs } from '../common/timestamp'\nimport { isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeBase62, encodeBase62 } from './base62'\n\n/**\n * KSUID (K-Sortable Unique Identifier)\n *\n * A 160-bit identifier consisting of:\n * - 4 bytes: timestamp (seconds since KSUID epoch: May 13, 2014)\n * - 16 bytes: cryptographically random payload\n *\n * Encoded as a 27-character Base62 string.\n */\n\n// KSUID epoch: May 13, 2014 00:00:00 UTC (Unix timestamp in seconds)\nconst KSUID_EPOCH = 1400000000\n\nconst KSUID_BYTES = 20\nconst KSUID_STRING_LEN = 27\nconst TIMESTAMP_BYTES = 4\nconst PAYLOAD_BYTES = 16\nconst KSUID_MAX_SECS = KSUID_EPOCH + 0xffffffff\n// 2^160 - 1 in Base62 ('aWgEPTl1tmebfsQzFP4bxwgy80V'), derived from the\n// encoder so it cannot drift from the decoder's 160-bit overflow bound.\nconst KSUID_MAX_STRING = encodeBase62(new Uint8Array(KSUID_BYTES).fill(0xff))\n\n// Validation regex: 27 alphanumeric characters\n// Note: Both cases are valid Base62 characters, but they decode to different values\n// (e.g., 'A' = 10, 'a' = 36). The regex validates format, not semantic equivalence.\nconst KSUID_REGEX = /^[0-9A-Za-z]{27}$/\n\nexport type KsuidOptions = {\n /**\n * 16 bytes of random data to use for KSUID payload.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since the Unix epoch.\n * Defaults to Date.now().\n * KSUID stores whole seconds, so sub-second precision is truncated.\n */\n msecs?: number\n /**\n * Timestamp in seconds since the Unix epoch.\n *\n * @deprecated Use `msecs` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n secs?: number\n}\n\nexport type Ksuid = {\n /** Generate a time-ordered KSUID string. */\n (): string\n /** Generate a KSUID with explicit options or write its 20 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: KsuidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a KSUID string with optional timestamp or random payload bytes. */\n (options?: KsuidOptions, buf?: undefined, offset?: number): string\n /** Convert a KSUID string to its canonical 20-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 20 canonical KSUID bytes to a KSUID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid KSUID string. */\n isValid(id: unknown): id is string\n /** The nil KSUID (all zeros) */\n NIL: string\n /** The max KSUID (maximum valid value) */\n MAX: string\n}\n\n/**\n * Write already-validated KSUID fields to a buffer.\n */\nfunction writeKsuidBytesUnchecked(timestamp: number, payload: Uint8Array, buf: Uint8Array, offset: number): void {\n // Timestamp (32-bit big-endian seconds since KSUID epoch) -> bytes 0-3\n writeTimestamp32(buf, offset, timestamp)\n\n // Payload (128 bits) -> bytes 4-19\n for (let i = 0; i < PAYLOAD_BYTES; i += 1) {\n buf[offset + TIMESTAMP_BYTES + i] = payload[i]\n }\n}\n\n/*\n * Overload: no buffer => return a KSUID string.\n */\nfunction ksuidFn(options?: KsuidOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with KSUID bytes.\n */\nfunction ksuidFn<TBuf extends Uint8Array = Uint8Array>(\n options: KsuidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction ksuidFn<TBuf extends Uint8Array = Uint8Array>(options?: KsuidOptions, buf?: TBuf, offset = 0): string | TBuf {\n const random = options?.random\n if (random && random.length < PAYLOAD_BYTES) {\n throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16 for KSUID', {\n strategy: 'ksuid',\n })\n }\n\n let timestamp: number\n const secs = options === undefined ? undefined : resolveTimestampSecs(options, KSUID_EPOCH, KSUID_MAX_SECS, 'ksuid')\n if (secs !== undefined) {\n timestamp = secs - KSUID_EPOCH\n } else {\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all KSUIDs generated within a single request will have the same timestamp.\n */\n timestamp = Math.floor(Date.now() / 1000) - KSUID_EPOCH\n }\n\n const payload = random ?? rng()\n\n if (buf) {\n if (!isWritableRange(buf, offset, KSUID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `KSUID byte range ${offset}:${offset + KSUID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'ksuid' },\n )\n }\n writeKsuidBytesUnchecked(timestamp, payload, buf, offset)\n return buf\n }\n\n const bytes = new Uint8Array(KSUID_BYTES)\n writeKsuidBytesUnchecked(timestamp, payload, bytes, 0)\n\n // String mode: create bytes then encode to Base62\n return encodeBase62(bytes)\n}\n\n/**\n * Convert a KSUID string to 20 bytes.\n *\n * Note: Base62 is case-sensitive. 'A' (value 10) and 'a' (value 36) decode\n * to different byte values. This function accepts both cases as valid input.\n */\nfunction toBytes(id: string): Uint8Array {\n return decodeBase62(id)\n}\n\n/**\n * Convert 20 bytes to a KSUID string.\n */\nfunction fromBytes(bytes: Uint8Array): string {\n if (bytes.length !== KSUID_BYTES) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `KSUID bytes must be exactly ${KSUID_BYTES} bytes, got ${bytes.length}`,\n { strategy: 'ksuid' },\n )\n }\n return encodeBase62(bytes)\n}\n\n/**\n * Extract the timestamp from a KSUID string.\n * Returns Unix timestamp in milliseconds for API consistency with ulid/uuidv7.\n * Note: KSUID only has second precision, so the returned value will always end in 000.\n */\nfunction timestamp(id: string): number {\n const bytes = decodeBase62(id)\n // First 4 bytes are big-endian timestamp (seconds since KSUID epoch)\n const secs = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0\n // Add KSUID epoch and convert to milliseconds\n return (secs + KSUID_EPOCH) * 1000\n}\n\n/**\n * Validate a KSUID string format and 160-bit numeric range.\n */\nfunction isValid(id: unknown): id is string {\n return (\n typeof id === 'string' &&\n id.length === KSUID_STRING_LEN &&\n KSUID_REGEX.test(id) &&\n // Fixed-length Base62 strings preserve numeric order because the alphabet is ASCII-sorted.\n id <= KSUID_MAX_STRING\n )\n}\n\n/**\n * Generate a KSUID string or write the bytes into a buffer.\n * Also includes helpers to convert to and from byte arrays.\n */\nexport const ksuid: Ksuid = Object.assign(ksuidFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '000000000000000000000000000',\n MAX: KSUID_MAX_STRING,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError } from "../errors-Dgoyi-ci.mjs";
import { i as InvalidInputError, o as UniqueIdError } from "../errors-Da-8dh4J.mjs";

@@ -9,4 +9,4 @@ //#region src/nanoid/nanoid.d.ts

* Random bytes for deterministic output (testing).
* For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `size` bytes needed.
* For other alphabets: ~size * 2 bytes needed (rejection sampling).
* For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `length` bytes needed.
* For other alphabets: ~length * 2 bytes needed (rejection sampling).
*/

@@ -22,2 +22,8 @@ random?: Uint8Array;

*/
length?: number;
/**
* Length of generated ID.
*
* @deprecated Use `length` instead. Will be removed at v1-rc.
*/
size?: number;

@@ -56,3 +62,3 @@ };

*
* @example Custom size
* @example Custom length
* ```ts

@@ -65,3 +71,3 @@ * const shortId = nanoid(10)

* ```ts
* const hexId = nanoid({ alphabet: '0123456789abcdef', size: 12 })
* const hexId = nanoid({ alphabet: '0123456789abcdef', length: 12 })
* // => "4f90d13a42bc"

@@ -79,5 +85,5 @@ * ```

*
* @throws {InvalidInputError} Size must be between 0 and 2048
* @throws {InvalidInputError} Length must be between 0 and 2048
* @throws {InvalidInputError} Alphabet must contain 2-256 unique printable ASCII characters
* @throws {InvalidInputError} Insufficient random bytes for requested size
* @throws {InvalidInputError} Insufficient random bytes for requested length
*/

@@ -84,0 +90,0 @@ declare const nanoid: Nanoid;

@@ -1,1 +0,1 @@

{"version":3,"file":"nanoid.d.mts","names":[],"sources":["../../src/nanoid/nanoid.ts"],"mappings":";;;;cAGa,YAAA;AAAA,KAqCD,aAAA;EArCZ;;;;AAAa;EA2CX,MAAA,GAAS,UAAA;EANC;;;;EAWV,QAAA;;;;EAIA,IAAA;AAAA;AAAA,KAGU,MAAA;;GAIT,IAAA;GAEA,OAAA,EAAS,aAAA;;;;AAKY;EAAtB,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;AAyLH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAR,MAAA,EAAQ,MAAA"}
{"version":3,"file":"nanoid.d.mts","names":[],"sources":["../../src/nanoid/nanoid.ts"],"mappings":";;;;cAGa,YAAA;AAAA,KAqCD,aAAA;EArCZ;;;;AAAa;EA2CX,MAAA,GAAS,UAAA;EANC;;;;EAWV,QAAA;;;;EAIA,MAAA;EAOA;AAGF;;;;EAHE,IAAA;AAAA;AAAA,KAGU,MAAA;;GAIT,IAAA,mBAOqB;EAAA,CALrB,OAAA,EAAS,aAAA;EA8MS;;;AAAA;EAzMnB,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyMX,MAAA,EAAQ,MAAA"}

@@ -1,2 +0,2 @@

import{InvalidInputError as e,UniqueIdError as t}from"../errors.mjs";const n=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`,r=2048,i=/^[A-Za-z0-9_-]+$/,a=new TextDecoder;let o,s=``,c=0;function l(e){let t=Math.min(e*128,65536);if((!o||o.length<t)&&(o=new Uint8Array(t)),c+e>s.length){crypto.getRandomValues(o);for(let e=0;e<o.length;e++)o[e]=n.charCodeAt(o[e]&63);s=a.decode(o),c=0}}function u(e){l(e);let t=s.substring(c,c+e);return c+=e,t}function d(t){if(t.length<2)throw new e(`NANOID_ALPHABET_TOO_SHORT`,`Alphabet must contain at least 2 characters`);if(t.length>256)throw new e(`NANOID_ALPHABET_TOO_LONG`,`Alphabet must not exceed 256 characters`);let n=new Set;for(let r of t){let t=r.charCodeAt(0);if(t<32||t>126)throw new e(`NANOID_ALPHABET_INVALID_CHAR`,`Alphabet must contain only printable ASCII characters (32-126)`);if(n.has(r))throw new e(`NANOID_ALPHABET_DUPLICATE`,`Duplicate character in alphabet: "${r}"`);n.add(r)}}function f(t){if(!Number.isInteger(t)||t<0)throw new e(`NANOID_SIZE_INVALID`,`Size must be a non-negative integer`);if(t>r)throw new e(`NANOID_SIZE_TOO_LARGE`,`Size must not exceed ${r}`)}function p(t){if(t===void 0)return u(21);let r=21,i=n,a;if(typeof t==`number`?r=t:(r=t.size??21,i=t.alphabet??`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`,a=t.random,t.alphabet!==void 0&&d(i)),f(r),r===0)return``;if(i===`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`&&a===void 0)return u(r);let o=i.length;if(!(o&o-1)){let t=o-1;if(a&&a.length<r)throw new e(`NANOID_RANDOM_BYTES_INSUFFICIENT`,`Insufficient random bytes: need ${r}, have ${a.length}`);let n=a?.subarray(0,r)??globalThis.crypto.getRandomValues(new Uint8Array(r)),s=``;for(let e=0;e<r;e++)s+=i[n[e]&t];return s}let s=(2<<31-Math.clz32(o-1|1))-1,c=Math.ceil(1.6*s*r/o),l=``,p=0;for(;l.length<r;){let t;if(a){if(a.length-p<c)throw new e(`NANOID_RANDOM_BYTES_INSUFFICIENT`,`Insufficient random bytes: need at least ${c} more, have ${a.length-p}`);t=a.subarray(p,p+c),p+=c}else t=globalThis.crypto.getRandomValues(new Uint8Array(c));for(let e=0;e<t.length&&l.length<r;e++){let n=t[e]&s;n<o&&(l+=i[n])}}return l}function m(e){return typeof e==`string`&&e.length>0&&i.test(e)}const h=Object.assign(p,{isValid:m});export{e as InvalidInputError,n as URL_ALPHABET,t as UniqueIdError,h as nanoid};
import{InvalidInputError as e,UniqueIdError as t}from"../errors.mjs";const n=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`,r=2048,i=/^[A-Za-z0-9_-]+$/,a=new TextDecoder;let o,s=``,c=0;function l(e){let t=Math.min(e*128,65536);if((!o||o.length<t)&&(o=new Uint8Array(t)),c+e>s.length){crypto.getRandomValues(o);for(let e=0;e<o.length;e++)o[e]=n.charCodeAt(o[e]&63);s=a.decode(o),c=0}}function u(e){l(e);let t=s.substring(c,c+e);return c+=e,t}function d(t){if(t.length<2)throw new e(`ALPHABET_OUT_OF_RANGE`,`Alphabet must contain at least 2 characters`,{strategy:`nanoid`});if(t.length>256)throw new e(`ALPHABET_OUT_OF_RANGE`,`Alphabet must not exceed 256 characters`,{strategy:`nanoid`});let n=new Set;for(let r of t){let t=r.charCodeAt(0);if(t<32||t>126)throw new e(`ALPHABET_INVALID_CHAR`,`Alphabet must contain only printable ASCII characters (32-126)`,{strategy:`nanoid`});if(n.has(r))throw new e(`ALPHABET_DUPLICATE`,`Duplicate character in alphabet: "${r}"`,{strategy:`nanoid`});n.add(r)}}function f(t){if(!Number.isInteger(t)||t<0)throw new e(`LENGTH_OUT_OF_RANGE`,`Length must be a non-negative integer`,{strategy:`nanoid`});if(t>r)throw new e(`LENGTH_OUT_OF_RANGE`,`Length must not exceed ${r}`,{strategy:`nanoid`})}function p(t){if(t===void 0)return u(21);let r=21,i=n,a;if(typeof t==`number`)r=t;else{if(t.length!==void 0&&t.size!==void 0)throw new e(`CONFLICTING_OPTIONS`,"Pass only one of `length` or `size`, not both",{strategy:`nanoid`});r=t.length??t.size??21,i=t.alphabet??`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`,a=t.random,t.alphabet!==void 0&&d(i)}if(f(r),r===0)return``;if(i===`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-`&&a===void 0)return u(r);let o=i.length;if(!(o&o-1)){let t=o-1;if(a&&a.length<r)throw new e(`RANDOM_BYTES_TOO_SHORT`,`Insufficient random bytes: need ${r}, have ${a.length}`,{strategy:`nanoid`});let n=a?.subarray(0,r)??globalThis.crypto.getRandomValues(new Uint8Array(r)),s=``;for(let e=0;e<r;e++)s+=i[n[e]&t];return s}let s=(2<<31-Math.clz32(o-1|1))-1,c=Math.ceil(1.6*s*r/o),l=``,p=0;for(;l.length<r;){let t;if(a){if(a.length-p<c)throw new e(`RANDOM_BYTES_TOO_SHORT`,`Insufficient random bytes: need at least ${c} more, have ${a.length-p}`,{strategy:`nanoid`});t=a.subarray(p,p+c),p+=c}else t=globalThis.crypto.getRandomValues(new Uint8Array(c));for(let e=0;e<t.length&&l.length<r;e++){let n=t[e]&s;n<o&&(l+=i[n])}}return l}function m(e){return typeof e==`string`&&e.length>0&&i.test(e)}const h=Object.assign(p,{isValid:m});export{e as InvalidInputError,n as URL_ALPHABET,t as UniqueIdError,h as nanoid};
//# sourceMappingURL=nanoid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"nanoid.mjs","names":[],"sources":["../../src/nanoid/nanoid.ts"],"sourcesContent":["import { InvalidInputError } from '../errors'\n\n/** Default URL-safe alphabet (64 characters): A-Z, a-z, 0-9, underscore, hyphen */\nexport const URL_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-'\n\nconst DEFAULT_SIZE = 21\nconst MAX_SIZE = 2048\nconst NANOID_REGEX = /^[A-Za-z0-9_-]+$/\n\n// Keep Nanoid's private pool for its default hot path. Translate random bytes\n// into URL-safe ASCII once per refill, then serve IDs as sequential substrings.\nconst POOL_SIZE_MULTIPLIER = 128\nconst MAX_POOL_SIZE = 65_536\nconst ASCII_DECODER = new TextDecoder()\nlet poolBytes: Uint8Array | undefined\nlet characterPool = ''\nlet poolOffset = 0\n\nfunction fillPool(bytes: number): void {\n const size = Math.min(bytes * POOL_SIZE_MULTIPLIER, MAX_POOL_SIZE)\n if (!poolBytes || poolBytes.length < size) {\n poolBytes = new Uint8Array(size)\n }\n if (poolOffset + bytes > characterPool.length) {\n crypto.getRandomValues(poolBytes)\n for (let i = 0; i < poolBytes.length; i++) {\n poolBytes[i] = URL_ALPHABET.charCodeAt(poolBytes[i] & 63)\n }\n characterPool = ASCII_DECODER.decode(poolBytes)\n poolOffset = 0\n }\n}\n\nfunction defaultAlphabetFromPool(size: number): string {\n fillPool(size)\n const id = characterPool.substring(poolOffset, poolOffset + size)\n poolOffset += size\n return id\n}\n\nexport type NanoidOptions = {\n /**\n * Random bytes for deterministic output (testing).\n * For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `size` bytes needed.\n * For other alphabets: ~size * 2 bytes needed (rejection sampling).\n */\n random?: Uint8Array\n /**\n * Custom alphabet to use. Default: URL-safe A-Za-z0-9_-\n * Must be 2-256 printable ASCII characters (32-126) with no duplicates.\n */\n alphabet?: string\n /**\n * Length of generated ID. Default: 21. Maximum: 2048.\n */\n size?: number\n}\n\nexport type Nanoid = {\n /** Generate a Nanoid with the default URL-safe alphabet and 21-character length. */\n (): string\n /** Generate a Nanoid with the default alphabet and a custom length. */\n (size: number): string\n /** Generate a Nanoid with a custom alphabet, length, or deterministic random bytes. */\n (options: NanoidOptions): string\n /**\n * Validate a nanoid string against the default URL-safe alphabet.\n * Note: Does not validate IDs generated with custom alphabets.\n */\n isValid(id: unknown): id is string\n}\n\n/**\n * Validate alphabet: 2-256 printable ASCII chars, no duplicates\n */\nfunction validateAlphabet(alphabet: string): void {\n if (alphabet.length < 2) {\n throw new InvalidInputError('NANOID_ALPHABET_TOO_SHORT', 'Alphabet must contain at least 2 characters')\n }\n if (alphabet.length > 256) {\n throw new InvalidInputError('NANOID_ALPHABET_TOO_LONG', 'Alphabet must not exceed 256 characters')\n }\n const seen = new Set<string>()\n for (const char of alphabet) {\n const code = char.charCodeAt(0)\n if (code < 32 || code > 126) {\n throw new InvalidInputError(\n 'NANOID_ALPHABET_INVALID_CHAR',\n 'Alphabet must contain only printable ASCII characters (32-126)',\n )\n }\n if (seen.has(char)) {\n throw new InvalidInputError('NANOID_ALPHABET_DUPLICATE', `Duplicate character in alphabet: \"${char}\"`)\n }\n seen.add(char)\n }\n}\n\n/**\n * Validate size parameter\n */\nfunction validateSize(size: number): void {\n if (!Number.isInteger(size) || size < 0) {\n throw new InvalidInputError('NANOID_SIZE_INVALID', 'Size must be a non-negative integer')\n }\n if (size > MAX_SIZE) {\n throw new InvalidInputError('NANOID_SIZE_TOO_LARGE', `Size must not exceed ${MAX_SIZE}`)\n }\n}\n\n// Overloads\nfunction nanoidFn(): string\nfunction nanoidFn(size: number): string\nfunction nanoidFn(options: NanoidOptions): string\nfunction nanoidFn(sizeOrOptions?: number | NanoidOptions): string {\n // ULTRA-FAST PATH: No arguments = default nanoid\n // Uses simple pooled random bytes (npm nanoid style) for best performance\n if (sizeOrOptions === undefined) {\n return defaultAlphabetFromPool(DEFAULT_SIZE)\n }\n\n let size = DEFAULT_SIZE\n let alphabet = URL_ALPHABET\n let randomBytes: Uint8Array | undefined\n\n if (typeof sizeOrOptions === 'number') {\n size = sizeOrOptions\n } else {\n size = sizeOrOptions.size ?? DEFAULT_SIZE\n alphabet = sizeOrOptions.alphabet ?? URL_ALPHABET\n randomBytes = sizeOrOptions.random\n if (sizeOrOptions.alphabet !== undefined) {\n validateAlphabet(alphabet)\n }\n }\n\n validateSize(size)\n\n if (size === 0) return ''\n\n if (alphabet === URL_ALPHABET && randomBytes === undefined) {\n return defaultAlphabetFromPool(size)\n }\n\n const alphabetLen = alphabet.length\n\n // FAST PATH: Power-of-2 alphabet (includes default 64-char)\n // No rejection needed - each byte maps directly to a character\n if ((alphabetLen & (alphabetLen - 1)) === 0) {\n const mask = alphabetLen - 1\n if (randomBytes && randomBytes.length < size) {\n throw new InvalidInputError(\n 'NANOID_RANDOM_BYTES_INSUFFICIENT',\n `Insufficient random bytes: need ${size}, have ${randomBytes.length}`,\n )\n }\n const bytes = randomBytes?.subarray(0, size) ?? globalThis.crypto.getRandomValues(new Uint8Array(size))\n let id = ''\n for (let i = 0; i < size; i++) {\n id += alphabet[bytes[i] & mask]\n }\n return id\n }\n\n // SLOW PATH: Rejection sampling for non-power-of-2 alphabets\n // Calculate mask: smallest power-of-2 minus 1 that covers alphabet size\n const mask = (2 << (31 - Math.clz32((alphabetLen - 1) | 1))) - 1\n // Calculate step: random bytes per batch (1.6x accounts for rejection)\n const step = Math.ceil((1.6 * mask * size) / alphabetLen)\n\n let id = ''\n let randomOffset = 0\n\n while (id.length < size) {\n let bytes: Uint8Array\n if (randomBytes) {\n if (randomBytes.length - randomOffset < step) {\n throw new InvalidInputError(\n 'NANOID_RANDOM_BYTES_INSUFFICIENT',\n `Insufficient random bytes: need at least ${step} more, have ${randomBytes.length - randomOffset}`,\n )\n }\n bytes = randomBytes.subarray(randomOffset, randomOffset + step)\n randomOffset += step\n } else {\n bytes = globalThis.crypto.getRandomValues(new Uint8Array(step))\n }\n\n for (let i = 0; i < bytes.length && id.length < size; i++) {\n const index = bytes[i] & mask\n if (index < alphabetLen) {\n id += alphabet[index]\n }\n // Otherwise reject and continue (no modulo bias)\n }\n }\n\n return id\n}\n\n/**\n * Validate a nanoid string against the default URL-safe alphabet.\n * Note: Does not validate IDs generated with custom alphabets.\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && id.length > 0 && NANOID_REGEX.test(id)\n}\n\n/**\n * Generate a URL-friendly unique string ID.\n *\n * Nanoid is a tiny, secure, URL-friendly unique string ID generator.\n * It uses a URL-safe alphabet (A-Za-z0-9_-) and generates 21-character\n * IDs by default with 126 bits of entropy.\n *\n * Unlike UUID v7 or ULID, nanoid is NOT time-ordered. Use it for:\n * - URL shorteners\n * - Session tokens\n * - Invite codes\n * - Any case where you need short, random IDs\n *\n * @example Basic usage\n * ```ts\n * import { nanoid } from 'uniku/nanoid'\n *\n * const id = nanoid()\n * // => \"V1StGXR8_Z5jdHi6B-myT\"\n * ```\n *\n * @example Custom size\n * ```ts\n * const shortId = nanoid(10)\n * // => \"IRFa-VaY2b\"\n * ```\n *\n * @example Custom alphabet (hex)\n * ```ts\n * const hexId = nanoid({ alphabet: '0123456789abcdef', size: 12 })\n * // => \"4f90d13a42bc\"\n * ```\n *\n * @example Validation\n * ```ts\n * const maybeId: unknown = getUserInput()\n * if (nanoid.isValid(maybeId)) {\n * // TypeScript knows maybeId is string\n * console.log(maybeId.length)\n * }\n * ```\n *\n * @throws {InvalidInputError} Size must be between 0 and 2048\n * @throws {InvalidInputError} Alphabet must contain 2-256 unique printable ASCII characters\n * @throws {InvalidInputError} Insufficient random bytes for requested size\n */\nexport const nanoid: Nanoid = Object.assign(nanoidFn, {\n isValid,\n})\n\nexport { InvalidInputError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"nanoid.mjs","names":[],"sources":["../../src/nanoid/nanoid.ts"],"sourcesContent":["import { InvalidInputError } from '../errors'\n\n/** Default URL-safe alphabet (64 characters): A-Z, a-z, 0-9, underscore, hyphen */\nexport const URL_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-'\n\nconst DEFAULT_SIZE = 21\nconst MAX_SIZE = 2048\nconst NANOID_REGEX = /^[A-Za-z0-9_-]+$/\n\n// Keep Nanoid's private pool for its default hot path. Translate random bytes\n// into URL-safe ASCII once per refill, then serve IDs as sequential substrings.\nconst POOL_SIZE_MULTIPLIER = 128\nconst MAX_POOL_SIZE = 65_536\nconst ASCII_DECODER = new TextDecoder()\nlet poolBytes: Uint8Array | undefined\nlet characterPool = ''\nlet poolOffset = 0\n\nfunction fillPool(bytes: number): void {\n const size = Math.min(bytes * POOL_SIZE_MULTIPLIER, MAX_POOL_SIZE)\n if (!poolBytes || poolBytes.length < size) {\n poolBytes = new Uint8Array(size)\n }\n if (poolOffset + bytes > characterPool.length) {\n crypto.getRandomValues(poolBytes)\n for (let i = 0; i < poolBytes.length; i++) {\n poolBytes[i] = URL_ALPHABET.charCodeAt(poolBytes[i] & 63)\n }\n characterPool = ASCII_DECODER.decode(poolBytes)\n poolOffset = 0\n }\n}\n\nfunction defaultAlphabetFromPool(size: number): string {\n fillPool(size)\n const id = characterPool.substring(poolOffset, poolOffset + size)\n poolOffset += size\n return id\n}\n\nexport type NanoidOptions = {\n /**\n * Random bytes for deterministic output (testing).\n * For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `length` bytes needed.\n * For other alphabets: ~length * 2 bytes needed (rejection sampling).\n */\n random?: Uint8Array\n /**\n * Custom alphabet to use. Default: URL-safe A-Za-z0-9_-\n * Must be 2-256 printable ASCII characters (32-126) with no duplicates.\n */\n alphabet?: string\n /**\n * Length of generated ID. Default: 21. Maximum: 2048.\n */\n length?: number\n /**\n * Length of generated ID.\n *\n * @deprecated Use `length` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n size?: number\n}\n\nexport type Nanoid = {\n /** Generate a Nanoid with the default URL-safe alphabet and 21-character length. */\n (): string\n /** Generate a Nanoid with the default alphabet and a custom length. */\n (size: number): string\n /** Generate a Nanoid with a custom alphabet, length, or deterministic random bytes. */\n (options: NanoidOptions): string\n /**\n * Validate a nanoid string against the default URL-safe alphabet.\n * Note: Does not validate IDs generated with custom alphabets.\n */\n isValid(id: unknown): id is string\n}\n\n/**\n * Validate alphabet: 2-256 printable ASCII chars, no duplicates\n */\nfunction validateAlphabet(alphabet: string): void {\n if (alphabet.length < 2) {\n throw new InvalidInputError('ALPHABET_OUT_OF_RANGE', 'Alphabet must contain at least 2 characters', {\n strategy: 'nanoid',\n })\n }\n if (alphabet.length > 256) {\n throw new InvalidInputError('ALPHABET_OUT_OF_RANGE', 'Alphabet must not exceed 256 characters', {\n strategy: 'nanoid',\n })\n }\n const seen = new Set<string>()\n for (const char of alphabet) {\n const code = char.charCodeAt(0)\n if (code < 32 || code > 126) {\n throw new InvalidInputError(\n 'ALPHABET_INVALID_CHAR',\n 'Alphabet must contain only printable ASCII characters (32-126)',\n {\n strategy: 'nanoid',\n },\n )\n }\n if (seen.has(char)) {\n throw new InvalidInputError('ALPHABET_DUPLICATE', `Duplicate character in alphabet: \"${char}\"`, {\n strategy: 'nanoid',\n })\n }\n seen.add(char)\n }\n}\n\n/**\n * Validate length parameter\n */\nfunction validateLength(size: number): void {\n if (!Number.isInteger(size) || size < 0) {\n throw new InvalidInputError('LENGTH_OUT_OF_RANGE', 'Length must be a non-negative integer', { strategy: 'nanoid' })\n }\n if (size > MAX_SIZE) {\n throw new InvalidInputError('LENGTH_OUT_OF_RANGE', `Length must not exceed ${MAX_SIZE}`, { strategy: 'nanoid' })\n }\n}\n\n// Overloads\nfunction nanoidFn(): string\nfunction nanoidFn(size: number): string\nfunction nanoidFn(options: NanoidOptions): string\nfunction nanoidFn(sizeOrOptions?: number | NanoidOptions): string {\n // ULTRA-FAST PATH: No arguments = default nanoid\n // Uses simple pooled random bytes (npm nanoid style) for best performance\n if (sizeOrOptions === undefined) {\n return defaultAlphabetFromPool(DEFAULT_SIZE)\n }\n\n let size = DEFAULT_SIZE\n let alphabet = URL_ALPHABET\n let randomBytes: Uint8Array | undefined\n\n if (typeof sizeOrOptions === 'number') {\n size = sizeOrOptions\n } else {\n if (sizeOrOptions.length !== undefined && sizeOrOptions.size !== undefined) {\n throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `length` or `size`, not both', {\n strategy: 'nanoid',\n })\n }\n size = sizeOrOptions.length ?? sizeOrOptions.size ?? DEFAULT_SIZE\n alphabet = sizeOrOptions.alphabet ?? URL_ALPHABET\n randomBytes = sizeOrOptions.random\n if (sizeOrOptions.alphabet !== undefined) {\n validateAlphabet(alphabet)\n }\n }\n\n validateLength(size)\n\n if (size === 0) return ''\n\n if (alphabet === URL_ALPHABET && randomBytes === undefined) {\n return defaultAlphabetFromPool(size)\n }\n\n const alphabetLen = alphabet.length\n\n // FAST PATH: Power-of-2 alphabet (includes default 64-char)\n // No rejection needed - each byte maps directly to a character\n if ((alphabetLen & (alphabetLen - 1)) === 0) {\n const mask = alphabetLen - 1\n if (randomBytes && randomBytes.length < size) {\n throw new InvalidInputError(\n 'RANDOM_BYTES_TOO_SHORT',\n `Insufficient random bytes: need ${size}, have ${randomBytes.length}`,\n { strategy: 'nanoid' },\n )\n }\n const bytes = randomBytes?.subarray(0, size) ?? globalThis.crypto.getRandomValues(new Uint8Array(size))\n let id = ''\n for (let i = 0; i < size; i++) {\n id += alphabet[bytes[i] & mask]\n }\n return id\n }\n\n // SLOW PATH: Rejection sampling for non-power-of-2 alphabets\n // Calculate mask: smallest power-of-2 minus 1 that covers alphabet size\n const mask = (2 << (31 - Math.clz32((alphabetLen - 1) | 1))) - 1\n // Calculate step: random bytes per batch (1.6x accounts for rejection)\n const step = Math.ceil((1.6 * mask * size) / alphabetLen)\n\n let id = ''\n let randomOffset = 0\n\n while (id.length < size) {\n let bytes: Uint8Array\n if (randomBytes) {\n if (randomBytes.length - randomOffset < step) {\n throw new InvalidInputError(\n 'RANDOM_BYTES_TOO_SHORT',\n `Insufficient random bytes: need at least ${step} more, have ${randomBytes.length - randomOffset}`,\n { strategy: 'nanoid' },\n )\n }\n bytes = randomBytes.subarray(randomOffset, randomOffset + step)\n randomOffset += step\n } else {\n bytes = globalThis.crypto.getRandomValues(new Uint8Array(step))\n }\n\n for (let i = 0; i < bytes.length && id.length < size; i++) {\n const index = bytes[i] & mask\n if (index < alphabetLen) {\n id += alphabet[index]\n }\n // Otherwise reject and continue (no modulo bias)\n }\n }\n\n return id\n}\n\n/**\n * Validate a nanoid string against the default URL-safe alphabet.\n * Note: Does not validate IDs generated with custom alphabets.\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && id.length > 0 && NANOID_REGEX.test(id)\n}\n\n/**\n * Generate a URL-friendly unique string ID.\n *\n * Nanoid is a tiny, secure, URL-friendly unique string ID generator.\n * It uses a URL-safe alphabet (A-Za-z0-9_-) and generates 21-character\n * IDs by default with 126 bits of entropy.\n *\n * Unlike UUID v7 or ULID, nanoid is NOT time-ordered. Use it for:\n * - URL shorteners\n * - Session tokens\n * - Invite codes\n * - Any case where you need short, random IDs\n *\n * @example Basic usage\n * ```ts\n * import { nanoid } from 'uniku/nanoid'\n *\n * const id = nanoid()\n * // => \"V1StGXR8_Z5jdHi6B-myT\"\n * ```\n *\n * @example Custom length\n * ```ts\n * const shortId = nanoid(10)\n * // => \"IRFa-VaY2b\"\n * ```\n *\n * @example Custom alphabet (hex)\n * ```ts\n * const hexId = nanoid({ alphabet: '0123456789abcdef', length: 12 })\n * // => \"4f90d13a42bc\"\n * ```\n *\n * @example Validation\n * ```ts\n * const maybeId: unknown = getUserInput()\n * if (nanoid.isValid(maybeId)) {\n * // TypeScript knows maybeId is string\n * console.log(maybeId.length)\n * }\n * ```\n *\n * @throws {InvalidInputError} Length must be between 0 and 2048\n * @throws {InvalidInputError} Alphabet must contain 2-256 unique printable ASCII characters\n * @throws {InvalidInputError} Insufficient random bytes for requested length\n */\nexport const nanoid: Nanoid = Object.assign(nanoidFn, {\n isValid,\n})\n\nexport { InvalidInputError, UniqueIdError } from '../errors'\n"],"mappings":"qEAGA,MAAa,EAAe,mEAGtB,EAAW,KACX,EAAe,mBAMf,EAAgB,IAAI,YAC1B,IAAI,EACA,EAAgB,GAChB,EAAa,EAEjB,SAAS,EAAS,EAAqB,CACrC,IAAM,EAAO,KAAK,IAAI,EAAQ,IAAsB,KAAa,EAIjE,IAHI,CAAC,GAAa,EAAU,OAAS,KACnC,EAAY,IAAI,WAAW,CAAI,GAE7B,EAAa,EAAQ,EAAc,OAAQ,CAC7C,OAAO,gBAAgB,CAAS,EAChC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAU,OAAQ,IACpC,EAAU,GAAK,EAAa,WAAW,EAAU,GAAK,EAAE,EAE1D,EAAgB,EAAc,OAAO,CAAS,EAC9C,EAAa,CACf,CACF,CAEA,SAAS,EAAwB,EAAsB,CACrD,EAAS,CAAI,EACb,IAAM,EAAK,EAAc,UAAU,EAAY,EAAa,CAAI,EAEhE,MADA,IAAc,EACP,CACT,CA4CA,SAAS,EAAiB,EAAwB,CAChD,GAAI,EAAS,OAAS,EACpB,MAAM,IAAI,EAAkB,wBAAyB,8CAA+C,CAClG,SAAU,QACZ,CAAC,EAEH,GAAI,EAAS,OAAS,IACpB,MAAM,IAAI,EAAkB,wBAAyB,0CAA2C,CAC9F,SAAU,QACZ,CAAC,EAEH,IAAM,EAAO,IAAI,IACjB,IAAK,IAAM,KAAQ,EAAU,CAC3B,IAAM,EAAO,EAAK,WAAW,CAAC,EAC9B,GAAI,EAAO,IAAM,EAAO,IACtB,MAAM,IAAI,EACR,wBACA,iEACA,CACE,SAAU,QACZ,CACF,EAEF,GAAI,EAAK,IAAI,CAAI,EACf,MAAM,IAAI,EAAkB,qBAAsB,qCAAqC,EAAK,GAAI,CAC9F,SAAU,QACZ,CAAC,EAEH,EAAK,IAAI,CAAI,CACf,CACF,CAKA,SAAS,EAAe,EAAoB,CAC1C,GAAI,CAAC,OAAO,UAAU,CAAI,GAAK,EAAO,EACpC,MAAM,IAAI,EAAkB,sBAAuB,wCAAyC,CAAE,SAAU,QAAS,CAAC,EAEpH,GAAI,EAAO,EACT,MAAM,IAAI,EAAkB,sBAAuB,0BAA0B,IAAY,CAAE,SAAU,QAAS,CAAC,CAEnH,CAMA,SAAS,EAAS,EAAgD,CAGhE,GAAI,IAAkB,IAAA,GACpB,OAAO,EAAwB,EAAY,EAG7C,IAAI,EAAO,GACP,EAAW,EACX,EAEJ,GAAI,OAAO,GAAkB,SAC3B,EAAO,MACF,CACL,GAAI,EAAc,SAAW,IAAA,IAAa,EAAc,OAAS,IAAA,GAC/D,MAAM,IAAI,EAAkB,sBAAuB,gDAAiD,CAClG,SAAU,QACZ,CAAC,EAEH,EAAO,EAAc,QAAU,EAAc,MAAQ,GACrD,EAAW,EAAc,UAAA,mEACzB,EAAc,EAAc,OACxB,EAAc,WAAa,IAAA,IAC7B,EAAiB,CAAQ,CAE7B,CAIA,GAFA,EAAe,CAAI,EAEf,IAAS,EAAG,MAAO,GAEvB,GAAI,IAAA,oEAA6B,IAAgB,IAAA,GAC/C,OAAO,EAAwB,CAAI,EAGrC,IAAM,EAAc,EAAS,OAI7B,GAAA,EAAK,EAAe,EAAc,GAAW,CAC3C,IAAM,EAAO,EAAc,EAC3B,GAAI,GAAe,EAAY,OAAS,EACtC,MAAM,IAAI,EACR,yBACA,mCAAmC,EAAK,SAAS,EAAY,SAC7D,CAAE,SAAU,QAAS,CACvB,EAEF,IAAM,EAAQ,GAAa,SAAS,EAAG,CAAI,GAAK,WAAW,OAAO,gBAAgB,IAAI,WAAW,CAAI,CAAC,EAClG,EAAK,GACT,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,IACxB,GAAM,EAAS,EAAM,GAAK,GAE5B,OAAO,CACT,CAIA,IAAM,GAAQ,GAAM,GAAK,KAAK,MAAO,EAAc,EAAK,CAAC,GAAM,EAEzD,EAAO,KAAK,KAAM,IAAM,EAAO,EAAQ,CAAW,EAEpD,EAAK,GACL,EAAe,EAEnB,KAAO,EAAG,OAAS,GAAM,CACvB,IAAI,EACJ,GAAI,EAAa,CACf,GAAI,EAAY,OAAS,EAAe,EACtC,MAAM,IAAI,EACR,yBACA,4CAA4C,EAAK,cAAc,EAAY,OAAS,IACpF,CAAE,SAAU,QAAS,CACvB,EAEF,EAAQ,EAAY,SAAS,EAAc,EAAe,CAAI,EAC9D,GAAgB,CAClB,KACE,GAAQ,WAAW,OAAO,gBAAgB,IAAI,WAAW,CAAI,CAAC,EAGhE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,QAAU,EAAG,OAAS,EAAM,IAAK,CACzD,IAAM,EAAQ,EAAM,GAAK,EACrB,EAAQ,IACV,GAAM,EAAS,GAGnB,CACF,CAEA,OAAO,CACT,CAMA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAG,OAAS,GAAK,EAAa,KAAK,CAAE,CACxE,CAgDA,MAAa,EAAiB,OAAO,OAAO,EAAU,CACpD,SACF,CAAC"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -10,5 +10,12 @@ //#region src/objectid/objectid.d.ts

/**
* Timestamp in seconds since Unix epoch.
* Defaults to Math.floor(Date.now() / 1000).
* Timestamp in milliseconds since the Unix epoch.
* Defaults to Date.now().
* ObjectID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number;
/**
* Timestamp in seconds since the Unix epoch.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
secs?: number;

@@ -15,0 +22,0 @@ /**

@@ -1,1 +0,1 @@

{"version":3,"file":"objectid.d.mts","names":[],"sources":["../../src/objectid/objectid.ts"],"mappings":";;;KA2BY,eAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;;;;;EAKT,IAAA;;;AAIA;EAAA,OAAA;AAAA;AAAA,KAGU,QAAA;;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,eAAA,cAA6B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEzG,OAAA,GAAU,eAAA,EAAiB,GAAA,cAAiB,MAAA;EAE7C,OAAA,CAAQ,EAAA,WAAa,UAAA,EAEJ;EAAjB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAA;AAkNF;;;;AAAuB;;;;cAAV,QAAA,EAAU,QAAA"}
{"version":3,"file":"objectid.d.mts","names":[],"sources":["../../src/objectid/objectid.ts"],"mappings":";;;KA4BY,eAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;;;;;;EAMT,KAAA;;;AAWA;AAGF;;EAPE,IAAA;;;;EAIA,OAAA;AAAA;AAAA,KAGU,QAAA;mEAUO;EAAA,cANH,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,eAAA,cAA6B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEzG,OAAA,GAAU,eAAA,EAAiB,GAAA,cAAiB,MAAA;EAE7C,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;AAAA;AAsNF;;;;AAAuB;;;;;;;;;;cAAV,QAAA,EAAU,QAAA"}

@@ -1,2 +0,2 @@

import{n as e,t}from"../random-Chp-Nkzi.mjs";import{n,t as r}from"../validation-CTNpXm94.mjs";import{BufferError as i,InvalidInputError as a,ParseError as o,UniqueIdError as s}from"../errors.mjs";import{n as c}from"../bytes-xqWxFYsM.mjs";const l=`0123456789abcdef`,u=Array.from({length:256},(e,t)=>l[t>>4&15]+l[t&15]),d=new Uint8Array(65536);d.fill(255);for(let e=0;e<=9;e+=1)d[48+e]=e;for(let e=0;e<6;e+=1)d[97+e]=10+e,d[65+e]=10+e;function f(e){if(e.length<12)throw new i(`OBJECTID_BYTES_TOO_SHORT`,`ObjectID bytes must be at least 12 bytes, got ${e.length}`);let t=``;for(let n=0;n<12;n+=1)t+=u[e[n]];return t}function p(e){if(e.length!==24)throw new o(`OBJECTID_INVALID_LENGTH`,`ObjectID string must be 24 characters, got ${e.length}`);let t=new Uint8Array(12);for(let n=0;n<12;n+=1){let r=n*2,i=r+1,a=d[e.charCodeAt(r)],s=d[e.charCodeAt(i)];if(a===255)throw new o(`OBJECTID_INVALID_CHAR`,`Invalid ObjectID character: ${e[r]}`);if(s===255)throw new o(`OBJECTID_INVALID_CHAR`,`Invalid ObjectID character: ${e[i]}`);t[n]=a<<4|s}return t}const m=4294967295,h=16777215,g=/^[0-9a-f]{24}$/i,_={random:void 0,counter:void 0};function v(){let e=new Uint8Array(5);return e.set(t(5)),e}function y(e,t,n,r,i){c(r,i,e);for(let e=0;e<5;e+=1)r[i+4+e]=t[e];r[i+4+5]=n>>>16&255,r[i+4+5+1]=n>>>8&255,r[i+4+5+3-1]=n&255}function b(t,o,s=0){let c,l,u;if(t){let n=t.random;if(n&&n.length<5)throw new a(`OBJECTID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 5 for ObjectID`);let i=t.secs;if(i!==void 0&&!r(i,0,m))throw new a(`OBJECTID_TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be between 0 and ${m}`);let o=t.counter;if(o!==void 0&&!r(o,0,h))throw new a(`OBJECTID_COUNTER_OUT_OF_RANGE`,`Counter must be between 0 and ${h}`);c=i??Math.floor(Date.now()/1e3),l=n??v(),u=o??e()&h}else _.random===void 0&&(_.random=v()),_.counter===void 0&&(_.counter=e()&h),c=Math.floor(Date.now()/1e3),l=_.random,_.counter=_.counter+1&h,u=_.counter;if(o){if(!n(o,s,12))throw new i(`OBJECTID_BUFFER_OUT_OF_BOUNDS`,`ObjectID byte range ${s}:${s+12-1} is out of buffer bounds`);return y(c,l,u,o,s),o}let d=new Uint8Array(12);return y(c,l,u,d,0),f(d)}function x(e){return p(e)}function S(e){if(e.length!==12)throw new i(`OBJECTID_BYTES_INVALID_LENGTH`,`ObjectID bytes must be exactly 12 bytes, got ${e.length}`);return f(e)}function C(e){let t=p(e);return((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)*1e3}function w(e){return typeof e==`string`&&g.test(e)}const T=Object.assign(b,{toBytes:x,fromBytes:S,timestamp:C,isValid:w,NIL:`0`.repeat(24),MAX:`f`.repeat(24)});export{i as BufferError,a as InvalidInputError,o as ParseError,s as UniqueIdError,T as objectid};
import{n as e,t}from"../random-Chp-Nkzi.mjs";import{n,t as r}from"../validation-CTNpXm94.mjs";import{BufferError as i,InvalidInputError as a,ParseError as o,UniqueIdError as s}from"../errors.mjs";import{n as c}from"../bytes-xqWxFYsM.mjs";import{t as l}from"../timestamp-ChrSuQCR.mjs";const u=`0123456789abcdef`,d=Array.from({length:256},(e,t)=>u[t>>4&15]+u[t&15]),f=new Uint8Array(65536);f.fill(255);for(let e=0;e<=9;e+=1)f[48+e]=e;for(let e=0;e<6;e+=1)f[97+e]=10+e,f[65+e]=10+e;function p(e){if(e.length<12)throw new i(`BYTES_INVALID_LENGTH`,`ObjectID bytes must be at least 12 bytes, got ${e.length}`,{strategy:`objectid`});let t=``;for(let n=0;n<12;n+=1)t+=d[e[n]];return t}function m(e){if(e.length!==24)throw new o(`INVALID_LENGTH`,`ObjectID string must be 24 characters, got ${e.length}`,{strategy:`objectid`});let t=new Uint8Array(12);for(let n=0;n<12;n+=1){let r=n*2,i=r+1,a=f[e.charCodeAt(r)],s=f[e.charCodeAt(i)];if(a===255)throw new o(`INVALID_CHAR`,`Invalid ObjectID character: ${e[r]}`,{strategy:`objectid`});if(s===255)throw new o(`INVALID_CHAR`,`Invalid ObjectID character: ${e[i]}`,{strategy:`objectid`});t[n]=a<<4|s}return t}const h=16777215,g=/^[0-9a-f]{24}$/i,_={random:void 0,counter:void 0};function v(){let e=new Uint8Array(5);return e.set(t(5)),e}function y(e,t,n,r,i){c(r,i,e);for(let e=0;e<5;e+=1)r[i+4+e]=t[e];r[i+4+5]=n>>>16&255,r[i+4+5+1]=n>>>8&255,r[i+4+5+3-1]=n&255}function b(t,o,s=0){let c,u,d;if(t){let n=t.random;if(n&&n.length<5)throw new a(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 5 for ObjectID`,{strategy:`objectid`});let i=l(t,0,4294967295,`objectid`),o=t.counter;if(o!==void 0&&!r(o,0,h))throw new a(`COUNTER_OUT_OF_RANGE`,`Counter must be between 0 and ${h}`,{strategy:`objectid`});c=i??Math.floor(Date.now()/1e3),u=n??v(),d=o??e()&h}else _.random===void 0&&(_.random=v()),_.counter===void 0&&(_.counter=e()&h),c=Math.floor(Date.now()/1e3),u=_.random,_.counter=_.counter+1&h,d=_.counter;if(o){if(!n(o,s,12))throw new i(`BUFFER_OUT_OF_BOUNDS`,`ObjectID byte range ${s}:${s+12-1} is out of buffer bounds`,{strategy:`objectid`});return y(c,u,d,o,s),o}let f=new Uint8Array(12);return y(c,u,d,f,0),p(f)}function x(e){return m(e)}function S(e){if(e.length!==12)throw new i(`BYTES_INVALID_LENGTH`,`ObjectID bytes must be exactly 12 bytes, got ${e.length}`,{strategy:`objectid`});return p(e)}function C(e){let t=m(e);return((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)*1e3}function w(e){return typeof e==`string`&&g.test(e)}const T=Object.assign(b,{toBytes:x,fromBytes:S,timestamp:C,isValid:w,NIL:`0`.repeat(24),MAX:`f`.repeat(24)});export{i as BufferError,a as InvalidInputError,o as ParseError,s as UniqueIdError,T as objectid};
//# sourceMappingURL=objectid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"objectid.mjs","names":["OBJECTID_BYTES"],"sources":["../../src/objectid/hex.ts","../../src/objectid/objectid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\n/**\n * Hex encoding/decoding for ObjectID.\n * Alphabet: 0-9a-f (lowercase on encode, case-insensitive on decode)\n *\n * ObjectID binary format: 12 bytes (96 bits)\n * - 4 bytes: big-endian Unix timestamp in seconds\n * - 5 bytes: per-process random value\n * - 3 bytes: big-endian counter\n *\n * String format: 24 characters of hex\n */\n\nconst HEX_CHARS = '0123456789abcdef'\nconst OBJECTID_BYTES = 12\nconst OBJECTID_STRING_LEN = 24\n\n// Pre-computed encode table: byte value (0-255) -> 2-char lowercase hex string.\nconst ENCODE_TABLE: string[] = Array.from(\n { length: 256 },\n (_, byte) => HEX_CHARS[(byte >> 4) & 0xf] + HEX_CHARS[byte & 0xf],\n)\n\n// Pre-computed decode table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 128 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\n// Note: unlike Base62, hex decoding is case-insensitive - 'a' and 'A' both decode to 10.\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\n\nfor (let i = 0; i <= 9; i += 1) {\n DECODING['0'.charCodeAt(0) + i] = i\n}\nfor (let i = 0; i < 6; i += 1) {\n DECODING['a'.charCodeAt(0) + i] = 10 + i\n DECODING['A'.charCodeAt(0) + i] = 10 + i\n}\n\n/**\n * Encode 12 ObjectID bytes to a 24-character lowercase hex string.\n */\nexport function encodeObjectIdHex(bytes: Uint8Array): string {\n if (bytes.length < OBJECTID_BYTES) {\n throw new BufferError(\n 'OBJECTID_BYTES_TOO_SHORT',\n `ObjectID bytes must be at least ${OBJECTID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n\n let encoded = ''\n for (let i = 0; i < OBJECTID_BYTES; i += 1) {\n encoded += ENCODE_TABLE[bytes[i]]\n }\n return encoded\n}\n\n/**\n * Decode a 24-character hex string to 12 ObjectID bytes.\n */\nexport function decodeObjectIdHex(str: string): Uint8Array {\n if (str.length !== OBJECTID_STRING_LEN) {\n throw new ParseError(\n 'OBJECTID_INVALID_LENGTH',\n `ObjectID string must be ${OBJECTID_STRING_LEN} characters, got ${str.length}`,\n )\n }\n\n const bytes = new Uint8Array(OBJECTID_BYTES)\n for (let i = 0; i < OBJECTID_BYTES; i += 1) {\n const hiIndex = i * 2\n const loIndex = hiIndex + 1\n const hi = DECODING[str.charCodeAt(hiIndex)]\n const lo = DECODING[str.charCodeAt(loIndex)]\n\n if (hi === 255) {\n throw new ParseError('OBJECTID_INVALID_CHAR', `Invalid ObjectID character: ${str[hiIndex]}`)\n }\n if (lo === 255) {\n throw new ParseError('OBJECTID_INVALID_CHAR', `Invalid ObjectID character: ${str[loIndex]}`)\n }\n\n bytes[i] = (hi << 4) | lo\n }\n\n return bytes\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { randomBytes, randomUint32 } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeObjectIdHex, encodeObjectIdHex } from './hex'\n\n/**\n * MongoDB ObjectID\n *\n * A 96-bit (12-byte) identifier consisting of:\n * - 4 bytes: big-endian Unix timestamp in seconds\n * - 5 bytes: per-process random value\n * - 3 bytes: big-endian counter, always incrementing (wraps at 0xFFFFFF back to 0)\n *\n * Encoded as a 24-character lowercase hex string.\n */\n\nconst OBJECTID_BYTES = 12\nconst TIMESTAMP_BYTES = 4\nconst RANDOM_BYTES = 5\nconst COUNTER_BYTES = 3\nconst MAX_SECS = 0xffffffff\nconst MAX_COUNTER = 0xffffff\n\n// Validation regex: case-insensitive per KTD7, matching bson's ObjectId.isValid()\nconst OBJECTID_REGEX = /^[0-9a-f]{24}$/i\n\nexport type ObjectIdOptions = {\n /**\n * 5 bytes of random data to use for the ObjectID's random field.\n */\n random?: Uint8Array\n /**\n * Timestamp in seconds since Unix epoch.\n * Defaults to Math.floor(Date.now() / 1000).\n */\n secs?: number\n /**\n * 24-bit counter value (0 to 0xFFFFFF).\n */\n counter?: number\n}\n\nexport type ObjectId = {\n /** Generate a MongoDB-compatible ObjectID string. */\n (): string\n /** Generate an ObjectID with explicit options or write its 12 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: ObjectIdOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate an ObjectID string with optional timestamp, random field, or counter. */\n (options?: ObjectIdOptions, buf?: undefined, offset?: number): string\n /** Convert an ObjectID string to its canonical 12-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 12 canonical ObjectID bytes to an ObjectID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid ObjectID string. */\n isValid(id: unknown): id is string\n /** The nil ObjectID (all zeros) */\n NIL: string\n /** The max ObjectID (all 0xff) */\n MAX: string\n}\n\ntype ObjectIdState = {\n random: Uint8Array | undefined\n counter: number | undefined\n}\n\n/**\n * Module-level state for the per-process random value and the always-incrementing counter.\n *\n * IMPORTANT: This state persists across all objectid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * Unlike ULID/UUIDv7's per-timestamp sequence reset, the counter continuing to climb\n * across warm starts is exactly the anti-collision behavior the ObjectID spec intends.\n * - For isolated state, pass explicit `random`, `secs`, or `counter` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: ObjectIdState = {\n random: undefined,\n counter: undefined,\n}\n\n/**\n * Draw 5 fresh random bytes into a newly-owned buffer, copying immediately so the\n * result is unaffected by any later pool refill triggered by other random draws\n * (e.g. the counter's `randomUint32()` call) before these bytes are consumed.\n */\nfunction freshRandom(): Uint8Array {\n const bytes = new Uint8Array(RANDOM_BYTES)\n bytes.set(randomBytes(RANDOM_BYTES))\n return bytes\n}\n\nfunction writeObjectIdBytesUnchecked(\n secs: number,\n random: Uint8Array,\n counter: number,\n buf: Uint8Array,\n offset: number,\n): void {\n // Timestamp (32-bit big-endian seconds since Unix epoch) -> bytes 0-3\n writeTimestamp32(buf, offset, secs)\n\n // Random (5 bytes) -> bytes 4-8\n for (let i = 0; i < RANDOM_BYTES; i += 1) {\n buf[offset + TIMESTAMP_BYTES + i] = random[i]\n }\n\n // Counter (24-bit big-endian) -> bytes 9-11\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES] = (counter >>> 16) & 0xff\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES + 1] = (counter >>> 8) & 0xff\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES + COUNTER_BYTES - 1] = counter & 0xff\n}\n\n/*\n * Overload: no buffer => return an ObjectID string.\n */\nfunction objectIdFn(options?: ObjectIdOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with ObjectID bytes.\n */\nfunction objectIdFn<TBuf extends Uint8Array = Uint8Array>(\n options: ObjectIdOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction objectIdFn<TBuf extends Uint8Array = Uint8Array>(\n options?: ObjectIdOptions,\n buf?: TBuf,\n offset = 0,\n): string | TBuf {\n let secs: number\n let random: Uint8Array\n let counter: number\n\n if (options) {\n const optRandom = options.random\n if (optRandom && optRandom.length < RANDOM_BYTES) {\n throw new InvalidInputError(\n 'OBJECTID_RANDOM_BYTES_TOO_SHORT',\n `Random bytes length must be >= ${RANDOM_BYTES} for ObjectID`,\n )\n }\n\n const optSecs = options.secs\n if (optSecs !== undefined && !isIntegerInRange(optSecs, 0, MAX_SECS)) {\n throw new InvalidInputError('OBJECTID_TIMESTAMP_OUT_OF_RANGE', `Timestamp must be between 0 and ${MAX_SECS}`)\n }\n\n const optCounter = options.counter\n if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, MAX_COUNTER)) {\n throw new InvalidInputError('OBJECTID_COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`)\n }\n\n // Options bypass persistent state entirely: every field is sourced fresh (given\n // value, or an independently-defaulted one), never read from or written to\n // `state` (see KTD2). This is what makes options-based generation deterministic\n // when all three fields are supplied.\n secs = optSecs ?? Math.floor(Date.now() / 1000)\n random = optRandom ?? freshRandom()\n counter = optCounter ?? randomUint32() & MAX_COUNTER\n } else {\n // Lazily initialize persistent state on first no-option call.\n if (state.random === undefined) {\n state.random = freshRandom()\n }\n if (state.counter === undefined) {\n state.counter = randomUint32() & MAX_COUNTER\n }\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all ObjectIDs generated within a single request will share the same timestamp.\n * - monotonic ordering relies entirely on the ever-incrementing counter.\n */\n secs = Math.floor(Date.now() / 1000)\n random = state.random\n state.counter = (state.counter + 1) & MAX_COUNTER\n counter = state.counter\n }\n\n if (buf) {\n if (!isWritableRange(buf, offset, OBJECTID_BYTES)) {\n throw new BufferError(\n 'OBJECTID_BUFFER_OUT_OF_BOUNDS',\n `ObjectID byte range ${offset}:${offset + OBJECTID_BYTES - 1} is out of buffer bounds`,\n )\n }\n writeObjectIdBytesUnchecked(secs, random, counter, buf, offset)\n return buf\n }\n\n const bytes = new Uint8Array(OBJECTID_BYTES)\n writeObjectIdBytesUnchecked(secs, random, counter, bytes, 0)\n return encodeObjectIdHex(bytes)\n}\n\n/**\n * Convert an ObjectID hex string to 12 bytes.\n */\nfunction toBytes(id: string): Uint8Array {\n return decodeObjectIdHex(id)\n}\n\n/**\n * Convert 12 bytes to an ObjectID hex string.\n */\nfunction fromBytes(bytes: Uint8Array): string {\n if (bytes.length !== OBJECTID_BYTES) {\n throw new BufferError(\n 'OBJECTID_BYTES_INVALID_LENGTH',\n `ObjectID bytes must be exactly ${OBJECTID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n return encodeObjectIdHex(bytes)\n}\n\n/**\n * Extract the timestamp from an ObjectID string.\n * Returns Unix timestamp in milliseconds for API consistency with ulid/uuidv7/ksuid.\n * Note: ObjectID only has second precision, so the returned value will always end in 000.\n */\nfunction timestamp(id: string): number {\n const bytes = decodeObjectIdHex(id)\n // First 4 bytes are big-endian timestamp (seconds since Unix epoch)\n const secs = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0\n return secs * 1000\n}\n\n/**\n * Validate an ObjectID string format.\n * Case-insensitive (KTD7), matching bson's ObjectId.isValid() and this repo's existing\n * convention (ulid, ksuid) of accepting mixed-case input for parsing, even though\n * generation always emits lowercase (matching MongoDB driver output).\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && OBJECTID_REGEX.test(id)\n}\n\n/**\n * Generate a MongoDB ObjectID string or write the bytes into a buffer.\n *\n * ObjectID is a 12-byte identifier consisting of a 4-byte timestamp, a 5-byte\n * per-process random value, and a 3-byte always-incrementing counter, encoded\n * as a 24-character lowercase hex string. It is time-ordered and compatible\n * with MongoDB's own ObjectID implementation.\n *\n * @example\n * ```ts\n * import { objectid } from 'uniku/objectid'\n *\n * const id = objectid()\n * // => \"667c3f2a1e2b3c4d5e6f7081\"\n *\n * // Extract timestamp\n * const ts = objectid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * objectid.isValid(id) // true\n *\n * // Convert to/from bytes (12 bytes)\n * const bytes = objectid.toBytes(id)\n * const restored = objectid.fromBytes(bytes)\n * ```\n */\nexport const objectid: ObjectId = Object.assign(objectIdFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '0'.repeat(24),\n MAX: 'f'.repeat(24),\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"8OAcA,MAAM,EAAY,mBAKZ,EAAyB,MAAM,KACnC,CAAE,OAAQ,GAAI,GACb,EAAG,IAAS,EAAW,GAAQ,EAAK,IAAO,EAAU,EAAO,GAC/D,EAQM,EAAW,IAAI,WAAW,KAAK,EACrC,EAAS,KAAK,GAAG,EAEjB,IAAK,IAAI,EAAI,EAAG,GAAK,EAAG,GAAK,EAC3B,EAAS,GAAoB,GAAK,EAEpC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,GAAK,EAC1B,EAAS,GAAoB,GAAK,GAAK,EACvC,EAAS,GAAoB,GAAK,GAAK,EAMzC,SAAgB,EAAkB,EAA2B,CAC3D,GAAI,EAAM,OAASA,GACjB,MAAM,IAAI,EACR,2BACA,iDAAgE,EAAM,QACxE,EAGF,IAAI,EAAU,GACd,IAAK,IAAI,EAAI,EAAG,EAAIA,GAAgB,GAAK,EACvC,GAAW,EAAa,EAAM,IAEhC,OAAO,CACT,CAKA,SAAgB,EAAkB,EAAyB,CACzD,GAAI,EAAI,SAAW,GACjB,MAAM,IAAI,EACR,0BACA,8CAAkE,EAAI,QACxE,EAGF,IAAM,EAAQ,IAAI,WAAWA,EAAc,EAC3C,IAAK,IAAI,EAAI,EAAG,EAAIA,GAAgB,GAAK,EAAG,CAC1C,IAAM,EAAU,EAAI,EACd,EAAU,EAAU,EACpB,EAAK,EAAS,EAAI,WAAW,CAAO,GACpC,EAAK,EAAS,EAAI,WAAW,CAAO,GAE1C,GAAI,IAAO,IACT,MAAM,IAAI,EAAW,wBAAyB,+BAA+B,EAAI,IAAU,EAE7F,GAAI,IAAO,IACT,MAAM,IAAI,EAAW,wBAAyB,+BAA+B,EAAI,IAAU,EAG7F,EAAM,GAAM,GAAM,EAAK,CACzB,CAEA,OAAO,CACT,CCvEA,MAIM,EAAW,WACX,EAAc,SAGd,EAAiB,kBAsDjB,EAAuB,CAC3B,OAAQ,IAAA,GACR,QAAS,IAAA,EACX,EAOA,SAAS,GAA0B,CACjC,IAAM,EAAQ,IAAI,WAAW,CAAY,EAEzC,OADA,EAAM,IAAI,EAAY,CAAY,CAAC,EAC5B,CACT,CAEA,SAAS,EACP,EACA,EACA,EACA,EACA,EACM,CAEN,EAAiB,EAAK,EAAQ,CAAI,EAGlC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAc,GAAK,EACrC,EAAI,EAAS,EAAkB,GAAK,EAAO,GAI7C,EAAI,EAAS,EAAkB,GAAiB,IAAY,GAAM,IAClE,EAAI,EAAS,EAAkB,EAAe,GAAM,IAAY,EAAK,IACrE,EAAI,EAAS,EAAkB,EAAe,EAAgB,GAAK,EAAU,GAC/E,CAcA,SAAS,EACP,EACA,EACA,EAAS,EACM,CACf,IAAI,EACA,EACA,EAEJ,GAAI,EAAS,CACX,IAAM,EAAY,EAAQ,OAC1B,GAAI,GAAa,EAAU,OAAS,EAClC,MAAM,IAAI,EACR,kCACA,+CACF,EAGF,IAAM,EAAU,EAAQ,KACxB,GAAI,IAAY,IAAA,IAAa,CAAC,EAAiB,EAAS,EAAG,CAAQ,EACjE,MAAM,IAAI,EAAkB,kCAAmC,mCAAmC,GAAU,EAG9G,IAAM,EAAa,EAAQ,QAC3B,GAAI,IAAe,IAAA,IAAa,CAAC,EAAiB,EAAY,EAAG,CAAW,EAC1E,MAAM,IAAI,EAAkB,gCAAiC,iCAAiC,GAAa,EAO7G,EAAO,GAAW,KAAK,MAAM,KAAK,IAAI,EAAI,GAAI,EAC9C,EAAS,GAAa,EAAY,EAClC,EAAU,GAAc,EAAa,EAAI,CAC3C,MAEM,EAAM,SAAW,IAAA,KACnB,EAAM,OAAS,EAAY,GAEzB,EAAM,UAAY,IAAA,KACpB,EAAM,QAAU,EAAa,EAAI,GAWnC,EAAO,KAAK,MAAM,KAAK,IAAI,EAAI,GAAI,EACnC,EAAS,EAAM,OACf,EAAM,QAAW,EAAM,QAAU,EAAK,EACtC,EAAU,EAAM,QAGlB,GAAI,EAAK,CACP,GAAI,CAAC,EAAgB,EAAK,EAAQ,EAAc,EAC9C,MAAM,IAAI,EACR,gCACA,uBAAuB,EAAO,GAAG,EAAS,GAAiB,EAAE,yBAC/D,EAGF,OADA,EAA4B,EAAM,EAAQ,EAAS,EAAK,CAAM,EACvD,CACT,CAEA,IAAM,EAAQ,IAAI,WAAW,EAAc,EAE3C,OADA,EAA4B,EAAM,EAAQ,EAAS,EAAO,CAAC,EACpD,EAAkB,CAAK,CAChC,CAKA,SAAS,EAAQ,EAAwB,CACvC,OAAO,EAAkB,CAAE,CAC7B,CAKA,SAAS,EAAU,EAA2B,CAC5C,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EACR,gCACA,gDAA+D,EAAM,QACvE,EAEF,OAAO,EAAkB,CAAK,CAChC,CAOA,SAAS,EAAU,EAAoB,CACrC,IAAM,EAAQ,EAAkB,CAAE,EAGlC,QADe,EAAM,IAAM,GAAO,EAAM,IAAM,GAAO,EAAM,IAAM,EAAK,EAAM,MAAQ,GACtE,GAChB,CAQA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAe,KAAK,CAAE,CACzD,CA6BA,MAAa,EAAqB,OAAO,OAAO,EAAY,CAC1D,UACA,YACA,YACA,UACA,IAAK,IAAI,OAAO,EAAE,EAClB,IAAK,IAAI,OAAO,EAAE,CACpB,CAAC"}
{"version":3,"file":"objectid.mjs","names":["OBJECTID_BYTES"],"sources":["../../src/objectid/hex.ts","../../src/objectid/objectid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\n/**\n * Hex encoding/decoding for ObjectID.\n * Alphabet: 0-9a-f (lowercase on encode, case-insensitive on decode)\n *\n * ObjectID binary format: 12 bytes (96 bits)\n * - 4 bytes: big-endian Unix timestamp in seconds\n * - 5 bytes: per-process random value\n * - 3 bytes: big-endian counter\n *\n * String format: 24 characters of hex\n */\n\nconst HEX_CHARS = '0123456789abcdef'\nconst OBJECTID_BYTES = 12\nconst OBJECTID_STRING_LEN = 24\n\n// Pre-computed encode table: byte value (0-255) -> 2-char lowercase hex string.\nconst ENCODE_TABLE: string[] = Array.from(\n { length: 256 },\n (_, byte) => HEX_CHARS[(byte >> 4) & 0xf] + HEX_CHARS[byte & 0xf],\n)\n\n// Pre-computed decode table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 128 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\n// Note: unlike Base62, hex decoding is case-insensitive - 'a' and 'A' both decode to 10.\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\n\nfor (let i = 0; i <= 9; i += 1) {\n DECODING['0'.charCodeAt(0) + i] = i\n}\nfor (let i = 0; i < 6; i += 1) {\n DECODING['a'.charCodeAt(0) + i] = 10 + i\n DECODING['A'.charCodeAt(0) + i] = 10 + i\n}\n\n/**\n * Encode 12 ObjectID bytes to a 24-character lowercase hex string.\n */\nexport function encodeObjectIdHex(bytes: Uint8Array): string {\n if (bytes.length < OBJECTID_BYTES) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `ObjectID bytes must be at least ${OBJECTID_BYTES} bytes, got ${bytes.length}`,\n { strategy: 'objectid' },\n )\n }\n\n let encoded = ''\n for (let i = 0; i < OBJECTID_BYTES; i += 1) {\n encoded += ENCODE_TABLE[bytes[i]]\n }\n return encoded\n}\n\n/**\n * Decode a 24-character hex string to 12 ObjectID bytes.\n */\nexport function decodeObjectIdHex(str: string): Uint8Array {\n if (str.length !== OBJECTID_STRING_LEN) {\n throw new ParseError(\n 'INVALID_LENGTH',\n `ObjectID string must be ${OBJECTID_STRING_LEN} characters, got ${str.length}`,\n { strategy: 'objectid' },\n )\n }\n\n const bytes = new Uint8Array(OBJECTID_BYTES)\n for (let i = 0; i < OBJECTID_BYTES; i += 1) {\n const hiIndex = i * 2\n const loIndex = hiIndex + 1\n const hi = DECODING[str.charCodeAt(hiIndex)]\n const lo = DECODING[str.charCodeAt(loIndex)]\n\n if (hi === 255) {\n throw new ParseError('INVALID_CHAR', `Invalid ObjectID character: ${str[hiIndex]}`, { strategy: 'objectid' })\n }\n if (lo === 255) {\n throw new ParseError('INVALID_CHAR', `Invalid ObjectID character: ${str[loIndex]}`, { strategy: 'objectid' })\n }\n\n bytes[i] = (hi << 4) | lo\n }\n\n return bytes\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { randomBytes, randomUint32 } from '../common/random'\nimport { resolveTimestampSecs } from '../common/timestamp'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeObjectIdHex, encodeObjectIdHex } from './hex'\n\n/**\n * MongoDB ObjectID\n *\n * A 96-bit (12-byte) identifier consisting of:\n * - 4 bytes: big-endian Unix timestamp in seconds\n * - 5 bytes: per-process random value\n * - 3 bytes: big-endian counter, always incrementing (wraps at 0xFFFFFF back to 0)\n *\n * Encoded as a 24-character lowercase hex string.\n */\n\nconst OBJECTID_BYTES = 12\nconst TIMESTAMP_BYTES = 4\nconst RANDOM_BYTES = 5\nconst COUNTER_BYTES = 3\nconst MAX_SECS = 0xffffffff\nconst MAX_COUNTER = 0xffffff\n\n// Validation regex: case-insensitive per KTD7, matching bson's ObjectId.isValid()\nconst OBJECTID_REGEX = /^[0-9a-f]{24}$/i\n\nexport type ObjectIdOptions = {\n /**\n * 5 bytes of random data to use for the ObjectID's random field.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since the Unix epoch.\n * Defaults to Date.now().\n * ObjectID stores whole seconds, so sub-second precision is truncated.\n */\n msecs?: number\n /**\n * Timestamp in seconds since the Unix epoch.\n *\n * @deprecated Use `msecs` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n secs?: number\n /**\n * 24-bit counter value (0 to 0xFFFFFF).\n */\n counter?: number\n}\n\nexport type ObjectId = {\n /** Generate a MongoDB-compatible ObjectID string. */\n (): string\n /** Generate an ObjectID with explicit options or write its 12 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: ObjectIdOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate an ObjectID string with optional timestamp, random field, or counter. */\n (options?: ObjectIdOptions, buf?: undefined, offset?: number): string\n /** Convert an ObjectID string to its canonical 12-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 12 canonical ObjectID bytes to an ObjectID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid ObjectID string. */\n isValid(id: unknown): id is string\n /** The nil ObjectID (all zeros) */\n NIL: string\n /** The max ObjectID (all 0xff) */\n MAX: string\n}\n\ntype ObjectIdState = {\n random: Uint8Array | undefined\n counter: number | undefined\n}\n\n/**\n * Module-level state for the per-process random value and the always-incrementing counter.\n *\n * IMPORTANT: This state persists across all objectid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * Unlike ULID/UUIDv7's per-timestamp sequence reset, the counter continuing to climb\n * across warm starts is exactly the anti-collision behavior the ObjectID spec intends.\n * - For isolated state, pass explicit `random`, `msecs`, or `counter` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: ObjectIdState = {\n random: undefined,\n counter: undefined,\n}\n\n/**\n * Draw 5 fresh random bytes into a newly-owned buffer, copying immediately so the\n * result is unaffected by any later pool refill triggered by other random draws\n * (e.g. the counter's `randomUint32()` call) before these bytes are consumed.\n */\nfunction freshRandom(): Uint8Array {\n const bytes = new Uint8Array(RANDOM_BYTES)\n bytes.set(randomBytes(RANDOM_BYTES))\n return bytes\n}\n\nfunction writeObjectIdBytesUnchecked(\n secs: number,\n random: Uint8Array,\n counter: number,\n buf: Uint8Array,\n offset: number,\n): void {\n // Timestamp (32-bit big-endian seconds since Unix epoch) -> bytes 0-3\n writeTimestamp32(buf, offset, secs)\n\n // Random (5 bytes) -> bytes 4-8\n for (let i = 0; i < RANDOM_BYTES; i += 1) {\n buf[offset + TIMESTAMP_BYTES + i] = random[i]\n }\n\n // Counter (24-bit big-endian) -> bytes 9-11\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES] = (counter >>> 16) & 0xff\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES + 1] = (counter >>> 8) & 0xff\n buf[offset + TIMESTAMP_BYTES + RANDOM_BYTES + COUNTER_BYTES - 1] = counter & 0xff\n}\n\n/*\n * Overload: no buffer => return an ObjectID string.\n */\nfunction objectIdFn(options?: ObjectIdOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with ObjectID bytes.\n */\nfunction objectIdFn<TBuf extends Uint8Array = Uint8Array>(\n options: ObjectIdOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction objectIdFn<TBuf extends Uint8Array = Uint8Array>(\n options?: ObjectIdOptions,\n buf?: TBuf,\n offset = 0,\n): string | TBuf {\n let secs: number\n let random: Uint8Array\n let counter: number\n\n if (options) {\n const optRandom = options.random\n if (optRandom && optRandom.length < RANDOM_BYTES) {\n throw new InvalidInputError(\n 'RANDOM_BYTES_TOO_SHORT',\n `Random bytes length must be >= ${RANDOM_BYTES} for ObjectID`,\n {\n strategy: 'objectid',\n },\n )\n }\n\n const optSecs = resolveTimestampSecs(options, 0, MAX_SECS, 'objectid')\n\n const optCounter = options.counter\n if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, MAX_COUNTER)) {\n throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`, {\n strategy: 'objectid',\n })\n }\n\n // Options bypass persistent state entirely: every field is sourced fresh (given\n // value, or an independently-defaulted one), never read from or written to\n // `state` (see KTD2). This is what makes options-based generation deterministic\n // when all three fields are supplied.\n secs = optSecs ?? Math.floor(Date.now() / 1000)\n random = optRandom ?? freshRandom()\n counter = optCounter ?? randomUint32() & MAX_COUNTER\n } else {\n // Lazily initialize persistent state on first no-option call.\n if (state.random === undefined) {\n state.random = freshRandom()\n }\n if (state.counter === undefined) {\n state.counter = randomUint32() & MAX_COUNTER\n }\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all ObjectIDs generated within a single request will share the same timestamp.\n * - monotonic ordering relies entirely on the ever-incrementing counter.\n */\n secs = Math.floor(Date.now() / 1000)\n random = state.random\n state.counter = (state.counter + 1) & MAX_COUNTER\n counter = state.counter\n }\n\n if (buf) {\n if (!isWritableRange(buf, offset, OBJECTID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `ObjectID byte range ${offset}:${offset + OBJECTID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'objectid' },\n )\n }\n writeObjectIdBytesUnchecked(secs, random, counter, buf, offset)\n return buf\n }\n\n const bytes = new Uint8Array(OBJECTID_BYTES)\n writeObjectIdBytesUnchecked(secs, random, counter, bytes, 0)\n return encodeObjectIdHex(bytes)\n}\n\n/**\n * Convert an ObjectID hex string to 12 bytes.\n */\nfunction toBytes(id: string): Uint8Array {\n return decodeObjectIdHex(id)\n}\n\n/**\n * Convert 12 bytes to an ObjectID hex string.\n */\nfunction fromBytes(bytes: Uint8Array): string {\n if (bytes.length !== OBJECTID_BYTES) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `ObjectID bytes must be exactly ${OBJECTID_BYTES} bytes, got ${bytes.length}`,\n { strategy: 'objectid' },\n )\n }\n return encodeObjectIdHex(bytes)\n}\n\n/**\n * Extract the timestamp from an ObjectID string.\n * Returns Unix timestamp in milliseconds for API consistency with ulid/uuidv7/ksuid.\n * Note: ObjectID only has second precision, so the returned value will always end in 000.\n */\nfunction timestamp(id: string): number {\n const bytes = decodeObjectIdHex(id)\n // First 4 bytes are big-endian timestamp (seconds since Unix epoch)\n const secs = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0\n return secs * 1000\n}\n\n/**\n * Validate an ObjectID string format.\n * Case-insensitive (KTD7), matching bson's ObjectId.isValid() and this repo's existing\n * convention (ulid, ksuid) of accepting mixed-case input for parsing, even though\n * generation always emits lowercase (matching MongoDB driver output).\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && OBJECTID_REGEX.test(id)\n}\n\n/**\n * Generate a MongoDB ObjectID string or write the bytes into a buffer.\n *\n * ObjectID is a 12-byte identifier consisting of a 4-byte timestamp, a 5-byte\n * per-process random value, and a 3-byte always-incrementing counter, encoded\n * as a 24-character lowercase hex string. It is time-ordered and compatible\n * with MongoDB's own ObjectID implementation.\n *\n * @example\n * ```ts\n * import { objectid } from 'uniku/objectid'\n *\n * const id = objectid()\n * // => \"667c3f2a1e2b3c4d5e6f7081\"\n *\n * // Extract timestamp\n * const ts = objectid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * objectid.isValid(id) // true\n *\n * // Convert to/from bytes (12 bytes)\n * const bytes = objectid.toBytes(id)\n * const restored = objectid.fromBytes(bytes)\n * ```\n */\nexport const objectid: ObjectId = Object.assign(objectIdFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '0'.repeat(24),\n MAX: 'f'.repeat(24),\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -3,0 +3,0 @@ //#region src/tsid/tsid.d.ts

@@ -1,1 +0,1 @@

{"version":3,"file":"tsid.d.mts","names":[],"sources":["../../src/tsid/tsid.ts"],"mappings":";;;KAiCY,WAAA;;;AAAZ;;EAKE,KAAA;EALU;;;;EAUV,KAAA;;;AAiBA;AAGF;EAfE,IAAA;;;;;;EAMA,QAAA;;;;;;EAMA,OAAA;AAAA;AAAA,KAGU,IAAA;;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,WAAA,cAAyB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAErG,OAAA,GAAU,WAAA,EAAa,GAAA,cAAiB,MAAA;EAEzC,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,QAAA,CAAS,EAAA;EAET,UAAA,CAAW,GAAA;EAEX,SAAA,CAAU,EAAA,UAAY,KAAA;EAEtB,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;AAAA;AA4PF;;;;AAAmB;;;;;;;;;;;;;;;;;;;;;;cAAN,IAAA,EAAM,IAAA"}
{"version":3,"file":"tsid.d.mts","names":[],"sources":["../../src/tsid/tsid.ts"],"mappings":";;;KAiCY,WAAA;;;AAAZ;;EAKE,KAAA;EALU;;;;EAUV,KAAA;;;AAiBA;AAGF;EAfE,IAAA;;;;;;EAMA,QAAA;;;;;;EAMA,OAAA;AAAA;AAAA,KAGU,IAAA;;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,WAAA,cAAyB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAErG,OAAA,GAAU,WAAA,EAAa,GAAA,cAAiB,MAAA;EAEzC,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,QAAA,CAAS,EAAA;EAET,UAAA,CAAW,GAAA;EAEX,SAAA,CAAU,EAAA,UAAY,KAAA;EAEtB,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;AAAA;AAmQF;;;;AAAmB;;;;;;;;;;;;;;;;;;;;;;cAAN,IAAA,EAAM,IAAA"}

@@ -1,2 +0,2 @@

import{n as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";const s=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,c=new Uint8Array(128).fill(255);for(let e=0;e<32;e+=1){let t=s[e],n=s.charCodeAt(e);c[n]=e,t>=`A`&&t<=`Z`&&(c[n+32]=e)}function l(e){let t=``;for(let n=0;n<13;n+=1){let r=BigInt(60-n*5),i=Number(e>>r&31n);t+=s[i]}return t}function u(e){if(e.length!==13)throw new a(`TSID_INVALID_LENGTH`,`TSID string must be 13 characters, got ${e.length}`);let t=0n;for(let n=0;n<13;n+=1){let r=e.charCodeAt(n),i=r<128?c[r]:255;if(i===255)throw new a(`TSID_INVALID_CHAR`,`Invalid TSID character: ${e[n]}`);if(n===0&&i>15)throw new a(`TSID_LEADING_CHAR_OUT_OF_RANGE`,`TSID leading character must be one of 0-9, A-F, got: ${e[n]}`);t=t<<5n|BigInt(i)}return t}const d=15778368e5,f=4095,p=(1n<<42n)-1n,m={node:void 0,msecs:-1/0,counter:0};function h(e,t,n,r){return e<<BigInt(22)|BigInt(t)<<BigInt(n)|BigInt(r)}function g(e,t,n){for(let r=0;r<8;r+=1)t[n+r]=Number(e>>BigInt((7-r)*8)&255n)}function _(t){let r=t.nodeBits??10;if(!n(r,0,20))throw new i(`TSID_NODE_BITS_OUT_OF_RANGE`,`nodeBits must be between 0 and 20`);let a=22-r,o=(1<<r)-1,s=(1<<a)-1,c=t.node;if(c!==void 0&&!n(c,0,o))throw new i(`TSID_NODE_OUT_OF_RANGE`,`node must be between 0 and ${o}`);let l=t.counter;if(l!==void 0&&!n(l,0,s))throw new i(`TSID_COUNTER_OUT_OF_RANGE`,`counter must be between 0 and ${s}`);let u=t.epoch??d;if(!Number.isInteger(u))throw new i(`TSID_EPOCH_INVALID`,`epoch must be a finite integer`);let f=t.msecs??Date.now();if(!Number.isInteger(f))throw new i(`TSID_TIMESTAMP_INVALID`,`msecs must be a finite integer`);let m=BigInt(f)-BigInt(u);if(m<0n||m>p)throw new i(`TSID_TIMESTAMP_OUT_OF_RANGE`,`msecs - epoch must be between 0 and ${p}`);return{msecsDiff:m,node:c??e()&o,counterBits:a,counter:l??e()&s}}function v(n,i,a=0){let o,s,c,l;if(n){let e=_(n);o=e.msecsDiff,s=e.node,c=e.counterBits,l=e.counter}else{m.node===void 0&&(m.node=e()&1023),s=m.node,c=12;let t=Date.now();t>m.msecs?(m.msecs=t,m.counter=e()&f):(m.counter+=1,m.counter>f&&(m.msecs+=1,m.counter=0)),l=m.counter,o=BigInt(m.msecs)-BigInt(d)}let u=h(o,s,c,l);if(i){if(!t(i,a,8))throw new r(`TSID_BUFFER_OUT_OF_BOUNDS`,`TSID byte range ${a}:${a+8-1} is out of buffer bounds`);return g(u,i,a),i}return u}function y(e){T(e);let t=new Uint8Array(8);return g(e,t,0),t}function b(e){if(e.length!==8)throw new r(`TSID_BYTES_INVALID_LENGTH`,`TSID bytes must be exactly 8 bytes, got ${e.length}`);let t=0n;for(let n=0;n<8;n+=1)t=t<<8n|BigInt(e[n]);return t}function x(e,t=d){if(T(e),!Number.isInteger(t))throw new i(`TSID_EPOCH_INVALID`,`epoch must be a finite integer`);return t+Number(e>>BigInt(22))}function S(e){return typeof e==`bigint`&&e>=0n&&e<=w}const C=0n,w=(1n<<64n)-1n;function T(e){if(e<C||e>w)throw new i(`TSID_VALUE_OUT_OF_RANGE`,`TSID value must be between ${C} and ${w}`)}function E(e){return T(e),l(e)}const D=Object.assign(v,{toBytes:y,fromBytes:b,toString:E,fromString:u,timestamp:x,isValid:S,NIL:C,MAX:w});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,D as tsid};
import{n as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";const s=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,c=new Uint8Array(128).fill(255);for(let e=0;e<32;e+=1){let t=s[e],n=s.charCodeAt(e);c[n]=e,t>=`A`&&t<=`Z`&&(c[n+32]=e)}function l(e){let t=``;for(let n=0;n<13;n+=1){let r=BigInt(60-n*5),i=Number(e>>r&31n);t+=s[i]}return t}function u(e){if(e.length!==13)throw new a(`INVALID_LENGTH`,`TSID string must be 13 characters, got ${e.length}`,{strategy:`tsid`});let t=0n;for(let n=0;n<13;n+=1){let r=e.charCodeAt(n),i=r<128?c[r]:255;if(i===255)throw new a(`INVALID_CHAR`,`Invalid TSID character: ${e[n]}`,{strategy:`tsid`});if(n===0&&i>15)throw new a(`VALUE_OUT_OF_RANGE`,`TSID leading character must be one of 0-9, A-F, got: ${e[n]}`,{strategy:`tsid`});t=t<<5n|BigInt(i)}return t}const d=15778368e5,f=4095,p=(1n<<42n)-1n,m={node:void 0,msecs:-1/0,counter:0};function h(e,t,n,r){return e<<BigInt(22)|BigInt(t)<<BigInt(n)|BigInt(r)}function g(e,t,n){for(let r=0;r<8;r+=1)t[n+r]=Number(e>>BigInt((7-r)*8)&255n)}function _(t){let r=t.nodeBits??10;if(!n(r,0,20))throw new i(`NODE_BITS_OUT_OF_RANGE`,`nodeBits must be between 0 and 20`,{strategy:`tsid`});let a=22-r,o=(1<<r)-1,s=(1<<a)-1,c=t.node;if(c!==void 0&&!n(c,0,o))throw new i(`NODE_OUT_OF_RANGE`,`node must be between 0 and ${o}`,{strategy:`tsid`});let l=t.counter;if(l!==void 0&&!n(l,0,s))throw new i(`COUNTER_OUT_OF_RANGE`,`counter must be between 0 and ${s}`,{strategy:`tsid`});let u=t.epoch??d;if(!Number.isInteger(u))throw new i(`EPOCH_INVALID`,`epoch must be a finite integer`,{strategy:`tsid`});let f=t.msecs??Date.now();if(!Number.isInteger(f))throw new i(`TIMESTAMP_OUT_OF_RANGE`,`msecs must be a finite integer`,{strategy:`tsid`});let m=BigInt(f)-BigInt(u);if(m<0n||m>p)throw new i(`TIMESTAMP_OUT_OF_RANGE`,`msecs - epoch must be between 0 and ${p}`,{strategy:`tsid`});return{msecsDiff:m,node:c??e()&o,counterBits:a,counter:l??e()&s}}function v(n,i,a=0){let o,s,c,l;if(n){let e=_(n);o=e.msecsDiff,s=e.node,c=e.counterBits,l=e.counter}else{m.node===void 0&&(m.node=e()&1023),s=m.node,c=12;let t=Date.now();t>m.msecs?(m.msecs=t,m.counter=e()&f):(m.counter+=1,m.counter>f&&(m.msecs+=1,m.counter=0)),l=m.counter,o=BigInt(m.msecs)-BigInt(d)}let u=h(o,s,c,l);if(i){if(!t(i,a,8))throw new r(`BUFFER_OUT_OF_BOUNDS`,`TSID byte range ${a}:${a+8-1} is out of buffer bounds`,{strategy:`tsid`});return g(u,i,a),i}return u}function y(e){T(e);let t=new Uint8Array(8);return g(e,t,0),t}function b(e){if(e.length!==8)throw new r(`BYTES_INVALID_LENGTH`,`TSID bytes must be exactly 8 bytes, got ${e.length}`,{strategy:`tsid`});let t=0n;for(let n=0;n<8;n+=1)t=t<<8n|BigInt(e[n]);return t}function x(e,t=d){if(T(e),!Number.isInteger(t))throw new i(`EPOCH_INVALID`,`epoch must be a finite integer`,{strategy:`tsid`});return t+Number(e>>BigInt(22))}function S(e){return typeof e==`bigint`&&e>=0n&&e<=w}const C=0n,w=(1n<<64n)-1n;function T(e){if(e<C||e>w)throw new i(`VALUE_OUT_OF_RANGE`,`TSID value must be between ${C} and ${w}`,{strategy:`tsid`})}function E(e){return T(e),l(e)}const D=Object.assign(v,{toBytes:y,fromBytes:b,toString:E,fromString:u,timestamp:x,isValid:S,NIL:C,MAX:w});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,D as tsid};
//# sourceMappingURL=tsid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"tsid.mjs","names":[],"sources":["../../src/tsid/crockford64.ts","../../src/tsid/tsid.ts"],"sourcesContent":["import { ParseError } from '../errors'\n\n/**\n * Crockford Base32 codec for TSID, operating directly on the primary `bigint`\n * value rather than an intermediate byte array (unlike ulid/crockford.ts) -\n * tsid's primary type never routes through a `Uint8Array` during string\n * conversion.\n *\n * TSID binary format: 64 bits (8 bytes), encoded as 13 Crockford Base32 characters.\n * 13 chars * 5 bits = 65 bits of capacity for a 64-bit value, leaving exactly 1 bit\n * of headroom on the leading character. That headroom bit is always 0, so the\n * leading character only carries 4 significant real bits (values 0-15, i.e. the\n * alphabet's first 16 symbols \"0\"-\"9\"/\"A\"-\"F\") rather than the full 32-symbol\n * range - the same overflow-prevention technique ULID uses for its own leading\n * `[0-7]` restriction (2 headroom bits there vs 1 here). Confirmed against\n * `tsid-ts`'s own `toCanonicalString`: `(number >> BigInt(60 - i * 5)) & 0x1f`.\n */\n\nconst TSID_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'\nconst TSID_STRING_LEN = 13\nconst TSID_LEADING_MAX = 15 // 4 significant bits on the leading character (see above)\n\n// Pre-computed decode table (case-insensitive) covering ASCII, so lookups never\n// go out of bounds and a single `=== 255` check rejects invalid input.\nconst DECODING = new Uint8Array(128).fill(255)\nfor (let i = 0; i < TSID_ALPHABET.length; i += 1) {\n const char = TSID_ALPHABET[i]\n const upperCode = TSID_ALPHABET.charCodeAt(i)\n DECODING[upperCode] = i\n // Only letters have a lowercase counterpart - applying +32 to digit codes\n // would land on unrelated uppercase letters (e.g. '5' + 32 -> 'U', which is\n // excluded from this alphabet and would never get overwritten back to 255).\n if (char >= 'A' && char <= 'Z') {\n DECODING[upperCode + 32] = i\n }\n}\n\n/**\n * Encode a TSID `bigint` value to its 13-character canonical Crockford Base32 string.\n */\nexport function encodeTsidString(value: bigint): string {\n let result = ''\n for (let i = 0; i < TSID_STRING_LEN; i += 1) {\n const shift = BigInt(60 - i * 5)\n const group = Number((value >> shift) & 0x1fn)\n result += TSID_ALPHABET[group]\n }\n return result\n}\n\n/**\n * Decode a 13-character canonical Crockford Base32 string to a TSID `bigint` value.\n */\nexport function decodeTsidString(str: string): bigint {\n if (str.length !== TSID_STRING_LEN) {\n throw new ParseError('TSID_INVALID_LENGTH', `TSID string must be ${TSID_STRING_LEN} characters, got ${str.length}`)\n }\n\n let value = 0n\n for (let i = 0; i < TSID_STRING_LEN; i += 1) {\n const code = str.charCodeAt(i)\n const group = code < 128 ? DECODING[code] : 255\n if (group === 255) {\n throw new ParseError('TSID_INVALID_CHAR', `Invalid TSID character: ${str[i]}`)\n }\n if (i === 0 && group > TSID_LEADING_MAX) {\n throw new ParseError(\n 'TSID_LEADING_CHAR_OUT_OF_RANGE',\n `TSID leading character must be one of 0-9, A-F, got: ${str[i]}`,\n )\n }\n value = (value << 5n) | BigInt(group)\n }\n return value\n}\n","import { randomUint32 } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeTsidString, encodeTsidString } from './crockford64'\n\n/**\n * TSID (Time-Sorted Unique Identifier)\n *\n * A 64-bit Snowflake-style identifier consisting of:\n * - 42 bits: millisecond timestamp relative to a custom epoch (default 2020-01-01T00:00:00.000Z)\n * - 10 bits: node ID (default; configurable via `nodeBits`)\n * - 12 bits: per-millisecond counter (default; `22 - nodeBits`)\n *\n * Unlike every other uniku generator, `tsid()` returns a `bigint` by default -\n * this is a deliberate design decision reflecting that TSID's value proposition\n * is native numeric storage (e.g. a database BIGINT primary key), not a\n * string-first identifier that happens to have a byte encoding. `toString`/\n * `fromString` are the boundary conversions to/from the 13-character canonical\n * Crockford Base32 string.\n *\n * Encoded as 8 big-endian bytes in buffer mode.\n */\n\nconst TSID_EPOCH = 1577836800000 // 2020-01-01T00:00:00.000Z\nconst TSID_BYTES = 8\nconst RANDOM_BITS = 22 // combined node + counter bits\nconst DEFAULT_NODE_BITS = 10\nconst DEFAULT_COUNTER_BITS = RANDOM_BITS - DEFAULT_NODE_BITS\nconst DEFAULT_NODE_MASK = (1 << DEFAULT_NODE_BITS) - 1\nconst DEFAULT_COUNTER_MASK = (1 << DEFAULT_COUNTER_BITS) - 1\nconst MAX_NODE_BITS = 20\nconst MAX_TIMESTAMP_DIFF = (1n << 42n) - 1n\n\nexport type TsidOptions = {\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n /**\n * Custom epoch in milliseconds since Unix epoch.\n * Defaults to 1577836800000 (2020-01-01T00:00:00.000Z).\n */\n epoch?: number\n /**\n * Node ID (0 to 2^nodeBits - 1).\n * Defaults to a lazily-initialized, persistent random value.\n */\n node?: number\n /**\n * Number of bits allocated to the node ID (0-20).\n * The remaining bits (22 - nodeBits) are allocated to the counter.\n * Defaults to 10.\n */\n nodeBits?: number\n /**\n * Per-millisecond counter (0 to 2^(22 - nodeBits) - 1).\n * Defaults to a fresh random value on a new millisecond, or the previous\n * value incremented by 1 within the same millisecond.\n */\n counter?: number\n}\n\nexport type Tsid = {\n /** Generate a time-sorted TSID bigint. */\n (): bigint\n /** Generate a TSID with explicit options or write its 8 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: TsidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a TSID bigint with optional timestamp, epoch, node, or counter controls. */\n (options?: TsidOptions, buf?: undefined, offset?: number): bigint\n /** Convert a TSID bigint to its canonical 8-byte representation. */\n toBytes(id: bigint): Uint8Array\n /** Convert 8 canonical TSID bytes to a TSID bigint. */\n fromBytes(bytes: Uint8Array): bigint\n /** Convert a TSID bigint to its canonical 13-character string. */\n toString(id: bigint): string\n /** Convert a canonical TSID string to a bigint. */\n fromString(str: string): bigint\n /** Read a TSID timestamp in milliseconds, using the supplied or default epoch. */\n timestamp(id: bigint, epoch?: number): number\n /** Return whether a value is a valid 64-bit TSID bigint. */\n isValid(id: unknown): id is bigint\n /** The nil TSID (all zeros) */\n NIL: bigint\n /** The max TSID (maximum valid 64-bit value) */\n MAX: bigint\n}\n\ntype TsidState = {\n node: number | undefined\n msecs: number\n counter: number\n}\n\n/**\n * Module-level state for the lazily-initialized persistent node ID and the\n * per-millisecond-reset counter.\n *\n * IMPORTANT: This state persists across all tsid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs`, `epoch`, `node`, `nodeBits`, or\n * `counter` via options - doing so bypasses `state` entirely.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: TsidState = {\n node: undefined,\n msecs: -Infinity,\n counter: 0,\n}\n\nfunction pack(msecsDiff: bigint, node: number, counterBits: number, counter: number): bigint {\n return (msecsDiff << BigInt(RANDOM_BITS)) | (BigInt(node) << BigInt(counterBits)) | BigInt(counter)\n}\n\nfunction writeTsidBytesUnchecked(value: bigint, buf: Uint8Array, offset: number): void {\n for (let i = 0; i < TSID_BYTES; i += 1) {\n buf[offset + i] = Number((value >> BigInt((TSID_BYTES - 1 - i) * 8)) & 0xffn)\n }\n}\n\ntype ResolvedTsidOptions = {\n msecsDiff: bigint\n node: number\n counterBits: number\n counter: number\n}\n\nfunction resolveTsidOptions(options: TsidOptions): ResolvedTsidOptions {\n const nodeBits = options.nodeBits ?? DEFAULT_NODE_BITS\n if (!isIntegerInRange(nodeBits, 0, MAX_NODE_BITS)) {\n throw new InvalidInputError('TSID_NODE_BITS_OUT_OF_RANGE', `nodeBits must be between 0 and ${MAX_NODE_BITS}`)\n }\n\n const counterBits = RANDOM_BITS - nodeBits\n const nodeMask = (1 << nodeBits) - 1\n const counterMask = (1 << counterBits) - 1\n const optNode = options.node\n if (optNode !== undefined && !isIntegerInRange(optNode, 0, nodeMask)) {\n throw new InvalidInputError('TSID_NODE_OUT_OF_RANGE', `node must be between 0 and ${nodeMask}`)\n }\n\n const optCounter = options.counter\n if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, counterMask)) {\n throw new InvalidInputError('TSID_COUNTER_OUT_OF_RANGE', `counter must be between 0 and ${counterMask}`)\n }\n\n const epoch = options.epoch ?? TSID_EPOCH\n if (!Number.isInteger(epoch)) {\n throw new InvalidInputError('TSID_EPOCH_INVALID', 'epoch must be a finite integer')\n }\n const msecs = options.msecs ?? Date.now()\n if (!Number.isInteger(msecs)) {\n throw new InvalidInputError('TSID_TIMESTAMP_INVALID', 'msecs must be a finite integer')\n }\n const msecsDiff = BigInt(msecs) - BigInt(epoch)\n if (msecsDiff < 0n || msecsDiff > MAX_TIMESTAMP_DIFF) {\n throw new InvalidInputError(\n 'TSID_TIMESTAMP_OUT_OF_RANGE',\n `msecs - epoch must be between 0 and ${MAX_TIMESTAMP_DIFF}`,\n )\n }\n\n return {\n msecsDiff,\n node: optNode ?? randomUint32() & nodeMask,\n counterBits,\n counter: optCounter ?? randomUint32() & counterMask,\n }\n}\n\n/*\n * Overload: no buffer => return a TSID bigint.\n */\nfunction tsidFn(options?: TsidOptions, buf?: undefined, offset?: number): bigint\n/*\n * Overload: caller provides a buffer slice to fill with TSID bytes.\n */\nfunction tsidFn<TBuf extends Uint8Array = Uint8Array>(\n options: TsidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction tsidFn<TBuf extends Uint8Array = Uint8Array>(options?: TsidOptions, buf?: TBuf, offset = 0): bigint | TBuf {\n let msecsDiff: bigint\n let node: number\n let counterBits: number\n let counter: number\n\n if (options) {\n const resolved = resolveTsidOptions(options)\n msecsDiff = resolved.msecsDiff\n node = resolved.node\n counterBits = resolved.counterBits\n counter = resolved.counter\n } else {\n // Lazily initialize the persistent node ID on first no-option call.\n if (state.node === undefined) {\n state.node = randomUint32() & DEFAULT_NODE_MASK\n }\n node = state.node\n counterBits = DEFAULT_COUNTER_BITS\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling\n * to prevent side-channel attacks, so Date.now() returns the same value for\n * the entire duration of a request. Monotonic ordering within such a request\n * relies entirely on the counter (and its clock-drift-ahead overflow below).\n */\n const now = Date.now()\n if (now > state.msecs) {\n state.msecs = now\n state.counter = randomUint32() & DEFAULT_COUNTER_MASK\n } else {\n state.counter += 1\n if (state.counter > DEFAULT_COUNTER_MASK) {\n // Counter overflowed within this real millisecond: advance the internal\n // virtual timestamp ahead of wall-clock time rather than throwing. A\n // 12-bit counter (4096 values/ms) is a realistic throughput ceiling.\n state.msecs += 1\n state.counter = 0\n }\n }\n counter = state.counter\n msecsDiff = BigInt(state.msecs) - BigInt(TSID_EPOCH)\n }\n\n const packed = pack(msecsDiff, node, counterBits, counter)\n\n if (buf) {\n if (!isWritableRange(buf, offset, TSID_BYTES)) {\n throw new BufferError(\n 'TSID_BUFFER_OUT_OF_BOUNDS',\n `TSID byte range ${offset}:${offset + TSID_BYTES - 1} is out of buffer bounds`,\n )\n }\n writeTsidBytesUnchecked(packed, buf, offset)\n return buf\n }\n\n return packed\n}\n\n/**\n * Convert a TSID bigint to 8 bytes.\n */\nfunction toBytes(id: bigint): Uint8Array {\n assertValidTsid(id)\n const bytes = new Uint8Array(TSID_BYTES)\n writeTsidBytesUnchecked(id, bytes, 0)\n return bytes\n}\n\n/**\n * Convert 8 bytes to a TSID bigint.\n */\nfunction fromBytes(bytes: Uint8Array): bigint {\n if (bytes.length !== TSID_BYTES) {\n throw new BufferError(\n 'TSID_BYTES_INVALID_LENGTH',\n `TSID bytes must be exactly ${TSID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n\n let value = 0n\n for (let i = 0; i < TSID_BYTES; i += 1) {\n value = (value << 8n) | BigInt(bytes[i])\n }\n return value\n}\n\n/**\n * Extract the timestamp (milliseconds since Unix epoch) from a TSID.\n * The epoch is not self-describing in the packed value - pass the same\n * `epoch` used at generation time if it was overridden from the default.\n */\nfunction timestamp(id: bigint, epoch: number = TSID_EPOCH): number {\n assertValidTsid(id)\n if (!Number.isInteger(epoch)) {\n throw new InvalidInputError('TSID_EPOCH_INVALID', 'epoch must be a finite integer')\n }\n return epoch + Number(id >> BigInt(RANDOM_BITS))\n}\n\n/**\n * Validate that a value is a TSID bigint within the 64-bit range.\n */\nfunction isValid(id: unknown): id is bigint {\n return typeof id === 'bigint' && id >= 0n && id <= MAX\n}\n\nconst NIL = 0n\nconst MAX = (1n << 64n) - 1n\n\nfunction assertValidTsid(id: bigint): void {\n if (id < NIL || id > MAX) {\n throw new InvalidInputError('TSID_VALUE_OUT_OF_RANGE', `TSID value must be between ${NIL} and ${MAX}`)\n }\n}\n\nfunction toString(id: bigint): string {\n assertValidTsid(id)\n return encodeTsidString(id)\n}\n\n/**\n * Generate a TSID bigint or write the bytes into a buffer.\n *\n * TSID (Time-Sorted Unique Identifier) is a 64-bit Snowflake-style identifier\n * combining a millisecond timestamp, a node ID, and a per-millisecond counter.\n * Unlike every other uniku generator, it returns a `bigint` by default, since\n * TSID's entire value proposition is native numeric storage (e.g. a database\n * BIGINT primary key).\n *\n * @example\n * ```ts\n * import { tsid } from 'uniku/tsid'\n *\n * const id = tsid()\n * // => 862301223059968074n\n *\n * // Canonical string form\n * const str = tsid.toString(id)\n * // => \"0QXW2CK4XZM2A\"\n * tsid.fromString(str) === id // true\n *\n * // Extract timestamp\n * const ts = tsid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * tsid.isValid(id) // true\n *\n * // Convert to/from bytes (8 bytes)\n * const bytes = tsid.toBytes(id)\n * const restored = tsid.fromBytes(bytes)\n * ```\n */\nexport const tsid: Tsid = Object.assign(tsidFn, {\n toBytes,\n fromBytes,\n toString,\n fromString: decodeTsidString,\n timestamp,\n isValid,\n NIL,\n MAX,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"tsid.mjs","names":[],"sources":["../../src/tsid/crockford64.ts","../../src/tsid/tsid.ts"],"sourcesContent":["import { ParseError } from '../errors'\n\n/**\n * Crockford Base32 codec for TSID, operating directly on the primary `bigint`\n * value rather than an intermediate byte array (unlike ulid/crockford.ts) -\n * tsid's primary type never routes through a `Uint8Array` during string\n * conversion.\n *\n * TSID binary format: 64 bits (8 bytes), encoded as 13 Crockford Base32 characters.\n * 13 chars * 5 bits = 65 bits of capacity for a 64-bit value, leaving exactly 1 bit\n * of headroom on the leading character. That headroom bit is always 0, so the\n * leading character only carries 4 significant real bits (values 0-15, i.e. the\n * alphabet's first 16 symbols \"0\"-\"9\"/\"A\"-\"F\") rather than the full 32-symbol\n * range - the same overflow-prevention technique ULID uses for its own leading\n * `[0-7]` restriction (2 headroom bits there vs 1 here). Confirmed against\n * `tsid-ts`'s own `toCanonicalString`: `(number >> BigInt(60 - i * 5)) & 0x1f`.\n */\n\nconst TSID_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'\nconst TSID_STRING_LEN = 13\nconst TSID_LEADING_MAX = 15 // 4 significant bits on the leading character (see above)\n\n// Pre-computed decode table (case-insensitive) covering ASCII, so lookups never\n// go out of bounds and a single `=== 255` check rejects invalid input.\nconst DECODING = new Uint8Array(128).fill(255)\nfor (let i = 0; i < TSID_ALPHABET.length; i += 1) {\n const char = TSID_ALPHABET[i]\n const upperCode = TSID_ALPHABET.charCodeAt(i)\n DECODING[upperCode] = i\n // Only letters have a lowercase counterpart - applying +32 to digit codes\n // would land on unrelated uppercase letters (e.g. '5' + 32 -> 'U', which is\n // excluded from this alphabet and would never get overwritten back to 255).\n if (char >= 'A' && char <= 'Z') {\n DECODING[upperCode + 32] = i\n }\n}\n\n/**\n * Encode a TSID `bigint` value to its 13-character canonical Crockford Base32 string.\n */\nexport function encodeTsidString(value: bigint): string {\n let result = ''\n for (let i = 0; i < TSID_STRING_LEN; i += 1) {\n const shift = BigInt(60 - i * 5)\n const group = Number((value >> shift) & 0x1fn)\n result += TSID_ALPHABET[group]\n }\n return result\n}\n\n/**\n * Decode a 13-character canonical Crockford Base32 string to a TSID `bigint` value.\n */\nexport function decodeTsidString(str: string): bigint {\n if (str.length !== TSID_STRING_LEN) {\n throw new ParseError('INVALID_LENGTH', `TSID string must be ${TSID_STRING_LEN} characters, got ${str.length}`, {\n strategy: 'tsid',\n })\n }\n\n let value = 0n\n for (let i = 0; i < TSID_STRING_LEN; i += 1) {\n const code = str.charCodeAt(i)\n const group = code < 128 ? DECODING[code] : 255\n if (group === 255) {\n throw new ParseError('INVALID_CHAR', `Invalid TSID character: ${str[i]}`, { strategy: 'tsid' })\n }\n if (i === 0 && group > TSID_LEADING_MAX) {\n throw new ParseError('VALUE_OUT_OF_RANGE', `TSID leading character must be one of 0-9, A-F, got: ${str[i]}`, {\n strategy: 'tsid',\n })\n }\n value = (value << 5n) | BigInt(group)\n }\n return value\n}\n","import { randomUint32 } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeTsidString, encodeTsidString } from './crockford64'\n\n/**\n * TSID (Time-Sorted Unique Identifier)\n *\n * A 64-bit Snowflake-style identifier consisting of:\n * - 42 bits: millisecond timestamp relative to a custom epoch (default 2020-01-01T00:00:00.000Z)\n * - 10 bits: node ID (default; configurable via `nodeBits`)\n * - 12 bits: per-millisecond counter (default; `22 - nodeBits`)\n *\n * Unlike every other uniku generator, `tsid()` returns a `bigint` by default -\n * this is a deliberate design decision reflecting that TSID's value proposition\n * is native numeric storage (e.g. a database BIGINT primary key), not a\n * string-first identifier that happens to have a byte encoding. `toString`/\n * `fromString` are the boundary conversions to/from the 13-character canonical\n * Crockford Base32 string.\n *\n * Encoded as 8 big-endian bytes in buffer mode.\n */\n\nconst TSID_EPOCH = 1577836800000 // 2020-01-01T00:00:00.000Z\nconst TSID_BYTES = 8\nconst RANDOM_BITS = 22 // combined node + counter bits\nconst DEFAULT_NODE_BITS = 10\nconst DEFAULT_COUNTER_BITS = RANDOM_BITS - DEFAULT_NODE_BITS\nconst DEFAULT_NODE_MASK = (1 << DEFAULT_NODE_BITS) - 1\nconst DEFAULT_COUNTER_MASK = (1 << DEFAULT_COUNTER_BITS) - 1\nconst MAX_NODE_BITS = 20\nconst MAX_TIMESTAMP_DIFF = (1n << 42n) - 1n\n\nexport type TsidOptions = {\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n /**\n * Custom epoch in milliseconds since Unix epoch.\n * Defaults to 1577836800000 (2020-01-01T00:00:00.000Z).\n */\n epoch?: number\n /**\n * Node ID (0 to 2^nodeBits - 1).\n * Defaults to a lazily-initialized, persistent random value.\n */\n node?: number\n /**\n * Number of bits allocated to the node ID (0-20).\n * The remaining bits (22 - nodeBits) are allocated to the counter.\n * Defaults to 10.\n */\n nodeBits?: number\n /**\n * Per-millisecond counter (0 to 2^(22 - nodeBits) - 1).\n * Defaults to a fresh random value on a new millisecond, or the previous\n * value incremented by 1 within the same millisecond.\n */\n counter?: number\n}\n\nexport type Tsid = {\n /** Generate a time-sorted TSID bigint. */\n (): bigint\n /** Generate a TSID with explicit options or write its 8 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: TsidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a TSID bigint with optional timestamp, epoch, node, or counter controls. */\n (options?: TsidOptions, buf?: undefined, offset?: number): bigint\n /** Convert a TSID bigint to its canonical 8-byte representation. */\n toBytes(id: bigint): Uint8Array\n /** Convert 8 canonical TSID bytes to a TSID bigint. */\n fromBytes(bytes: Uint8Array): bigint\n /** Convert a TSID bigint to its canonical 13-character string. */\n toString(id: bigint): string\n /** Convert a canonical TSID string to a bigint. */\n fromString(str: string): bigint\n /** Read a TSID timestamp in milliseconds, using the supplied or default epoch. */\n timestamp(id: bigint, epoch?: number): number\n /** Return whether a value is a valid 64-bit TSID bigint. */\n isValid(id: unknown): id is bigint\n /** The nil TSID (all zeros) */\n NIL: bigint\n /** The max TSID (maximum valid 64-bit value) */\n MAX: bigint\n}\n\ntype TsidState = {\n node: number | undefined\n msecs: number\n counter: number\n}\n\n/**\n * Module-level state for the lazily-initialized persistent node ID and the\n * per-millisecond-reset counter.\n *\n * IMPORTANT: This state persists across all tsid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs`, `epoch`, `node`, `nodeBits`, or\n * `counter` via options - doing so bypasses `state` entirely.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: TsidState = {\n node: undefined,\n msecs: -Infinity,\n counter: 0,\n}\n\nfunction pack(msecsDiff: bigint, node: number, counterBits: number, counter: number): bigint {\n return (msecsDiff << BigInt(RANDOM_BITS)) | (BigInt(node) << BigInt(counterBits)) | BigInt(counter)\n}\n\nfunction writeTsidBytesUnchecked(value: bigint, buf: Uint8Array, offset: number): void {\n for (let i = 0; i < TSID_BYTES; i += 1) {\n buf[offset + i] = Number((value >> BigInt((TSID_BYTES - 1 - i) * 8)) & 0xffn)\n }\n}\n\ntype ResolvedTsidOptions = {\n msecsDiff: bigint\n node: number\n counterBits: number\n counter: number\n}\n\nfunction resolveTsidOptions(options: TsidOptions): ResolvedTsidOptions {\n const nodeBits = options.nodeBits ?? DEFAULT_NODE_BITS\n if (!isIntegerInRange(nodeBits, 0, MAX_NODE_BITS)) {\n throw new InvalidInputError('NODE_BITS_OUT_OF_RANGE', `nodeBits must be between 0 and ${MAX_NODE_BITS}`, {\n strategy: 'tsid',\n })\n }\n\n const counterBits = RANDOM_BITS - nodeBits\n const nodeMask = (1 << nodeBits) - 1\n const counterMask = (1 << counterBits) - 1\n const optNode = options.node\n if (optNode !== undefined && !isIntegerInRange(optNode, 0, nodeMask)) {\n throw new InvalidInputError('NODE_OUT_OF_RANGE', `node must be between 0 and ${nodeMask}`, { strategy: 'tsid' })\n }\n\n const optCounter = options.counter\n if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, counterMask)) {\n throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `counter must be between 0 and ${counterMask}`, {\n strategy: 'tsid',\n })\n }\n\n const epoch = options.epoch ?? TSID_EPOCH\n if (!Number.isInteger(epoch)) {\n throw new InvalidInputError('EPOCH_INVALID', 'epoch must be a finite integer', { strategy: 'tsid' })\n }\n const msecs = options.msecs ?? Date.now()\n if (!Number.isInteger(msecs)) {\n throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', 'msecs must be a finite integer', { strategy: 'tsid' })\n }\n const msecsDiff = BigInt(msecs) - BigInt(epoch)\n if (msecsDiff < 0n || msecsDiff > MAX_TIMESTAMP_DIFF) {\n throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `msecs - epoch must be between 0 and ${MAX_TIMESTAMP_DIFF}`, {\n strategy: 'tsid',\n })\n }\n\n return {\n msecsDiff,\n node: optNode ?? randomUint32() & nodeMask,\n counterBits,\n counter: optCounter ?? randomUint32() & counterMask,\n }\n}\n\n/*\n * Overload: no buffer => return a TSID bigint.\n */\nfunction tsidFn(options?: TsidOptions, buf?: undefined, offset?: number): bigint\n/*\n * Overload: caller provides a buffer slice to fill with TSID bytes.\n */\nfunction tsidFn<TBuf extends Uint8Array = Uint8Array>(\n options: TsidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction tsidFn<TBuf extends Uint8Array = Uint8Array>(options?: TsidOptions, buf?: TBuf, offset = 0): bigint | TBuf {\n let msecsDiff: bigint\n let node: number\n let counterBits: number\n let counter: number\n\n if (options) {\n const resolved = resolveTsidOptions(options)\n msecsDiff = resolved.msecsDiff\n node = resolved.node\n counterBits = resolved.counterBits\n counter = resolved.counter\n } else {\n // Lazily initialize the persistent node ID on first no-option call.\n if (state.node === undefined) {\n state.node = randomUint32() & DEFAULT_NODE_MASK\n }\n node = state.node\n counterBits = DEFAULT_COUNTER_BITS\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling\n * to prevent side-channel attacks, so Date.now() returns the same value for\n * the entire duration of a request. Monotonic ordering within such a request\n * relies entirely on the counter (and its clock-drift-ahead overflow below).\n */\n const now = Date.now()\n if (now > state.msecs) {\n state.msecs = now\n state.counter = randomUint32() & DEFAULT_COUNTER_MASK\n } else {\n state.counter += 1\n if (state.counter > DEFAULT_COUNTER_MASK) {\n // Counter overflowed within this real millisecond: advance the internal\n // virtual timestamp ahead of wall-clock time rather than throwing. A\n // 12-bit counter (4096 values/ms) is a realistic throughput ceiling.\n state.msecs += 1\n state.counter = 0\n }\n }\n counter = state.counter\n msecsDiff = BigInt(state.msecs) - BigInt(TSID_EPOCH)\n }\n\n const packed = pack(msecsDiff, node, counterBits, counter)\n\n if (buf) {\n if (!isWritableRange(buf, offset, TSID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `TSID byte range ${offset}:${offset + TSID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'tsid' },\n )\n }\n writeTsidBytesUnchecked(packed, buf, offset)\n return buf\n }\n\n return packed\n}\n\n/**\n * Convert a TSID bigint to 8 bytes.\n */\nfunction toBytes(id: bigint): Uint8Array {\n assertValidTsid(id)\n const bytes = new Uint8Array(TSID_BYTES)\n writeTsidBytesUnchecked(id, bytes, 0)\n return bytes\n}\n\n/**\n * Convert 8 bytes to a TSID bigint.\n */\nfunction fromBytes(bytes: Uint8Array): bigint {\n if (bytes.length !== TSID_BYTES) {\n throw new BufferError(\n 'BYTES_INVALID_LENGTH',\n `TSID bytes must be exactly ${TSID_BYTES} bytes, got ${bytes.length}`,\n { strategy: 'tsid' },\n )\n }\n\n let value = 0n\n for (let i = 0; i < TSID_BYTES; i += 1) {\n value = (value << 8n) | BigInt(bytes[i])\n }\n return value\n}\n\n/**\n * Extract the timestamp (milliseconds since Unix epoch) from a TSID.\n * The epoch is not self-describing in the packed value - pass the same\n * `epoch` used at generation time if it was overridden from the default.\n */\nfunction timestamp(id: bigint, epoch: number = TSID_EPOCH): number {\n assertValidTsid(id)\n if (!Number.isInteger(epoch)) {\n throw new InvalidInputError('EPOCH_INVALID', 'epoch must be a finite integer', { strategy: 'tsid' })\n }\n return epoch + Number(id >> BigInt(RANDOM_BITS))\n}\n\n/**\n * Validate that a value is a TSID bigint within the 64-bit range.\n */\nfunction isValid(id: unknown): id is bigint {\n return typeof id === 'bigint' && id >= 0n && id <= MAX\n}\n\nconst NIL = 0n\nconst MAX = (1n << 64n) - 1n\n\nfunction assertValidTsid(id: bigint): void {\n if (id < NIL || id > MAX) {\n throw new InvalidInputError('VALUE_OUT_OF_RANGE', `TSID value must be between ${NIL} and ${MAX}`, {\n strategy: 'tsid',\n })\n }\n}\n\nfunction toString(id: bigint): string {\n assertValidTsid(id)\n return encodeTsidString(id)\n}\n\n/**\n * Generate a TSID bigint or write the bytes into a buffer.\n *\n * TSID (Time-Sorted Unique Identifier) is a 64-bit Snowflake-style identifier\n * combining a millisecond timestamp, a node ID, and a per-millisecond counter.\n * Unlike every other uniku generator, it returns a `bigint` by default, since\n * TSID's entire value proposition is native numeric storage (e.g. a database\n * BIGINT primary key).\n *\n * @example\n * ```ts\n * import { tsid } from 'uniku/tsid'\n *\n * const id = tsid()\n * // => 862301223059968074n\n *\n * // Canonical string form\n * const str = tsid.toString(id)\n * // => \"0QXW2CK4XZM2A\"\n * tsid.fromString(str) === id // true\n *\n * // Extract timestamp\n * const ts = tsid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * tsid.isValid(id) // true\n *\n * // Convert to/from bytes (8 bytes)\n * const bytes = tsid.toBytes(id)\n * const restored = tsid.fromBytes(bytes)\n * ```\n */\nexport const tsid: Tsid = Object.assign(tsidFn, {\n toBytes,\n fromBytes,\n toString,\n fromString: decodeTsidString,\n timestamp,\n isValid,\n NIL,\n MAX,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";
import { UuidV7Options } from "../uuid/v7.mjs";

@@ -7,3 +7,5 @@

type Typeid = {
/** Generate a TypeID from a lowercase entity prefix and a UUID v7 suffix. */(prefix: string, options?: TypeidOptions): string; /** Convert a TypeID's UUID v7 suffix to its canonical 16-byte representation. */
/** Generate a TypeID from a lowercase entity prefix and a UUID v7 suffix. */(prefix: string, options?: TypeidOptions): string; /** Generate a TypeID with explicit options or write its 16 canonical UUID v7 bytes into a caller-owned buffer. */
<TBuf extends Uint8Array = Uint8Array>(prefix: string, options: TypeidOptions | undefined, buf: TBuf, offset?: number): TBuf; /** Generate a TypeID string with optional timestamp, counter, or random bytes. */
(prefix: string, options?: TypeidOptions, buf?: undefined, offset?: number): string; /** Convert a TypeID's UUID v7 suffix to its canonical 16-byte representation. */
toBytes(id: string): Uint8Array; /** Build a TypeID from a prefix and canonical UUID v7 bytes. */

@@ -10,0 +12,0 @@ fromBytes(prefix: string, bytes: Uint8Array): string; /** Convert a TypeID to its UUID v7 string. */

@@ -1,1 +0,1 @@

{"version":3,"file":"typeid.d.mts","names":[],"sources":["../../src/typeid/typeid.ts"],"mappings":";;;;KAIY,aAAA,GAAgB,aAAA;AAAA,KAEhB,MAAA;gFAET,MAAA,UAAgB,OAAA,GAAU,aAAA,WAJjB;EAMV,OAAA,CAAQ,EAAA,WAAa,UAAA,EANK;EAQ1B,SAAA,CAAU,MAAA,UAAgB,KAAA,EAAO,UAAA,WANnC;EAQE,MAAA,CAAO,EAAA;EAEP,QAAA,CAAS,MAAA,UAAgB,IAAA;EAEzB,SAAA,CAAU,EAAA,mBANuB;EAQjC,MAAA,CAAO,EAAA;EAEP,MAAA,CAAO,EAAA;EAEP,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;;;;;;;;;;;;;;;;;cAgQX,MAAA,EAAQ,MAAA"}
{"version":3,"file":"typeid.d.mts","names":[],"sources":["../../src/typeid/typeid.ts"],"mappings":";;;;KAKY,aAAA,GAAgB,aAAA;AAAA,KAEhB,MAAA;gFAET,MAAA,UAAgB,OAAA,GAAU,aAAA,WAJjB;EAAA,cAMI,UAAA,GAAa,UAAA,EACzB,MAAA,UACA,OAAA,EAAS,aAAA,cACT,GAAA,EAAK,IAAA,EACL,MAAA,YACC,IAAA,EAXuB;EAAA,CAazB,MAAA,UAAgB,OAAA,GAAU,aAAA,EAAe,GAAA,cAAiB,MAAA,oBAX7D;EAaE,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,MAAA,UAAgB,KAAA,EAAO,UAAA;EAEjC,MAAA,CAAO,EAAA;EAEP,QAAA,CAAS,MAAA,UAAgB,IAAA;EAEzB,SAAA,CAAU,EAAA;EAEV,MAAA,CAAO,EAAA,mBAR0B;EAUjC,MAAA,CAAO,EAAA;EAEP,OAAA,CAAQ,EAAA,YAAc,EAAA;AAAA;;;;;;;;;;;;;;;;;;;cAgVX,MAAA,EAAQ,MAAA"}

@@ -1,2 +0,2 @@

import{BufferError as e,InvalidInputError as t,ParseError as n,UniqueIdError as r}from"../errors.mjs";import{uuidv7 as i}from"../uuid/v7.mjs";const a=`0123456789abcdefghjkmnpqrstvwxyz`,o=Array.from({length:128},()=>-1);for(let e=0;e<32;e+=1)o[a.charCodeAt(e)]=e;function s(e){if(e.length!==0){if(e.length>63)throw new t(`TYPEID_PREFIX_TOO_LONG`,`TypeID prefix must be at most 63 characters`);for(let n=0;n<e.length;n+=1){let r=e.charCodeAt(n),i=r>=97&&r<=122;if(!i&&r!==95)throw new t(`TYPEID_PREFIX_INVALID_CHARACTER`,`TypeID prefix must contain only lowercase ASCII letters and underscores`);if((n===0||n===e.length-1)&&!i)throw new t(`TYPEID_PREFIX_INVALID_BOUNDARY`,`TypeID prefix must start and end with a-z`)}}}function c(e,t){let r=e.charCodeAt(t),i=r<o.length?o[r]:-1;if(i===-1)throw new n(`TYPEID_SUFFIX_INVALID_CHARACTER`,`TypeID suffix contains invalid character at position ${t}`);return i}function l(e){if(e.length!==26)throw new n(`TYPEID_SUFFIX_INVALID_LENGTH`,`TypeID suffix must be 26 characters, got ${e.length}`);if(e[0]>`7`)throw new n(`TYPEID_SUFFIX_OVERFLOW`,`TypeID suffix must encode a 128-bit value`)}function u(e){if(e.length!==16)throw new t(`TYPEID_UUID_BYTES_INVALID_LENGTH`,`UUID bytes must be 16 bytes, got ${e.length}`);return a[(e[0]&224)>>5]+a[e[0]&31]+a[(e[1]&248)>>3]+a[(e[1]&7)<<2|(e[2]&192)>>6]+a[(e[2]&62)>>1]+a[(e[2]&1)<<4|(e[3]&240)>>4]+a[(e[3]&15)<<1|(e[4]&128)>>7]+a[(e[4]&124)>>2]+a[(e[4]&3)<<3|(e[5]&224)>>5]+a[e[5]&31]+a[(e[6]&248)>>3]+a[(e[6]&7)<<2|(e[7]&192)>>6]+a[(e[7]&62)>>1]+a[(e[7]&1)<<4|(e[8]&240)>>4]+a[(e[8]&15)<<1|(e[9]&128)>>7]+a[(e[9]&124)>>2]+a[(e[9]&3)<<3|(e[10]&224)>>5]+a[e[10]&31]+a[(e[11]&248)>>3]+a[(e[11]&7)<<2|(e[12]&192)>>6]+a[(e[12]&62)>>1]+a[(e[12]&1)<<4|(e[13]&240)>>4]+a[(e[13]&15)<<1|(e[14]&128)>>7]+a[(e[14]&124)>>2]+a[(e[14]&3)<<3|(e[15]&224)>>5]+a[e[15]&31]}function d(e){l(e);let t=Array(26);for(let n=0;n<26;n+=1)t[n]=c(e,n);let n=new Uint8Array(16);return n[0]=t[0]<<5|t[1],n[1]=t[2]<<3|t[3]>>2,n[2]=(t[3]&3)<<6|t[4]<<1|t[5]>>4,n[3]=(t[5]&15)<<4|t[6]>>1,n[4]=(t[6]&1)<<7|t[7]<<2|t[8]>>3,n[5]=(t[8]&7)<<5|t[9],n[6]=t[10]<<3|t[11]>>2,n[7]=(t[11]&3)<<6|t[12]<<1|t[13]>>4,n[8]=(t[13]&15)<<4|t[14]>>1,n[9]=(t[14]&1)<<7|t[15]<<2|t[16]>>3,n[10]=(t[16]&7)<<5|t[17],n[11]=t[18]<<3|t[19]>>2,n[12]=(t[19]&3)<<6|t[20]<<1|t[21]>>4,n[13]=(t[21]&15)<<4|t[22]>>1,n[14]=(t[22]&1)<<7|t[23]<<2|t[24]>>3,n[15]=(t[24]&7)<<5|t[25],n}function f(e){if(e.length!==16)throw new t(`TYPEID_UUID_BYTES_INVALID_LENGTH`,`UUID bytes must be 16 bytes, got ${e.length}`);if(e[6]>>4!=7||(e[8]&192)!=128)throw new t(`TYPEID_UUID_NOT_V7`,`TypeID UUID bytes must encode a UUID v7 value`)}function p(e){let t=d(e);return f(t),t}function m(e){if(!i.isValid(e))throw new t(`TYPEID_UUID_NOT_V7`,`TypeID can only wrap UUID v7 values`);return i.toBytes(e)}function h(e){let t=e.lastIndexOf(`_`);if(t===0)throw new n(`TYPEID_INVALID_FORMAT`,`TypeID must not start with "_"`);let r=t===-1?``:e.slice(0,t),i=t===-1?e:e.slice(t+1);return s(r),{prefix:r,suffix:i,bytes:p(i)}}function g(e,t){return e===``?t:`${e}_${t}`}function _(e,t){return s(e),f(t),g(e,u(t))}function v(e){let t=0;for(let n=0;n<6;n+=1)t=t*256+e[n];return t}function y(e,t){return _(e,i(t,new Uint8Array(16)))}function b(e){return h(e).bytes}function x(e,t){return _(e,t)}function S(e){return i.fromBytes(b(e))}function C(e,t){return _(e,m(t))}function w(e){return v(h(e).bytes)}function T(e){return h(e).prefix}function E(e){return h(e).suffix}function D(e){if(typeof e!=`string`)return!1;try{h(e)}catch{return!1}return!0}const O=Object.assign(y,{toBytes:b,fromBytes:x,toUuid:S,fromUuid:C,timestamp:w,prefix:T,suffix:E,isValid:D});export{e as BufferError,t as InvalidInputError,n as ParseError,r as UniqueIdError,O as typeid};
import{n as e,t}from"../validation-CTNpXm94.mjs";import{BufferError as n,InvalidInputError as r,ParseError as i,UniqueIdError as a}from"../errors.mjs";import{uuidv7 as o}from"../uuid/v7.mjs";const s=0xffffffffffff,c=4294967295,l=`0123456789abcdefghjkmnpqrstvwxyz`,u=Array.from({length:128},()=>-1);for(let e=0;e<32;e+=1)u[l.charCodeAt(e)]=e;function d(e){if(e.length!==0){if(e.length>63)throw new r(`PREFIX_TOO_LONG`,`TypeID prefix must be at most 63 characters`,{strategy:`typeid`});for(let t=0;t<e.length;t+=1){let n=e.charCodeAt(t),i=n>=97&&n<=122;if(!i&&n!==95)throw new r(`PREFIX_INVALID_CHAR`,`TypeID prefix must contain only lowercase ASCII letters and underscores`,{strategy:`typeid`});if((t===0||t===e.length-1)&&!i)throw new r(`PREFIX_INVALID_BOUNDARY`,`TypeID prefix must start and end with a-z`,{strategy:`typeid`})}}}function f(e,t){let n=e.charCodeAt(t),r=n<u.length?u[n]:-1;if(r===-1)throw new i(`INVALID_CHAR`,`TypeID suffix contains invalid character at position ${t}`,{strategy:`typeid`});return r}function p(e){if(e.length!==26)throw new i(`INVALID_LENGTH`,`TypeID suffix must be 26 characters, got ${e.length}`,{strategy:`typeid`});if(e[0]>`7`)throw new i(`VALUE_OUT_OF_RANGE`,`TypeID suffix must encode a 128-bit value`,{strategy:`typeid`})}function m(e){if(e.length!==16)throw new r(`BYTES_INVALID_LENGTH`,`UUID bytes must be 16 bytes, got ${e.length}`,{strategy:`typeid`});return l[(e[0]&224)>>5]+l[e[0]&31]+l[(e[1]&248)>>3]+l[(e[1]&7)<<2|(e[2]&192)>>6]+l[(e[2]&62)>>1]+l[(e[2]&1)<<4|(e[3]&240)>>4]+l[(e[3]&15)<<1|(e[4]&128)>>7]+l[(e[4]&124)>>2]+l[(e[4]&3)<<3|(e[5]&224)>>5]+l[e[5]&31]+l[(e[6]&248)>>3]+l[(e[6]&7)<<2|(e[7]&192)>>6]+l[(e[7]&62)>>1]+l[(e[7]&1)<<4|(e[8]&240)>>4]+l[(e[8]&15)<<1|(e[9]&128)>>7]+l[(e[9]&124)>>2]+l[(e[9]&3)<<3|(e[10]&224)>>5]+l[e[10]&31]+l[(e[11]&248)>>3]+l[(e[11]&7)<<2|(e[12]&192)>>6]+l[(e[12]&62)>>1]+l[(e[12]&1)<<4|(e[13]&240)>>4]+l[(e[13]&15)<<1|(e[14]&128)>>7]+l[(e[14]&124)>>2]+l[(e[14]&3)<<3|(e[15]&224)>>5]+l[e[15]&31]}function h(e){p(e);let t=Array(26);for(let n=0;n<26;n+=1)t[n]=f(e,n);let n=new Uint8Array(16);return n[0]=t[0]<<5|t[1],n[1]=t[2]<<3|t[3]>>2,n[2]=(t[3]&3)<<6|t[4]<<1|t[5]>>4,n[3]=(t[5]&15)<<4|t[6]>>1,n[4]=(t[6]&1)<<7|t[7]<<2|t[8]>>3,n[5]=(t[8]&7)<<5|t[9],n[6]=t[10]<<3|t[11]>>2,n[7]=(t[11]&3)<<6|t[12]<<1|t[13]>>4,n[8]=(t[13]&15)<<4|t[14]>>1,n[9]=(t[14]&1)<<7|t[15]<<2|t[16]>>3,n[10]=(t[16]&7)<<5|t[17],n[11]=t[18]<<3|t[19]>>2,n[12]=(t[19]&3)<<6|t[20]<<1|t[21]>>4,n[13]=(t[21]&15)<<4|t[22]>>1,n[14]=(t[22]&1)<<7|t[23]<<2|t[24]>>3,n[15]=(t[24]&7)<<5|t[25],n}function g(e){if(e.length!==16)throw new r(`BYTES_INVALID_LENGTH`,`UUID bytes must be 16 bytes, got ${e.length}`,{strategy:`typeid`});if(e[6]>>4!=7||(e[8]&192)!=128)throw new r(`UUID_NOT_V7`,`TypeID UUID bytes must encode a UUID v7 value`,{strategy:`typeid`})}function _(e){let t=h(e);return g(t),t}function v(e){if(!o.isValid(e))throw new r(`UUID_NOT_V7`,`TypeID can only wrap UUID v7 values`,{strategy:`typeid`});return o.toBytes(e)}function y(e){let t=e.lastIndexOf(`_`);if(t===0)throw new i(`INVALID_FORMAT`,`TypeID must not start with "_"`,{strategy:`typeid`});let n=t===-1?``:e.slice(0,t),r=t===-1?e:e.slice(t+1);return d(n),{prefix:n,suffix:r,bytes:_(r)}}function b(e,t){return e===``?t:`${e}_${t}`}function x(e,t){return d(e),g(t),b(e,m(t))}function S(e){let t=0;for(let n=0;n<6;n+=1)t=t*256+e[n];return t}function C(e){let n=e.msecs;if(n!==void 0&&!t(n,0,s))throw new r(`TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between 0 and ${s}`,{strategy:`typeid`});if(e.counter!==void 0&&e.seq!==void 0)throw new r(`CONFLICTING_OPTIONS`,"Pass only one of `counter` or `seq`, not both",{strategy:`typeid`});let i=e.counter??e.seq;if(i!==void 0&&!t(i,0,c))throw new r(`COUNTER_OUT_OF_RANGE`,`Counter must be an integer between 0 and ${c}`,{strategy:`typeid`});let a=e.random;if(a&&a.length<16)throw new r(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`,{strategy:`typeid`})}function w(t,r,i,a=0){if(r!==void 0&&C(r),i){if(!e(i,a,16))throw new n(`BUFFER_OUT_OF_BOUNDS`,`TypeID byte range ${a}:${a+16-1} is out of buffer bounds`,{strategy:`typeid`});return d(t),o(r,i,a)}return x(t,o(r,new Uint8Array(16)))}function T(e){return y(e).bytes}function E(e,t){return x(e,t)}function D(e){return o.fromBytes(T(e))}function O(e,t){return x(e,v(t))}function k(e){return S(y(e).bytes)}function A(e){return y(e).prefix}function j(e){return y(e).suffix}function M(e){if(typeof e!=`string`)return!1;try{y(e)}catch{return!1}return!0}const N=Object.assign(w,{toBytes:T,fromBytes:E,toUuid:D,fromUuid:O,timestamp:k,prefix:A,suffix:j,isValid:M});export{n as BufferError,r as InvalidInputError,i as ParseError,a as UniqueIdError,N as typeid};
//# sourceMappingURL=typeid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"typeid.mjs","names":[],"sources":["../../src/typeid/typeid.ts"],"sourcesContent":["import { InvalidInputError, ParseError } from '../errors'\nimport type { UuidV7Options } from '../uuid/v7'\nimport { uuidv7 } from '../uuid/v7'\n\nexport type TypeidOptions = UuidV7Options\n\nexport type Typeid = {\n /** Generate a TypeID from a lowercase entity prefix and a UUID v7 suffix. */\n (prefix: string, options?: TypeidOptions): string\n /** Convert a TypeID's UUID v7 suffix to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Build a TypeID from a prefix and canonical UUID v7 bytes. */\n fromBytes(prefix: string, bytes: Uint8Array): string\n /** Convert a TypeID to its UUID v7 string. */\n toUuid(id: string): string\n /** Build a TypeID from a prefix and UUID v7 string. */\n fromUuid(prefix: string, uuid: string): string\n /** Read the UUID v7 timestamp embedded in a TypeID, in milliseconds. */\n timestamp(id: string): number\n /** Read a TypeID's entity prefix. */\n prefix(id: string): string\n /** Read a TypeID's UUID v7 suffix. */\n suffix(id: string): string\n /** Return whether a value is a syntactically valid TypeID. */\n isValid(id: unknown): id is string\n}\n\nconst TYPEID_SUFFIX_LENGTH = 26\nconst TYPEID_UUID_BYTE_LENGTH = 16\nconst TYPEID_ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz'\n\nconst BASE32_DECODE: number[] = Array.from({ length: 128 }, () => -1)\nfor (let i = 0; i < TYPEID_ALPHABET.length; i += 1) {\n BASE32_DECODE[TYPEID_ALPHABET.charCodeAt(i)] = i\n}\n\ntype ParsedTypeid = {\n prefix: string\n suffix: string\n bytes: Uint8Array\n}\n\nfunction assertValidPrefix(prefix: string): void {\n if (prefix.length === 0) {\n return\n }\n\n if (prefix.length > 63) {\n throw new InvalidInputError('TYPEID_PREFIX_TOO_LONG', 'TypeID prefix must be at most 63 characters')\n }\n\n for (let i = 0; i < prefix.length; i += 1) {\n const code = prefix.charCodeAt(i)\n const isLowercaseLetter = code >= 97 && code <= 122\n const isUnderscore = code === 95\n\n if (!isLowercaseLetter && !isUnderscore) {\n throw new InvalidInputError(\n 'TYPEID_PREFIX_INVALID_CHARACTER',\n 'TypeID prefix must contain only lowercase ASCII letters and underscores',\n )\n }\n\n if ((i === 0 || i === prefix.length - 1) && !isLowercaseLetter) {\n throw new InvalidInputError('TYPEID_PREFIX_INVALID_BOUNDARY', 'TypeID prefix must start and end with a-z')\n }\n }\n}\n\nfunction decodeSuffixValue(suffix: string, index: number): number {\n const code = suffix.charCodeAt(index)\n const value = code < BASE32_DECODE.length ? BASE32_DECODE[code] : -1\n\n if (value === -1) {\n throw new ParseError(\n 'TYPEID_SUFFIX_INVALID_CHARACTER',\n `TypeID suffix contains invalid character at position ${index}`,\n )\n }\n\n return value\n}\n\nfunction assertValidSuffixShape(suffix: string): void {\n if (suffix.length !== TYPEID_SUFFIX_LENGTH) {\n throw new ParseError('TYPEID_SUFFIX_INVALID_LENGTH', `TypeID suffix must be 26 characters, got ${suffix.length}`)\n }\n\n if (suffix[0] > '7') {\n throw new ParseError('TYPEID_SUFFIX_OVERFLOW', 'TypeID suffix must encode a 128-bit value')\n }\n}\n\nfunction encodeBytesToSuffix(bytes: Uint8Array): string {\n if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {\n throw new InvalidInputError('TYPEID_UUID_BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`)\n }\n\n return (\n TYPEID_ALPHABET[(bytes[0] & 0xe0) >> 5] +\n TYPEID_ALPHABET[bytes[0] & 0x1f] +\n TYPEID_ALPHABET[(bytes[1] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[1] & 0x07) << 2) | ((bytes[2] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[2] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[2] & 0x01) << 4) | ((bytes[3] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[3] & 0x0f) << 1) | ((bytes[4] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[4] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[4] & 0x03) << 3) | ((bytes[5] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[5] & 0x1f] +\n TYPEID_ALPHABET[(bytes[6] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[6] & 0x07) << 2) | ((bytes[7] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[7] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[7] & 0x01) << 4) | ((bytes[8] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[8] & 0x0f) << 1) | ((bytes[9] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[9] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[9] & 0x03) << 3) | ((bytes[10] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[10] & 0x1f] +\n TYPEID_ALPHABET[(bytes[11] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[11] & 0x07) << 2) | ((bytes[12] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[12] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[12] & 0x01) << 4) | ((bytes[13] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[13] & 0x0f) << 1) | ((bytes[14] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[14] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[14] & 0x03) << 3) | ((bytes[15] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[15] & 0x1f]\n )\n}\n\nfunction decodeSuffixToBytes(suffix: string): Uint8Array {\n assertValidSuffixShape(suffix)\n\n const values = new Array<number>(TYPEID_SUFFIX_LENGTH)\n for (let i = 0; i < TYPEID_SUFFIX_LENGTH; i += 1) {\n values[i] = decodeSuffixValue(suffix, i)\n }\n\n const bytes = new Uint8Array(TYPEID_UUID_BYTE_LENGTH)\n bytes[0] = (values[0] << 5) | values[1]\n bytes[1] = (values[2] << 3) | (values[3] >> 2)\n bytes[2] = ((values[3] & 0x03) << 6) | (values[4] << 1) | (values[5] >> 4)\n bytes[3] = ((values[5] & 0x0f) << 4) | (values[6] >> 1)\n bytes[4] = ((values[6] & 0x01) << 7) | (values[7] << 2) | (values[8] >> 3)\n bytes[5] = ((values[8] & 0x07) << 5) | values[9]\n bytes[6] = (values[10] << 3) | (values[11] >> 2)\n bytes[7] = ((values[11] & 0x03) << 6) | (values[12] << 1) | (values[13] >> 4)\n bytes[8] = ((values[13] & 0x0f) << 4) | (values[14] >> 1)\n bytes[9] = ((values[14] & 0x01) << 7) | (values[15] << 2) | (values[16] >> 3)\n bytes[10] = ((values[16] & 0x07) << 5) | values[17]\n bytes[11] = (values[18] << 3) | (values[19] >> 2)\n bytes[12] = ((values[19] & 0x03) << 6) | (values[20] << 1) | (values[21] >> 4)\n bytes[13] = ((values[21] & 0x0f) << 4) | (values[22] >> 1)\n bytes[14] = ((values[22] & 0x01) << 7) | (values[23] << 2) | (values[24] >> 3)\n bytes[15] = ((values[24] & 0x07) << 5) | values[25]\n\n return bytes\n}\n\nfunction assertUuidV7Bytes(bytes: Uint8Array): void {\n if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {\n throw new InvalidInputError('TYPEID_UUID_BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`)\n }\n\n if (bytes[6] >> 4 !== 7 || (bytes[8] & 0xc0) !== 0x80) {\n throw new InvalidInputError('TYPEID_UUID_NOT_V7', 'TypeID UUID bytes must encode a UUID v7 value')\n }\n}\n\nfunction uuidV7BytesFromSuffix(suffix: string): Uint8Array {\n const bytes = decodeSuffixToBytes(suffix)\n assertUuidV7Bytes(bytes)\n return bytes\n}\n\nfunction uuidV7BytesFromUuid(uuid: string): Uint8Array {\n if (!uuidv7.isValid(uuid)) {\n throw new InvalidInputError('TYPEID_UUID_NOT_V7', 'TypeID can only wrap UUID v7 values')\n }\n\n return uuidv7.toBytes(uuid)\n}\n\nfunction parseTypeid(id: string): ParsedTypeid {\n const separatorIndex = id.lastIndexOf('_')\n\n if (separatorIndex === 0) {\n throw new ParseError('TYPEID_INVALID_FORMAT', 'TypeID must not start with \"_\"')\n }\n\n const prefix = separatorIndex === -1 ? '' : id.slice(0, separatorIndex)\n const suffix = separatorIndex === -1 ? id : id.slice(separatorIndex + 1)\n\n assertValidPrefix(prefix)\n const bytes = uuidV7BytesFromSuffix(suffix)\n\n return { prefix, suffix, bytes }\n}\n\nfunction joinPrefixAndSuffix(prefix: string, suffix: string): string {\n return prefix === '' ? suffix : `${prefix}_${suffix}`\n}\n\nfunction formatTypeidFromUuidV7Bytes(prefix: string, bytes: Uint8Array): string {\n assertValidPrefix(prefix)\n assertUuidV7Bytes(bytes)\n return joinPrefixAndSuffix(prefix, encodeBytesToSuffix(bytes))\n}\n\nfunction timestampFromUuidV7Bytes(bytes: Uint8Array): number {\n let msecs = 0\n for (let i = 0; i < 6; i += 1) {\n msecs = msecs * 256 + bytes[i]\n }\n return msecs\n}\n\nfunction typeidFn(prefix: string, options?: TypeidOptions): string {\n const bytes = uuidv7(options, new Uint8Array(TYPEID_UUID_BYTE_LENGTH))\n return formatTypeidFromUuidV7Bytes(prefix, bytes)\n}\n\nfunction typeidToBytes(id: string): Uint8Array {\n return parseTypeid(id).bytes\n}\n\nfunction typeidFromBytes(prefix: string, bytes: Uint8Array): string {\n return formatTypeidFromUuidV7Bytes(prefix, bytes)\n}\n\nfunction typeidToUuid(id: string): string {\n return uuidv7.fromBytes(typeidToBytes(id))\n}\n\nfunction typeidFromUuid(prefix: string, uuid: string): string {\n return formatTypeidFromUuidV7Bytes(prefix, uuidV7BytesFromUuid(uuid))\n}\n\nfunction timestamp(id: string): number {\n return timestampFromUuidV7Bytes(parseTypeid(id).bytes)\n}\n\nfunction prefix(id: string): string {\n return parseTypeid(id).prefix\n}\n\nfunction suffix(id: string): string {\n return parseTypeid(id).suffix\n}\n\nfunction isValid(id: unknown): id is string {\n if (typeof id !== 'string') {\n return false\n }\n\n try {\n parseTypeid(id)\n } catch {\n return false\n }\n\n return true\n}\n\n/**\n * Generate a TypeID string backed by UUID v7.\n *\n * TypeID combines a lowercase snake_case type prefix with a 26-character\n * modified base32 encoding of a UUID v7, producing sortable domain identifiers\n * such as `user_01h2xcejqtf2nbrexx3vqjhp41`.\n *\n * @example\n * ```ts\n * import { typeid } from 'uniku/typeid'\n *\n * const id = typeid('user')\n * // => \"user_01h2xcejqtf2nbrexx3vqjhp41\"\n *\n * const uuid = typeid.toUuid(id)\n * const restored = typeid.fromUuid('user', uuid)\n * ```\n */\nexport const typeid: Typeid = Object.assign(typeidFn, {\n toBytes: typeidToBytes,\n fromBytes: typeidFromBytes,\n toUuid: typeidToUuid,\n fromUuid: typeidFromUuid,\n timestamp,\n prefix,\n suffix,\n isValid,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"8IA2BA,MAEM,EAAkB,mCAElB,EAA0B,MAAM,KAAK,CAAE,OAAQ,GAAI,MAAS,EAAE,EACpE,IAAK,IAAI,EAAI,EAAG,EAAI,GAAwB,GAAK,EAC/C,EAAc,EAAgB,WAAW,CAAC,GAAK,EASjD,SAAS,EAAkB,EAAsB,CAC3C,KAAO,SAAW,EAItB,IAAI,EAAO,OAAS,GAClB,MAAM,IAAI,EAAkB,yBAA0B,6CAA6C,EAGrG,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,GAAK,EAAG,CACzC,IAAM,EAAO,EAAO,WAAW,CAAC,EAC1B,EAAoB,GAAQ,IAAM,GAAQ,IAGhD,GAAI,CAAC,GAFgB,IAAS,GAG5B,MAAM,IAAI,EACR,kCACA,yEACF,EAGF,IAAK,IAAM,GAAK,IAAM,EAAO,OAAS,IAAM,CAAC,EAC3C,MAAM,IAAI,EAAkB,iCAAkC,2CAA2C,CAE7G,CAlBqG,CAmBvG,CAEA,SAAS,EAAkB,EAAgB,EAAuB,CAChE,IAAM,EAAO,EAAO,WAAW,CAAK,EAC9B,EAAQ,EAAO,EAAc,OAAS,EAAc,GAAQ,GAElE,GAAI,IAAU,GACZ,MAAM,IAAI,EACR,kCACA,wDAAwD,GAC1D,EAGF,OAAO,CACT,CAEA,SAAS,EAAuB,EAAsB,CACpD,GAAI,EAAO,SAAW,GACpB,MAAM,IAAI,EAAW,+BAAgC,4CAA4C,EAAO,QAAQ,EAGlH,GAAI,EAAO,GAAK,IACd,MAAM,IAAI,EAAW,yBAA0B,2CAA2C,CAE9F,CAEA,SAAS,EAAoB,EAA2B,CACtD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAkB,mCAAoC,oCAAoC,EAAM,QAAQ,EAGpH,OACE,GAAiB,EAAM,GAAK,MAAS,GACrC,EAAgB,EAAM,GAAK,IAC3B,GAAiB,EAAM,GAAK,MAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAiB,EAAM,GAAK,KAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAkB,EAAM,GAAK,KAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAiB,EAAM,GAAK,MAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,GAAK,MAAS,GACjE,EAAgB,EAAM,GAAK,IAC3B,GAAiB,EAAM,GAAK,MAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAiB,EAAM,GAAK,KAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAkB,EAAM,GAAK,KAAS,GAAO,EAAM,GAAK,MAAS,GACjE,GAAiB,EAAM,GAAK,MAAS,GACrC,GAAkB,EAAM,GAAK,IAAS,GAAO,EAAM,IAAM,MAAS,GAClE,EAAgB,EAAM,IAAM,IAC5B,GAAiB,EAAM,IAAM,MAAS,GACtC,GAAkB,EAAM,IAAM,IAAS,GAAO,EAAM,IAAM,MAAS,GACnE,GAAiB,EAAM,IAAM,KAAS,GACtC,GAAkB,EAAM,IAAM,IAAS,GAAO,EAAM,IAAM,MAAS,GACnE,GAAkB,EAAM,IAAM,KAAS,GAAO,EAAM,IAAM,MAAS,GACnE,GAAiB,EAAM,IAAM,MAAS,GACtC,GAAkB,EAAM,IAAM,IAAS,GAAO,EAAM,IAAM,MAAS,GACnE,EAAgB,EAAM,IAAM,GAEhC,CAEA,SAAS,EAAoB,EAA4B,CACvD,EAAuB,CAAM,EAE7B,IAAM,EAAa,MAAc,EAAoB,EACrD,IAAK,IAAI,EAAI,EAAG,EAAI,GAAsB,GAAK,EAC7C,EAAO,GAAK,EAAkB,EAAQ,CAAC,EAGzC,IAAM,EAAQ,IAAI,WAAW,EAAuB,EAkBpD,MAjBA,GAAM,GAAM,EAAO,IAAM,EAAK,EAAO,GACrC,EAAM,GAAM,EAAO,IAAM,EAAM,EAAO,IAAM,EAC5C,EAAM,IAAO,EAAO,GAAK,IAAS,EAAM,EAAO,IAAM,EAAM,EAAO,IAAM,EACxE,EAAM,IAAO,EAAO,GAAK,KAAS,EAAM,EAAO,IAAM,EACrD,EAAM,IAAO,EAAO,GAAK,IAAS,EAAM,EAAO,IAAM,EAAM,EAAO,IAAM,EACxE,EAAM,IAAO,EAAO,GAAK,IAAS,EAAK,EAAO,GAC9C,EAAM,GAAM,EAAO,KAAO,EAAM,EAAO,KAAO,EAC9C,EAAM,IAAO,EAAO,IAAM,IAAS,EAAM,EAAO,KAAO,EAAM,EAAO,KAAO,EAC3E,EAAM,IAAO,EAAO,IAAM,KAAS,EAAM,EAAO,KAAO,EACvD,EAAM,IAAO,EAAO,IAAM,IAAS,EAAM,EAAO,KAAO,EAAM,EAAO,KAAO,EAC3E,EAAM,KAAQ,EAAO,IAAM,IAAS,EAAK,EAAO,IAChD,EAAM,IAAO,EAAO,KAAO,EAAM,EAAO,KAAO,EAC/C,EAAM,KAAQ,EAAO,IAAM,IAAS,EAAM,EAAO,KAAO,EAAM,EAAO,KAAO,EAC5E,EAAM,KAAQ,EAAO,IAAM,KAAS,EAAM,EAAO,KAAO,EACxD,EAAM,KAAQ,EAAO,IAAM,IAAS,EAAM,EAAO,KAAO,EAAM,EAAO,KAAO,EAC5E,EAAM,KAAQ,EAAO,IAAM,IAAS,EAAK,EAAO,IAEzC,CACT,CAEA,SAAS,EAAkB,EAAyB,CAClD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAkB,mCAAoC,oCAAoC,EAAM,QAAQ,EAGpH,GAAI,EAAM,IAAM,GAAM,IAAM,EAAM,GAAK,MAAU,IAC/C,MAAM,IAAI,EAAkB,qBAAsB,+CAA+C,CAErG,CAEA,SAAS,EAAsB,EAA4B,CACzD,IAAM,EAAQ,EAAoB,CAAM,EAExC,OADA,EAAkB,CAAK,EAChB,CACT,CAEA,SAAS,EAAoB,EAA0B,CACrD,GAAI,CAAC,EAAO,QAAQ,CAAI,EACtB,MAAM,IAAI,EAAkB,qBAAsB,qCAAqC,EAGzF,OAAO,EAAO,QAAQ,CAAI,CAC5B,CAEA,SAAS,EAAY,EAA0B,CAC7C,IAAM,EAAiB,EAAG,YAAY,GAAG,EAEzC,GAAI,IAAmB,EACrB,MAAM,IAAI,EAAW,wBAAyB,gCAAgC,EAGhF,IAAM,EAAS,IAAmB,GAAK,GAAK,EAAG,MAAM,EAAG,CAAc,EAChE,EAAS,IAAmB,GAAK,EAAK,EAAG,MAAM,EAAiB,CAAC,EAKvE,OAHA,EAAkB,CAAM,EAGjB,CAAE,SAAQ,SAAQ,MAFX,EAAsB,CAEP,CAAE,CACjC,CAEA,SAAS,EAAoB,EAAgB,EAAwB,CACnE,OAAO,IAAW,GAAK,EAAS,GAAG,EAAO,GAAG,GAC/C,CAEA,SAAS,EAA4B,EAAgB,EAA2B,CAG9E,OAFA,EAAkB,CAAM,EACxB,EAAkB,CAAK,EAChB,EAAoB,EAAQ,EAAoB,CAAK,CAAC,CAC/D,CAEA,SAAS,EAAyB,EAA2B,CAC3D,IAAI,EAAQ,EACZ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,GAAK,EAC1B,EAAQ,EAAQ,IAAM,EAAM,GAE9B,OAAO,CACT,CAEA,SAAS,EAAS,EAAgB,EAAiC,CAEjE,OAAO,EAA4B,EADrB,EAAO,EAAS,IAAI,WAAW,EAAuB,CACrB,CAAC,CAClD,CAEA,SAAS,EAAc,EAAwB,CAC7C,OAAO,EAAY,CAAE,CAAC,CAAC,KACzB,CAEA,SAAS,EAAgB,EAAgB,EAA2B,CAClE,OAAO,EAA4B,EAAQ,CAAK,CAClD,CAEA,SAAS,EAAa,EAAoB,CACxC,OAAO,EAAO,UAAU,EAAc,CAAE,CAAC,CAC3C,CAEA,SAAS,EAAe,EAAgB,EAAsB,CAC5D,OAAO,EAA4B,EAAQ,EAAoB,CAAI,CAAC,CACtE,CAEA,SAAS,EAAU,EAAoB,CACrC,OAAO,EAAyB,EAAY,CAAE,CAAC,CAAC,KAAK,CACvD,CAEA,SAAS,EAAO,EAAoB,CAClC,OAAO,EAAY,CAAE,CAAC,CAAC,MACzB,CAEA,SAAS,EAAO,EAAoB,CAClC,OAAO,EAAY,CAAE,CAAC,CAAC,MACzB,CAEA,SAAS,EAAQ,EAA2B,CAC1C,GAAI,OAAO,GAAO,SAChB,MAAO,GAGT,GAAI,CACF,EAAY,CAAE,CAChB,MAAQ,CACN,MAAO,EACT,CAEA,MAAO,EACT,CAoBA,MAAa,EAAiB,OAAO,OAAO,EAAU,CACpD,QAAS,EACT,UAAW,EACX,OAAQ,EACR,SAAU,EACV,YACA,SACA,SACA,SACF,CAAC"}
{"version":3,"file":"typeid.mjs","names":[],"sources":["../../src/typeid/typeid.ts"],"sourcesContent":["import { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError, ParseError } from '../errors'\nimport type { UuidV7Options } from '../uuid/v7'\nimport { uuidv7 } from '../uuid/v7'\n\nexport type TypeidOptions = UuidV7Options\n\nexport type Typeid = {\n /** Generate a TypeID from a lowercase entity prefix and a UUID v7 suffix. */\n (prefix: string, options?: TypeidOptions): string\n /** Generate a TypeID with explicit options or write its 16 canonical UUID v7 bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(\n prefix: string,\n options: TypeidOptions | undefined,\n buf: TBuf,\n offset?: number,\n ): TBuf\n /** Generate a TypeID string with optional timestamp, counter, or random bytes. */\n (prefix: string, options?: TypeidOptions, buf?: undefined, offset?: number): string\n /** Convert a TypeID's UUID v7 suffix to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Build a TypeID from a prefix and canonical UUID v7 bytes. */\n fromBytes(prefix: string, bytes: Uint8Array): string\n /** Convert a TypeID to its UUID v7 string. */\n toUuid(id: string): string\n /** Build a TypeID from a prefix and UUID v7 string. */\n fromUuid(prefix: string, uuid: string): string\n /** Read the UUID v7 timestamp embedded in a TypeID, in milliseconds. */\n timestamp(id: string): number\n /** Read a TypeID's entity prefix. */\n prefix(id: string): string\n /** Read a TypeID's UUID v7 suffix. */\n suffix(id: string): string\n /** Return whether a value is a syntactically valid TypeID. */\n isValid(id: unknown): id is string\n}\n\nconst TYPEID_SUFFIX_LENGTH = 26\nconst TYPEID_UUID_BYTE_LENGTH = 16\n// 48-bit UUID v7 timestamp capacity, mirrored from uuid/v7 alongside the\n// 32-bit counter capacity, so option validation is attributed to the typeid\n// boundary instead of leaking `strategy: 'uuid'` through delegation.\nconst MAX_MSECS = 0xffffffffffff\nconst MAX_COUNTER = 0xffffffff\nconst TYPEID_ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz'\n\nconst BASE32_DECODE: number[] = Array.from({ length: 128 }, () => -1)\nfor (let i = 0; i < TYPEID_ALPHABET.length; i += 1) {\n BASE32_DECODE[TYPEID_ALPHABET.charCodeAt(i)] = i\n}\n\ntype ParsedTypeid = {\n prefix: string\n suffix: string\n bytes: Uint8Array\n}\n\nfunction assertValidPrefix(prefix: string): void {\n if (prefix.length === 0) {\n return\n }\n\n if (prefix.length > 63) {\n throw new InvalidInputError('PREFIX_TOO_LONG', 'TypeID prefix must be at most 63 characters', {\n strategy: 'typeid',\n })\n }\n\n for (let i = 0; i < prefix.length; i += 1) {\n const code = prefix.charCodeAt(i)\n const isLowercaseLetter = code >= 97 && code <= 122\n const isUnderscore = code === 95\n\n if (!isLowercaseLetter && !isUnderscore) {\n throw new InvalidInputError(\n 'PREFIX_INVALID_CHAR',\n 'TypeID prefix must contain only lowercase ASCII letters and underscores',\n { strategy: 'typeid' },\n )\n }\n\n if ((i === 0 || i === prefix.length - 1) && !isLowercaseLetter) {\n throw new InvalidInputError('PREFIX_INVALID_BOUNDARY', 'TypeID prefix must start and end with a-z', {\n strategy: 'typeid',\n })\n }\n }\n}\n\nfunction decodeSuffixValue(suffix: string, index: number): number {\n const code = suffix.charCodeAt(index)\n const value = code < BASE32_DECODE.length ? BASE32_DECODE[code] : -1\n\n if (value === -1) {\n throw new ParseError('INVALID_CHAR', `TypeID suffix contains invalid character at position ${index}`, {\n strategy: 'typeid',\n })\n }\n\n return value\n}\n\nfunction assertValidSuffixShape(suffix: string): void {\n if (suffix.length !== TYPEID_SUFFIX_LENGTH) {\n throw new ParseError('INVALID_LENGTH', `TypeID suffix must be 26 characters, got ${suffix.length}`, {\n strategy: 'typeid',\n })\n }\n\n if (suffix[0] > '7') {\n throw new ParseError('VALUE_OUT_OF_RANGE', 'TypeID suffix must encode a 128-bit value', {\n strategy: 'typeid',\n })\n }\n}\n\nfunction encodeBytesToSuffix(bytes: Uint8Array): string {\n if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {\n throw new InvalidInputError('BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`, {\n strategy: 'typeid',\n })\n }\n\n return (\n TYPEID_ALPHABET[(bytes[0] & 0xe0) >> 5] +\n TYPEID_ALPHABET[bytes[0] & 0x1f] +\n TYPEID_ALPHABET[(bytes[1] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[1] & 0x07) << 2) | ((bytes[2] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[2] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[2] & 0x01) << 4) | ((bytes[3] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[3] & 0x0f) << 1) | ((bytes[4] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[4] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[4] & 0x03) << 3) | ((bytes[5] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[5] & 0x1f] +\n TYPEID_ALPHABET[(bytes[6] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[6] & 0x07) << 2) | ((bytes[7] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[7] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[7] & 0x01) << 4) | ((bytes[8] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[8] & 0x0f) << 1) | ((bytes[9] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[9] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[9] & 0x03) << 3) | ((bytes[10] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[10] & 0x1f] +\n TYPEID_ALPHABET[(bytes[11] & 0xf8) >> 3] +\n TYPEID_ALPHABET[((bytes[11] & 0x07) << 2) | ((bytes[12] & 0xc0) >> 6)] +\n TYPEID_ALPHABET[(bytes[12] & 0x3e) >> 1] +\n TYPEID_ALPHABET[((bytes[12] & 0x01) << 4) | ((bytes[13] & 0xf0) >> 4)] +\n TYPEID_ALPHABET[((bytes[13] & 0x0f) << 1) | ((bytes[14] & 0x80) >> 7)] +\n TYPEID_ALPHABET[(bytes[14] & 0x7c) >> 2] +\n TYPEID_ALPHABET[((bytes[14] & 0x03) << 3) | ((bytes[15] & 0xe0) >> 5)] +\n TYPEID_ALPHABET[bytes[15] & 0x1f]\n )\n}\n\nfunction decodeSuffixToBytes(suffix: string): Uint8Array {\n assertValidSuffixShape(suffix)\n\n const values = new Array<number>(TYPEID_SUFFIX_LENGTH)\n for (let i = 0; i < TYPEID_SUFFIX_LENGTH; i += 1) {\n values[i] = decodeSuffixValue(suffix, i)\n }\n\n const bytes = new Uint8Array(TYPEID_UUID_BYTE_LENGTH)\n bytes[0] = (values[0] << 5) | values[1]\n bytes[1] = (values[2] << 3) | (values[3] >> 2)\n bytes[2] = ((values[3] & 0x03) << 6) | (values[4] << 1) | (values[5] >> 4)\n bytes[3] = ((values[5] & 0x0f) << 4) | (values[6] >> 1)\n bytes[4] = ((values[6] & 0x01) << 7) | (values[7] << 2) | (values[8] >> 3)\n bytes[5] = ((values[8] & 0x07) << 5) | values[9]\n bytes[6] = (values[10] << 3) | (values[11] >> 2)\n bytes[7] = ((values[11] & 0x03) << 6) | (values[12] << 1) | (values[13] >> 4)\n bytes[8] = ((values[13] & 0x0f) << 4) | (values[14] >> 1)\n bytes[9] = ((values[14] & 0x01) << 7) | (values[15] << 2) | (values[16] >> 3)\n bytes[10] = ((values[16] & 0x07) << 5) | values[17]\n bytes[11] = (values[18] << 3) | (values[19] >> 2)\n bytes[12] = ((values[19] & 0x03) << 6) | (values[20] << 1) | (values[21] >> 4)\n bytes[13] = ((values[21] & 0x0f) << 4) | (values[22] >> 1)\n bytes[14] = ((values[22] & 0x01) << 7) | (values[23] << 2) | (values[24] >> 3)\n bytes[15] = ((values[24] & 0x07) << 5) | values[25]\n\n return bytes\n}\n\nfunction assertUuidV7Bytes(bytes: Uint8Array): void {\n if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {\n throw new InvalidInputError('BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`, {\n strategy: 'typeid',\n })\n }\n\n if (bytes[6] >> 4 !== 7 || (bytes[8] & 0xc0) !== 0x80) {\n throw new InvalidInputError('UUID_NOT_V7', 'TypeID UUID bytes must encode a UUID v7 value', {\n strategy: 'typeid',\n })\n }\n}\n\nfunction uuidV7BytesFromSuffix(suffix: string): Uint8Array {\n const bytes = decodeSuffixToBytes(suffix)\n assertUuidV7Bytes(bytes)\n return bytes\n}\n\nfunction uuidV7BytesFromUuid(uuid: string): Uint8Array {\n if (!uuidv7.isValid(uuid)) {\n throw new InvalidInputError('UUID_NOT_V7', 'TypeID can only wrap UUID v7 values', { strategy: 'typeid' })\n }\n\n return uuidv7.toBytes(uuid)\n}\n\nfunction parseTypeid(id: string): ParsedTypeid {\n const separatorIndex = id.lastIndexOf('_')\n\n if (separatorIndex === 0) {\n throw new ParseError('INVALID_FORMAT', 'TypeID must not start with \"_\"', { strategy: 'typeid' })\n }\n\n const prefix = separatorIndex === -1 ? '' : id.slice(0, separatorIndex)\n const suffix = separatorIndex === -1 ? id : id.slice(separatorIndex + 1)\n\n assertValidPrefix(prefix)\n const bytes = uuidV7BytesFromSuffix(suffix)\n\n return { prefix, suffix, bytes }\n}\n\nfunction joinPrefixAndSuffix(prefix: string, suffix: string): string {\n return prefix === '' ? suffix : `${prefix}_${suffix}`\n}\n\nfunction formatTypeidFromUuidV7Bytes(prefix: string, bytes: Uint8Array): string {\n assertValidPrefix(prefix)\n assertUuidV7Bytes(bytes)\n return joinPrefixAndSuffix(prefix, encodeBytesToSuffix(bytes))\n}\n\nfunction timestampFromUuidV7Bytes(bytes: Uint8Array): number {\n let msecs = 0\n for (let i = 0; i < 6; i += 1) {\n msecs = msecs * 256 + bytes[i]\n }\n return msecs\n}\n\n/**\n * Mirror uuid/v7's option validation at the typeid boundary, so failures are\n * attributed to `strategy: 'typeid'` instead of leaking `strategy: 'uuid'`\n * through delegation.\n */\nfunction validateTypeidOptions(options: TypeidOptions): void {\n const msecs = options.msecs\n if (msecs !== undefined && !isIntegerInRange(msecs, 0, MAX_MSECS)) {\n throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {\n strategy: 'typeid',\n })\n }\n\n if (options.counter !== undefined && options.seq !== undefined) {\n throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `counter` or `seq`, not both', {\n strategy: 'typeid',\n })\n }\n const counter = options.counter ?? options.seq\n if (counter !== undefined && !isIntegerInRange(counter, 0, MAX_COUNTER)) {\n throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be an integer between 0 and ${MAX_COUNTER}`, {\n strategy: 'typeid',\n })\n }\n\n const random = options.random\n if (random && random.length < TYPEID_UUID_BYTE_LENGTH) {\n throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${TYPEID_UUID_BYTE_LENGTH}`, {\n strategy: 'typeid',\n })\n }\n}\n\nfunction typeidFn(prefix: string, options?: TypeidOptions, buf?: undefined, offset?: number): string\nfunction typeidFn<TBuf extends Uint8Array = Uint8Array>(\n prefix: string,\n options: TypeidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction typeidFn<TBuf extends Uint8Array = Uint8Array>(\n prefix: string,\n options?: TypeidOptions,\n buf?: TBuf,\n offset = 0,\n): string | TBuf {\n if (options !== undefined) {\n validateTypeidOptions(options)\n }\n\n if (buf) {\n if (!isWritableRange(buf, offset, TYPEID_UUID_BYTE_LENGTH)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `TypeID byte range ${offset}:${offset + TYPEID_UUID_BYTE_LENGTH - 1} is out of buffer bounds`,\n { strategy: 'typeid' },\n )\n }\n assertValidPrefix(prefix)\n return uuidv7(options, buf, offset)\n }\n\n const bytes = uuidv7(options, new Uint8Array(TYPEID_UUID_BYTE_LENGTH))\n return formatTypeidFromUuidV7Bytes(prefix, bytes)\n}\n\nfunction typeidToBytes(id: string): Uint8Array {\n return parseTypeid(id).bytes\n}\n\nfunction typeidFromBytes(prefix: string, bytes: Uint8Array): string {\n return formatTypeidFromUuidV7Bytes(prefix, bytes)\n}\n\nfunction typeidToUuid(id: string): string {\n return uuidv7.fromBytes(typeidToBytes(id))\n}\n\nfunction typeidFromUuid(prefix: string, uuid: string): string {\n return formatTypeidFromUuidV7Bytes(prefix, uuidV7BytesFromUuid(uuid))\n}\n\nfunction timestamp(id: string): number {\n return timestampFromUuidV7Bytes(parseTypeid(id).bytes)\n}\n\nfunction prefix(id: string): string {\n return parseTypeid(id).prefix\n}\n\nfunction suffix(id: string): string {\n return parseTypeid(id).suffix\n}\n\nfunction isValid(id: unknown): id is string {\n if (typeof id !== 'string') {\n return false\n }\n\n try {\n parseTypeid(id)\n } catch {\n return false\n }\n\n return true\n}\n\n/**\n * Generate a TypeID string backed by UUID v7.\n *\n * TypeID combines a lowercase snake_case type prefix with a 26-character\n * modified base32 encoding of a UUID v7, producing sortable domain identifiers\n * such as `user_01h2xcejqtf2nbrexx3vqjhp41`.\n *\n * @example\n * ```ts\n * import { typeid } from 'uniku/typeid'\n *\n * const id = typeid('user')\n * // => \"user_01h2xcejqtf2nbrexx3vqjhp41\"\n *\n * const uuid = typeid.toUuid(id)\n * const restored = typeid.fromUuid('user', uuid)\n * ```\n */\nexport const typeid: Typeid = Object.assign(typeidFn, {\n toBytes: typeidToBytes,\n fromBytes: typeidFromBytes,\n toUuid: typeidToUuid,\n fromUuid: typeidFromUuid,\n timestamp,\n prefix,\n suffix,\n isValid,\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -3,0 +3,0 @@ //#region src/ulid/ulid.d.ts

@@ -1,1 +0,1 @@

{"version":3,"file":"ulid.d.mts","names":[],"sources":["../../src/ulid/ulid.ts"],"mappings":";;;KAMY,WAAA;;;AAAZ;;EAKE,MAAA,GAAS,UAAA;EAAA;;;;EAKT,KAAA;AAAA;AAAA,KAGU,IAAA;EAAA;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,WAAA,cAAyB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAErG,OAAA,GAAU,WAAA,EAAa,GAAA,cAAiB,MAAA;EAEzC,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA,WAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;cA+JW,IAAA,EAAM,IAAA"}
{"version":3,"file":"ulid.d.mts","names":[],"sources":["../../src/ulid/ulid.ts"],"mappings":";;;KAMY,WAAA;;;AAAZ;;EAKE,MAAA,GAAS,UAAA;EAAA;;;;EAKT,KAAA;AAAA;AAAA,KAGU,IAAA;EAAA;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,WAAA,cAAyB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAErG,OAAA,GAAU,WAAA,EAAa,GAAA,cAAiB,MAAA;EAEzC,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA,WAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;cAmKW,IAAA,EAAM,IAAA"}

@@ -1,2 +0,2 @@

import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";import{r as s,t as c}from"../bytes-xqWxFYsM.mjs";const l=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,u=new Uint8Array(65536);u.fill(255);for(let e=0;e<32;e+=1){let t=l.charCodeAt(e),n=l[e].toLowerCase().charCodeAt(0);u[t]=e,u[n]=e}function d(e,t){return new a(`ULID_INVALID_CHAR`,`Invalid ULID character: ${e[t]}`)}function f(){return new a(`ULID_TIMESTAMP_OVERFLOW`,`ULID timestamp exceeds 48 bits`)}function p(e){let t=u[e.charCodeAt(0)];if(t===255)throw d(e,0);if(t>7)throw f();let n=t;for(let t=1;t<10;t+=1){let r=u[e.charCodeAt(t)];if(r===255)throw d(e,t);n=n*32+r}return n}function m(e){return l[Math.floor(e/35184372088832)&31]+l[Math.floor(e/1099511627776)&31]+l[Math.floor(e/34359738368)&31]+l[Math.floor(e/1073741824)&31]+l[Math.floor(e/33554432)&31]+l[Math.floor(e/1048576)&31]+l[Math.floor(e/32768)&31]+l[Math.floor(e/1024)&31]+l[Math.floor(e/32)&31]+l[e&31]}function h(e){return l[e[0]>>3&31]+l[(e[0]<<2|e[1]>>6)&31]+l[e[1]>>1&31]+l[(e[1]<<4|e[2]>>4)&31]+l[(e[2]<<1|e[3]>>7)&31]+l[e[3]>>2&31]+l[(e[3]<<3|e[4]>>5)&31]+l[e[4]&31]+l[e[5]>>3&31]+l[(e[5]<<2|e[6]>>6)&31]+l[e[6]>>1&31]+l[(e[6]<<4|e[7]>>4)&31]+l[(e[7]<<1|e[8]>>7)&31]+l[e[8]>>2&31]+l[(e[8]<<3|e[9]>>5)&31]+l[e[9]&31]}function g(e){if(e.length!==26)throw new a(`ULID_INVALID_LENGTH`,`ULID string must be 26 characters`);return p(e)}function _(e){if(e.length!==26)throw new a(`ULID_INVALID_LENGTH`,`ULID string must be 26 characters`);let t=new Uint8Array(16),n=u[e.charCodeAt(0)],r=u[e.charCodeAt(1)],i=u[e.charCodeAt(2)],o=u[e.charCodeAt(3)],s=u[e.charCodeAt(4)],c=u[e.charCodeAt(5)],l=u[e.charCodeAt(6)],p=u[e.charCodeAt(7)],m=u[e.charCodeAt(8)],h=u[e.charCodeAt(9)],g=u[e.charCodeAt(10)],_=u[e.charCodeAt(11)],v=u[e.charCodeAt(12)],y=u[e.charCodeAt(13)],b=u[e.charCodeAt(14)],x=u[e.charCodeAt(15)],S=u[e.charCodeAt(16)],C=u[e.charCodeAt(17)],w=u[e.charCodeAt(18)],T=u[e.charCodeAt(19)],E=u[e.charCodeAt(20)],D=u[e.charCodeAt(21)],O=u[e.charCodeAt(22)],k=u[e.charCodeAt(23)],A=u[e.charCodeAt(24)],j=u[e.charCodeAt(25)];if((n|r|i|o|s|c|l|p|m|h|g|_|v|y|b|x|S|C|w|T|E|D|O|k|A|j)&128){for(let t=0;t<26;t+=1)if(u[e.charCodeAt(t)]===255)throw d(e,t)}if(n>7)throw f();return t[0]=n<<5|r,t[1]=i<<3|o>>2,t[2]=o<<6|s<<1|c>>4,t[3]=c<<4|l>>1,t[4]=l<<7|p<<2|m>>3,t[5]=m<<5|h,t[6]=g<<3|_>>2,t[7]=_<<6|v<<1|y>>4,t[8]=y<<4|b>>1,t[9]=b<<7|x<<2|S>>3,t[10]=S<<5|C,t[11]=w<<3|T>>2,t[12]=T<<6|E<<1|D>>4,t[13]=D<<4|O>>1,t[14]=O<<7|k<<2|A>>3,t[15]=A<<5|j,t}function v(e){if(e.length!==16)throw new r(`ULID_BYTES_INVALID_LENGTH`,`ULID bytes must be exactly 16 bytes, got ${e.length}`);let t=0;for(let n=0;n<6;n+=1)t=t*256+e[n];return m(t)+h(e.subarray(6,16))}const y=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i,b=0xffffffffffff,x={msecs:-1/0,lastRandom:new Uint8Array(10)};function S(e,t,n,r){s(n,r,e);for(let e=0;e<10;e+=1)n[r+6+e]=t[e]}function C(e,n,i,a){if(!t(i,a,16))throw new r(`ULID_BUFFER_OUT_OF_BOUNDS`,`ULID byte range ${a}:${a+16-1} is out of buffer bounds`);S(e,n,i,a)}function w(t,r,a=0){let o,s;if(t){let r=t.msecs;if(r!==void 0&&!n(r,0,b))throw new i(`ULID_TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between 0 and ${b}`);o=r??Date.now();let a=t.random;if(a){if(a.length<10)throw new i(`ULID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 10 for ULID`);s=a}else s=e()}else if(o=Date.now(),o>x.msecs)s=e(),x.msecs=o,x.lastRandom.set(s.subarray(0,10));else{if(o=x.msecs,!c(x.lastRandom))throw x.lastRandom.fill(255),new i(`ULID_RANDOM_OVERFLOW`,`ULID random component overflowed while preserving monotonic order`);s=x.lastRandom}return r?(C(o,s,r,a),r):m(o)+h(s)}function T(e){return typeof e==`string`&&y.test(e)}const E=Object.assign(w,{toBytes:e=>_(e),fromBytes:e=>v(e),timestamp:e=>g(e),isValid:T,NIL:`00000000000000000000000000`,MAX:`7ZZZZZZZZZZZZZZZZZZZZZZZZZ`});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,E as ulid};
import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";import{r as s,t as c}from"../bytes-xqWxFYsM.mjs";const l=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,u=new Uint8Array(65536);u.fill(255);for(let e=0;e<32;e+=1){let t=l.charCodeAt(e),n=l[e].toLowerCase().charCodeAt(0);u[t]=e,u[n]=e}function d(e,t){return new a(`INVALID_CHAR`,`Invalid ULID character: ${e[t]}`,{strategy:`ulid`})}function f(){return new a(`TIMESTAMP_OUT_OF_RANGE`,`ULID timestamp exceeds 48 bits`,{strategy:`ulid`})}function p(e){let t=u[e.charCodeAt(0)];if(t===255)throw d(e,0);if(t>7)throw f();let n=t;for(let t=1;t<10;t+=1){let r=u[e.charCodeAt(t)];if(r===255)throw d(e,t);n=n*32+r}return n}function m(e){return l[Math.floor(e/35184372088832)&31]+l[Math.floor(e/1099511627776)&31]+l[Math.floor(e/34359738368)&31]+l[Math.floor(e/1073741824)&31]+l[Math.floor(e/33554432)&31]+l[Math.floor(e/1048576)&31]+l[Math.floor(e/32768)&31]+l[Math.floor(e/1024)&31]+l[Math.floor(e/32)&31]+l[e&31]}function h(e){return l[e[0]>>3&31]+l[(e[0]<<2|e[1]>>6)&31]+l[e[1]>>1&31]+l[(e[1]<<4|e[2]>>4)&31]+l[(e[2]<<1|e[3]>>7)&31]+l[e[3]>>2&31]+l[(e[3]<<3|e[4]>>5)&31]+l[e[4]&31]+l[e[5]>>3&31]+l[(e[5]<<2|e[6]>>6)&31]+l[e[6]>>1&31]+l[(e[6]<<4|e[7]>>4)&31]+l[(e[7]<<1|e[8]>>7)&31]+l[e[8]>>2&31]+l[(e[8]<<3|e[9]>>5)&31]+l[e[9]&31]}function g(e){if(e.length!==26)throw new a(`INVALID_LENGTH`,`ULID string must be 26 characters`,{strategy:`ulid`});return p(e)}function _(e){if(e.length!==26)throw new a(`INVALID_LENGTH`,`ULID string must be 26 characters`,{strategy:`ulid`});let t=new Uint8Array(16),n=u[e.charCodeAt(0)],r=u[e.charCodeAt(1)],i=u[e.charCodeAt(2)],o=u[e.charCodeAt(3)],s=u[e.charCodeAt(4)],c=u[e.charCodeAt(5)],l=u[e.charCodeAt(6)],p=u[e.charCodeAt(7)],m=u[e.charCodeAt(8)],h=u[e.charCodeAt(9)],g=u[e.charCodeAt(10)],_=u[e.charCodeAt(11)],v=u[e.charCodeAt(12)],y=u[e.charCodeAt(13)],b=u[e.charCodeAt(14)],x=u[e.charCodeAt(15)],S=u[e.charCodeAt(16)],C=u[e.charCodeAt(17)],w=u[e.charCodeAt(18)],T=u[e.charCodeAt(19)],E=u[e.charCodeAt(20)],D=u[e.charCodeAt(21)],O=u[e.charCodeAt(22)],k=u[e.charCodeAt(23)],A=u[e.charCodeAt(24)],j=u[e.charCodeAt(25)];if((n|r|i|o|s|c|l|p|m|h|g|_|v|y|b|x|S|C|w|T|E|D|O|k|A|j)&128){for(let t=0;t<26;t+=1)if(u[e.charCodeAt(t)]===255)throw d(e,t)}if(n>7)throw f();return t[0]=n<<5|r,t[1]=i<<3|o>>2,t[2]=o<<6|s<<1|c>>4,t[3]=c<<4|l>>1,t[4]=l<<7|p<<2|m>>3,t[5]=m<<5|h,t[6]=g<<3|_>>2,t[7]=_<<6|v<<1|y>>4,t[8]=y<<4|b>>1,t[9]=b<<7|x<<2|S>>3,t[10]=S<<5|C,t[11]=w<<3|T>>2,t[12]=T<<6|E<<1|D>>4,t[13]=D<<4|O>>1,t[14]=O<<7|k<<2|A>>3,t[15]=A<<5|j,t}function v(e){if(e.length!==16)throw new r(`BYTES_INVALID_LENGTH`,`ULID bytes must be exactly 16 bytes, got ${e.length}`,{strategy:`ulid`});let t=0;for(let n=0;n<6;n+=1)t=t*256+e[n];return m(t)+h(e.subarray(6,16))}const y=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i,b=0xffffffffffff,x={msecs:-1/0,lastRandom:new Uint8Array(10)};function S(e,t,n,r){s(n,r,e);for(let e=0;e<10;e+=1)n[r+6+e]=t[e]}function C(e,n,i,a){if(!t(i,a,16))throw new r(`BUFFER_OUT_OF_BOUNDS`,`ULID byte range ${a}:${a+16-1} is out of buffer bounds`,{strategy:`ulid`});S(e,n,i,a)}function w(t,r,a=0){let o,s;if(t){let r=t.msecs;if(r!==void 0&&!n(r,0,b))throw new i(`TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between 0 and ${b}`,{strategy:`ulid`});o=r??Date.now();let a=t.random;if(a){if(a.length<10)throw new i(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 10 for ULID`,{strategy:`ulid`});s=a}else s=e()}else if(o=Date.now(),o>x.msecs)s=e(),x.msecs=o,x.lastRandom.set(s.subarray(0,10));else{if(o=x.msecs,!c(x.lastRandom))throw x.lastRandom.fill(255),new i(`RANDOM_OVERFLOW`,`ULID random component overflowed while preserving monotonic order`,{strategy:`ulid`});s=x.lastRandom}return r?(C(o,s,r,a),r):m(o)+h(s)}function T(e){return typeof e==`string`&&y.test(e)}const E=Object.assign(w,{toBytes:e=>_(e),fromBytes:e=>v(e),timestamp:e=>g(e),isValid:T,NIL:`00000000000000000000000000`,MAX:`7ZZZZZZZZZZZZZZZZZZZZZZZZZ`});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,E as ulid};
//# sourceMappingURL=ulid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/ulid/crockford.ts","../../src/ulid/ulid.ts"],"sourcesContent":["/**\n * Crockford's Base32 encoding/decoding for ULID.\n * Alphabet excludes I, L, O, U to avoid confusion with similar-looking characters.\n */\n\nimport { BufferError, ParseError } from '../errors'\n\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'\n\n// Pre-computed decoding table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 64 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\nfor (let i = 0; i < ENCODING.length; i += 1) {\n const upper = ENCODING.charCodeAt(i)\n const lower = ENCODING[i].toLowerCase().charCodeAt(0)\n DECODING[upper] = i\n DECODING[lower] = i\n}\n\nconst TIME_LEN = 10\nconst ULID_LEN = 26\n\nfunction invalidCharError(str: string, index: number): ParseError {\n return new ParseError('ULID_INVALID_CHAR', `Invalid ULID character: ${str[index]}`)\n}\n\nfunction timestampOverflowError(): ParseError {\n return new ParseError('ULID_TIMESTAMP_OVERFLOW', 'ULID timestamp exceeds 48 bits')\n}\n\nfunction decodeTimeChars(str: string): number {\n const firstValue = DECODING[str.charCodeAt(0)]\n if (firstValue === 255) {\n throw invalidCharError(str, 0)\n }\n\n if (firstValue > 7) {\n throw timestampOverflowError()\n }\n\n let time = firstValue\n for (let i = 1; i < TIME_LEN; i += 1) {\n const value = DECODING[str.charCodeAt(i)]\n if (value === 255) {\n throw invalidCharError(str, i)\n }\n\n time = time * 32 + value\n }\n return time\n}\n\n/**\n * Encode a 48-bit timestamp to a 10-character Crockford Base32 string.\n * Uses unrolled division for performance.\n */\nexport function encodeTime(time: number): string {\n // Unrolled encoding - each step divides by 32 and extracts 5 bits\n // Powers of 32: 32^9=0x200000000000, 32^8=0x10000000000, etc.\n return (\n ENCODING[Math.floor(time / 0x200000000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x10000000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x800000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x40000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x2000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x100000) & 0x1f] +\n ENCODING[Math.floor(time / 0x8000) & 0x1f] +\n ENCODING[Math.floor(time / 0x400) & 0x1f] +\n ENCODING[Math.floor(time / 0x20) & 0x1f] +\n ENCODING[time & 0x1f]\n )\n}\n\n/**\n * Encode 10 bytes (80 bits) of random data to a 16-character Crockford Base32 string.\n */\nexport function encodeRandom(bytes: Uint8Array): string {\n // Each character encodes 5 bits. 80 bits = 16 characters.\n // Single concatenation expression for optimal performance.\n return (\n ENCODING[(bytes[0] >> 3) & 0x1f] +\n ENCODING[((bytes[0] << 2) | (bytes[1] >> 6)) & 0x1f] +\n ENCODING[(bytes[1] >> 1) & 0x1f] +\n ENCODING[((bytes[1] << 4) | (bytes[2] >> 4)) & 0x1f] +\n ENCODING[((bytes[2] << 1) | (bytes[3] >> 7)) & 0x1f] +\n ENCODING[(bytes[3] >> 2) & 0x1f] +\n ENCODING[((bytes[3] << 3) | (bytes[4] >> 5)) & 0x1f] +\n ENCODING[bytes[4] & 0x1f] +\n ENCODING[(bytes[5] >> 3) & 0x1f] +\n ENCODING[((bytes[5] << 2) | (bytes[6] >> 6)) & 0x1f] +\n ENCODING[(bytes[6] >> 1) & 0x1f] +\n ENCODING[((bytes[6] << 4) | (bytes[7] >> 4)) & 0x1f] +\n ENCODING[((bytes[7] << 1) | (bytes[8] >> 7)) & 0x1f] +\n ENCODING[(bytes[8] >> 2) & 0x1f] +\n ENCODING[((bytes[8] << 3) | (bytes[9] >> 5)) & 0x1f] +\n ENCODING[bytes[9] & 0x1f]\n )\n}\n\n/**\n * Decode a 10-character ULID timestamp string to Unix epoch milliseconds.\n */\nexport function decodeTime(str: string): number {\n if (str.length !== TIME_LEN) {\n throw new ParseError('ULID_INVALID_LENGTH', `ULID timestamp must be ${TIME_LEN} characters`)\n }\n return decodeTimeChars(str)\n}\n\n/**\n * Decode the timestamp from a full 26-character ULID string.\n */\nexport function decodeUlidTime(str: string): number {\n if (str.length !== ULID_LEN) {\n throw new ParseError('ULID_INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`)\n }\n return decodeTimeChars(str)\n}\n\n/**\n * Decode a 26-character ULID string to 16 bytes.\n * Inlines all lookups to avoid intermediate array allocation.\n */\nexport function decodeToBytes(str: string): Uint8Array {\n if (str.length !== ULID_LEN) {\n throw new ParseError('ULID_INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`)\n }\n\n const bytes = new Uint8Array(16)\n\n // Inline all 26 character lookups\n const v0 = DECODING[str.charCodeAt(0)]\n const v1 = DECODING[str.charCodeAt(1)]\n const v2 = DECODING[str.charCodeAt(2)]\n const v3 = DECODING[str.charCodeAt(3)]\n const v4 = DECODING[str.charCodeAt(4)]\n const v5 = DECODING[str.charCodeAt(5)]\n const v6 = DECODING[str.charCodeAt(6)]\n const v7 = DECODING[str.charCodeAt(7)]\n const v8 = DECODING[str.charCodeAt(8)]\n const v9 = DECODING[str.charCodeAt(9)]\n const v10 = DECODING[str.charCodeAt(10)]\n const v11 = DECODING[str.charCodeAt(11)]\n const v12 = DECODING[str.charCodeAt(12)]\n const v13 = DECODING[str.charCodeAt(13)]\n const v14 = DECODING[str.charCodeAt(14)]\n const v15 = DECODING[str.charCodeAt(15)]\n const v16 = DECODING[str.charCodeAt(16)]\n const v17 = DECODING[str.charCodeAt(17)]\n const v18 = DECODING[str.charCodeAt(18)]\n const v19 = DECODING[str.charCodeAt(19)]\n const v20 = DECODING[str.charCodeAt(20)]\n const v21 = DECODING[str.charCodeAt(21)]\n const v22 = DECODING[str.charCodeAt(22)]\n const v23 = DECODING[str.charCodeAt(23)]\n const v24 = DECODING[str.charCodeAt(24)]\n const v25 = DECODING[str.charCodeAt(25)]\n\n // Validate all characters at once (255 = invalid marker, so any invalid\n // character sets the 0x80 bit in the OR of all values)\n if (\n ((v0 |\n v1 |\n v2 |\n v3 |\n v4 |\n v5 |\n v6 |\n v7 |\n v8 |\n v9 |\n v10 |\n v11 |\n v12 |\n v13 |\n v14 |\n v15 |\n v16 |\n v17 |\n v18 |\n v19 |\n v20 |\n v21 |\n v22 |\n v23 |\n v24 |\n v25) &\n 0x80) !==\n 0\n ) {\n // Find the invalid character for error message\n for (let i = 0; i < ULID_LEN; i += 1) {\n if (DECODING[str.charCodeAt(i)] === 255) {\n throw invalidCharError(str, i)\n }\n }\n }\n\n if (v0 > 7) {\n throw timestampOverflowError()\n }\n\n // Timestamp: first 10 characters -> bytes 0-5\n bytes[0] = (v0 << 5) | v1\n bytes[1] = (v2 << 3) | (v3 >> 2)\n bytes[2] = (v3 << 6) | (v4 << 1) | (v5 >> 4)\n bytes[3] = (v5 << 4) | (v6 >> 1)\n bytes[4] = (v6 << 7) | (v7 << 2) | (v8 >> 3)\n bytes[5] = (v8 << 5) | v9\n\n // Random: last 16 characters -> bytes 6-15\n bytes[6] = (v10 << 3) | (v11 >> 2)\n bytes[7] = (v11 << 6) | (v12 << 1) | (v13 >> 4)\n bytes[8] = (v13 << 4) | (v14 >> 1)\n bytes[9] = (v14 << 7) | (v15 << 2) | (v16 >> 3)\n bytes[10] = (v16 << 5) | v17\n bytes[11] = (v18 << 3) | (v19 >> 2)\n bytes[12] = (v19 << 6) | (v20 << 1) | (v21 >> 4)\n bytes[13] = (v21 << 4) | (v22 >> 1)\n bytes[14] = (v22 << 7) | (v23 << 2) | (v24 >> 3)\n bytes[15] = (v24 << 5) | v25\n\n return bytes\n}\n\n/**\n * Encode 16 bytes to a 26-character ULID string.\n */\nexport function bytesToUlid(bytes: Uint8Array): string {\n if (bytes.length !== 16) {\n throw new BufferError('ULID_BYTES_INVALID_LENGTH', `ULID bytes must be exactly 16 bytes, got ${bytes.length}`)\n }\n\n // Timestamp: bytes 0-5 -> 10 characters\n let time = 0\n for (let i = 0; i < 6; i += 1) {\n time = time * 256 + bytes[i]\n }\n const timeStr = encodeTime(time)\n\n // Random: bytes 6-15 -> 16 characters\n const randomStr = encodeRandom(bytes.subarray(6, 16))\n\n return timeStr + randomStr\n}\n","import { incrementBytesInPlace, writeTimestamp48 } from '../common/bytes'\nimport { rng } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { bytesToUlid, decodeToBytes, decodeUlidTime, encodeRandom, encodeTime } from './crockford'\n\nexport type UlidOptions = {\n /**\n * 16 bytes of random data to use for ULID generation.\n * Only the first 10 bytes are used.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n}\n\nexport type Ulid = {\n /** Generate a time-ordered ULID string. */\n (): string\n /** Generate a ULID with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UlidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a ULID string with optional timestamp or random bytes. */\n (options?: UlidOptions, buf?: undefined, offset?: number): string\n /** Convert a ULID string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical ULID bytes to a ULID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid ULID string. */\n isValid(id: unknown): id is string\n /** The nil ULID (all zeros) */\n NIL: string\n /** The max ULID (maximum valid value) */\n MAX: string\n}\n\n// Validation regex: first char [0-7] to prevent overflow, rest from Crockford alphabet\nconst ULID_REGEX = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i\nconst ULID_BYTES = 16\nconst RANDOM_BYTES = 10\nconst MAX_MSECS = 0xffffffffffff\n\ntype UlidState = {\n msecs: number\n lastRandom: Uint8Array\n}\n\n/**\n * Module-level state for maintaining monotonic ordering within the same millisecond.\n *\n * IMPORTANT: This state persists across all ulid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs` and `random` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: UlidState = {\n msecs: -Infinity,\n lastRandom: new Uint8Array(RANDOM_BYTES),\n}\n\nfunction writeUlidBytesUnchecked(time: number, random: Uint8Array, buf: Uint8Array, offset: number): void {\n // Timestamp (48-bit big-endian milliseconds since Unix epoch) -> bytes 0-5\n writeTimestamp48(buf, offset, time)\n\n // Random (80 bits) -> bytes 6-15\n for (let i = 0; i < RANDOM_BYTES; i += 1) {\n buf[offset + 6 + i] = random[i]\n }\n}\n\nfunction writeUlidBytes(time: number, random: Uint8Array, buf: Uint8Array, offset: number): void {\n if (!isWritableRange(buf, offset, ULID_BYTES)) {\n throw new BufferError(\n 'ULID_BUFFER_OUT_OF_BOUNDS',\n `ULID byte range ${offset}:${offset + ULID_BYTES - 1} is out of buffer bounds`,\n )\n }\n writeUlidBytesUnchecked(time, random, buf, offset)\n}\n\n/*\n * Overload: no buffer => return a ULID string.\n */\nfunction ulidFn(options?: UlidOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with ULID bytes.\n */\nfunction ulidFn<TBuf extends Uint8Array = Uint8Array>(\n options: UlidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction ulidFn<TBuf extends Uint8Array = Uint8Array>(options?: UlidOptions, buf?: TBuf, offset = 0): string | TBuf {\n let time: number\n let random: Uint8Array\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all ULIDs generated within a single request will have the same timestamp.\n * - the monotonic ordering will rely entirely on incrementing the random portion.\n */\n if (options) {\n // Explicit options provided - use them directly without monotonic state\n const optMsecs = options.msecs\n if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {\n throw new InvalidInputError(\n 'ULID_TIMESTAMP_OUT_OF_RANGE',\n `Timestamp must be an integer between 0 and ${MAX_MSECS}`,\n )\n }\n time = optMsecs ?? Date.now()\n const optRandom = options.random\n if (optRandom) {\n if (optRandom.length < RANDOM_BYTES) {\n throw new InvalidInputError(\n 'ULID_RANDOM_BYTES_TOO_SHORT',\n `Random bytes length must be >= ${RANDOM_BYTES} for ULID`,\n )\n }\n random = optRandom\n } else {\n random = rng()\n }\n } else {\n time = Date.now()\n\n if (time > state.msecs) {\n // New millisecond: generate fresh random\n random = rng()\n state.msecs = time\n state.lastRandom.set(random.subarray(0, RANDOM_BYTES))\n } else {\n // Same millisecond or clock rollback: preserve last timestamp and increment random portion.\n time = state.msecs\n if (!incrementBytesInPlace(state.lastRandom)) {\n state.lastRandom.fill(0xff)\n throw new InvalidInputError(\n 'ULID_RANDOM_OVERFLOW',\n 'ULID random component overflowed while preserving monotonic order',\n )\n }\n random = state.lastRandom\n }\n }\n\n if (buf) {\n writeUlidBytes(time, random, buf, offset)\n return buf\n }\n\n // String mode: encode directly without buffer allocation\n return encodeTime(time) + encodeRandom(random)\n}\n\n/**\n * Generate a ULID string or write the bytes into a buffer.\n *\n * ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit\n * identifier with millisecond timestamp precision and 80 bits of randomness.\n * ULIDs are URL-safe, use Crockford's Base32 encoding, and sort lexicographically\n * by creation time.\n *\n * @example\n * ```ts\n * import { ulid } from 'uniku/ulid'\n *\n * const id = ulid()\n * // => \"01HW9T2W9W9YJ3JZ1H4P4M2T8Q\"\n *\n * // Extract timestamp\n * const ts = ulid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * ulid.isValid(id) // true\n *\n * // Convert to/from bytes (16 bytes)\n * const bytes = ulid.toBytes(id)\n * const restored = ulid.fromBytes(bytes)\n * ```\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && ULID_REGEX.test(id)\n}\n\n/**\n * Generate a ULID string or write its 16 canonical bytes into a buffer.\n * ULIDs are URL-safe, carry a millisecond timestamp, and sort by creation time.\n */\nexport const ulid: Ulid = Object.assign(ulidFn, {\n toBytes: (id: string) => decodeToBytes(id),\n fromBytes: (bytes: Uint8Array) => bytesToUlid(bytes),\n timestamp: (id: string) => decodeUlidTime(id),\n isValid,\n NIL: '00000000000000000000000000',\n MAX: '7ZZZZZZZZZZZZZZZZZZZZZZZZZ',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/ulid/crockford.ts","../../src/ulid/ulid.ts"],"sourcesContent":["/**\n * Crockford's Base32 encoding/decoding for ULID.\n * Alphabet excludes I, L, O, U to avoid confusion with similar-looking characters.\n */\n\nimport { BufferError, ParseError } from '../errors'\n\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'\n\n// Pre-computed decoding table covering every UTF-16 code unit charCodeAt can\n// return, so lookups never go out of bounds and a single `=== 255` check\n// rejects invalid input (including non-ASCII) without a per-character range\n// check. Costs 64 KiB once at module load; valid inputs only touch the first\n// 128 bytes, so cache behavior is unaffected.\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255) // 255 = invalid marker\nfor (let i = 0; i < ENCODING.length; i += 1) {\n const upper = ENCODING.charCodeAt(i)\n const lower = ENCODING[i].toLowerCase().charCodeAt(0)\n DECODING[upper] = i\n DECODING[lower] = i\n}\n\nconst TIME_LEN = 10\nconst ULID_LEN = 26\n\nfunction invalidCharError(str: string, index: number): ParseError {\n return new ParseError('INVALID_CHAR', `Invalid ULID character: ${str[index]}`, { strategy: 'ulid' })\n}\n\nfunction timestampOverflowError(): ParseError {\n return new ParseError('TIMESTAMP_OUT_OF_RANGE', 'ULID timestamp exceeds 48 bits', { strategy: 'ulid' })\n}\n\nfunction decodeTimeChars(str: string): number {\n const firstValue = DECODING[str.charCodeAt(0)]\n if (firstValue === 255) {\n throw invalidCharError(str, 0)\n }\n\n if (firstValue > 7) {\n throw timestampOverflowError()\n }\n\n let time = firstValue\n for (let i = 1; i < TIME_LEN; i += 1) {\n const value = DECODING[str.charCodeAt(i)]\n if (value === 255) {\n throw invalidCharError(str, i)\n }\n\n time = time * 32 + value\n }\n return time\n}\n\n/**\n * Encode a 48-bit timestamp to a 10-character Crockford Base32 string.\n * Uses unrolled division for performance.\n */\nexport function encodeTime(time: number): string {\n // Unrolled encoding - each step divides by 32 and extracts 5 bits\n // Powers of 32: 32^9=0x200000000000, 32^8=0x10000000000, etc.\n return (\n ENCODING[Math.floor(time / 0x200000000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x10000000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x800000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x40000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x2000000) & 0x1f] +\n ENCODING[Math.floor(time / 0x100000) & 0x1f] +\n ENCODING[Math.floor(time / 0x8000) & 0x1f] +\n ENCODING[Math.floor(time / 0x400) & 0x1f] +\n ENCODING[Math.floor(time / 0x20) & 0x1f] +\n ENCODING[time & 0x1f]\n )\n}\n\n/**\n * Encode 10 bytes (80 bits) of random data to a 16-character Crockford Base32 string.\n */\nexport function encodeRandom(bytes: Uint8Array): string {\n // Each character encodes 5 bits. 80 bits = 16 characters.\n // Single concatenation expression for optimal performance.\n return (\n ENCODING[(bytes[0] >> 3) & 0x1f] +\n ENCODING[((bytes[0] << 2) | (bytes[1] >> 6)) & 0x1f] +\n ENCODING[(bytes[1] >> 1) & 0x1f] +\n ENCODING[((bytes[1] << 4) | (bytes[2] >> 4)) & 0x1f] +\n ENCODING[((bytes[2] << 1) | (bytes[3] >> 7)) & 0x1f] +\n ENCODING[(bytes[3] >> 2) & 0x1f] +\n ENCODING[((bytes[3] << 3) | (bytes[4] >> 5)) & 0x1f] +\n ENCODING[bytes[4] & 0x1f] +\n ENCODING[(bytes[5] >> 3) & 0x1f] +\n ENCODING[((bytes[5] << 2) | (bytes[6] >> 6)) & 0x1f] +\n ENCODING[(bytes[6] >> 1) & 0x1f] +\n ENCODING[((bytes[6] << 4) | (bytes[7] >> 4)) & 0x1f] +\n ENCODING[((bytes[7] << 1) | (bytes[8] >> 7)) & 0x1f] +\n ENCODING[(bytes[8] >> 2) & 0x1f] +\n ENCODING[((bytes[8] << 3) | (bytes[9] >> 5)) & 0x1f] +\n ENCODING[bytes[9] & 0x1f]\n )\n}\n\n/**\n * Decode a 10-character ULID timestamp string to Unix epoch milliseconds.\n */\nexport function decodeTime(str: string): number {\n if (str.length !== TIME_LEN) {\n throw new ParseError('INVALID_LENGTH', `ULID timestamp must be ${TIME_LEN} characters`, { strategy: 'ulid' })\n }\n return decodeTimeChars(str)\n}\n\n/**\n * Decode the timestamp from a full 26-character ULID string.\n */\nexport function decodeUlidTime(str: string): number {\n if (str.length !== ULID_LEN) {\n throw new ParseError('INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`, { strategy: 'ulid' })\n }\n return decodeTimeChars(str)\n}\n\n/**\n * Decode a 26-character ULID string to 16 bytes.\n * Inlines all lookups to avoid intermediate array allocation.\n */\nexport function decodeToBytes(str: string): Uint8Array {\n if (str.length !== ULID_LEN) {\n throw new ParseError('INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`, { strategy: 'ulid' })\n }\n\n const bytes = new Uint8Array(16)\n\n // Inline all 26 character lookups\n const v0 = DECODING[str.charCodeAt(0)]\n const v1 = DECODING[str.charCodeAt(1)]\n const v2 = DECODING[str.charCodeAt(2)]\n const v3 = DECODING[str.charCodeAt(3)]\n const v4 = DECODING[str.charCodeAt(4)]\n const v5 = DECODING[str.charCodeAt(5)]\n const v6 = DECODING[str.charCodeAt(6)]\n const v7 = DECODING[str.charCodeAt(7)]\n const v8 = DECODING[str.charCodeAt(8)]\n const v9 = DECODING[str.charCodeAt(9)]\n const v10 = DECODING[str.charCodeAt(10)]\n const v11 = DECODING[str.charCodeAt(11)]\n const v12 = DECODING[str.charCodeAt(12)]\n const v13 = DECODING[str.charCodeAt(13)]\n const v14 = DECODING[str.charCodeAt(14)]\n const v15 = DECODING[str.charCodeAt(15)]\n const v16 = DECODING[str.charCodeAt(16)]\n const v17 = DECODING[str.charCodeAt(17)]\n const v18 = DECODING[str.charCodeAt(18)]\n const v19 = DECODING[str.charCodeAt(19)]\n const v20 = DECODING[str.charCodeAt(20)]\n const v21 = DECODING[str.charCodeAt(21)]\n const v22 = DECODING[str.charCodeAt(22)]\n const v23 = DECODING[str.charCodeAt(23)]\n const v24 = DECODING[str.charCodeAt(24)]\n const v25 = DECODING[str.charCodeAt(25)]\n\n // Validate all characters at once (255 = invalid marker, so any invalid\n // character sets the 0x80 bit in the OR of all values)\n if (\n ((v0 |\n v1 |\n v2 |\n v3 |\n v4 |\n v5 |\n v6 |\n v7 |\n v8 |\n v9 |\n v10 |\n v11 |\n v12 |\n v13 |\n v14 |\n v15 |\n v16 |\n v17 |\n v18 |\n v19 |\n v20 |\n v21 |\n v22 |\n v23 |\n v24 |\n v25) &\n 0x80) !==\n 0\n ) {\n // Find the invalid character for error message\n for (let i = 0; i < ULID_LEN; i += 1) {\n if (DECODING[str.charCodeAt(i)] === 255) {\n throw invalidCharError(str, i)\n }\n }\n }\n\n if (v0 > 7) {\n throw timestampOverflowError()\n }\n\n // Timestamp: first 10 characters -> bytes 0-5\n bytes[0] = (v0 << 5) | v1\n bytes[1] = (v2 << 3) | (v3 >> 2)\n bytes[2] = (v3 << 6) | (v4 << 1) | (v5 >> 4)\n bytes[3] = (v5 << 4) | (v6 >> 1)\n bytes[4] = (v6 << 7) | (v7 << 2) | (v8 >> 3)\n bytes[5] = (v8 << 5) | v9\n\n // Random: last 16 characters -> bytes 6-15\n bytes[6] = (v10 << 3) | (v11 >> 2)\n bytes[7] = (v11 << 6) | (v12 << 1) | (v13 >> 4)\n bytes[8] = (v13 << 4) | (v14 >> 1)\n bytes[9] = (v14 << 7) | (v15 << 2) | (v16 >> 3)\n bytes[10] = (v16 << 5) | v17\n bytes[11] = (v18 << 3) | (v19 >> 2)\n bytes[12] = (v19 << 6) | (v20 << 1) | (v21 >> 4)\n bytes[13] = (v21 << 4) | (v22 >> 1)\n bytes[14] = (v22 << 7) | (v23 << 2) | (v24 >> 3)\n bytes[15] = (v24 << 5) | v25\n\n return bytes\n}\n\n/**\n * Encode 16 bytes to a 26-character ULID string.\n */\nexport function bytesToUlid(bytes: Uint8Array): string {\n if (bytes.length !== 16) {\n throw new BufferError('BYTES_INVALID_LENGTH', `ULID bytes must be exactly 16 bytes, got ${bytes.length}`, {\n strategy: 'ulid',\n })\n }\n\n // Timestamp: bytes 0-5 -> 10 characters\n let time = 0\n for (let i = 0; i < 6; i += 1) {\n time = time * 256 + bytes[i]\n }\n const timeStr = encodeTime(time)\n\n // Random: bytes 6-15 -> 16 characters\n const randomStr = encodeRandom(bytes.subarray(6, 16))\n\n return timeStr + randomStr\n}\n","import { incrementBytesInPlace, writeTimestamp48 } from '../common/bytes'\nimport { rng } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { bytesToUlid, decodeToBytes, decodeUlidTime, encodeRandom, encodeTime } from './crockford'\n\nexport type UlidOptions = {\n /**\n * 16 bytes of random data to use for ULID generation.\n * Only the first 10 bytes are used.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n}\n\nexport type Ulid = {\n /** Generate a time-ordered ULID string. */\n (): string\n /** Generate a ULID with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UlidOptions | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a ULID string with optional timestamp or random bytes. */\n (options?: UlidOptions, buf?: undefined, offset?: number): string\n /** Convert a ULID string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical ULID bytes to a ULID string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid ULID string. */\n isValid(id: unknown): id is string\n /** The nil ULID (all zeros) */\n NIL: string\n /** The max ULID (maximum valid value) */\n MAX: string\n}\n\n// Validation regex: first char [0-7] to prevent overflow, rest from Crockford alphabet\nconst ULID_REGEX = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i\nconst ULID_BYTES = 16\nconst RANDOM_BYTES = 10\nconst MAX_MSECS = 0xffffffffffff\n\ntype UlidState = {\n msecs: number\n lastRandom: Uint8Array\n}\n\n/**\n * Module-level state for maintaining monotonic ordering within the same millisecond.\n *\n * IMPORTANT: This state persists across all ulid() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs` and `random` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: UlidState = {\n msecs: -Infinity,\n lastRandom: new Uint8Array(RANDOM_BYTES),\n}\n\nfunction writeUlidBytesUnchecked(time: number, random: Uint8Array, buf: Uint8Array, offset: number): void {\n // Timestamp (48-bit big-endian milliseconds since Unix epoch) -> bytes 0-5\n writeTimestamp48(buf, offset, time)\n\n // Random (80 bits) -> bytes 6-15\n for (let i = 0; i < RANDOM_BYTES; i += 1) {\n buf[offset + 6 + i] = random[i]\n }\n}\n\nfunction writeUlidBytes(time: number, random: Uint8Array, buf: Uint8Array, offset: number): void {\n if (!isWritableRange(buf, offset, ULID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `ULID byte range ${offset}:${offset + ULID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'ulid' },\n )\n }\n writeUlidBytesUnchecked(time, random, buf, offset)\n}\n\n/*\n * Overload: no buffer => return a ULID string.\n */\nfunction ulidFn(options?: UlidOptions, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with ULID bytes.\n */\nfunction ulidFn<TBuf extends Uint8Array = Uint8Array>(\n options: UlidOptions | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction ulidFn<TBuf extends Uint8Array = Uint8Array>(options?: UlidOptions, buf?: TBuf, offset = 0): string | TBuf {\n let time: number\n let random: Uint8Array\n\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all ULIDs generated within a single request will have the same timestamp.\n * - the monotonic ordering will rely entirely on incrementing the random portion.\n */\n if (options) {\n // Explicit options provided - use them directly without monotonic state\n const optMsecs = options.msecs\n if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {\n throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {\n strategy: 'ulid',\n })\n }\n time = optMsecs ?? Date.now()\n const optRandom = options.random\n if (optRandom) {\n if (optRandom.length < RANDOM_BYTES) {\n throw new InvalidInputError(\n 'RANDOM_BYTES_TOO_SHORT',\n `Random bytes length must be >= ${RANDOM_BYTES} for ULID`,\n {\n strategy: 'ulid',\n },\n )\n }\n random = optRandom\n } else {\n random = rng()\n }\n } else {\n time = Date.now()\n\n if (time > state.msecs) {\n // New millisecond: generate fresh random\n random = rng()\n state.msecs = time\n state.lastRandom.set(random.subarray(0, RANDOM_BYTES))\n } else {\n // Same millisecond or clock rollback: preserve last timestamp and increment random portion.\n time = state.msecs\n if (!incrementBytesInPlace(state.lastRandom)) {\n state.lastRandom.fill(0xff)\n throw new InvalidInputError(\n 'RANDOM_OVERFLOW',\n 'ULID random component overflowed while preserving monotonic order',\n { strategy: 'ulid' },\n )\n }\n random = state.lastRandom\n }\n }\n\n if (buf) {\n writeUlidBytes(time, random, buf, offset)\n return buf\n }\n\n // String mode: encode directly without buffer allocation\n return encodeTime(time) + encodeRandom(random)\n}\n\n/**\n * Generate a ULID string or write the bytes into a buffer.\n *\n * ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit\n * identifier with millisecond timestamp precision and 80 bits of randomness.\n * ULIDs are URL-safe, use Crockford's Base32 encoding, and sort lexicographically\n * by creation time.\n *\n * @example\n * ```ts\n * import { ulid } from 'uniku/ulid'\n *\n * const id = ulid()\n * // => \"01HW9T2W9W9YJ3JZ1H4P4M2T8Q\"\n *\n * // Extract timestamp\n * const ts = ulid.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * ulid.isValid(id) // true\n *\n * // Convert to/from bytes (16 bytes)\n * const bytes = ulid.toBytes(id)\n * const restored = ulid.fromBytes(bytes)\n * ```\n */\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && ULID_REGEX.test(id)\n}\n\n/**\n * Generate a ULID string or write its 16 canonical bytes into a buffer.\n * ULIDs are URL-safe, carry a millisecond timestamp, and sort by creation time.\n */\nexport const ulid: Ulid = Object.assign(ulidFn, {\n toBytes: (id: string) => decodeToBytes(id),\n fromBytes: (bytes: Uint8Array) => bytesToUlid(bytes),\n timestamp: (id: string) => decodeUlidTime(id),\n isValid,\n NIL: '00000000000000000000000000',\n MAX: '7ZZZZZZZZZZZZZZZZZZZZZZZZZ',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -3,0 +3,0 @@ //#region src/uuid/v4.d.ts

@@ -1,1 +0,1 @@

{"version":3,"file":"v4.d.mts","names":[],"sources":["../../src/uuid/v4.ts"],"mappings":";;;KASY,aAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;AAAA;AAAA,KAGC,MAAA;EAHD,oDAGC;EAAA,cAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,aAAA,cAA2B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEvG,OAAA,GAAU,aAAA,EAAe,GAAA,cAAiB,MAAA;EAE3C,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,OAAA,CAAQ,EAAA,YAAc,EAAA,YAFL;EAIjB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;cAiFW,MAAA,EAAQ,MAAA"}
{"version":3,"file":"v4.d.mts","names":[],"sources":["../../src/uuid/v4.ts"],"mappings":";;;KASY,aAAA;;;AAAZ;EAIE,MAAA,GAAS,UAAA;AAAA;AAAA,KAGC,MAAA;EAHD,oDAGC;EAAA,cAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,aAAA,cAA2B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEvG,OAAA,GAAU,aAAA,EAAe,GAAA,cAAiB,MAAA;EAE3C,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,OAAA,CAAQ,EAAA,YAAc,EAAA,YAFL;EAIjB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;cAoFW,MAAA,EAAQ,MAAA"}

@@ -1,2 +0,2 @@

import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t}from"../validation-CTNpXm94.mjs";import{BufferError as n,InvalidInputError as r,ParseError as i,UniqueIdError as a}from"../errors.mjs";import{n as o,r as s,t as c}from"../uuid-CnQIYoQi.mjs";const l=globalThis.crypto.randomUUID.bind(globalThis.crypto),u=new Uint8Array(16),d=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function f(e,t,n){for(let r=0;r<16;r+=1)t[n+r]=e[r];t[n+6]=t[n+6]&15|64,t[n+8]=t[n+8]&63|128}function p(e,t,n){return!t&&!e?l():m(e,t,n)}function m(i,a,s){let c=i?.random;if(c&&c.length<16)throw new r(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);let l=a?s??0:0;if(a&&!t(a,l,16))throw new n(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${l}:${l+16-1} is out of buffer bounds`);let d=a??u;return f(c??e(),d,l),a??o(d)}function h(e){return typeof e==`string`&&d.test(e)}const g=Object.assign(p,{toBytes:s,fromBytes:c,isValid:h,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{n as BufferError,r as InvalidInputError,i as ParseError,a as UniqueIdError,g as uuidv4};
import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t}from"../validation-CTNpXm94.mjs";import{BufferError as n,InvalidInputError as r,ParseError as i,UniqueIdError as a}from"../errors.mjs";import{n as o,r as s,t as c}from"../uuid-BPebYihz.mjs";const l=globalThis.crypto.randomUUID.bind(globalThis.crypto),u=new Uint8Array(16),d=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function f(e,t,n){for(let r=0;r<16;r+=1)t[n+r]=e[r];t[n+6]=t[n+6]&15|64,t[n+8]=t[n+8]&63|128}function p(e,t,n){return!t&&!e?l():m(e,t,n)}function m(i,a,s){let c=i?.random;if(c&&c.length<16)throw new r(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`,{strategy:`uuid`});let l=a?s??0:0;if(a&&!t(a,l,16))throw new n(`BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${l}:${l+16-1} is out of buffer bounds`,{strategy:`uuid`});let d=a??u;return f(c??e(),d,l),a??o(d)}function h(e){return typeof e==`string`&&d.test(e)}const g=Object.assign(p,{toBytes:s,fromBytes:c,isValid:h,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{n as BufferError,r as InvalidInputError,i as ParseError,a as UniqueIdError,g as uuidv4};
//# sourceMappingURL=v4.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"v4.mjs","names":[],"sources":["../../src/uuid/v4.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, formatUuidUnchecked, parseUuid } from './common/uuid'\n\nconst randomUUID = /*@__PURE__*/ globalThis.crypto.randomUUID.bind(globalThis.crypto)\nconst UUID_BYTES = 16\nconst reusableBuf = new Uint8Array(UUID_BYTES)\n\nexport type UuidV4Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n */\n random?: Uint8Array\n}\n\nexport type UuidV4 = {\n /** Generate a random UUID v4 string. */\n (): string\n /** Generate a UUID v4 with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a UUID v4 string with optional deterministic random bytes. */\n (options?: UuidV4Options, buf?: undefined, offset?: number): string\n /** Convert a UUID v4 string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical UUID bytes to a UUID v4 string. */\n fromBytes(bytes: Uint8Array): string\n /** Return whether a value is a syntactically valid UUID v4 string. */\n isValid(id: unknown): id is string\n /** The nil UUID (all zeros) */\n NIL: string\n /** The max UUID (all ones) */\n MAX: string\n}\n\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction writeV4BytesUnchecked(rnds: Uint8Array, buf: Uint8Array, offset: number): void {\n // Copy 16 UUID bytes into the provided buffer slice.\n for (let i = 0; i < UUID_BYTES; i += 1) {\n buf[offset + i] = rnds[i]\n }\n\n // Set RFC 4122 version (4) and variant (10xx) bits on owned output only.\n buf[offset + 6] = (buf[offset + 6] & 0x0f) | 0x40\n buf[offset + 8] = (buf[offset + 8] & 0x3f) | 0x80\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v4(options?: UuidV4Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options?: UuidV4Options, buf?: TBuf, offset?: number): string | TBuf {\n if (!buf && !options) {\n return randomUUID()\n }\n\n return _v4(options, buf, offset)\n}\n\nfunction _v4<TBuf extends Uint8Array = Uint8Array>(\n options?: UuidV4Options,\n buf?: TBuf,\n offset?: number,\n): string | TBuf {\n const random = options?.random\n if (random && random.length < UUID_BYTES) {\n throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`)\n }\n\n const outputOffset = buf ? (offset ?? 0) : 0\n if (buf && !isWritableRange(buf, outputOffset, UUID_BYTES)) {\n throw new BufferError(\n 'UUID_BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${outputOffset}:${outputOffset + UUID_BYTES - 1} is out of buffer bounds`,\n )\n }\n\n const output = buf ?? reusableBuf\n writeV4BytesUnchecked(random ?? rng(), output, outputOffset)\n return buf ?? formatUuidUnchecked(output)\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && UUID_V4_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v4 string or write the bytes into a buffer.\n *\n * UUID v4 is a purely random UUID with 122 bits of entropy. It's the most\n * widely compatible UUID format, supported by virtually all databases and systems.\n * Use when you need maximum compatibility and don't require time-ordering.\n *\n * @example\n * ```ts\n * import { uuidv4 } from 'uniku/uuid/v4'\n *\n * const id = uuidv4()\n * // => \"550e8400-e29b-41d4-a716-446655440000\"\n *\n * // Validate\n * uuidv4.isValid(id) // true\n *\n * // Convert to/from bytes (16 bytes)\n * const bytes = uuidv4.toBytes(id)\n * const restored = uuidv4.fromBytes(bytes)\n * ```\n */\nexport const uuidv4: UuidV4 = Object.assign(v4, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n isValid,\n NIL: '00000000-0000-0000-0000-000000000000',\n MAX: 'ffffffff-ffff-ffff-ffff-ffffffffffff',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"uPAKA,MAAM,EAA2B,WAAW,OAAO,WAAW,KAAK,WAAW,MAAM,EAE9E,EAAc,IAAI,WAAW,EAAU,EA4BvC,EAAgB,yEAEtB,SAAS,EAAsB,EAAkB,EAAiB,EAAsB,CAEtF,IAAK,IAAI,EAAI,EAAG,EAAI,GAAY,GAAK,EACnC,EAAI,EAAS,GAAK,EAAK,GAIzB,EAAI,EAAS,GAAM,EAAI,EAAS,GAAK,GAAQ,GAC7C,EAAI,EAAS,GAAM,EAAI,EAAS,GAAK,GAAQ,GAC/C,CAUA,SAAS,EAAyC,EAAyB,EAAY,EAAgC,CAKrH,MAJI,CAAC,GAAO,CAAC,EACJ,EAAW,EAGb,EAAI,EAAS,EAAK,CAAM,CACjC,CAEA,SAAS,EACP,EACA,EACA,EACe,CACf,IAAM,EAAS,GAAS,OACxB,GAAI,GAAU,EAAO,OAAS,GAC5B,MAAM,IAAI,EAAkB,8BAA+B,mCAA8C,EAG3G,IAAM,EAAe,EAAO,GAAU,EAAK,EAC3C,GAAI,GAAO,CAAC,EAAgB,EAAK,EAAc,EAAU,EACvD,MAAM,IAAI,EACR,4BACA,mBAAmB,EAAa,GAAG,EAAe,GAAa,EAAE,yBACnE,EAGF,IAAM,EAAS,GAAO,EAEtB,OADA,EAAsB,GAAU,EAAI,EAAG,EAAQ,CAAY,EACpD,GAAO,EAAoB,CAAM,CAC1C,CAEA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAc,KAAK,CAAE,CACxD,CAwBA,MAAa,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,UACA,IAAK,uCACL,IAAK,sCACP,CAAC"}
{"version":3,"file":"v4.mjs","names":[],"sources":["../../src/uuid/v4.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, formatUuidUnchecked, parseUuid } from './common/uuid'\n\nconst randomUUID = /*@__PURE__*/ globalThis.crypto.randomUUID.bind(globalThis.crypto)\nconst UUID_BYTES = 16\nconst reusableBuf = new Uint8Array(UUID_BYTES)\n\nexport type UuidV4Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n */\n random?: Uint8Array\n}\n\nexport type UuidV4 = {\n /** Generate a random UUID v4 string. */\n (): string\n /** Generate a UUID v4 with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a UUID v4 string with optional deterministic random bytes. */\n (options?: UuidV4Options, buf?: undefined, offset?: number): string\n /** Convert a UUID v4 string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical UUID bytes to a UUID v4 string. */\n fromBytes(bytes: Uint8Array): string\n /** Return whether a value is a syntactically valid UUID v4 string. */\n isValid(id: unknown): id is string\n /** The nil UUID (all zeros) */\n NIL: string\n /** The max UUID (all ones) */\n MAX: string\n}\n\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction writeV4BytesUnchecked(rnds: Uint8Array, buf: Uint8Array, offset: number): void {\n // Copy 16 UUID bytes into the provided buffer slice.\n for (let i = 0; i < UUID_BYTES; i += 1) {\n buf[offset + i] = rnds[i]\n }\n\n // Set RFC 4122 version (4) and variant (10xx) bits on owned output only.\n buf[offset + 6] = (buf[offset + 6] & 0x0f) | 0x40\n buf[offset + 8] = (buf[offset + 8] & 0x3f) | 0x80\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v4(options?: UuidV4Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options?: UuidV4Options, buf?: TBuf, offset?: number): string | TBuf {\n if (!buf && !options) {\n return randomUUID()\n }\n\n return _v4(options, buf, offset)\n}\n\nfunction _v4<TBuf extends Uint8Array = Uint8Array>(\n options?: UuidV4Options,\n buf?: TBuf,\n offset?: number,\n): string | TBuf {\n const random = options?.random\n if (random && random.length < UUID_BYTES) {\n throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`, {\n strategy: 'uuid',\n })\n }\n\n const outputOffset = buf ? (offset ?? 0) : 0\n if (buf && !isWritableRange(buf, outputOffset, UUID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${outputOffset}:${outputOffset + UUID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'uuid' },\n )\n }\n\n const output = buf ?? reusableBuf\n writeV4BytesUnchecked(random ?? rng(), output, outputOffset)\n return buf ?? formatUuidUnchecked(output)\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && UUID_V4_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v4 string or write the bytes into a buffer.\n *\n * UUID v4 is a purely random UUID with 122 bits of entropy. It's the most\n * widely compatible UUID format, supported by virtually all databases and systems.\n * Use when you need maximum compatibility and don't require time-ordering.\n *\n * @example\n * ```ts\n * import { uuidv4 } from 'uniku/uuid/v4'\n *\n * const id = uuidv4()\n * // => \"550e8400-e29b-41d4-a716-446655440000\"\n *\n * // Validate\n * uuidv4.isValid(id) // true\n *\n * // Convert to/from bytes (16 bytes)\n * const bytes = uuidv4.toBytes(id)\n * const restored = uuidv4.fromBytes(bytes)\n * ```\n */\nexport const uuidv4: UuidV4 = Object.assign(v4, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n isValid,\n NIL: '00000000-0000-0000-0000-000000000000',\n MAX: 'ffffffff-ffff-ffff-ffff-ffffffffffff',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"uPAKA,MAAM,EAA2B,WAAW,OAAO,WAAW,KAAK,WAAW,MAAM,EAE9E,EAAc,IAAI,WAAW,EAAU,EA4BvC,EAAgB,yEAEtB,SAAS,EAAsB,EAAkB,EAAiB,EAAsB,CAEtF,IAAK,IAAI,EAAI,EAAG,EAAI,GAAY,GAAK,EACnC,EAAI,EAAS,GAAK,EAAK,GAIzB,EAAI,EAAS,GAAM,EAAI,EAAS,GAAK,GAAQ,GAC7C,EAAI,EAAS,GAAM,EAAI,EAAS,GAAK,GAAQ,GAC/C,CAUA,SAAS,EAAyC,EAAyB,EAAY,EAAgC,CAKrH,MAJI,CAAC,GAAO,CAAC,EACJ,EAAW,EAGb,EAAI,EAAS,EAAK,CAAM,CACjC,CAEA,SAAS,EACP,EACA,EACA,EACe,CACf,IAAM,EAAS,GAAS,OACxB,GAAI,GAAU,EAAO,OAAS,GAC5B,MAAM,IAAI,EAAkB,yBAA0B,oCAAgD,CACpG,SAAU,MACZ,CAAC,EAGH,IAAM,EAAe,EAAO,GAAU,EAAK,EAC3C,GAAI,GAAO,CAAC,EAAgB,EAAK,EAAc,EAAU,EACvD,MAAM,IAAI,EACR,uBACA,mBAAmB,EAAa,GAAG,EAAe,GAAa,EAAE,0BACjE,CAAE,SAAU,MAAO,CACrB,EAGF,IAAM,EAAS,GAAO,EAEtB,OADA,EAAsB,GAAU,EAAI,EAAG,EAAQ,CAAY,EACpD,GAAO,EAAoB,CAAM,CAC1C,CAEA,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAc,KAAK,CAAE,CACxD,CAwBA,MAAa,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,UACA,IAAK,uCACL,IAAK,sCACP,CAAC"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -16,3 +16,9 @@ //#region src/uuid/v7.d.ts

/**
* Unsigned 32-bit counter value.
*/
counter?: number;
/**
* Unsigned 32-bit sequence value.
*
* @deprecated Use `counter` instead. Will be removed at v1-rc.
*/

@@ -23,3 +29,3 @@ seq?: number;

/** Generate a time-ordered UUID v7 string. */(): string; /** Generate a UUID v7 with explicit options or write its 16 canonical bytes into a caller-owned buffer. */
<TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf; /** Generate a UUID v7 string with optional timestamp, sequence, or random bytes. */
<TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf; /** Generate a UUID v7 string with optional timestamp, counter, or random bytes. */
(options?: UuidV7Options, buf?: undefined, offset?: number): string; /** Convert a UUID v7 string to its canonical 16-byte representation. */

@@ -26,0 +32,0 @@ toBytes(id: string): Uint8Array; /** Convert 16 canonical UUID bytes to a UUID v7 string. */

@@ -1,1 +0,1 @@

{"version":3,"file":"v7.d.mts","names":[],"sources":["../../src/uuid/v7.ts"],"mappings":";;;KAKY,aAAA;;;AAAZ;;EAKE,MAAA,GAAS,UAAA;EAAA;;;;EAKT,KAAA;EAIA;AAAA;AAGF;EAHE,GAAA;AAAA;AAAA,KAGU,MAAA;;gBAII,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,aAAA,cAA2B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEvG,OAAA,GAAU,aAAA,EAAe,GAAA,cAAiB,MAAA;EAE3C,OAAA,CAAQ,EAAA,WAAa,UAAA,EAEJ;EAAjB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;;;;;;AAAA;AA2KF;;;;AAAqB;;;;cAAR,MAAA,EAAQ,MAAA"}
{"version":3,"file":"v7.d.mts","names":[],"sources":["../../src/uuid/v7.ts"],"mappings":";;;KAKY,aAAA;;;AAAZ;;EAKE,MAAA,GAAS,UAAA;EAAA;;;;EAKT,KAAA;;;AAWA;EAPA,OAAA;EAUU;;;;;EAHV,GAAA;AAAA;AAAA,KAGU,MAAA;4DAUO;EAAA,cANH,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,aAAA,cAA2B,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;GAEvG,OAAA,GAAU,aAAA,EAAe,GAAA,cAAiB,MAAA;EAE3C,OAAA,CAAQ,EAAA,WAAa,UAAA;EAErB,SAAA,CAAU,KAAA,EAAO,UAAA;EAEjB,SAAA,CAAU,EAAA;EAEV,OAAA,CAAQ,EAAA,YAAc,EAAA;EAEtB,GAAA;EAEA,GAAA;AAAA;;;;;;;;;;;;;AAAA;AAoLF;;;;AAAqB;;;;;;;;;cAAR,MAAA,EAAQ,MAAA"}

@@ -1,2 +0,2 @@

import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";import{n as s,r as c,t as l}from"../uuid-CnQIYoQi.mjs";const u=/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,d=0xffffffffffff,f=4294967295,p=new Uint8Array(16),m={msecs:-1/0,seq:0};function h(e,t,n,r,i){r[i++]=t/1099511627776&255,r[i++]=t/4294967296&255,r[i++]=t/16777216&255,r[i++]=t/65536&255,r[i++]=t/256&255,r[i++]=t&255,r[i++]=112|n>>>28&15,r[i++]=n>>>20&255,r[i++]=128|n>>>14&63,r[i++]=n>>>6&255,r[i++]=n<<2&255|e[10]&3,r[i++]=e[11],r[i++]=e[12],r[i++]=e[13],r[i++]=e[14],r[i++]=e[15]}function g(e,n,i,a,o){if(!t(a,o,16))throw new r(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${o}:${o+16-1} is out of buffer bounds`);h(e,n,i,a,o)}function _(t,r,a=0){let o=t.msecs;if(o!==void 0&&!n(o,0,d))throw new i(`UUID_TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between 0 and ${d}`);let c=t.seq;if(c!==void 0&&!n(c,0,f))throw new i(`UUID_SEQUENCE_OUT_OF_RANGE`,`Sequence must be an integer between 0 and ${f}`);let l=t.random;if(l&&l.length<16)throw new i(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);let u=l??e(),m=o??Date.now(),_=c??u[6]<<23|u[7]<<16|u[8]<<8|u[9];return r?(g(u,m,_,r,a),r):(h(u,m,_,p,0),s(p))}function v(t,n,r){if(t)return _(t,n,r);let i=Date.now(),a=e();return i>m.msecs?(m.seq=a[6]<<23|a[7]<<16|a[8]<<8|a[9],m.msecs=i):(m.seq=m.seq+1|0,m.seq<0&&(m.seq=0,m.msecs++)),n?(g(a,m.msecs,m.seq,n,r??0),n):(h(a,m.msecs,m.seq,p,0),s(p))}function y(e){let t=c(e),n=0;for(let e=0;e<6;e+=1)n=n*256+t[e];return n}function b(e){return typeof e==`string`&&u.test(e)}const x=Object.assign(v,{toBytes:c,fromBytes:l,timestamp:y,isValid:b,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,x as uuidv7};
import{r as e}from"../random-Chp-Nkzi.mjs";import{n as t,t as n}from"../validation-CTNpXm94.mjs";import{BufferError as r,InvalidInputError as i,ParseError as a,UniqueIdError as o}from"../errors.mjs";import{n as s,r as c,t as l}from"../uuid-BPebYihz.mjs";const u=/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,d=0xffffffffffff,f=4294967295,p=new Uint8Array(16),m={msecs:-1/0,seq:0};function h(e,t,n,r,i){r[i++]=t/1099511627776&255,r[i++]=t/4294967296&255,r[i++]=t/16777216&255,r[i++]=t/65536&255,r[i++]=t/256&255,r[i++]=t&255,r[i++]=112|n>>>28&15,r[i++]=n>>>20&255,r[i++]=128|n>>>14&63,r[i++]=n>>>6&255,r[i++]=n<<2&255|e[10]&3,r[i++]=e[11],r[i++]=e[12],r[i++]=e[13],r[i++]=e[14],r[i++]=e[15]}function g(e,n,i,a,o){if(!t(a,o,16))throw new r(`BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${o}:${o+16-1} is out of buffer bounds`,{strategy:`uuid`});h(e,n,i,a,o)}function _(t,r,a=0){let o=t.msecs;if(o!==void 0&&!n(o,0,d))throw new i(`TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be an integer between 0 and ${d}`,{strategy:`uuid`});if(t.counter!==void 0&&t.seq!==void 0)throw new i(`CONFLICTING_OPTIONS`,"Pass only one of `counter` or `seq`, not both",{strategy:`uuid`});let c=t.counter??t.seq;if(c!==void 0&&!n(c,0,f))throw new i(`COUNTER_OUT_OF_RANGE`,`Counter must be an integer between 0 and ${f}`,{strategy:`uuid`});let l=t.random;if(l&&l.length<16)throw new i(`RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`,{strategy:`uuid`});let u=l??e(),m=o??Date.now(),_=c??u[6]<<23|u[7]<<16|u[8]<<8|u[9];return r?(g(u,m,_,r,a),r):(h(u,m,_,p,0),s(p))}function v(t,n,r){if(t)return _(t,n,r);let i=Date.now(),a=e();return i>m.msecs?(m.seq=a[6]<<23|a[7]<<16|a[8]<<8|a[9],m.msecs=i):(m.seq=m.seq+1|0,m.seq<0&&(m.seq=0,m.msecs++)),n?(g(a,m.msecs,m.seq,n,r??0),n):(h(a,m.msecs,m.seq,p,0),s(p))}function y(e){let t=c(e),n=0;for(let e=0;e<6;e+=1)n=n*256+t[e];return n}function b(e){return typeof e==`string`&&u.test(e)}const x=Object.assign(v,{toBytes:c,fromBytes:l,timestamp:y,isValid:b,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{r as BufferError,i as InvalidInputError,a as ParseError,o as UniqueIdError,x as uuidv7};
//# sourceMappingURL=v7.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"v7.mjs","names":[],"sources":["../../src/uuid/v7.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, formatUuidUnchecked, parseUuid } from './common/uuid'\n\nexport type UuidV7Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n * Note: Several bytes will be overwritten with timestamp, version, and variant data.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n /**\n * Unsigned 32-bit sequence value.\n */\n seq?: number\n}\n\nexport type UuidV7 = {\n /** Generate a time-ordered UUID v7 string. */\n (): string\n /** Generate a UUID v7 with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a UUID v7 string with optional timestamp, sequence, or random bytes. */\n (options?: UuidV7Options, buf?: undefined, offset?: number): string\n /** Convert a UUID v7 string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical UUID bytes to a UUID v7 string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid UUID v7 string. */\n isValid(id: unknown): id is string\n /** The nil UUID (all zeros) */\n NIL: string\n /** The max UUID (all ones) */\n MAX: string\n}\n\nconst UUID_V7_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\nconst UUID_BYTES = 16\nconst MAX_MSECS = 0xffffffffffff\nconst MAX_SEQ = 0xffffffff\n\n// Reusable buffer for string output path - avoids allocation per call.\n// Safe because bytes are consumed synchronously by formatUuidUnchecked().\nconst reusableBuf = new Uint8Array(UUID_BYTES)\n\ntype V7State = {\n msecs: number\n seq: number\n}\n\n/**\n * Module-level state for maintaining monotonic ordering within the same millisecond.\n *\n * IMPORTANT: This state persists across all uuidv7() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs` and `seq` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: V7State = { msecs: -Infinity, seq: 0 }\n\nfunction writeV7BytesUnchecked(rnds: Uint8Array, msecs: number, seq: number, buf: Uint8Array, offset: number): void {\n // Keep this inline on the UUID v7 hot path. Using writeTimestamp48() here\n // benchmarked slower than the direct byte writes.\n buf[offset++] = (msecs / 0x10000000000) & 0xff\n buf[offset++] = (msecs / 0x100000000) & 0xff\n buf[offset++] = (msecs / 0x1000000) & 0xff\n buf[offset++] = (msecs / 0x10000) & 0xff\n buf[offset++] = (msecs / 0x100) & 0xff\n buf[offset++] = msecs & 0xff\n\n // Set version (7) and variant (10xx), then pack sequence and random tail bytes.\n buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f)\n buf[offset++] = (seq >>> 20) & 0xff\n buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f)\n buf[offset++] = (seq >>> 6) & 0xff\n // Lower seq bits plus 2 random bits to complete the 128-bit payload.\n buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03)\n buf[offset++] = rnds[11]\n buf[offset++] = rnds[12]\n buf[offset++] = rnds[13]\n buf[offset++] = rnds[14]\n buf[offset++] = rnds[15]\n}\n\nfunction writeV7Bytes(rnds: Uint8Array, msecs: number, seq: number, buf: Uint8Array, offset: number): void {\n if (!isWritableRange(buf, offset, UUID_BYTES)) {\n throw new BufferError(\n 'UUID_BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${offset}:${offset + UUID_BYTES - 1} is out of buffer bounds`,\n )\n }\n writeV7BytesUnchecked(rnds, msecs, seq, buf, offset)\n}\n\nfunction v7WithOptions<TBuf extends Uint8Array = Uint8Array>(\n options: UuidV7Options,\n buf?: TBuf,\n offset = 0,\n): string | TBuf {\n const optMsecs = options.msecs\n if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {\n throw new InvalidInputError(\n 'UUID_TIMESTAMP_OUT_OF_RANGE',\n `Timestamp must be an integer between 0 and ${MAX_MSECS}`,\n )\n }\n const optSeq = options.seq\n if (optSeq !== undefined && !isIntegerInRange(optSeq, 0, MAX_SEQ)) {\n throw new InvalidInputError('UUID_SEQUENCE_OUT_OF_RANGE', `Sequence must be an integer between 0 and ${MAX_SEQ}`)\n }\n const optRandom = options.random\n if (optRandom && optRandom.length < UUID_BYTES) {\n throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`)\n }\n\n const rnds = optRandom ?? rng()\n const msecs = optMsecs ?? Date.now()\n // Derive a 31-bit sequence if not provided by the caller, matching the default hot path.\n const seq = optSeq ?? (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n\n if (buf) {\n writeV7Bytes(rnds, msecs, seq, buf, offset)\n return buf\n }\n writeV7BytesUnchecked(rnds, msecs, seq, reusableBuf, 0)\n return formatUuidUnchecked(reusableBuf)\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v7(options?: UuidV7Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v7<TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\nfunction v7<TBuf extends Uint8Array = Uint8Array>(options?: UuidV7Options, buf?: TBuf, offset?: number): string | TBuf {\n if (options) {\n return v7WithOptions(options, buf, offset)\n }\n\n // HOT PATH: Inline state management and byte generation for best performance\n const now = Date.now()\n const rnds = rng()\n\n // Update state (inlined for performance)\n if (now > state.msecs) {\n state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n state.msecs = now\n } else {\n state.seq = (state.seq + 1) | 0\n if (state.seq < 0) {\n state.seq = 0\n state.msecs++\n }\n }\n\n if (buf) {\n writeV7Bytes(rnds, state.msecs, state.seq, buf, offset ?? 0)\n return buf\n }\n writeV7BytesUnchecked(rnds, state.msecs, state.seq, reusableBuf, 0)\n return formatUuidUnchecked(reusableBuf)\n}\n\nfunction timestamp(id: string): number {\n const bytes = parseUuid(id)\n let msecs = 0\n for (let i = 0; i < 6; i += 1) {\n msecs = msecs * 256 + bytes[i]\n }\n return msecs\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && UUID_V7_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v7 string or write the bytes into a buffer.\n *\n * UUID v7 is a time-ordered UUID that embeds a Unix timestamp in milliseconds,\n * making IDs naturally sortable by creation time. Ideal for database primary keys\n * where chronological ordering improves index performance.\n *\n * @example\n * ```ts\n * import { uuidv7 } from 'uniku/uuid/v7'\n *\n * const id = uuidv7()\n * // => \"018e5e5c-7c8a-7000-8000-000000000000\"\n *\n * // Extract timestamp\n * const ts = uuidv7.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * uuidv7.isValid(id) // true\n *\n * // Convert to/from bytes\n * const bytes = uuidv7.toBytes(id)\n * const restored = uuidv7.fromBytes(bytes)\n * ```\n */\nexport const uuidv7: UuidV7 = Object.assign(v7, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n timestamp,\n isValid,\n NIL: '00000000-0000-0000-0000-000000000000',\n MAX: 'ffffffff-ffff-ffff-ffff-ffffffffffff',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"v7.mjs","names":[],"sources":["../../src/uuid/v7.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, formatUuidUnchecked, parseUuid } from './common/uuid'\n\nexport type UuidV7Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n * Note: Several bytes will be overwritten with timestamp, version, and variant data.\n */\n random?: Uint8Array\n /**\n * Timestamp in milliseconds since Unix epoch.\n * Defaults to Date.now().\n */\n msecs?: number\n /**\n * Unsigned 32-bit counter value.\n */\n counter?: number\n /**\n * Unsigned 32-bit sequence value.\n *\n * @deprecated Use `counter` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n seq?: number\n}\n\nexport type UuidV7 = {\n /** Generate a time-ordered UUID v7 string. */\n (): string\n /** Generate a UUID v7 with explicit options or write its 16 canonical bytes into a caller-owned buffer. */\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\n /** Generate a UUID v7 string with optional timestamp, counter, or random bytes. */\n (options?: UuidV7Options, buf?: undefined, offset?: number): string\n /** Convert a UUID v7 string to its canonical 16-byte representation. */\n toBytes(id: string): Uint8Array\n /** Convert 16 canonical UUID bytes to a UUID v7 string. */\n fromBytes(bytes: Uint8Array): string\n /** Read the embedded Unix timestamp in milliseconds. */\n timestamp(id: string): number\n /** Return whether a value is a syntactically valid UUID v7 string. */\n isValid(id: unknown): id is string\n /** The nil UUID (all zeros) */\n NIL: string\n /** The max UUID (all ones) */\n MAX: string\n}\n\nconst UUID_V7_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\nconst UUID_BYTES = 16\nconst MAX_MSECS = 0xffffffffffff\nconst MAX_SEQ = 0xffffffff\n\n// Reusable buffer for string output path - avoids allocation per call.\n// Safe because bytes are consumed synchronously by formatUuidUnchecked().\nconst reusableBuf = new Uint8Array(UUID_BYTES)\n\ntype V7State = {\n msecs: number\n seq: number\n}\n\n/**\n * Module-level state for maintaining monotonic ordering within the same millisecond.\n *\n * IMPORTANT: This state persists across all uuidv7() calls in the module's lifetime.\n * - In serverless/edge functions with warm starts, state persists between invocations.\n * - For isolated state, pass explicit `msecs` and `seq` via options.\n * - Tests should mock Date.now() or provide explicit options for deterministic behavior.\n */\nconst state: V7State = { msecs: -Infinity, seq: 0 }\n\nfunction writeV7BytesUnchecked(rnds: Uint8Array, msecs: number, seq: number, buf: Uint8Array, offset: number): void {\n // Keep this inline on the UUID v7 hot path. Using writeTimestamp48() here\n // benchmarked slower than the direct byte writes.\n buf[offset++] = (msecs / 0x10000000000) & 0xff\n buf[offset++] = (msecs / 0x100000000) & 0xff\n buf[offset++] = (msecs / 0x1000000) & 0xff\n buf[offset++] = (msecs / 0x10000) & 0xff\n buf[offset++] = (msecs / 0x100) & 0xff\n buf[offset++] = msecs & 0xff\n\n // Set version (7) and variant (10xx), then pack sequence and random tail bytes.\n buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f)\n buf[offset++] = (seq >>> 20) & 0xff\n buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f)\n buf[offset++] = (seq >>> 6) & 0xff\n // Lower seq bits plus 2 random bits to complete the 128-bit payload.\n buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03)\n buf[offset++] = rnds[11]\n buf[offset++] = rnds[12]\n buf[offset++] = rnds[13]\n buf[offset++] = rnds[14]\n buf[offset++] = rnds[15]\n}\n\nfunction writeV7Bytes(rnds: Uint8Array, msecs: number, seq: number, buf: Uint8Array, offset: number): void {\n if (!isWritableRange(buf, offset, UUID_BYTES)) {\n throw new BufferError(\n 'BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${offset}:${offset + UUID_BYTES - 1} is out of buffer bounds`,\n { strategy: 'uuid' },\n )\n }\n writeV7BytesUnchecked(rnds, msecs, seq, buf, offset)\n}\n\nfunction v7WithOptions<TBuf extends Uint8Array = Uint8Array>(\n options: UuidV7Options,\n buf?: TBuf,\n offset = 0,\n): string | TBuf {\n const optMsecs = options.msecs\n if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {\n throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {\n strategy: 'uuid',\n })\n }\n if (options.counter !== undefined && options.seq !== undefined) {\n throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `counter` or `seq`, not both', {\n strategy: 'uuid',\n })\n }\n const optSeq = options.counter ?? options.seq\n if (optSeq !== undefined && !isIntegerInRange(optSeq, 0, MAX_SEQ)) {\n throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be an integer between 0 and ${MAX_SEQ}`, {\n strategy: 'uuid',\n })\n }\n const optRandom = options.random\n if (optRandom && optRandom.length < UUID_BYTES) {\n throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`, {\n strategy: 'uuid',\n })\n }\n\n const rnds = optRandom ?? rng()\n const msecs = optMsecs ?? Date.now()\n // Derive a 31-bit sequence if not provided by the caller, matching the default hot path.\n const seq = optSeq ?? (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n\n if (buf) {\n writeV7Bytes(rnds, msecs, seq, buf, offset)\n return buf\n }\n writeV7BytesUnchecked(rnds, msecs, seq, reusableBuf, 0)\n return formatUuidUnchecked(reusableBuf)\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v7(options?: UuidV7Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v7<TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\nfunction v7<TBuf extends Uint8Array = Uint8Array>(options?: UuidV7Options, buf?: TBuf, offset?: number): string | TBuf {\n if (options) {\n return v7WithOptions(options, buf, offset)\n }\n\n // HOT PATH: Inline state management and byte generation for best performance\n const now = Date.now()\n const rnds = rng()\n\n // Update state (inlined for performance)\n if (now > state.msecs) {\n state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n state.msecs = now\n } else {\n state.seq = (state.seq + 1) | 0\n if (state.seq < 0) {\n state.seq = 0\n state.msecs++\n }\n }\n\n if (buf) {\n writeV7Bytes(rnds, state.msecs, state.seq, buf, offset ?? 0)\n return buf\n }\n writeV7BytesUnchecked(rnds, state.msecs, state.seq, reusableBuf, 0)\n return formatUuidUnchecked(reusableBuf)\n}\n\nfunction timestamp(id: string): number {\n const bytes = parseUuid(id)\n let msecs = 0\n for (let i = 0; i < 6; i += 1) {\n msecs = msecs * 256 + bytes[i]\n }\n return msecs\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && UUID_V7_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v7 string or write the bytes into a buffer.\n *\n * UUID v7 is a time-ordered UUID that embeds a Unix timestamp in milliseconds,\n * making IDs naturally sortable by creation time. Ideal for database primary keys\n * where chronological ordering improves index performance.\n *\n * @example\n * ```ts\n * import { uuidv7 } from 'uniku/uuid/v7'\n *\n * const id = uuidv7()\n * // => \"018e5e5c-7c8a-7000-8000-000000000000\"\n *\n * // Extract timestamp\n * const ts = uuidv7.timestamp(id)\n * console.log(new Date(ts))\n *\n * // Validate\n * uuidv7.isValid(id) // true\n *\n * // Convert to/from bytes\n * const bytes = uuidv7.toBytes(id)\n * const restored = uuidv7.fromBytes(bytes)\n * ```\n */\nexport const uuidv7: UuidV7 = Object.assign(v7, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n timestamp,\n isValid,\n NIL: '00000000-0000-0000-0000-000000000000',\n MAX: 'ffffffff-ffff-ffff-ffff-ffffffffffff',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}

@@ -1,2 +0,2 @@

import { i as UniqueIdError, n as InvalidInputError, r as ParseError, t as BufferError } from "../errors-Dgoyi-ci.mjs";
import { a as ParseError, i as InvalidInputError, o as UniqueIdError, t as BufferError } from "../errors-Da-8dh4J.mjs";

@@ -6,3 +6,13 @@ //#region src/xid/xid.d.ts

/** First three bytes used as the XID machine identity. */machineId?: Uint8Array; /** 16-bit process identity. */
processId?: number; /** Unix timestamp in seconds. Defaults to the current second. */
processId?: number;
/**
* Unix timestamp in milliseconds. Defaults to Date.now().
* XID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number;
/**
* Unix timestamp in seconds.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
secs?: number; /** 24-bit counter. Explicit values do not consume shared state. */

@@ -9,0 +19,0 @@ counter?: number;

@@ -1,1 +0,1 @@

{"version":3,"file":"xid.d.mts","names":[],"sources":["../../src/xid/xid.ts"],"mappings":";;;KAgBY,UAAA;4DAEV,SAAA,GAAY,UAAA,EAFd;EAIE,SAAA;EAEA,IAAA;EAEA,OAAA;AAAA;AAAA,KAGU,GAAA;EAAA;EAAA,cAEI,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,UAAA,cAAwB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;EAAA,CACpG,OAAA,GAAU,UAAA,EAAY,GAAA,cAAiB,MAAA;EACxC,OAAA,CAAQ,EAAA,WAAa,UAAA;EACrB,SAAA,CAAU,KAAA,EAAO,UAAA;EACjB,SAAA,CAAU,EAAA;EACV,OAAA,CAAQ,EAAA,YAAc,EAAA;EACtB,GAAA;EACA,GAAA;AAAA;;;;;;;;cA8HW,GAAA,EAAK,GAAA"}
{"version":3,"file":"xid.d.mts","names":[],"sources":["../../src/xid/xid.ts"],"mappings":";;;KAiBY,UAAA;4DAEV,SAAA,GAAY,UAAA,EAFd;EAIE,SAAA;;;;;EAKA,KAAA;;;;;AASA;EAFA,IAAA,WAKU;EAHV,OAAA;AAAA;AAAA,KAGU,GAAA;EAAA;EAAA,cAEI,UAAA,GAAa,UAAA,EAAY,OAAA,EAAS,UAAA,cAAwB,GAAA,EAAK,IAAA,EAAM,MAAA,YAAkB,IAAA;EAAA,CACpG,OAAA,GAAU,UAAA,EAAY,GAAA,cAAiB,MAAA;EACxC,OAAA,CAAQ,EAAA,WAAa,UAAA;EACrB,SAAA,CAAU,KAAA,EAAO,UAAA;EACjB,SAAA,CAAU,EAAA;EACV,OAAA,CAAQ,EAAA,YAAc,EAAA;EACtB,GAAA;EACA,GAAA;AAAA;;;;;;;;cAgIW,GAAA,EAAK,GAAA"}

@@ -1,2 +0,2 @@

import{n as e,t}from"../random-Chp-Nkzi.mjs";import{n,t as r}from"../validation-CTNpXm94.mjs";import{BufferError as i,InvalidInputError as a,ParseError as o,UniqueIdError as s}from"../errors.mjs";import{n as c}from"../bytes-xqWxFYsM.mjs";const l=`0123456789abcdefghijklmnopqrstuv`,u=Uint8Array.from(l,e=>e.charCodeAt(0)),d=Array(20),f=[,,,,,,],p=new Uint8Array(65536);p.fill(255);for(let e=0;e<32;e+=1)p[l.charCodeAt(e)]=e;function m(e){if(e.length!==12)throw new i(`XID_BYTES_INVALID_LENGTH`,`XID bytes must be exactly 12 bytes, got ${e.length}`);return d[0]=u[e[0]>>3],d[1]=u[(e[0]<<2|e[1]>>6)&31],d[2]=u[e[1]>>1&31],d[3]=u[(e[1]<<4|e[2]>>4)&31],d[4]=u[(e[2]<<1|e[3]>>7)&31],d[5]=u[e[3]>>2&31],d[6]=u[(e[3]<<3|e[4]>>5)&31],d[7]=u[e[4]&31],d[8]=u[e[5]>>3],d[9]=u[(e[5]<<2|e[6]>>6)&31],d[10]=u[e[6]>>1&31],d[11]=u[(e[6]<<4|e[7]>>4)&31],d[12]=u[(e[7]<<1|e[8]>>7)&31],d[13]=u[e[8]>>2&31],d[14]=u[(e[8]<<3|e[9]>>5)&31],d[15]=u[e[9]&31],d[16]=u[e[10]>>3],d[17]=u[(e[10]<<2|e[11]>>6)&31],d[18]=u[e[11]>>1&31],d[19]=u[e[11]<<4&31],String.fromCharCode(...d)}function h(e,t){let n=t>>>16,r=t>>>8&255,i=t&255;return f[0]=u[(e<<3|n>>5)&31],f[1]=u[n&31],f[2]=u[r>>3],f[3]=u[(r<<2|i>>6)&31],f[4]=u[i>>1&31],f[5]=u[i<<4&31],String.fromCharCode(...f)}function g(e){if(e.length!==20)throw new o(`XID_INVALID_LENGTH`,`XID string must be 20 characters, got ${e.length}`);let t=new Uint8Array(20);for(let n=0;n<20;n+=1){let r=p[e.charCodeAt(n)];if(r===255)throw new o(`XID_INVALID_CHAR`,`Invalid XID character: ${e[n]}`);t[n]=r}if(t[19]!==0&&t[19]!==16)throw new o(`XID_NON_CANONICAL`,`XID trailing bits must be canonically encoded`);return new Uint8Array([t[0]<<3|t[1]>>2,t[1]<<6|t[2]<<1|t[3]>>4,t[3]<<4|t[4]>>1,t[4]<<7|t[5]<<2|t[6]>>3,t[6]<<5|t[7],t[8]<<3|t[9]>>2,t[9]<<6|t[10]<<1|t[11]>>4,t[11]<<4|t[12]>>1,t[12]<<7|t[13]<<2|t[14]>>3,t[14]<<5|t[15],t[16]<<3|t[17]>>2,t[17]<<6|t[18]<<1|t[19]>>4])}const _=4294967295,v=65535,y=16777215,b=/^[0-9a-v]{19}[0g]$/,x=new Uint8Array(12);let S=-1,C=``;const w={machineId:void 0,processId:void 0,counter:void 0};function T(e){return t(e).slice()}function E(){w.machineId===void 0&&(w.machineId=T(3)),w.processId===void 0&&(w.processId=e()&v)}function D(){return w.counter===void 0&&(w.counter=e()&y),w.counter=w.counter+1&y,w.counter}function O(e,t,n,r,i,a){c(i,a,e),i.set(t.subarray(0,3),a+4),i[a+7]=n>>>8,i[a+8]=n&255,i[a+9]=r>>>16,i[a+10]=r>>>8&255,i[a+11]=r&255}function k(e){if(e.machineId!==void 0&&e.machineId.length<3)throw new a(`XID_MACHINE_ID_BYTES_TOO_SHORT`,`Machine ID bytes length must be >= 3 for XID`);if(e.processId!==void 0&&!r(e.processId,0,v))throw new a(`XID_PROCESS_ID_OUT_OF_RANGE`,`Process ID must be between 0 and ${v}`);if(e.secs!==void 0&&!r(e.secs,0,_))throw new a(`XID_TIMESTAMP_OUT_OF_RANGE`,`Timestamp must be between 0 and ${_}`);if(e.counter!==void 0&&!r(e.counter,0,y))throw new a(`XID_COUNTER_OUT_OF_RANGE`,`Counter must be between 0 and ${y}`)}function A(e,t,r=0){if(e===void 0&&t===void 0){E();let e=Math.floor(Date.now()/1e3),t=D();return e!==S&&(O(e,w.machineId,w.processId,t,x,0),C=m(x).slice(0,14),S=e),C+h(w.processId&255,t)}e!==void 0&&k(e);let a=e?.secs??Math.floor(Date.now()/1e3);(e?.machineId===void 0||e.processId===void 0)&&E();let o=e?.machineId??w.machineId,s=e?.processId??w.processId,c=e?.counter??D();if(t!==void 0){if(!n(t,r,12))throw new i(`XID_BUFFER_OUT_OF_BOUNDS`,`XID byte range ${r}:${r+11} is out of buffer bounds`);return O(a,o,s,c,t,r),t}return O(a,o,s,c,x,0),m(x)}function j(e){return g(e)}function M(e){return m(e)}function N(e){let t=g(e);return((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)*1e3}function P(e){return typeof e==`string`&&b.test(e)}const F=Object.assign(A,{toBytes:j,fromBytes:M,timestamp:N,isValid:P,NIL:`0`.repeat(20),MAX:m(new Uint8Array(12).fill(255))});export{i as BufferError,a as InvalidInputError,o as ParseError,s as UniqueIdError,F as xid};
import{n as e,t}from"../random-Chp-Nkzi.mjs";import{n,t as r}from"../validation-CTNpXm94.mjs";import{BufferError as i,InvalidInputError as a,ParseError as o,UniqueIdError as s}from"../errors.mjs";import{n as c}from"../bytes-xqWxFYsM.mjs";import{t as l}from"../timestamp-ChrSuQCR.mjs";const u=`0123456789abcdefghijklmnopqrstuv`,d=Uint8Array.from(u,e=>e.charCodeAt(0)),f=Array(20),p=[,,,,,,],m=new Uint8Array(65536);m.fill(255);for(let e=0;e<32;e+=1)m[u.charCodeAt(e)]=e;function h(e){if(e.length!==12)throw new i(`BYTES_INVALID_LENGTH`,`XID bytes must be exactly 12 bytes, got ${e.length}`,{strategy:`xid`});return f[0]=d[e[0]>>3],f[1]=d[(e[0]<<2|e[1]>>6)&31],f[2]=d[e[1]>>1&31],f[3]=d[(e[1]<<4|e[2]>>4)&31],f[4]=d[(e[2]<<1|e[3]>>7)&31],f[5]=d[e[3]>>2&31],f[6]=d[(e[3]<<3|e[4]>>5)&31],f[7]=d[e[4]&31],f[8]=d[e[5]>>3],f[9]=d[(e[5]<<2|e[6]>>6)&31],f[10]=d[e[6]>>1&31],f[11]=d[(e[6]<<4|e[7]>>4)&31],f[12]=d[(e[7]<<1|e[8]>>7)&31],f[13]=d[e[8]>>2&31],f[14]=d[(e[8]<<3|e[9]>>5)&31],f[15]=d[e[9]&31],f[16]=d[e[10]>>3],f[17]=d[(e[10]<<2|e[11]>>6)&31],f[18]=d[e[11]>>1&31],f[19]=d[e[11]<<4&31],String.fromCharCode(...f)}function g(e,t){let n=t>>>16,r=t>>>8&255,i=t&255;return p[0]=d[(e<<3|n>>5)&31],p[1]=d[n&31],p[2]=d[r>>3],p[3]=d[(r<<2|i>>6)&31],p[4]=d[i>>1&31],p[5]=d[i<<4&31],String.fromCharCode(...p)}function _(e){if(e.length!==20)throw new o(`INVALID_LENGTH`,`XID string must be 20 characters, got ${e.length}`,{strategy:`xid`});let t=new Uint8Array(20);for(let n=0;n<20;n+=1){let r=m[e.charCodeAt(n)];if(r===255)throw new o(`INVALID_CHAR`,`Invalid XID character: ${e[n]}`,{strategy:`xid`});t[n]=r}if(t[19]!==0&&t[19]!==16)throw new o(`NON_CANONICAL`,`XID trailing bits must be canonically encoded`,{strategy:`xid`});return new Uint8Array([t[0]<<3|t[1]>>2,t[1]<<6|t[2]<<1|t[3]>>4,t[3]<<4|t[4]>>1,t[4]<<7|t[5]<<2|t[6]>>3,t[6]<<5|t[7],t[8]<<3|t[9]>>2,t[9]<<6|t[10]<<1|t[11]>>4,t[11]<<4|t[12]>>1,t[12]<<7|t[13]<<2|t[14]>>3,t[14]<<5|t[15],t[16]<<3|t[17]>>2,t[17]<<6|t[18]<<1|t[19]>>4])}const v=65535,y=16777215,b=/^[0-9a-v]{19}[0g]$/,x=new Uint8Array(12);let S=-1,C=``;const w={machineId:void 0,processId:void 0,counter:void 0};function T(e){return t(e).slice()}function E(){w.machineId===void 0&&(w.machineId=T(3)),w.processId===void 0&&(w.processId=e()&v)}function D(){return w.counter===void 0&&(w.counter=e()&y),w.counter=w.counter+1&y,w.counter}function O(e,t,n,r,i,a){c(i,a,e),i.set(t.subarray(0,3),a+4),i[a+7]=n>>>8,i[a+8]=n&255,i[a+9]=r>>>16,i[a+10]=r>>>8&255,i[a+11]=r&255}function k(e){if(e.machineId!==void 0&&e.machineId.length<3)throw new a(`MACHINE_ID_BYTES_TOO_SHORT`,`Machine ID bytes length must be >= 3 for XID`,{strategy:`xid`});if(e.processId!==void 0&&!r(e.processId,0,v))throw new a(`PROCESS_ID_OUT_OF_RANGE`,`Process ID must be between 0 and ${v}`,{strategy:`xid`});if(e.counter!==void 0&&!r(e.counter,0,y))throw new a(`COUNTER_OUT_OF_RANGE`,`Counter must be between 0 and ${y}`,{strategy:`xid`})}function A(e,t,r=0){if(e===void 0&&t===void 0){E();let e=Math.floor(Date.now()/1e3),t=D();return e!==S&&(O(e,w.machineId,w.processId,t,x,0),C=h(x).slice(0,14),S=e),C+g(w.processId&255,t)}e!==void 0&&k(e);let a=(e===void 0?void 0:l(e,0,4294967295,`xid`))??Math.floor(Date.now()/1e3);(e?.machineId===void 0||e.processId===void 0)&&E();let o=e?.machineId??w.machineId,s=e?.processId??w.processId,c=e?.counter??D();if(t!==void 0){if(!n(t,r,12))throw new i(`BUFFER_OUT_OF_BOUNDS`,`XID byte range ${r}:${r+11} is out of buffer bounds`,{strategy:`xid`});return O(a,o,s,c,t,r),t}return O(a,o,s,c,x,0),h(x)}function j(e){return _(e)}function M(e){return h(e)}function N(e){let t=_(e);return((t[0]<<24|t[1]<<16|t[2]<<8|t[3])>>>0)*1e3}function P(e){return typeof e==`string`&&b.test(e)}const F=Object.assign(A,{toBytes:j,fromBytes:M,timestamp:N,isValid:P,NIL:`0`.repeat(20),MAX:h(new Uint8Array(12).fill(255))});export{i as BufferError,a as InvalidInputError,o as ParseError,s as UniqueIdError,F as xid};
//# sourceMappingURL=xid.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"file":"xid.mjs","names":["XID_BYTES"],"sources":["../../src/xid/base32hex.ts","../../src/xid/xid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\nconst ENCODING = '0123456789abcdefghijklmnopqrstuv'\nconst ENCODING_CODES = Uint8Array.from(ENCODING, (character) => character.charCodeAt(0))\nconst XID_BYTES = 12\nconst XID_LENGTH = 20\nconst ENCODED = new Array<number>(XID_LENGTH)\nconst COUNTER_SUFFIX = new Array<number>(6)\n\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255)\nfor (let i = 0; i < ENCODING.length; i += 1) {\n DECODING[ENCODING.charCodeAt(i)] = i\n}\n\n/** Encode the 12 canonical XID bytes as lowercase base32hex. */\nexport function encodeBase32Hex(bytes: Uint8Array): string {\n if (bytes.length !== XID_BYTES) {\n throw new BufferError(\n 'XID_BYTES_INVALID_LENGTH',\n `XID bytes must be exactly ${XID_BYTES} bytes, got ${bytes.length}`,\n )\n }\n\n ENCODED[0] = ENCODING_CODES[bytes[0] >> 3]\n ENCODED[1] = ENCODING_CODES[((bytes[0] << 2) | (bytes[1] >> 6)) & 0x1f]\n ENCODED[2] = ENCODING_CODES[(bytes[1] >> 1) & 0x1f]\n ENCODED[3] = ENCODING_CODES[((bytes[1] << 4) | (bytes[2] >> 4)) & 0x1f]\n ENCODED[4] = ENCODING_CODES[((bytes[2] << 1) | (bytes[3] >> 7)) & 0x1f]\n ENCODED[5] = ENCODING_CODES[(bytes[3] >> 2) & 0x1f]\n ENCODED[6] = ENCODING_CODES[((bytes[3] << 3) | (bytes[4] >> 5)) & 0x1f]\n ENCODED[7] = ENCODING_CODES[bytes[4] & 0x1f]\n ENCODED[8] = ENCODING_CODES[bytes[5] >> 3]\n ENCODED[9] = ENCODING_CODES[((bytes[5] << 2) | (bytes[6] >> 6)) & 0x1f]\n ENCODED[10] = ENCODING_CODES[(bytes[6] >> 1) & 0x1f]\n ENCODED[11] = ENCODING_CODES[((bytes[6] << 4) | (bytes[7] >> 4)) & 0x1f]\n ENCODED[12] = ENCODING_CODES[((bytes[7] << 1) | (bytes[8] >> 7)) & 0x1f]\n ENCODED[13] = ENCODING_CODES[(bytes[8] >> 2) & 0x1f]\n ENCODED[14] = ENCODING_CODES[((bytes[8] << 3) | (bytes[9] >> 5)) & 0x1f]\n ENCODED[15] = ENCODING_CODES[bytes[9] & 0x1f]\n ENCODED[16] = ENCODING_CODES[bytes[10] >> 3]\n ENCODED[17] = ENCODING_CODES[((bytes[10] << 2) | (bytes[11] >> 6)) & 0x1f]\n ENCODED[18] = ENCODING_CODES[(bytes[11] >> 1) & 0x1f]\n ENCODED[19] = ENCODING_CODES[(bytes[11] << 4) & 0x1f]\n return String.fromCharCode(...ENCODED)\n}\n\n/** Encode the six XID characters affected by the 24-bit counter. */\nexport function encodeCounterSuffix(lastIdentityByte: number, counter: number): string {\n const high = counter >>> 16\n const middle = (counter >>> 8) & 0xff\n const low = counter & 0xff\n COUNTER_SUFFIX[0] = ENCODING_CODES[((lastIdentityByte << 3) | (high >> 5)) & 0x1f]\n COUNTER_SUFFIX[1] = ENCODING_CODES[high & 0x1f]\n COUNTER_SUFFIX[2] = ENCODING_CODES[middle >> 3]\n COUNTER_SUFFIX[3] = ENCODING_CODES[((middle << 2) | (low >> 6)) & 0x1f]\n COUNTER_SUFFIX[4] = ENCODING_CODES[(low >> 1) & 0x1f]\n COUNTER_SUFFIX[5] = ENCODING_CODES[(low << 4) & 0x1f]\n return String.fromCharCode(...COUNTER_SUFFIX)\n}\n\n/** Decode a canonical lowercase base32hex XID string to its 12 bytes. */\nexport function decodeBase32Hex(id: string): Uint8Array {\n if (id.length !== XID_LENGTH) {\n throw new ParseError('XID_INVALID_LENGTH', `XID string must be ${XID_LENGTH} characters, got ${id.length}`)\n }\n\n const values = new Uint8Array(XID_LENGTH)\n for (let i = 0; i < XID_LENGTH; i += 1) {\n const value = DECODING[id.charCodeAt(i)]\n if (value === 255) {\n throw new ParseError('XID_INVALID_CHAR', `Invalid XID character: ${id[i]}`)\n }\n values[i] = value\n }\n\n if (values[19] !== 0 && values[19] !== 16) {\n throw new ParseError('XID_NON_CANONICAL', 'XID trailing bits must be canonically encoded')\n }\n\n return new Uint8Array([\n (values[0] << 3) | (values[1] >> 2),\n (values[1] << 6) | (values[2] << 1) | (values[3] >> 4),\n (values[3] << 4) | (values[4] >> 1),\n (values[4] << 7) | (values[5] << 2) | (values[6] >> 3),\n (values[6] << 5) | values[7],\n (values[8] << 3) | (values[9] >> 2),\n (values[9] << 6) | (values[10] << 1) | (values[11] >> 4),\n (values[11] << 4) | (values[12] >> 1),\n (values[12] << 7) | (values[13] << 2) | (values[14] >> 3),\n (values[14] << 5) | values[15],\n (values[16] << 3) | (values[17] >> 2),\n (values[17] << 6) | (values[18] << 1) | (values[19] >> 4),\n ])\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { randomBytes, randomUint32 } from '../common/random'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeBase32Hex, encodeBase32Hex, encodeCounterSuffix } from './base32hex'\n\nconst XID_BYTES = 12\nconst MACHINE_ID_BYTES = 3\nconst MAX_SECS = 0xffffffff\nconst MAX_PROCESS_ID = 0xffff\nconst MAX_COUNTER = 0xffffff\nconst XID_REGEX = /^[0-9a-v]{19}[0g]$/\nconst stringBuffer = new Uint8Array(XID_BYTES)\nlet cachedPrefixSecs = -1\nlet cachedPrefix = ''\n\nexport type XidOptions = {\n /** First three bytes used as the XID machine identity. */\n machineId?: Uint8Array\n /** 16-bit process identity. */\n processId?: number\n /** Unix timestamp in seconds. Defaults to the current second. */\n secs?: number\n /** 24-bit counter. Explicit values do not consume shared state. */\n counter?: number\n}\n\nexport type Xid = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: XidOptions | undefined, buf: TBuf, offset?: number): TBuf\n (options?: XidOptions, buf?: undefined, offset?: number): string\n toBytes(id: string): Uint8Array\n fromBytes(bytes: Uint8Array): string\n timestamp(id: string): number\n isValid(id: unknown): id is string\n NIL: string\n MAX: string\n}\n\ntype XidState = {\n machineId: Uint8Array | undefined\n processId: number | undefined\n counter: number | undefined\n}\n\nconst state: XidState = { machineId: undefined, processId: undefined, counter: undefined }\n\n/** Copy pooled bytes before another random draw can refill their backing pool. */\nfunction freshRandom(count: number): Uint8Array {\n return randomBytes(count).slice()\n}\n\nfunction initializeIdentity(): void {\n if (state.machineId === undefined) state.machineId = freshRandom(MACHINE_ID_BYTES)\n if (state.processId === undefined) state.processId = randomUint32() & MAX_PROCESS_ID\n}\n\nfunction nextCounter(): number {\n if (state.counter === undefined) state.counter = randomUint32() & MAX_COUNTER\n state.counter = (state.counter + 1) & MAX_COUNTER\n return state.counter\n}\n\nfunction writeXidBytesUnchecked(\n secs: number,\n machineId: Uint8Array,\n processId: number,\n counter: number,\n buf: Uint8Array,\n offset: number,\n): void {\n writeTimestamp32(buf, offset, secs)\n buf.set(machineId.subarray(0, MACHINE_ID_BYTES), offset + 4)\n buf[offset + 7] = processId >>> 8\n buf[offset + 8] = processId & 0xff\n buf[offset + 9] = counter >>> 16\n buf[offset + 10] = (counter >>> 8) & 0xff\n buf[offset + 11] = counter & 0xff\n}\n\nfunction validateOptions(options: XidOptions): void {\n if (options.machineId !== undefined && options.machineId.length < MACHINE_ID_BYTES) {\n throw new InvalidInputError(\n 'XID_MACHINE_ID_BYTES_TOO_SHORT',\n `Machine ID bytes length must be >= ${MACHINE_ID_BYTES} for XID`,\n )\n }\n if (options.processId !== undefined && !isIntegerInRange(options.processId, 0, MAX_PROCESS_ID)) {\n throw new InvalidInputError('XID_PROCESS_ID_OUT_OF_RANGE', `Process ID must be between 0 and ${MAX_PROCESS_ID}`)\n }\n if (options.secs !== undefined && !isIntegerInRange(options.secs, 0, MAX_SECS)) {\n throw new InvalidInputError('XID_TIMESTAMP_OUT_OF_RANGE', `Timestamp must be between 0 and ${MAX_SECS}`)\n }\n if (options.counter !== undefined && !isIntegerInRange(options.counter, 0, MAX_COUNTER)) {\n throw new InvalidInputError('XID_COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`)\n }\n}\n\nfunction xidFn(options?: XidOptions, buf?: undefined, offset?: number): string\nfunction xidFn<TBuf extends Uint8Array = Uint8Array>(options: XidOptions | undefined, buf: TBuf, offset?: number): TBuf\nfunction xidFn<TBuf extends Uint8Array = Uint8Array>(options?: XidOptions, buf?: TBuf, offset = 0): string | TBuf {\n if (options === undefined && buf === undefined) {\n initializeIdentity()\n const secs = Math.floor(Date.now() / 1000)\n const counter = nextCounter()\n if (secs !== cachedPrefixSecs) {\n writeXidBytesUnchecked(secs, state.machineId!, state.processId!, counter, stringBuffer, 0)\n cachedPrefix = encodeBase32Hex(stringBuffer).slice(0, 14)\n cachedPrefixSecs = secs\n }\n return cachedPrefix + encodeCounterSuffix(state.processId! & 0xff, counter)\n }\n\n if (options !== undefined) validateOptions(options)\n\n const secs = options?.secs ?? Math.floor(Date.now() / 1000)\n if (options?.machineId === undefined || options.processId === undefined) {\n initializeIdentity()\n }\n const machineId = options?.machineId ?? state.machineId!\n const processId = options?.processId ?? state.processId!\n const counter = options?.counter ?? nextCounter()\n\n if (buf !== undefined) {\n if (!isWritableRange(buf, offset, XID_BYTES)) {\n throw new BufferError(\n 'XID_BUFFER_OUT_OF_BOUNDS',\n `XID byte range ${offset}:${offset + 11} is out of buffer bounds`,\n )\n }\n writeXidBytesUnchecked(secs, machineId, processId, counter, buf, offset)\n return buf\n }\n\n writeXidBytesUnchecked(secs, machineId, processId, counter, stringBuffer, 0)\n return encodeBase32Hex(stringBuffer)\n}\n\nfunction toBytes(id: string): Uint8Array {\n return decodeBase32Hex(id)\n}\n\nfunction fromBytes(bytes: Uint8Array): string {\n return encodeBase32Hex(bytes)\n}\n\nfunction timestamp(id: string): number {\n const bytes = decodeBase32Hex(id)\n return (((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0) * 1000\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && XID_REGEX.test(id)\n}\n\n/**\n * Generate a 20-character rs/xid-compatible identifier.\n *\n * XID embeds seconds, a lazily-random per-runtime identity, and a shared\n * always-incrementing counter. In Cloudflare Workers, time is frozen during a\n * request, so the counter preserves ordering for IDs made in that request.\n */\nexport const xid: Xid = Object.assign(xidFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '0'.repeat(20),\n MAX: encodeBase32Hex(new Uint8Array(12).fill(0xff)),\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{"version":3,"file":"xid.mjs","names":["XID_BYTES"],"sources":["../../src/xid/base32hex.ts","../../src/xid/xid.ts"],"sourcesContent":["import { BufferError, ParseError } from '../errors'\n\nconst ENCODING = '0123456789abcdefghijklmnopqrstuv'\nconst ENCODING_CODES = Uint8Array.from(ENCODING, (character) => character.charCodeAt(0))\nconst XID_BYTES = 12\nconst XID_LENGTH = 20\nconst ENCODED = new Array<number>(XID_LENGTH)\nconst COUNTER_SUFFIX = new Array<number>(6)\n\nconst DECODING = new Uint8Array(65536)\nDECODING.fill(255)\nfor (let i = 0; i < ENCODING.length; i += 1) {\n DECODING[ENCODING.charCodeAt(i)] = i\n}\n\n/** Encode the 12 canonical XID bytes as lowercase base32hex. */\nexport function encodeBase32Hex(bytes: Uint8Array): string {\n if (bytes.length !== XID_BYTES) {\n throw new BufferError('BYTES_INVALID_LENGTH', `XID bytes must be exactly ${XID_BYTES} bytes, got ${bytes.length}`, {\n strategy: 'xid',\n })\n }\n\n ENCODED[0] = ENCODING_CODES[bytes[0] >> 3]\n ENCODED[1] = ENCODING_CODES[((bytes[0] << 2) | (bytes[1] >> 6)) & 0x1f]\n ENCODED[2] = ENCODING_CODES[(bytes[1] >> 1) & 0x1f]\n ENCODED[3] = ENCODING_CODES[((bytes[1] << 4) | (bytes[2] >> 4)) & 0x1f]\n ENCODED[4] = ENCODING_CODES[((bytes[2] << 1) | (bytes[3] >> 7)) & 0x1f]\n ENCODED[5] = ENCODING_CODES[(bytes[3] >> 2) & 0x1f]\n ENCODED[6] = ENCODING_CODES[((bytes[3] << 3) | (bytes[4] >> 5)) & 0x1f]\n ENCODED[7] = ENCODING_CODES[bytes[4] & 0x1f]\n ENCODED[8] = ENCODING_CODES[bytes[5] >> 3]\n ENCODED[9] = ENCODING_CODES[((bytes[5] << 2) | (bytes[6] >> 6)) & 0x1f]\n ENCODED[10] = ENCODING_CODES[(bytes[6] >> 1) & 0x1f]\n ENCODED[11] = ENCODING_CODES[((bytes[6] << 4) | (bytes[7] >> 4)) & 0x1f]\n ENCODED[12] = ENCODING_CODES[((bytes[7] << 1) | (bytes[8] >> 7)) & 0x1f]\n ENCODED[13] = ENCODING_CODES[(bytes[8] >> 2) & 0x1f]\n ENCODED[14] = ENCODING_CODES[((bytes[8] << 3) | (bytes[9] >> 5)) & 0x1f]\n ENCODED[15] = ENCODING_CODES[bytes[9] & 0x1f]\n ENCODED[16] = ENCODING_CODES[bytes[10] >> 3]\n ENCODED[17] = ENCODING_CODES[((bytes[10] << 2) | (bytes[11] >> 6)) & 0x1f]\n ENCODED[18] = ENCODING_CODES[(bytes[11] >> 1) & 0x1f]\n ENCODED[19] = ENCODING_CODES[(bytes[11] << 4) & 0x1f]\n return String.fromCharCode(...ENCODED)\n}\n\n/** Encode the six XID characters affected by the 24-bit counter. */\nexport function encodeCounterSuffix(lastIdentityByte: number, counter: number): string {\n const high = counter >>> 16\n const middle = (counter >>> 8) & 0xff\n const low = counter & 0xff\n COUNTER_SUFFIX[0] = ENCODING_CODES[((lastIdentityByte << 3) | (high >> 5)) & 0x1f]\n COUNTER_SUFFIX[1] = ENCODING_CODES[high & 0x1f]\n COUNTER_SUFFIX[2] = ENCODING_CODES[middle >> 3]\n COUNTER_SUFFIX[3] = ENCODING_CODES[((middle << 2) | (low >> 6)) & 0x1f]\n COUNTER_SUFFIX[4] = ENCODING_CODES[(low >> 1) & 0x1f]\n COUNTER_SUFFIX[5] = ENCODING_CODES[(low << 4) & 0x1f]\n return String.fromCharCode(...COUNTER_SUFFIX)\n}\n\n/** Decode a canonical lowercase base32hex XID string to its 12 bytes. */\nexport function decodeBase32Hex(id: string): Uint8Array {\n if (id.length !== XID_LENGTH) {\n throw new ParseError('INVALID_LENGTH', `XID string must be ${XID_LENGTH} characters, got ${id.length}`, {\n strategy: 'xid',\n })\n }\n\n const values = new Uint8Array(XID_LENGTH)\n for (let i = 0; i < XID_LENGTH; i += 1) {\n const value = DECODING[id.charCodeAt(i)]\n if (value === 255) {\n throw new ParseError('INVALID_CHAR', `Invalid XID character: ${id[i]}`, { strategy: 'xid' })\n }\n values[i] = value\n }\n\n if (values[19] !== 0 && values[19] !== 16) {\n throw new ParseError('NON_CANONICAL', 'XID trailing bits must be canonically encoded', { strategy: 'xid' })\n }\n\n return new Uint8Array([\n (values[0] << 3) | (values[1] >> 2),\n (values[1] << 6) | (values[2] << 1) | (values[3] >> 4),\n (values[3] << 4) | (values[4] >> 1),\n (values[4] << 7) | (values[5] << 2) | (values[6] >> 3),\n (values[6] << 5) | values[7],\n (values[8] << 3) | (values[9] >> 2),\n (values[9] << 6) | (values[10] << 1) | (values[11] >> 4),\n (values[11] << 4) | (values[12] >> 1),\n (values[12] << 7) | (values[13] << 2) | (values[14] >> 3),\n (values[14] << 5) | values[15],\n (values[16] << 3) | (values[17] >> 2),\n (values[17] << 6) | (values[18] << 1) | (values[19] >> 4),\n ])\n}\n","import { writeTimestamp32 } from '../common/bytes'\nimport { randomBytes, randomUint32 } from '../common/random'\nimport { resolveTimestampSecs } from '../common/timestamp'\nimport { isIntegerInRange, isWritableRange } from '../common/validation'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { decodeBase32Hex, encodeBase32Hex, encodeCounterSuffix } from './base32hex'\n\nconst XID_BYTES = 12\nconst MACHINE_ID_BYTES = 3\nconst MAX_SECS = 0xffffffff\nconst MAX_PROCESS_ID = 0xffff\nconst MAX_COUNTER = 0xffffff\nconst XID_REGEX = /^[0-9a-v]{19}[0g]$/\nconst stringBuffer = new Uint8Array(XID_BYTES)\nlet cachedPrefixSecs = -1\nlet cachedPrefix = ''\n\nexport type XidOptions = {\n /** First three bytes used as the XID machine identity. */\n machineId?: Uint8Array\n /** 16-bit process identity. */\n processId?: number\n /**\n * Unix timestamp in milliseconds. Defaults to Date.now().\n * XID stores whole seconds, so sub-second precision is truncated.\n */\n msecs?: number\n /**\n * Unix timestamp in seconds.\n *\n * @deprecated Use `msecs` instead. Will be removed at v1-rc.\n */\n // TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).\n secs?: number\n /** 24-bit counter. Explicit values do not consume shared state. */\n counter?: number\n}\n\nexport type Xid = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: XidOptions | undefined, buf: TBuf, offset?: number): TBuf\n (options?: XidOptions, buf?: undefined, offset?: number): string\n toBytes(id: string): Uint8Array\n fromBytes(bytes: Uint8Array): string\n timestamp(id: string): number\n isValid(id: unknown): id is string\n NIL: string\n MAX: string\n}\n\ntype XidState = {\n machineId: Uint8Array | undefined\n processId: number | undefined\n counter: number | undefined\n}\n\nconst state: XidState = { machineId: undefined, processId: undefined, counter: undefined }\n\n/** Copy pooled bytes before another random draw can refill their backing pool. */\nfunction freshRandom(count: number): Uint8Array {\n return randomBytes(count).slice()\n}\n\nfunction initializeIdentity(): void {\n if (state.machineId === undefined) state.machineId = freshRandom(MACHINE_ID_BYTES)\n if (state.processId === undefined) state.processId = randomUint32() & MAX_PROCESS_ID\n}\n\nfunction nextCounter(): number {\n if (state.counter === undefined) state.counter = randomUint32() & MAX_COUNTER\n state.counter = (state.counter + 1) & MAX_COUNTER\n return state.counter\n}\n\nfunction writeXidBytesUnchecked(\n secs: number,\n machineId: Uint8Array,\n processId: number,\n counter: number,\n buf: Uint8Array,\n offset: number,\n): void {\n writeTimestamp32(buf, offset, secs)\n buf.set(machineId.subarray(0, MACHINE_ID_BYTES), offset + 4)\n buf[offset + 7] = processId >>> 8\n buf[offset + 8] = processId & 0xff\n buf[offset + 9] = counter >>> 16\n buf[offset + 10] = (counter >>> 8) & 0xff\n buf[offset + 11] = counter & 0xff\n}\n\nfunction validateOptions(options: XidOptions): void {\n if (options.machineId !== undefined && options.machineId.length < MACHINE_ID_BYTES) {\n throw new InvalidInputError(\n 'MACHINE_ID_BYTES_TOO_SHORT',\n `Machine ID bytes length must be >= ${MACHINE_ID_BYTES} for XID`,\n { strategy: 'xid' },\n )\n }\n if (options.processId !== undefined && !isIntegerInRange(options.processId, 0, MAX_PROCESS_ID)) {\n throw new InvalidInputError('PROCESS_ID_OUT_OF_RANGE', `Process ID must be between 0 and ${MAX_PROCESS_ID}`, {\n strategy: 'xid',\n })\n }\n if (options.counter !== undefined && !isIntegerInRange(options.counter, 0, MAX_COUNTER)) {\n throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`, {\n strategy: 'xid',\n })\n }\n}\n\nfunction xidFn(options?: XidOptions, buf?: undefined, offset?: number): string\nfunction xidFn<TBuf extends Uint8Array = Uint8Array>(options: XidOptions | undefined, buf: TBuf, offset?: number): TBuf\nfunction xidFn<TBuf extends Uint8Array = Uint8Array>(options?: XidOptions, buf?: TBuf, offset = 0): string | TBuf {\n if (options === undefined && buf === undefined) {\n initializeIdentity()\n const secs = Math.floor(Date.now() / 1000)\n const counter = nextCounter()\n if (secs !== cachedPrefixSecs) {\n writeXidBytesUnchecked(secs, state.machineId!, state.processId!, counter, stringBuffer, 0)\n cachedPrefix = encodeBase32Hex(stringBuffer).slice(0, 14)\n cachedPrefixSecs = secs\n }\n return cachedPrefix + encodeCounterSuffix(state.processId! & 0xff, counter)\n }\n\n if (options !== undefined) validateOptions(options)\n\n const resolvedSecs = options === undefined ? undefined : resolveTimestampSecs(options, 0, MAX_SECS, 'xid')\n const secs = resolvedSecs ?? Math.floor(Date.now() / 1000)\n if (options?.machineId === undefined || options.processId === undefined) {\n initializeIdentity()\n }\n const machineId = options?.machineId ?? state.machineId!\n const processId = options?.processId ?? state.processId!\n const counter = options?.counter ?? nextCounter()\n\n if (buf !== undefined) {\n if (!isWritableRange(buf, offset, XID_BYTES)) {\n throw new BufferError('BUFFER_OUT_OF_BOUNDS', `XID byte range ${offset}:${offset + 11} is out of buffer bounds`, {\n strategy: 'xid',\n })\n }\n writeXidBytesUnchecked(secs, machineId, processId, counter, buf, offset)\n return buf\n }\n\n writeXidBytesUnchecked(secs, machineId, processId, counter, stringBuffer, 0)\n return encodeBase32Hex(stringBuffer)\n}\n\nfunction toBytes(id: string): Uint8Array {\n return decodeBase32Hex(id)\n}\n\nfunction fromBytes(bytes: Uint8Array): string {\n return encodeBase32Hex(bytes)\n}\n\nfunction timestamp(id: string): number {\n const bytes = decodeBase32Hex(id)\n return (((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0) * 1000\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && XID_REGEX.test(id)\n}\n\n/**\n * Generate a 20-character rs/xid-compatible identifier.\n *\n * XID embeds seconds, a lazily-random per-runtime identity, and a shared\n * always-incrementing counter. In Cloudflare Workers, time is frozen during a\n * request, so the counter preserves ordering for IDs made in that request.\n */\nexport const xid: Xid = Object.assign(xidFn, {\n toBytes,\n fromBytes,\n timestamp,\n isValid,\n NIL: '0'.repeat(20),\n MAX: encodeBase32Hex(new Uint8Array(12).fill(0xff)),\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
{
"private": false,
"name": "uniku",
"version": "0.4.3",
"version": "0.5.0",
"description": "Minimal, tree-shakeable unique ID generators for every JavaScript runtime",

@@ -6,0 +6,0 @@ "author": {

@@ -125,3 +125,5 @@ import { sha3_512 } from '@noble/hashes/sha3.js'

if (random.length === 0) {
throw new InvalidInputError('CUID2_RANDOM_BYTES_EMPTY', 'Random byte array cannot be empty')
throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', 'Random byte array cannot be empty', {
strategy: 'cuid',
})
}

@@ -148,4 +150,5 @@ let index = 0

throw new InvalidInputError(
'CUID2_LENGTH_OUT_OF_RANGE',
'LENGTH_OUT_OF_RANGE',
`CUID2 length must be between ${MIN_LENGTH} and ${MAX_LENGTH}. Received: ${requestedLength}`,
{ strategy: 'cuid' },
)

@@ -152,0 +155,0 @@ }

@@ -0,13 +1,75 @@

import type { IdGenerator } from './generators'
/**
* The canonical, ordered list of machine-readable error codes emitted by
* uniku's public API.
*
* Codes describe the failure independently of an ID format. Use an error's
* `strategy` field when the generator that raised it matters.
*/
// Plain `as const` keeps declaration emit compatible with
// `isolatedDeclarations`; every member is already a string literal.
export const ERROR_CODES = [
'TIMESTAMP_OUT_OF_RANGE',
'CONFLICTING_OPTIONS',
'COUNTER_OUT_OF_RANGE',
'NODE_OUT_OF_RANGE',
'NODE_BITS_OUT_OF_RANGE',
'EPOCH_INVALID',
'PROCESS_ID_OUT_OF_RANGE',
'MACHINE_ID_BYTES_TOO_SHORT',
'RANDOM_BYTES_TOO_SHORT',
'RANDOM_OVERFLOW',
'LENGTH_OUT_OF_RANGE',
'ALPHABET_OUT_OF_RANGE',
'ALPHABET_INVALID_CHAR',
'ALPHABET_DUPLICATE',
'PREFIX_TOO_LONG',
'PREFIX_INVALID_CHAR',
'PREFIX_INVALID_BOUNDARY',
'UUID_NOT_V7',
'BYTES_INVALID_LENGTH',
'BUFFER_OUT_OF_BOUNDS',
'INVALID_CHAR',
'INVALID_LENGTH',
'INVALID_FORMAT',
'NON_CANONICAL',
'VALUE_OUT_OF_RANGE',
] as const
/**
* A machine-readable error code emitted by uniku, derived from
* {@link ERROR_CODES}.
*/
export type ErrorCode = (typeof ERROR_CODES)[number]
/**
* Extra context carried by every uniku error.
*/
export type UniqueIdErrorOptions = {
/**
* The ID strategy whose public boundary raised the error.
* Error codes are strategy-agnostic (e.g. `TIMESTAMP_OUT_OF_RANGE`), so this
* field attributes the failure to the generator that produced it.
*/
readonly strategy?: IdGenerator
}
/**
* Base error for all uniku errors.
* Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`)
* and `code` for machine-readable error identification.
* Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`),
* `code` for machine-readable error identification, and `strategy` to attribute
* unified codes to the ID generator that raised them.
*/
export abstract class UniqueIdError extends Error {
abstract readonly _tag: string
abstract readonly code: string
abstract readonly code: ErrorCode
constructor(message: string) {
/** The ID strategy whose public boundary raised the error. */
readonly strategy?: IdGenerator
constructor(message: string, options?: UniqueIdErrorOptions) {
super(message)
this.name = this.constructor.name
this.strategy = options?.strategy
}

@@ -23,6 +85,7 @@ }

constructor(
readonly code: string,
readonly code: ErrorCode,
message: string,
options?: UniqueIdErrorOptions,
) {
super(message)
super(message, options)
}

@@ -38,6 +101,7 @@ }

constructor(
readonly code: string,
readonly code: ErrorCode,
message: string,
options?: UniqueIdErrorOptions,
) {
super(message)
super(message, options)
}

@@ -53,7 +117,8 @@ }

constructor(
readonly code: string,
readonly code: ErrorCode,
message: string,
options?: UniqueIdErrorOptions,
) {
super(message)
super(message, options)
}
}

@@ -43,4 +43,5 @@ import { BufferError, ParseError } from '../errors'

throw new BufferError(
'KSUID_BYTES_TOO_SHORT',
'BYTES_INVALID_LENGTH',
`KSUID bytes must be at least ${KSUID_BYTES} bytes, got ${bytes.length}`,
{ strategy: 'ksuid' },
)

@@ -76,6 +77,5 @@ }

if (str.length !== KSUID_STRING_LEN) {
throw new ParseError(
'KSUID_INVALID_LENGTH',
`KSUID string must be ${KSUID_STRING_LEN} characters, got ${str.length}`,
)
throw new ParseError('INVALID_LENGTH', `KSUID string must be ${KSUID_STRING_LEN} characters, got ${str.length}`, {
strategy: 'ksuid',
})
}

@@ -88,3 +88,3 @@

if (value === 255) {
throw new ParseError('KSUID_INVALID_CHAR', `Invalid KSUID character: ${str[i]}`)
throw new ParseError('INVALID_CHAR', `Invalid KSUID character: ${str[i]}`, { strategy: 'ksuid' })
}

@@ -95,3 +95,3 @@ num = num * BASE + BigInt(value)

if (num > MAX_KSUID_VALUE) {
throw new ParseError('KSUID_OVERFLOW', 'KSUID string exceeds 160-bit range')
throw new ParseError('VALUE_OUT_OF_RANGE', 'KSUID string exceeds 160-bit range', { strategy: 'ksuid' })
}

@@ -98,0 +98,0 @@

import { writeTimestamp32 } from '../common/bytes'
import { rng } from '../common/random'
import { resolveTimestampSecs } from '../common/timestamp'
import { isWritableRange } from '../common/validation'

@@ -40,6 +41,13 @@ import { BufferError, InvalidInputError } from '../errors'

/**
* Timestamp in seconds since Unix epoch.
* Defaults to Math.floor(Date.now() / 1000).
* KSUID natively uses second precision.
* Timestamp in milliseconds since the Unix epoch.
* Defaults to Date.now().
* KSUID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number
/**
* Timestamp in seconds since the Unix epoch.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
secs?: number

@@ -97,16 +105,10 @@ }

if (random && random.length < PAYLOAD_BYTES) {
throw new InvalidInputError('KSUID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16 for KSUID')
throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16 for KSUID', {
strategy: 'ksuid',
})
}
let timestamp: number
const secs = options?.secs
const secs = options === undefined ? undefined : resolveTimestampSecs(options, KSUID_EPOCH, KSUID_MAX_SECS, 'ksuid')
if (secs !== undefined) {
if (!Number.isInteger(secs) || secs < KSUID_EPOCH) {
throw new InvalidInputError('KSUID_TIMESTAMP_TOO_LOW', 'Timestamp must be >= KSUID epoch')
}
if (secs > KSUID_MAX_SECS) {
throw new InvalidInputError('KSUID_TIMESTAMP_TOO_HIGH', 'Timestamp must be <= maximum KSUID timestamp')
}
timestamp = secs - KSUID_EPOCH

@@ -129,4 +131,5 @@ } else {

throw new BufferError(
'KSUID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`KSUID byte range ${offset}:${offset + KSUID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'ksuid' },
)

@@ -161,4 +164,5 @@ }

throw new BufferError(
'KSUID_BYTES_INVALID_LENGTH',
'BYTES_INVALID_LENGTH',
`KSUID bytes must be exactly ${KSUID_BYTES} bytes, got ${bytes.length}`,
{ strategy: 'ksuid' },
)

@@ -165,0 +169,0 @@ }

@@ -44,4 +44,4 @@ import { InvalidInputError } from '../errors'

* Random bytes for deterministic output (testing).
* For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `size` bytes needed.
* For other alphabets: ~size * 2 bytes needed (rejection sampling).
* For power-of-2 alphabets (2, 4, 8, 16, 32, 64, 128, 256): exactly `length` bytes needed.
* For other alphabets: ~length * 2 bytes needed (rejection sampling).
*/

@@ -57,2 +57,9 @@ random?: Uint8Array

*/
length?: number
/**
* Length of generated ID.
*
* @deprecated Use `length` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
size?: number

@@ -80,6 +87,10 @@ }

if (alphabet.length < 2) {
throw new InvalidInputError('NANOID_ALPHABET_TOO_SHORT', 'Alphabet must contain at least 2 characters')
throw new InvalidInputError('ALPHABET_OUT_OF_RANGE', 'Alphabet must contain at least 2 characters', {
strategy: 'nanoid',
})
}
if (alphabet.length > 256) {
throw new InvalidInputError('NANOID_ALPHABET_TOO_LONG', 'Alphabet must not exceed 256 characters')
throw new InvalidInputError('ALPHABET_OUT_OF_RANGE', 'Alphabet must not exceed 256 characters', {
strategy: 'nanoid',
})
}

@@ -91,8 +102,13 @@ const seen = new Set<string>()

throw new InvalidInputError(
'NANOID_ALPHABET_INVALID_CHAR',
'ALPHABET_INVALID_CHAR',
'Alphabet must contain only printable ASCII characters (32-126)',
{
strategy: 'nanoid',
},
)
}
if (seen.has(char)) {
throw new InvalidInputError('NANOID_ALPHABET_DUPLICATE', `Duplicate character in alphabet: "${char}"`)
throw new InvalidInputError('ALPHABET_DUPLICATE', `Duplicate character in alphabet: "${char}"`, {
strategy: 'nanoid',
})
}

@@ -104,10 +120,10 @@ seen.add(char)

/**
* Validate size parameter
* Validate length parameter
*/
function validateSize(size: number): void {
function validateLength(size: number): void {
if (!Number.isInteger(size) || size < 0) {
throw new InvalidInputError('NANOID_SIZE_INVALID', 'Size must be a non-negative integer')
throw new InvalidInputError('LENGTH_OUT_OF_RANGE', 'Length must be a non-negative integer', { strategy: 'nanoid' })
}
if (size > MAX_SIZE) {
throw new InvalidInputError('NANOID_SIZE_TOO_LARGE', `Size must not exceed ${MAX_SIZE}`)
throw new InvalidInputError('LENGTH_OUT_OF_RANGE', `Length must not exceed ${MAX_SIZE}`, { strategy: 'nanoid' })
}

@@ -134,3 +150,8 @@ }

} else {
size = sizeOrOptions.size ?? DEFAULT_SIZE
if (sizeOrOptions.length !== undefined && sizeOrOptions.size !== undefined) {
throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `length` or `size`, not both', {
strategy: 'nanoid',
})
}
size = sizeOrOptions.length ?? sizeOrOptions.size ?? DEFAULT_SIZE
alphabet = sizeOrOptions.alphabet ?? URL_ALPHABET

@@ -143,3 +164,3 @@ randomBytes = sizeOrOptions.random

validateSize(size)
validateLength(size)

@@ -160,4 +181,5 @@ if (size === 0) return ''

throw new InvalidInputError(
'NANOID_RANDOM_BYTES_INSUFFICIENT',
'RANDOM_BYTES_TOO_SHORT',
`Insufficient random bytes: need ${size}, have ${randomBytes.length}`,
{ strategy: 'nanoid' },
)

@@ -187,4 +209,5 @@ }

throw new InvalidInputError(
'NANOID_RANDOM_BYTES_INSUFFICIENT',
'RANDOM_BYTES_TOO_SHORT',
`Insufficient random bytes: need at least ${step} more, have ${randomBytes.length - randomOffset}`,
{ strategy: 'nanoid' },
)

@@ -239,3 +262,3 @@ }

*
* @example Custom size
* @example Custom length
* ```ts

@@ -248,3 +271,3 @@ * const shortId = nanoid(10)

* ```ts
* const hexId = nanoid({ alphabet: '0123456789abcdef', size: 12 })
* const hexId = nanoid({ alphabet: '0123456789abcdef', length: 12 })
* // => "4f90d13a42bc"

@@ -262,5 +285,5 @@ * ```

*
* @throws {InvalidInputError} Size must be between 0 and 2048
* @throws {InvalidInputError} Length must be between 0 and 2048
* @throws {InvalidInputError} Alphabet must contain 2-256 unique printable ASCII characters
* @throws {InvalidInputError} Insufficient random bytes for requested size
* @throws {InvalidInputError} Insufficient random bytes for requested length
*/

@@ -267,0 +290,0 @@ export const nanoid: Nanoid = Object.assign(nanoidFn, {

@@ -48,4 +48,5 @@ import { BufferError, ParseError } from '../errors'

throw new BufferError(
'OBJECTID_BYTES_TOO_SHORT',
'BYTES_INVALID_LENGTH',
`ObjectID bytes must be at least ${OBJECTID_BYTES} bytes, got ${bytes.length}`,
{ strategy: 'objectid' },
)

@@ -67,4 +68,5 @@ }

throw new ParseError(
'OBJECTID_INVALID_LENGTH',
'INVALID_LENGTH',
`ObjectID string must be ${OBJECTID_STRING_LEN} characters, got ${str.length}`,
{ strategy: 'objectid' },
)

@@ -81,6 +83,6 @@ }

if (hi === 255) {
throw new ParseError('OBJECTID_INVALID_CHAR', `Invalid ObjectID character: ${str[hiIndex]}`)
throw new ParseError('INVALID_CHAR', `Invalid ObjectID character: ${str[hiIndex]}`, { strategy: 'objectid' })
}
if (lo === 255) {
throw new ParseError('OBJECTID_INVALID_CHAR', `Invalid ObjectID character: ${str[loIndex]}`)
throw new ParseError('INVALID_CHAR', `Invalid ObjectID character: ${str[loIndex]}`, { strategy: 'objectid' })
}

@@ -87,0 +89,0 @@

import { writeTimestamp32 } from '../common/bytes'
import { randomBytes, randomUint32 } from '../common/random'
import { resolveTimestampSecs } from '../common/timestamp'
import { isIntegerInRange, isWritableRange } from '../common/validation'

@@ -34,5 +35,13 @@ import { BufferError, InvalidInputError } from '../errors'

/**
* Timestamp in seconds since Unix epoch.
* Defaults to Math.floor(Date.now() / 1000).
* Timestamp in milliseconds since the Unix epoch.
* Defaults to Date.now().
* ObjectID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number
/**
* Timestamp in seconds since the Unix epoch.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
secs?: number

@@ -78,3 +87,3 @@ /**

* across warm starts is exactly the anti-collision behavior the ObjectID spec intends.
* - For isolated state, pass explicit `random`, `secs`, or `counter` via options.
* - For isolated state, pass explicit `random`, `msecs`, or `counter` via options.
* - Tests should mock Date.now() or provide explicit options for deterministic behavior.

@@ -144,15 +153,17 @@ */

throw new InvalidInputError(
'OBJECTID_RANDOM_BYTES_TOO_SHORT',
'RANDOM_BYTES_TOO_SHORT',
`Random bytes length must be >= ${RANDOM_BYTES} for ObjectID`,
{
strategy: 'objectid',
},
)
}
const optSecs = options.secs
if (optSecs !== undefined && !isIntegerInRange(optSecs, 0, MAX_SECS)) {
throw new InvalidInputError('OBJECTID_TIMESTAMP_OUT_OF_RANGE', `Timestamp must be between 0 and ${MAX_SECS}`)
}
const optSecs = resolveTimestampSecs(options, 0, MAX_SECS, 'objectid')
const optCounter = options.counter
if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, MAX_COUNTER)) {
throw new InvalidInputError('OBJECTID_COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`)
throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`, {
strategy: 'objectid',
})
}

@@ -193,4 +204,5 @@

throw new BufferError(
'OBJECTID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`ObjectID byte range ${offset}:${offset + OBJECTID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'objectid' },
)

@@ -220,4 +232,5 @@ }

throw new BufferError(
'OBJECTID_BYTES_INVALID_LENGTH',
'BYTES_INVALID_LENGTH',
`ObjectID bytes must be exactly ${OBJECTID_BYTES} bytes, got ${bytes.length}`,
{ strategy: 'objectid' },
)

@@ -224,0 +237,0 @@ }

@@ -56,3 +56,5 @@ import { ParseError } from '../errors'

if (str.length !== TSID_STRING_LEN) {
throw new ParseError('TSID_INVALID_LENGTH', `TSID string must be ${TSID_STRING_LEN} characters, got ${str.length}`)
throw new ParseError('INVALID_LENGTH', `TSID string must be ${TSID_STRING_LEN} characters, got ${str.length}`, {
strategy: 'tsid',
})
}

@@ -65,9 +67,8 @@

if (group === 255) {
throw new ParseError('TSID_INVALID_CHAR', `Invalid TSID character: ${str[i]}`)
throw new ParseError('INVALID_CHAR', `Invalid TSID character: ${str[i]}`, { strategy: 'tsid' })
}
if (i === 0 && group > TSID_LEADING_MAX) {
throw new ParseError(
'TSID_LEADING_CHAR_OUT_OF_RANGE',
`TSID leading character must be one of 0-9, A-F, got: ${str[i]}`,
)
throw new ParseError('VALUE_OUT_OF_RANGE', `TSID leading character must be one of 0-9, A-F, got: ${str[i]}`, {
strategy: 'tsid',
})
}

@@ -74,0 +75,0 @@ value = (value << 5n) | BigInt(group)

@@ -131,3 +131,5 @@ import { randomUint32 } from '../common/random'

if (!isIntegerInRange(nodeBits, 0, MAX_NODE_BITS)) {
throw new InvalidInputError('TSID_NODE_BITS_OUT_OF_RANGE', `nodeBits must be between 0 and ${MAX_NODE_BITS}`)
throw new InvalidInputError('NODE_BITS_OUT_OF_RANGE', `nodeBits must be between 0 and ${MAX_NODE_BITS}`, {
strategy: 'tsid',
})
}

@@ -140,3 +142,3 @@

if (optNode !== undefined && !isIntegerInRange(optNode, 0, nodeMask)) {
throw new InvalidInputError('TSID_NODE_OUT_OF_RANGE', `node must be between 0 and ${nodeMask}`)
throw new InvalidInputError('NODE_OUT_OF_RANGE', `node must be between 0 and ${nodeMask}`, { strategy: 'tsid' })
}

@@ -146,3 +148,5 @@

if (optCounter !== undefined && !isIntegerInRange(optCounter, 0, counterMask)) {
throw new InvalidInputError('TSID_COUNTER_OUT_OF_RANGE', `counter must be between 0 and ${counterMask}`)
throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `counter must be between 0 and ${counterMask}`, {
strategy: 'tsid',
})
}

@@ -152,14 +156,13 @@

if (!Number.isInteger(epoch)) {
throw new InvalidInputError('TSID_EPOCH_INVALID', 'epoch must be a finite integer')
throw new InvalidInputError('EPOCH_INVALID', 'epoch must be a finite integer', { strategy: 'tsid' })
}
const msecs = options.msecs ?? Date.now()
if (!Number.isInteger(msecs)) {
throw new InvalidInputError('TSID_TIMESTAMP_INVALID', 'msecs must be a finite integer')
throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', 'msecs must be a finite integer', { strategy: 'tsid' })
}
const msecsDiff = BigInt(msecs) - BigInt(epoch)
if (msecsDiff < 0n || msecsDiff > MAX_TIMESTAMP_DIFF) {
throw new InvalidInputError(
'TSID_TIMESTAMP_OUT_OF_RANGE',
`msecs - epoch must be between 0 and ${MAX_TIMESTAMP_DIFF}`,
)
throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `msecs - epoch must be between 0 and ${MAX_TIMESTAMP_DIFF}`, {
strategy: 'tsid',
})
}

@@ -236,4 +239,5 @@

throw new BufferError(
'TSID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`TSID byte range ${offset}:${offset + TSID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'tsid' },
)

@@ -264,4 +268,5 @@ }

throw new BufferError(
'TSID_BYTES_INVALID_LENGTH',
'BYTES_INVALID_LENGTH',
`TSID bytes must be exactly ${TSID_BYTES} bytes, got ${bytes.length}`,
{ strategy: 'tsid' },
)

@@ -285,3 +290,3 @@ }

if (!Number.isInteger(epoch)) {
throw new InvalidInputError('TSID_EPOCH_INVALID', 'epoch must be a finite integer')
throw new InvalidInputError('EPOCH_INVALID', 'epoch must be a finite integer', { strategy: 'tsid' })
}

@@ -303,3 +308,5 @@ return epoch + Number(id >> BigInt(RANDOM_BITS))

if (id < NIL || id > MAX) {
throw new InvalidInputError('TSID_VALUE_OUT_OF_RANGE', `TSID value must be between ${NIL} and ${MAX}`)
throw new InvalidInputError('VALUE_OUT_OF_RANGE', `TSID value must be between ${NIL} and ${MAX}`, {
strategy: 'tsid',
})
}

@@ -306,0 +313,0 @@ }

@@ -1,2 +0,3 @@

import { InvalidInputError, ParseError } from '../errors'
import { isIntegerInRange, isWritableRange } from '../common/validation'
import { BufferError, InvalidInputError, ParseError } from '../errors'
import type { UuidV7Options } from '../uuid/v7'

@@ -10,2 +11,11 @@ import { uuidv7 } from '../uuid/v7'

(prefix: string, options?: TypeidOptions): string
/** Generate a TypeID with explicit options or write its 16 canonical UUID v7 bytes into a caller-owned buffer. */
<TBuf extends Uint8Array = Uint8Array>(
prefix: string,
options: TypeidOptions | undefined,
buf: TBuf,
offset?: number,
): TBuf
/** Generate a TypeID string with optional timestamp, counter, or random bytes. */
(prefix: string, options?: TypeidOptions, buf?: undefined, offset?: number): string
/** Convert a TypeID's UUID v7 suffix to its canonical 16-byte representation. */

@@ -31,2 +41,7 @@ toBytes(id: string): Uint8Array

const TYPEID_UUID_BYTE_LENGTH = 16
// 48-bit UUID v7 timestamp capacity, mirrored from uuid/v7 alongside the
// 32-bit counter capacity, so option validation is attributed to the typeid
// boundary instead of leaking `strategy: 'uuid'` through delegation.
const MAX_MSECS = 0xffffffffffff
const MAX_COUNTER = 0xffffffff
const TYPEID_ALPHABET = '0123456789abcdefghjkmnpqrstvwxyz'

@@ -51,3 +66,5 @@

if (prefix.length > 63) {
throw new InvalidInputError('TYPEID_PREFIX_TOO_LONG', 'TypeID prefix must be at most 63 characters')
throw new InvalidInputError('PREFIX_TOO_LONG', 'TypeID prefix must be at most 63 characters', {
strategy: 'typeid',
})
}

@@ -62,4 +79,5 @@

throw new InvalidInputError(
'TYPEID_PREFIX_INVALID_CHARACTER',
'PREFIX_INVALID_CHAR',
'TypeID prefix must contain only lowercase ASCII letters and underscores',
{ strategy: 'typeid' },
)

@@ -69,3 +87,5 @@ }

if ((i === 0 || i === prefix.length - 1) && !isLowercaseLetter) {
throw new InvalidInputError('TYPEID_PREFIX_INVALID_BOUNDARY', 'TypeID prefix must start and end with a-z')
throw new InvalidInputError('PREFIX_INVALID_BOUNDARY', 'TypeID prefix must start and end with a-z', {
strategy: 'typeid',
})
}

@@ -80,6 +100,5 @@ }

if (value === -1) {
throw new ParseError(
'TYPEID_SUFFIX_INVALID_CHARACTER',
`TypeID suffix contains invalid character at position ${index}`,
)
throw new ParseError('INVALID_CHAR', `TypeID suffix contains invalid character at position ${index}`, {
strategy: 'typeid',
})
}

@@ -92,7 +111,11 @@

if (suffix.length !== TYPEID_SUFFIX_LENGTH) {
throw new ParseError('TYPEID_SUFFIX_INVALID_LENGTH', `TypeID suffix must be 26 characters, got ${suffix.length}`)
throw new ParseError('INVALID_LENGTH', `TypeID suffix must be 26 characters, got ${suffix.length}`, {
strategy: 'typeid',
})
}
if (suffix[0] > '7') {
throw new ParseError('TYPEID_SUFFIX_OVERFLOW', 'TypeID suffix must encode a 128-bit value')
throw new ParseError('VALUE_OUT_OF_RANGE', 'TypeID suffix must encode a 128-bit value', {
strategy: 'typeid',
})
}

@@ -103,3 +126,5 @@ }

if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {
throw new InvalidInputError('TYPEID_UUID_BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`)
throw new InvalidInputError('BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`, {
strategy: 'typeid',
})
}

@@ -168,7 +193,11 @@

if (bytes.length !== TYPEID_UUID_BYTE_LENGTH) {
throw new InvalidInputError('TYPEID_UUID_BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`)
throw new InvalidInputError('BYTES_INVALID_LENGTH', `UUID bytes must be 16 bytes, got ${bytes.length}`, {
strategy: 'typeid',
})
}
if (bytes[6] >> 4 !== 7 || (bytes[8] & 0xc0) !== 0x80) {
throw new InvalidInputError('TYPEID_UUID_NOT_V7', 'TypeID UUID bytes must encode a UUID v7 value')
throw new InvalidInputError('UUID_NOT_V7', 'TypeID UUID bytes must encode a UUID v7 value', {
strategy: 'typeid',
})
}

@@ -185,3 +214,3 @@ }

if (!uuidv7.isValid(uuid)) {
throw new InvalidInputError('TYPEID_UUID_NOT_V7', 'TypeID can only wrap UUID v7 values')
throw new InvalidInputError('UUID_NOT_V7', 'TypeID can only wrap UUID v7 values', { strategy: 'typeid' })
}

@@ -196,3 +225,3 @@

if (separatorIndex === 0) {
throw new ParseError('TYPEID_INVALID_FORMAT', 'TypeID must not start with "_"')
throw new ParseError('INVALID_FORMAT', 'TypeID must not start with "_"', { strategy: 'typeid' })
}

@@ -227,3 +256,64 @@

function typeidFn(prefix: string, options?: TypeidOptions): string {
/**
* Mirror uuid/v7's option validation at the typeid boundary, so failures are
* attributed to `strategy: 'typeid'` instead of leaking `strategy: 'uuid'`
* through delegation.
*/
function validateTypeidOptions(options: TypeidOptions): void {
const msecs = options.msecs
if (msecs !== undefined && !isIntegerInRange(msecs, 0, MAX_MSECS)) {
throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {
strategy: 'typeid',
})
}
if (options.counter !== undefined && options.seq !== undefined) {
throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `counter` or `seq`, not both', {
strategy: 'typeid',
})
}
const counter = options.counter ?? options.seq
if (counter !== undefined && !isIntegerInRange(counter, 0, MAX_COUNTER)) {
throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be an integer between 0 and ${MAX_COUNTER}`, {
strategy: 'typeid',
})
}
const random = options.random
if (random && random.length < TYPEID_UUID_BYTE_LENGTH) {
throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${TYPEID_UUID_BYTE_LENGTH}`, {
strategy: 'typeid',
})
}
}
function typeidFn(prefix: string, options?: TypeidOptions, buf?: undefined, offset?: number): string
function typeidFn<TBuf extends Uint8Array = Uint8Array>(
prefix: string,
options: TypeidOptions | undefined,
buf: TBuf,
offset?: number,
): TBuf
function typeidFn<TBuf extends Uint8Array = Uint8Array>(
prefix: string,
options?: TypeidOptions,
buf?: TBuf,
offset = 0,
): string | TBuf {
if (options !== undefined) {
validateTypeidOptions(options)
}
if (buf) {
if (!isWritableRange(buf, offset, TYPEID_UUID_BYTE_LENGTH)) {
throw new BufferError(
'BUFFER_OUT_OF_BOUNDS',
`TypeID byte range ${offset}:${offset + TYPEID_UUID_BYTE_LENGTH - 1} is out of buffer bounds`,
{ strategy: 'typeid' },
)
}
assertValidPrefix(prefix)
return uuidv7(options, buf, offset)
}
const bytes = uuidv7(options, new Uint8Array(TYPEID_UUID_BYTE_LENGTH))

@@ -230,0 +320,0 @@ return formatTypeidFromUuidV7Bytes(prefix, bytes)

@@ -28,7 +28,7 @@ /**

function invalidCharError(str: string, index: number): ParseError {
return new ParseError('ULID_INVALID_CHAR', `Invalid ULID character: ${str[index]}`)
return new ParseError('INVALID_CHAR', `Invalid ULID character: ${str[index]}`, { strategy: 'ulid' })
}
function timestampOverflowError(): ParseError {
return new ParseError('ULID_TIMESTAMP_OVERFLOW', 'ULID timestamp exceeds 48 bits')
return new ParseError('TIMESTAMP_OUT_OF_RANGE', 'ULID timestamp exceeds 48 bits', { strategy: 'ulid' })
}

@@ -110,3 +110,3 @@

if (str.length !== TIME_LEN) {
throw new ParseError('ULID_INVALID_LENGTH', `ULID timestamp must be ${TIME_LEN} characters`)
throw new ParseError('INVALID_LENGTH', `ULID timestamp must be ${TIME_LEN} characters`, { strategy: 'ulid' })
}

@@ -121,3 +121,3 @@ return decodeTimeChars(str)

if (str.length !== ULID_LEN) {
throw new ParseError('ULID_INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`)
throw new ParseError('INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`, { strategy: 'ulid' })
}

@@ -133,3 +133,3 @@ return decodeTimeChars(str)

if (str.length !== ULID_LEN) {
throw new ParseError('ULID_INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`)
throw new ParseError('INVALID_LENGTH', `ULID string must be ${ULID_LEN} characters`, { strategy: 'ulid' })
}

@@ -239,3 +239,5 @@

if (bytes.length !== 16) {
throw new BufferError('ULID_BYTES_INVALID_LENGTH', `ULID bytes must be exactly 16 bytes, got ${bytes.length}`)
throw new BufferError('BYTES_INVALID_LENGTH', `ULID bytes must be exactly 16 bytes, got ${bytes.length}`, {
strategy: 'ulid',
})
}

@@ -242,0 +244,0 @@

@@ -78,4 +78,5 @@ import { incrementBytesInPlace, writeTimestamp48 } from '../common/bytes'

throw new BufferError(
'ULID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`ULID byte range ${offset}:${offset + ULID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'ulid' },
)

@@ -114,6 +115,5 @@ }

if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {
throw new InvalidInputError(
'ULID_TIMESTAMP_OUT_OF_RANGE',
`Timestamp must be an integer between 0 and ${MAX_MSECS}`,
)
throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {
strategy: 'ulid',
})
}

@@ -125,4 +125,7 @@ time = optMsecs ?? Date.now()

throw new InvalidInputError(
'ULID_RANDOM_BYTES_TOO_SHORT',
'RANDOM_BYTES_TOO_SHORT',
`Random bytes length must be >= ${RANDOM_BYTES} for ULID`,
{
strategy: 'ulid',
},
)

@@ -148,4 +151,5 @@ }

throw new InvalidInputError(
'ULID_RANDOM_OVERFLOW',
'RANDOM_OVERFLOW',
'ULID random component overflowed while preserving monotonic order',
{ strategy: 'ulid' },
)

@@ -152,0 +156,0 @@ }

@@ -98,4 +98,7 @@ import { BufferError, ParseError } from '../../errors'

throw new BufferError(
'UUID_BYTES_INVALID_LENGTH',
'BYTES_INVALID_LENGTH',
`UUID bytes must be exactly ${UUID_BYTE_LENGTH} bytes, got ${bytes.length}`,
{
strategy: 'uuid',
},
)

@@ -137,3 +140,5 @@ }

if (value.length !== UUID_STRING_LENGTH) {
throw new ParseError('UUID_INVALID_LENGTH', `UUID string must be 36 characters, got ${value.length}`)
throw new ParseError('INVALID_LENGTH', `UUID string must be 36 characters, got ${value.length}`, {
strategy: 'uuid',
})
}

@@ -144,4 +149,5 @@

throw new ParseError(
'UUID_INVALID_SEPARATORS',
'INVALID_FORMAT',
`UUID string has invalid separators at positions 8, 13, 18, 23. Received: "${value}"`,
{ strategy: 'uuid' },
)

@@ -160,3 +166,5 @@ }

if (nibble === -1) {
throw new ParseError('UUID_INVALID_HEX_CHAR', `UUID string contains invalid hex character at position ${i}`)
throw new ParseError('INVALID_CHAR', `UUID string contains invalid hex character at position ${i}`, {
strategy: 'uuid',
})
}

@@ -163,0 +171,0 @@

@@ -72,3 +72,5 @@ import { rng } from '../common/random'

if (random && random.length < UUID_BYTES) {
throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`)
throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`, {
strategy: 'uuid',
})
}

@@ -79,4 +81,5 @@

throw new BufferError(
'UUID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`UUID byte range ${outputOffset}:${outputOffset + UUID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'uuid' },
)

@@ -83,0 +86,0 @@ }

@@ -18,4 +18,11 @@ import { rng } from '../common/random'

/**
* Unsigned 32-bit counter value.
*/
counter?: number
/**
* Unsigned 32-bit sequence value.
*
* @deprecated Use `counter` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
seq?: number

@@ -29,3 +36,3 @@ }

<TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf
/** Generate a UUID v7 string with optional timestamp, sequence, or random bytes. */
/** Generate a UUID v7 string with optional timestamp, counter, or random bytes. */
(options?: UuidV7Options, buf?: undefined, offset?: number): string

@@ -97,4 +104,5 @@ /** Convert a UUID v7 string to its canonical 16-byte representation. */

throw new BufferError(
'UUID_BUFFER_OUT_OF_BOUNDS',
'BUFFER_OUT_OF_BOUNDS',
`UUID byte range ${offset}:${offset + UUID_BYTES - 1} is out of buffer bounds`,
{ strategy: 'uuid' },
)

@@ -112,14 +120,22 @@ }

if (optMsecs !== undefined && !isIntegerInRange(optMsecs, 0, MAX_MSECS)) {
throw new InvalidInputError(
'UUID_TIMESTAMP_OUT_OF_RANGE',
`Timestamp must be an integer between 0 and ${MAX_MSECS}`,
)
throw new InvalidInputError('TIMESTAMP_OUT_OF_RANGE', `Timestamp must be an integer between 0 and ${MAX_MSECS}`, {
strategy: 'uuid',
})
}
const optSeq = options.seq
if (options.counter !== undefined && options.seq !== undefined) {
throw new InvalidInputError('CONFLICTING_OPTIONS', 'Pass only one of `counter` or `seq`, not both', {
strategy: 'uuid',
})
}
const optSeq = options.counter ?? options.seq
if (optSeq !== undefined && !isIntegerInRange(optSeq, 0, MAX_SEQ)) {
throw new InvalidInputError('UUID_SEQUENCE_OUT_OF_RANGE', `Sequence must be an integer between 0 and ${MAX_SEQ}`)
throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be an integer between 0 and ${MAX_SEQ}`, {
strategy: 'uuid',
})
}
const optRandom = options.random
if (optRandom && optRandom.length < UUID_BYTES) {
throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`)
throw new InvalidInputError('RANDOM_BYTES_TOO_SHORT', `Random bytes length must be >= ${UUID_BYTES}`, {
strategy: 'uuid',
})
}

@@ -126,0 +142,0 @@

@@ -19,6 +19,5 @@ import { BufferError, ParseError } from '../errors'

if (bytes.length !== XID_BYTES) {
throw new BufferError(
'XID_BYTES_INVALID_LENGTH',
`XID bytes must be exactly ${XID_BYTES} bytes, got ${bytes.length}`,
)
throw new BufferError('BYTES_INVALID_LENGTH', `XID bytes must be exactly ${XID_BYTES} bytes, got ${bytes.length}`, {
strategy: 'xid',
})
}

@@ -66,3 +65,5 @@

if (id.length !== XID_LENGTH) {
throw new ParseError('XID_INVALID_LENGTH', `XID string must be ${XID_LENGTH} characters, got ${id.length}`)
throw new ParseError('INVALID_LENGTH', `XID string must be ${XID_LENGTH} characters, got ${id.length}`, {
strategy: 'xid',
})
}

@@ -74,3 +75,3 @@

if (value === 255) {
throw new ParseError('XID_INVALID_CHAR', `Invalid XID character: ${id[i]}`)
throw new ParseError('INVALID_CHAR', `Invalid XID character: ${id[i]}`, { strategy: 'xid' })
}

@@ -81,3 +82,3 @@ values[i] = value

if (values[19] !== 0 && values[19] !== 16) {
throw new ParseError('XID_NON_CANONICAL', 'XID trailing bits must be canonically encoded')
throw new ParseError('NON_CANONICAL', 'XID trailing bits must be canonically encoded', { strategy: 'xid' })
}

@@ -84,0 +85,0 @@

import { writeTimestamp32 } from '../common/bytes'
import { randomBytes, randomUint32 } from '../common/random'
import { resolveTimestampSecs } from '../common/timestamp'
import { isIntegerInRange, isWritableRange } from '../common/validation'

@@ -22,3 +23,13 @@ import { BufferError, InvalidInputError } from '../errors'

processId?: number
/** Unix timestamp in seconds. Defaults to the current second. */
/**
* Unix timestamp in milliseconds. Defaults to Date.now().
* XID stores whole seconds, so sub-second precision is truncated.
*/
msecs?: number
/**
* Unix timestamp in seconds.
*
* @deprecated Use `msecs` instead. Will be removed at v1-rc.
*/
// TODO(v1-rc): remove this alias (tracked in docs/STABILITY.md).
secs?: number

@@ -85,14 +96,16 @@ /** 24-bit counter. Explicit values do not consume shared state. */

throw new InvalidInputError(
'XID_MACHINE_ID_BYTES_TOO_SHORT',
'MACHINE_ID_BYTES_TOO_SHORT',
`Machine ID bytes length must be >= ${MACHINE_ID_BYTES} for XID`,
{ strategy: 'xid' },
)
}
if (options.processId !== undefined && !isIntegerInRange(options.processId, 0, MAX_PROCESS_ID)) {
throw new InvalidInputError('XID_PROCESS_ID_OUT_OF_RANGE', `Process ID must be between 0 and ${MAX_PROCESS_ID}`)
throw new InvalidInputError('PROCESS_ID_OUT_OF_RANGE', `Process ID must be between 0 and ${MAX_PROCESS_ID}`, {
strategy: 'xid',
})
}
if (options.secs !== undefined && !isIntegerInRange(options.secs, 0, MAX_SECS)) {
throw new InvalidInputError('XID_TIMESTAMP_OUT_OF_RANGE', `Timestamp must be between 0 and ${MAX_SECS}`)
}
if (options.counter !== undefined && !isIntegerInRange(options.counter, 0, MAX_COUNTER)) {
throw new InvalidInputError('XID_COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`)
throw new InvalidInputError('COUNTER_OUT_OF_RANGE', `Counter must be between 0 and ${MAX_COUNTER}`, {
strategy: 'xid',
})
}

@@ -118,3 +131,4 @@ }

const secs = options?.secs ?? Math.floor(Date.now() / 1000)
const resolvedSecs = options === undefined ? undefined : resolveTimestampSecs(options, 0, MAX_SECS, 'xid')
const secs = resolvedSecs ?? Math.floor(Date.now() / 1000)
if (options?.machineId === undefined || options.processId === undefined) {

@@ -129,6 +143,5 @@ initializeIdentity()

if (!isWritableRange(buf, offset, XID_BYTES)) {
throw new BufferError(
'XID_BUFFER_OUT_OF_BOUNDS',
`XID byte range ${offset}:${offset + 11} is out of buffer bounds`,
)
throw new BufferError('BUFFER_OUT_OF_BOUNDS', `XID byte range ${offset}:${offset + 11} is out of buffer bounds`, {
strategy: 'xid',
})
}

@@ -135,0 +148,0 @@ writeXidBytesUnchecked(secs, machineId, processId, counter, buf, offset)

//#region src/errors.d.ts
/**
* Base error for all uniku errors.
* Provides `_tag` for discriminated matching (compatible with Effect's `catchTag`)
* and `code` for machine-readable error identification.
*/
declare abstract class UniqueIdError extends Error {
abstract readonly _tag: string;
abstract readonly code: string;
constructor(message: string);
}
/**
* Thrown when generator arguments are invalid (bad size, alphabet, length, timestamp, version).
*/
declare class InvalidInputError extends UniqueIdError {
readonly code: string;
readonly _tag = "InvalidInputError";
constructor(code: string, message: string);
}
/**
* Thrown when parsing/decoding an ID string that has invalid format or characters.
*/
declare class ParseError extends UniqueIdError {
readonly code: string;
readonly _tag = "ParseError";
constructor(code: string, message: string);
}
/**
* Thrown when a byte array or buffer is too short or an offset is out of bounds.
*/
declare class BufferError extends UniqueIdError {
readonly code: string;
readonly _tag = "BufferError";
constructor(code: string, message: string);
}
//#endregion
export { UniqueIdError as i, InvalidInputError as n, ParseError as r, BufferError as t };
//# sourceMappingURL=errors-Dgoyi-ci.d.mts.map
{"version":3,"file":"errors-Dgoyi-ci.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;AAKA;;;;uBAAsB,aAAA,SAAsB,KAAA;EAAA,kBACxB,IAAA;EAAA,kBACA,IAAA;EAElB,WAAA,CAAY,OAAA;AAAA;;AAAA;AASd;cAAa,iBAAA,SAA0B,aAAA;EAAA,SAInC,IAAA;EAAA,SAHO,IAAA;EAET,WAAA,CACE,IAAA,UACA,OAAA;AAAA;;;;cASS,UAAA,SAAmB,aAAA;EAAA,SAI5B,IAAA;EAAA,SAHO,IAAA;EAET,WAAA,CACE,IAAA,UACA,OAAA;AAAA;;;;cASS,WAAA,SAAoB,aAAA;EAAA,SAI7B,IAAA;EAAA,SAHO,IAAA;EAET,WAAA,CACE,IAAA,UACA,OAAA;AAAA"}
{"version":3,"file":"generators.d.mts","names":[],"sources":["../src/generators.ts"],"mappings":";;AAWA;;;;AAAuG;AAKvG;;cALa,aAAA;;AAKqB;;KAAtB,WAAA,WAAsB,aAAA"}
import{BufferError as e,ParseError as t}from"./errors.mjs";function n(e){return e>=48&&e<=57?e-48:e>=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:-1}const r=[0,0,1,1,2,2,3,3,-1,4,4,5,5,-1,6,6,7,7,-1,8,8,9,9,-1,10,10,11,11,12,12,13,13,14,14,15,15],i=[!0,!1,!0,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!1,!0,!1,!0,!1,!0,!1,!0,!1,!0,!1,!0,!1],a=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,`0`));function o(t){if(t.length!==16)throw new e(`UUID_BYTES_INVALID_LENGTH`,`UUID bytes must be exactly 16 bytes, got ${t.length}`);return s(t)}function s(e){return a[e[0]]+a[e[1]]+a[e[2]]+a[e[3]]+`-`+a[e[4]]+a[e[5]]+`-`+a[e[6]]+a[e[7]]+`-`+a[e[8]]+a[e[9]]+`-`+a[e[10]]+a[e[11]]+a[e[12]]+a[e[13]]+a[e[14]]+a[e[15]]}function c(e){if(e.length!==36)throw new t(`UUID_INVALID_LENGTH`,`UUID string must be 36 characters, got ${e.length}`);if(e[8]!==`-`||e[13]!==`-`||e[18]!==`-`||e[23]!==`-`)throw new t(`UUID_INVALID_SEPARATORS`,`UUID string has invalid separators at positions 8, 13, 18, 23. Received: "${e}"`);let a=new Uint8Array(16);for(let o=0;o<36;o+=1){let s=r[o];if(s===-1)continue;let c=n(e.charCodeAt(o));if(c===-1)throw new t(`UUID_INVALID_HEX_CHAR`,`UUID string contains invalid hex character at position ${o}`);i[o]?a[s]=c<<4:a[s]|=c}return a}export{s as n,c as r,o as t};
//# sourceMappingURL=uuid-CnQIYoQi.mjs.map
{"version":3,"file":"uuid-CnQIYoQi.mjs","names":[],"sources":["../src/uuid/common/hex.ts","../src/uuid/common/uuid.ts"],"sourcesContent":["// ASCII code ranges for hex character validation\nconst ASCII_0 = 48 // '0'\nconst ASCII_9 = 57 // '9'\nconst ASCII_A = 65 // 'A'\nconst ASCII_F = 70 // 'F'\nconst ASCII_a = 97 // 'a'\nconst ASCII_f = 102 // 'f'\n\n/**\n * Convert a hex character ASCII code to its numeric value (0-15).\n * Returns -1 for invalid hex characters.\n */\nexport function hexValue(code: number): number {\n if (code >= ASCII_0 && code <= ASCII_9) {\n return code - ASCII_0\n }\n if (code >= ASCII_A && code <= ASCII_F) {\n return code - ASCII_A + 10\n }\n if (code >= ASCII_a && code <= ASCII_f) {\n return code - ASCII_a + 10\n }\n return -1 // Invalid hex character\n}\n","import { BufferError, ParseError } from '../../errors'\nimport { hexValue } from './hex'\n\nconst UUID_BYTE_LENGTH = 16\nconst UUID_STRING_LENGTH = 36\n\n// Mapping from UUID string position to byte index.\n// -1 indicates a dash position that should be skipped.\n// This avoids intermediate string allocations during parsing.\nconst UUID_CHAR_TO_BYTE: number[] = [\n 0,\n 0,\n 1,\n 1,\n 2,\n 2,\n 3,\n 3, // chars 0-7 → bytes 0-3\n -1, // char 8 is '-'\n 4,\n 4,\n 5,\n 5, // chars 9-12 → bytes 4-5\n -1, // char 13 is '-'\n 6,\n 6,\n 7,\n 7, // chars 14-17 → bytes 6-7\n -1, // char 18 is '-'\n 8,\n 8,\n 9,\n 9, // chars 19-22 → bytes 8-9\n -1, // char 23 is '-'\n 10,\n 10,\n 11,\n 11,\n 12,\n 12,\n 13,\n 13,\n 14,\n 14,\n 15,\n 15, // chars 24-35 → bytes 10-15\n]\n\n// Whether each position is the high nibble (true) or low nibble (false)\nconst UUID_CHAR_IS_HIGH: boolean[] = [\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false, // chars 0-7\n false, // dash (ignored)\n true,\n false,\n true,\n false, // chars 9-12\n false, // dash\n true,\n false,\n true,\n false, // chars 14-17\n false, // dash\n true,\n false,\n true,\n false, // chars 19-22\n false, // dash\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false,\n true,\n false, // chars 24-35\n]\n\n// Pre-computed lookup table for byte-to-hex conversion (0x00 -> \"00\", 0xff -> \"ff\")\n//\n// Note: this table must remain defined in the same module as `formatUuid`, otherwise the v8 optimizer\n// will cause a performance drop of ~36%.\nconst HEX_TABLE: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))\n\nexport function formatUuid(bytes: Uint8Array): string {\n if (bytes.length !== UUID_BYTE_LENGTH) {\n throw new BufferError(\n 'UUID_BYTES_INVALID_LENGTH',\n `UUID bytes must be exactly ${UUID_BYTE_LENGTH} bytes, got ${bytes.length}`,\n )\n }\n\n return formatUuidUnchecked(bytes)\n}\n\nexport function formatUuidUnchecked(bytes: Uint8Array): string {\n // Direct string concatenation - optimized for V8's string builder.\n // This approach avoids loop overhead and intermediate allocations.\n // See: https://github.com/uuidjs/uuid/pull/434\n return (\n HEX_TABLE[bytes[0]] +\n HEX_TABLE[bytes[1]] +\n HEX_TABLE[bytes[2]] +\n HEX_TABLE[bytes[3]] +\n '-' +\n HEX_TABLE[bytes[4]] +\n HEX_TABLE[bytes[5]] +\n '-' +\n HEX_TABLE[bytes[6]] +\n HEX_TABLE[bytes[7]] +\n '-' +\n HEX_TABLE[bytes[8]] +\n HEX_TABLE[bytes[9]] +\n '-' +\n HEX_TABLE[bytes[10]] +\n HEX_TABLE[bytes[11]] +\n HEX_TABLE[bytes[12]] +\n HEX_TABLE[bytes[13]] +\n HEX_TABLE[bytes[14]] +\n HEX_TABLE[bytes[15]]\n )\n}\n\nexport function parseUuid(value: string): Uint8Array {\n if (value.length !== UUID_STRING_LENGTH) {\n throw new ParseError('UUID_INVALID_LENGTH', `UUID string must be 36 characters, got ${value.length}`)\n }\n\n // Validate separator positions directly (more efficient than full loop)\n if (value[8] !== '-' || value[13] !== '-' || value[18] !== '-' || value[23] !== '-') {\n throw new ParseError(\n 'UUID_INVALID_SEPARATORS',\n `UUID string has invalid separators at positions 8, 13, 18, 23. Received: \"${value}\"`,\n )\n }\n\n // Parse bytes directly from UUID string without intermediate string allocations.\n // This avoids the 9 allocations (5 slices + 4 concatenations) of the naive approach.\n const bytes = new Uint8Array(UUID_BYTE_LENGTH)\n\n for (let i = 0; i < UUID_STRING_LENGTH; i += 1) {\n const byteIdx = UUID_CHAR_TO_BYTE[i]\n if (byteIdx === -1) continue // Skip dash positions\n\n const nibble = hexValue(value.charCodeAt(i))\n if (nibble === -1) {\n throw new ParseError('UUID_INVALID_HEX_CHAR', `UUID string contains invalid hex character at position ${i}`)\n }\n\n if (UUID_CHAR_IS_HIGH[i]) {\n bytes[byteIdx] = nibble << 4\n } else {\n bytes[byteIdx] |= nibble\n }\n }\n\n return bytes\n}\n"],"mappings":"2DAYA,SAAgB,EAAS,EAAsB,CAU7C,OATI,GAAQ,IAAW,GAAQ,GACtB,EAAO,GAEZ,GAAQ,IAAW,GAAQ,GACtB,EAAO,GAAU,GAEtB,GAAQ,IAAW,GAAQ,IACtB,EAAO,GAAU,GAEnB,EACT,CCpBA,MAMM,EAA8B,CAClC,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACF,EAGM,EAA+B,CACnC,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACF,EAMM,EAAsB,MAAM,KAAK,CAAE,OAAQ,GAAI,GAAI,EAAG,IAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,EAEjG,SAAgB,EAAW,EAA2B,CACpD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EACR,4BACA,4CAA6D,EAAM,QACrE,EAGF,OAAO,EAAoB,CAAK,CAClC,CAEA,SAAgB,EAAoB,EAA2B,CAI7D,OACE,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,IAChB,EAAU,EAAM,IAChB,IACA,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,KAChB,EAAU,EAAM,IAEpB,CAEA,SAAgB,EAAU,EAA2B,CACnD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAW,sBAAuB,0CAA0C,EAAM,QAAQ,EAItG,GAAI,EAAM,KAAO,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,IAC9E,MAAM,IAAI,EACR,0BACA,6EAA6E,EAAM,EACrF,EAKF,IAAM,EAAQ,IAAI,WAAW,EAAgB,EAE7C,IAAK,IAAI,EAAI,EAAG,EAAI,GAAoB,GAAK,EAAG,CAC9C,IAAM,EAAU,EAAkB,GAClC,GAAI,IAAY,GAAI,SAEpB,IAAM,EAAS,EAAS,EAAM,WAAW,CAAC,CAAC,EAC3C,GAAI,IAAW,GACb,MAAM,IAAI,EAAW,wBAAyB,0DAA0D,GAAG,EAGzG,EAAkB,GACpB,EAAM,GAAW,GAAU,EAE3B,EAAM,IAAY,CAEtB,CAEA,OAAO,CACT"}