uniku 0.0.12 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +63 -13
  2. package/build/{bytes-BBjKLOBR.mjs → bytes-DzcOKIx1.mjs} +1 -1
  3. package/build/{bytes-BBjKLOBR.mjs.map → bytes-DzcOKIx1.mjs.map} +1 -1
  4. package/build/cuid2/cuid2.d.mts.map +1 -1
  5. package/build/cuid2/cuid2.mjs +1 -1
  6. package/build/cuid2/cuid2.mjs.map +1 -1
  7. package/build/ksuid/ksuid.d.mts.map +1 -1
  8. package/build/ksuid/ksuid.mjs +1 -1
  9. package/build/ksuid/ksuid.mjs.map +1 -1
  10. package/build/nanoid/nanoid.d.mts.map +1 -1
  11. package/build/nanoid/nanoid.mjs +1 -1
  12. package/build/nanoid/nanoid.mjs.map +1 -1
  13. package/build/random-CGMm8owG.mjs +2 -0
  14. package/build/random-CGMm8owG.mjs.map +1 -0
  15. package/build/tsconfig.tsbuildinfo +1 -1
  16. package/build/typeid/typeid.d.mts +38 -0
  17. package/build/typeid/typeid.d.mts.map +1 -0
  18. package/build/typeid/typeid.mjs +2 -0
  19. package/build/typeid/typeid.mjs.map +1 -0
  20. package/build/ulid/ulid.d.mts.map +1 -1
  21. package/build/ulid/ulid.mjs +1 -1
  22. package/build/ulid/ulid.mjs.map +1 -1
  23. package/build/uuid/v4.mjs +1 -1
  24. package/build/uuid/v7.d.mts.map +1 -1
  25. package/build/uuid/v7.mjs +1 -1
  26. package/build/uuid/v7.mjs.map +1 -1
  27. package/build/{uuid-QysI8pWE.mjs → uuid-Ub6ladEr.mjs} +1 -1
  28. package/build/{uuid-QysI8pWE.mjs.map → uuid-Ub6ladEr.mjs.map} +1 -1
  29. package/package.json +21 -31
  30. package/src/common/bytes.ts +59 -0
  31. package/src/common/random.ts +66 -0
  32. package/src/cuid2/cuid2.ts +211 -0
  33. package/src/errors.ts +56 -0
  34. package/src/ksuid/base62.ts +103 -0
  35. package/src/ksuid/ksuid.ts +195 -0
  36. package/src/nanoid/nanoid.ts +257 -0
  37. package/src/typeid/typeid.ts +283 -0
  38. package/src/ulid/crockford.ts +249 -0
  39. package/src/ulid/ulid.ts +184 -0
  40. package/src/uuid/common/hex.ts +24 -0
  41. package/src/uuid/common/uuid.ts +157 -0
  42. package/src/uuid/v4.ts +119 -0
  43. package/src/uuid/v7.ts +182 -0
  44. package/build/random-DcKA4vF7.mjs +0 -2
  45. package/build/random-DcKA4vF7.mjs.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { BufferError, InvalidInputError, ParseError, UniqueIdError } from "../errors.mjs";
2
+ import { UuidV7Options } from "../uuid/v7.mjs";
3
+
4
+ //#region src/typeid/typeid.d.ts
5
+ type TypeidOptions = UuidV7Options;
6
+ type Typeid = {
7
+ (prefix: string, options?: TypeidOptions): string;
8
+ toBytes(id: string): Uint8Array;
9
+ fromBytes(prefix: string, bytes: Uint8Array): string;
10
+ toUuid(id: string): string;
11
+ fromUuid(prefix: string, uuid: string): string;
12
+ timestamp(id: string): number;
13
+ prefix(id: string): string;
14
+ suffix(id: string): string;
15
+ isValid(id: unknown): id is string;
16
+ };
17
+ /**
18
+ * Generate a TypeID string backed by UUID v7.
19
+ *
20
+ * TypeID combines a lowercase snake_case type prefix with a 26-character
21
+ * modified base32 encoding of a UUID v7, producing sortable domain identifiers
22
+ * such as `user_01h2xcejqtf2nbrexx3vqjhp41`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { typeid } from 'uniku/typeid'
27
+ *
28
+ * const id = typeid('user')
29
+ * // => "user_01h2xcejqtf2nbrexx3vqjhp41"
30
+ *
31
+ * const uuid = typeid.toUuid(id)
32
+ * const restored = typeid.fromUuid('user', uuid)
33
+ * ```
34
+ */
35
+ declare const typeid: Typeid;
36
+ //#endregion
37
+ export { BufferError, InvalidInputError, ParseError, Typeid, TypeidOptions, UniqueIdError, typeid };
38
+ //# sourceMappingURL=typeid.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeid.d.mts","names":["typeid: Typeid"],"sources":["../../src/typeid/typeid.ts"],"sourcesContent":[],"mappings":";;;;KAIY,aAAA,GAAgB;KAEhB,MAAA;6BACiB;EAH7B,OAAY,CAAA,EAAA,EAAA,MAAA,CAAA,EAIW,UAJK;EAE5B,SAAY,CAAA,MAAA,EAAA,MAAA,EAAA,KAAA,EAGuB,UAHvB,CAAA,EAAA,MAAA;EACiB,MAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EACN,QAAA,CAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EACY,SAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,MAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAsQnC,MAAaA,CAAAA,EAAAA,EAAAA,MAAQ,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;cAARA,QAAQ"}
@@ -0,0 +1,2 @@
1
+ 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};
2
+ //# sourceMappingURL=typeid.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeid.mjs","names":["BASE32_DECODE: number[]","prefix","suffix","typeid: Typeid"],"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 (prefix: string, options?: TypeidOptions): string\n toBytes(id: string): Uint8Array\n fromBytes(prefix: string, bytes: Uint8Array): string\n toUuid(id: string): string\n fromUuid(prefix: string, uuid: string): string\n timestamp(id: string): number\n prefix(id: string): string\n suffix(id: string): string\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":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ulid.d.mts","names":["ulid: Ulid"],"sources":["../../src/ulid/ulid.ts"],"sourcesContent":[],"mappings":";;;KAKY,WAAA;;;AAAZ;AAaA;EAEgB,MAAA,CAAA,EAVL,UAUK;EAAa;;;;EAChB,KAAA,CAAA,EAAA,MAAA;CACU;AACJ,KALP,IAAA,GAKO;EAAA,EAAA,EAAA,MAAA;EAgJnB,CAAA,aAnJgB,UAmJG,GAnJU,UAmJV,CAAA,CAAA,OAAA,EAnJ+B,WAmJ/B,GAAA,SAAA,EAAA,GAAA,EAnJ6D,IAmJ7D,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAnJqF,IAmJrF;aAlJN;uBACU;mBACJ;;;;;;;;cAgJNA,MAAM"}
1
+ {"version":3,"file":"ulid.d.mts","names":["ulid: Ulid"],"sources":["../../src/ulid/ulid.ts"],"sourcesContent":[],"mappings":";;;KAKY,WAAA;;;AAAZ;AAaA;EAEgB,MAAA,CAAA,EAVL,UAUK;EAAa;;;;EAChB,KAAA,CAAA,EAAA,MAAA;CACU;AACJ,KALP,IAAA,GAKO;EAAA,EAAA,EAAA,MAAA;EAuJnB,CAAA,aA1JgB,UA0JG,GA1JU,UA0JV,CAAA,CAAA,OAAA,EA1J+B,WA0J/B,GAAA,SAAA,EAAA,GAAA,EA1J6D,IA0J7D,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EA1JqF,IA0JrF;aAzJN;uBACU;mBACJ;;;;;;;;cAuJNA,MAAM"}
@@ -1,2 +1,2 @@
1
- import{BufferError as e,InvalidInputError as t,ParseError as n,UniqueIdError as r}from"../errors.mjs";import{r as i,t as a}from"../bytes-BBjKLOBR.mjs";import{t as o}from"../random-DcKA4vF7.mjs";const s=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,c=new Uint8Array(128);c.fill(255);for(let e=0;e<32;e+=1){let t=s.charCodeAt(e),n=s[e].toLowerCase().charCodeAt(0);c[t]=e,c[n]=e}function l(e){return s[Math.floor(e/35184372088832)&31]+s[Math.floor(e/1099511627776)&31]+s[Math.floor(e/34359738368)&31]+s[Math.floor(e/1073741824)&31]+s[Math.floor(e/33554432)&31]+s[Math.floor(e/1048576)&31]+s[Math.floor(e/32768)&31]+s[Math.floor(e/1024)&31]+s[Math.floor(e/32)&31]+s[e&31]}function u(e){return s[e[0]>>3&31]+s[(e[0]<<2|e[1]>>6)&31]+s[e[1]>>1&31]+s[(e[1]<<4|e[2]>>4)&31]+s[(e[2]<<1|e[3]>>7)&31]+s[e[3]>>2&31]+s[(e[3]<<3|e[4]>>5)&31]+s[e[4]&31]+s[e[5]>>3&31]+s[(e[5]<<2|e[6]>>6)&31]+s[e[6]>>1&31]+s[(e[6]<<4|e[7]>>4)&31]+s[(e[7]<<1|e[8]>>7)&31]+s[e[8]>>2&31]+s[(e[8]<<3|e[9]>>5)&31]+s[e[9]&31]}function d(e){let t=0;for(let r=0;r<10;r+=1){let i=c[e.charCodeAt(r)];if(i===255)throw new n(`ULID_INVALID_CHAR`,`Invalid ULID character: ${e[r]}`);t=t*32+i}return t}function f(e){if(e.length!==26)throw new n(`ULID_INVALID_LENGTH`,`ULID string must be 26 characters`);let t=new Uint8Array(16),r=c[e.charCodeAt(0)],i=c[e.charCodeAt(1)],a=c[e.charCodeAt(2)],o=c[e.charCodeAt(3)],s=c[e.charCodeAt(4)],l=c[e.charCodeAt(5)],u=c[e.charCodeAt(6)],d=c[e.charCodeAt(7)],f=c[e.charCodeAt(8)],p=c[e.charCodeAt(9)],m=c[e.charCodeAt(10)],h=c[e.charCodeAt(11)],g=c[e.charCodeAt(12)],_=c[e.charCodeAt(13)],v=c[e.charCodeAt(14)],y=c[e.charCodeAt(15)],b=c[e.charCodeAt(16)],x=c[e.charCodeAt(17)],S=c[e.charCodeAt(18)],C=c[e.charCodeAt(19)],w=c[e.charCodeAt(20)],T=c[e.charCodeAt(21)],E=c[e.charCodeAt(22)],D=c[e.charCodeAt(23)],O=c[e.charCodeAt(24)],k=c[e.charCodeAt(25)];if((r|i|a|o|s|l|u|d|f|p|m|h|g|_|v|y|b|x|S|C|w|T|E|D|O|k)&128){for(let t=0;t<26;t+=1)if(c[e.charCodeAt(t)]===255)throw new n(`ULID_INVALID_CHAR`,`Invalid ULID character: ${e[t]}`)}return t[0]=r<<5|i,t[1]=a<<3|o>>2,t[2]=o<<6|s<<1|l>>4,t[3]=l<<4|u>>1,t[4]=u<<7|d<<2|f>>3,t[5]=f<<5|p,t[6]=m<<3|h>>2,t[7]=h<<6|g<<1|_>>4,t[8]=_<<4|v>>1,t[9]=v<<7|y<<2|b>>3,t[10]=b<<5|x,t[11]=S<<3|C>>2,t[12]=C<<6|w<<1|T>>4,t[13]=T<<4|E>>1,t[14]=E<<7|D<<2|O>>3,t[15]=O<<5|k,t}function p(t){if(t.length<16)throw new e(`ULID_BYTES_TOO_SHORT`,`Byte array must be at least 16 bytes`);let n=0;for(let e=0;e<6;e+=1)n=n*256+t[e];return l(n)+u(t.subarray(6,16))}const m=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i,h={msecs:-1/0,lastRandom:new Uint8Array(10)};function g(t,n,r,a=0){if(!r)r=new Uint8Array(16),a=0;else if(a<0||a+16>r.length)throw new e(`ULID_BUFFER_OUT_OF_BOUNDS`,`ULID byte range ${a}:${a+15} is out of buffer bounds`);i(r,a,t);for(let e=0;e<10;e+=1)r[a+6+e]=n[e];return r}function _(e,n,r=0){let i,s,c=Date.now();if(e)if(i=e.msecs??c,e.random){if(e.random.length<10)throw new t(`ULID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 10 for ULID`);s=e.random}else s=o();else i=c,i>h.msecs?(s=o(),h.msecs=i,h.lastRandom.set(s.subarray(0,10))):(a(h.lastRandom),s=h.lastRandom);return n?(g(i,s,n,r),n):l(i)+u(s)}function v(e){return typeof e==`string`&&m.test(e)}const y=Object.assign(_,{toBytes:e=>f(e),fromBytes:e=>p(e),timestamp:e=>d(e.slice(0,10)),isValid:v,NIL:`00000000000000000000000000`,MAX:`7ZZZZZZZZZZZZZZZZZZZZZZZZZ`});export{e as BufferError,t as InvalidInputError,n as ParseError,r as UniqueIdError,y as ulid};
1
+ import{n as e}from"../random-CGMm8owG.mjs";import{BufferError as t,InvalidInputError as n,ParseError as r,UniqueIdError as i}from"../errors.mjs";import{r as a,t as o}from"../bytes-DzcOKIx1.mjs";const s=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,c=new Uint8Array(65536);c.fill(255);for(let e=0;e<32;e+=1){let t=s.charCodeAt(e),n=s[e].toLowerCase().charCodeAt(0);c[t]=e,c[n]=e}function l(e,t){return new r(`ULID_INVALID_CHAR`,`Invalid ULID character: ${e[t]}`)}function u(){return new r(`ULID_TIMESTAMP_OVERFLOW`,`ULID timestamp exceeds 48 bits`)}function d(e){let t=c[e.charCodeAt(0)];if(t===255)throw l(e,0);if(t>7)throw u();let n=t;for(let t=1;t<10;t+=1){let r=c[e.charCodeAt(t)];if(r===255)throw l(e,t);n=n*32+r}return n}function f(e){return s[Math.floor(e/35184372088832)&31]+s[Math.floor(e/1099511627776)&31]+s[Math.floor(e/34359738368)&31]+s[Math.floor(e/1073741824)&31]+s[Math.floor(e/33554432)&31]+s[Math.floor(e/1048576)&31]+s[Math.floor(e/32768)&31]+s[Math.floor(e/1024)&31]+s[Math.floor(e/32)&31]+s[e&31]}function p(e){return s[e[0]>>3&31]+s[(e[0]<<2|e[1]>>6)&31]+s[e[1]>>1&31]+s[(e[1]<<4|e[2]>>4)&31]+s[(e[2]<<1|e[3]>>7)&31]+s[e[3]>>2&31]+s[(e[3]<<3|e[4]>>5)&31]+s[e[4]&31]+s[e[5]>>3&31]+s[(e[5]<<2|e[6]>>6)&31]+s[e[6]>>1&31]+s[(e[6]<<4|e[7]>>4)&31]+s[(e[7]<<1|e[8]>>7)&31]+s[e[8]>>2&31]+s[(e[8]<<3|e[9]>>5)&31]+s[e[9]&31]}function m(e){if(e.length!==26)throw new r(`ULID_INVALID_LENGTH`,`ULID string must be 26 characters`);return d(e)}function h(e){if(e.length!==26)throw new r(`ULID_INVALID_LENGTH`,`ULID string must be 26 characters`);let t=new Uint8Array(16),n=c[e.charCodeAt(0)],i=c[e.charCodeAt(1)],a=c[e.charCodeAt(2)],o=c[e.charCodeAt(3)],s=c[e.charCodeAt(4)],d=c[e.charCodeAt(5)],f=c[e.charCodeAt(6)],p=c[e.charCodeAt(7)],m=c[e.charCodeAt(8)],h=c[e.charCodeAt(9)],g=c[e.charCodeAt(10)],_=c[e.charCodeAt(11)],v=c[e.charCodeAt(12)],y=c[e.charCodeAt(13)],b=c[e.charCodeAt(14)],x=c[e.charCodeAt(15)],S=c[e.charCodeAt(16)],C=c[e.charCodeAt(17)],w=c[e.charCodeAt(18)],T=c[e.charCodeAt(19)],E=c[e.charCodeAt(20)],D=c[e.charCodeAt(21)],O=c[e.charCodeAt(22)],k=c[e.charCodeAt(23)],A=c[e.charCodeAt(24)],j=c[e.charCodeAt(25)];if((n|i|a|o|s|d|f|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(c[e.charCodeAt(t)]===255)throw l(e,t)}if(n>7)throw u();return t[0]=n<<5|i,t[1]=a<<3|o>>2,t[2]=o<<6|s<<1|d>>4,t[3]=d<<4|f>>1,t[4]=f<<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 g(e){if(e.length<16)throw new t(`ULID_BYTES_TOO_SHORT`,`Byte array must be at least 16 bytes`);let n=0;for(let t=0;t<6;t+=1)n=n*256+e[t];return f(n)+p(e.subarray(6,16))}const _=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i,v={msecs:-1/0,lastRandom:new Uint8Array(10)};function y(e,n,r,i=0){if(!r)r=new Uint8Array(16),i=0;else if(i<0||i+16>r.length)throw new t(`ULID_BUFFER_OUT_OF_BOUNDS`,`ULID byte range ${i}:${i+15} is out of buffer bounds`);a(r,i,e);for(let e=0;e<10;e+=1)r[i+6+e]=n[e];return r}function b(t,r,i=0){let a,s,c=Date.now();if(t)if(a=t.msecs??c,t.random){if(t.random.length<10)throw new n(`ULID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 10 for ULID`);s=t.random}else s=e();else if(a=c,a>v.msecs)s=e(),v.msecs=a,v.lastRandom.set(s.subarray(0,10));else{if(a=v.msecs,!o(v.lastRandom))throw v.lastRandom.fill(255),new n(`ULID_RANDOM_OVERFLOW`,`ULID random component overflowed while preserving monotonic order`);s=v.lastRandom}return r?(y(a,s,r,i),r):f(a)+p(s)}function x(e){return typeof e==`string`&&_.test(e)}const S=Object.assign(b,{toBytes:e=>h(e),fromBytes:e=>g(e),timestamp:e=>m(e),isValid:x,NIL:`00000000000000000000000000`,MAX:`7ZZZZZZZZZZZZZZZZZZZZZZZZZ`});export{t as BufferError,n as InvalidInputError,r as ParseError,i as UniqueIdError,S as ulid};
2
2
  //# sourceMappingURL=ulid.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ulid.mjs","names":["state: UlidState","time: number","random: Uint8Array","ulid: Ulid"],"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 indexed by ASCII code (0-127)\n// Uses Uint8Array for cache-efficient lookups via charCodeAt\nconst DECODING = new Uint8Array(128)\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\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 the first 10 characters of a ULID string to a timestamp (Unix epoch milliseconds).\n */\nexport function decodeTime(str: string): number {\n let time = 0\n for (let i = 0; i < TIME_LEN; i += 1) {\n const value = DECODING[str.charCodeAt(i)]\n if (value === 255) {\n throw new ParseError('ULID_INVALID_CHAR', `Invalid ULID character: ${str[i]}`)\n }\n time = time * 32 + value\n }\n return time\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 !== 26) {\n throw new ParseError('ULID_INVALID_LENGTH', 'ULID string must be 26 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 (255 = invalid marker)\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 ) {\n // Find the invalid character for error message\n for (let i = 0; i < 26; i += 1) {\n if (DECODING[str.charCodeAt(i)] === 255) {\n throw new ParseError('ULID_INVALID_CHAR', `Invalid ULID character: ${str[i]}`)\n }\n }\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_TOO_SHORT', 'Byte array must be at least 16 bytes')\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 { BufferError, InvalidInputError } from '../errors'\nimport { bytesToUlid, decodeTime, decodeToBytes, 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 (): string\n <TBuf extends Uint8Array = Uint8Array>(options: UlidOptions | undefined, buf: TBuf, offset?: number): TBuf\n (options?: UlidOptions, 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 /** 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\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(10),\n}\n\nfunction ulidBytes(time: number, random: Uint8Array, buf?: Uint8Array, offset = 0): Uint8Array {\n if (!buf) {\n buf = new Uint8Array(16)\n offset = 0\n } else if (offset < 0 || offset + 16 > buf.length) {\n throw new BufferError(\n 'ULID_BUFFER_OUT_OF_BOUNDS',\n `ULID byte range ${offset}:${offset + 15} is out of buffer bounds`,\n )\n }\n\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 < 10; i += 1) {\n buf[offset + 6 + i] = random[i]\n }\n\n return buf\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 const defaultTime = Date.now()\n\n if (options) {\n // Explicit options provided - use them directly without monotonic state\n time = options.msecs ?? defaultTime\n if (options.random) {\n if (options.random.length < 10) {\n throw new InvalidInputError('ULID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 10 for ULID')\n }\n random = options.random\n } else {\n random = rng()\n }\n } else {\n time = defaultTime\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, 10))\n } else {\n // Same millisecond: increment random portion for monotonic ordering\n incrementBytesInPlace(state.lastRandom)\n random = state.lastRandom\n }\n }\n\n if (buf) {\n ulidBytes(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\nexport const ulid: Ulid = Object.assign(ulidFn, {\n toBytes: (id: string) => decodeToBytes(id),\n fromBytes: (bytes: Uint8Array) => bytesToUlid(bytes),\n timestamp: (id: string) => decodeTime(id.slice(0, 10)),\n isValid,\n NIL: '00000000000000000000000000',\n MAX: '7ZZZZZZZZZZZZZZZZZZZZZZZZZ',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"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"}
1
+ {"version":3,"file":"ulid.mjs","names":["state: UlidState","time: number","random: Uint8Array","ulid: Ulid"],"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_TOO_SHORT', 'Byte array must be at least 16 bytes')\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 { 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 (): string\n <TBuf extends Uint8Array = Uint8Array>(options: UlidOptions | undefined, buf: TBuf, offset?: number): TBuf\n (options?: UlidOptions, 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 /** 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\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(10),\n}\n\nfunction ulidBytes(time: number, random: Uint8Array, buf?: Uint8Array, offset = 0): Uint8Array {\n if (!buf) {\n buf = new Uint8Array(16)\n offset = 0\n } else if (offset < 0 || offset + 16 > buf.length) {\n throw new BufferError(\n 'ULID_BUFFER_OUT_OF_BOUNDS',\n `ULID byte range ${offset}:${offset + 15} is out of buffer bounds`,\n )\n }\n\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 < 10; i += 1) {\n buf[offset + 6 + i] = random[i]\n }\n\n return buf\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 const defaultTime = Date.now()\n\n if (options) {\n // Explicit options provided - use them directly without monotonic state\n time = options.msecs ?? defaultTime\n if (options.random) {\n if (options.random.length < 10) {\n throw new InvalidInputError('ULID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 10 for ULID')\n }\n random = options.random\n } else {\n random = rng()\n }\n } else {\n time = defaultTime\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, 10))\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 ulidBytes(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\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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"}
package/build/uuid/v4.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{BufferError as e,InvalidInputError as t,ParseError as n,UniqueIdError as r}from"../errors.mjs";import{t as i}from"../random-DcKA4vF7.mjs";import{n as a,t as o}from"../uuid-QysI8pWE.mjs";const s=globalThis.crypto.randomUUID.bind(globalThis.crypto),c=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function l(n,r,i=0){if(n.length<16)throw new t(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);if(n[6]=n[6]&15|64,n[8]=n[8]&63|128,!r)return n;if(i<0||i+16>r.length)throw new e(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${i}:${i+15} is out of buffer bounds`);for(let e=0;e<16;e+=1)r[i+e]=n[e];return r}function u(e,t,n){return!t&&!e?s():d(e,t,n)}function d(e,t,n){let r=l(e?.random??i(),t,n);return t??o(r)}function f(e){return typeof e==`string`&&c.test(e)}const p=Object.assign(u,{toBytes:a,fromBytes:o,isValid:f,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{e as BufferError,t as InvalidInputError,n as ParseError,r as UniqueIdError,p as uuidv4};
1
+ import{n as e}from"../random-CGMm8owG.mjs";import{BufferError as t,InvalidInputError as n,ParseError as r,UniqueIdError as i}from"../errors.mjs";import{n as a,t as o}from"../uuid-Ub6ladEr.mjs";const s=globalThis.crypto.randomUUID.bind(globalThis.crypto),c=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function l(e,r,i=0){if(e.length<16)throw new n(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);if(e[6]=e[6]&15|64,e[8]=e[8]&63|128,!r)return e;if(i<0||i+16>r.length)throw new t(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${i}:${i+15} is out of buffer bounds`);for(let t=0;t<16;t+=1)r[i+t]=e[t];return r}function u(e,t,n){return!t&&!e?s():d(e,t,n)}function d(t,n,r){let i=l(t?.random??e(),n,r);return n??o(i)}function f(e){return typeof e==`string`&&c.test(e)}const p=Object.assign(u,{toBytes:a,fromBytes:o,isValid:f,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{t as BufferError,n as InvalidInputError,r as ParseError,i as UniqueIdError,p as uuidv4};
2
2
  //# sourceMappingURL=v4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"v7.d.mts","names":["uuidv7: UuidV7"],"sources":["../../src/uuid/v7.ts"],"sourcesContent":[],"mappings":";;;KAIY,aAAA;;;AAAZ;AAUA;EAEgB,MAAA,CAAA,EAPL,UAOK;EAAa,KAAA,CAAA,EAAA,MAAA;EAAqB,GAAA,CAAA,EAAA,MAAA;CAAgC;AAAwB,KAF9F,MAAA,GAE8F;EAC7F,EAAA,EAAA,MAAA;EACU,CAAA,aAFP,UAEO,GAFM,UAEN,CAAA,CAAA,OAAA,EAF2B,aAE3B,GAAA,SAAA,EAAA,GAAA,EAF2D,IAE3D,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAFmF,IAEnF;EACJ,CAAA,OAAA,CAAA,EAFN,aAEM,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EADI,UACJ;EAwJnB,SAAaA,CAAAA,KAAQ,EAxJF,UAwJE,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAARA,QAAQ"}
1
+ {"version":3,"file":"v7.d.mts","names":["uuidv7: UuidV7"],"sources":["../../src/uuid/v7.ts"],"sourcesContent":[],"mappings":";;;KAIY,aAAA;;;AAAZ;AAUA;EAEgB,MAAA,CAAA,EAPL,UAOK;EAAa,KAAA,CAAA,EAAA,MAAA;EAAqB,GAAA,CAAA,EAAA,MAAA;CAAgC;AAAwB,KAF9F,MAAA,GAE8F;EAC7F,EAAA,EAAA,MAAA;EACU,CAAA,aAFP,UAEO,GAFM,UAEN,CAAA,CAAA,OAAA,EAF2B,aAE3B,GAAA,SAAA,EAAA,GAAA,EAF2D,IAE3D,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAFmF,IAEnF;EACJ,CAAA,OAAA,CAAA,EAFN,aAEM,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EADI,UACJ;EAyJnB,SAAaA,CAAAA,KAAQ,EAzJF,UAyJE,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAARA,QAAQ"}
package/build/uuid/v7.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{BufferError as e,InvalidInputError as t,ParseError as n,UniqueIdError as r}from"../errors.mjs";import{t as i}from"../random-DcKA4vF7.mjs";import{n as a,t as o}from"../uuid-QysI8pWE.mjs";const s=/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,c=new Uint8Array(16),l={msecs:-1/0,seq:0};function u(n,r,i,a,o=0){if(n.length<16)throw new t(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);if(o<0||o+16>a.length)throw new e(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${o}:${o+15} is out of buffer bounds`);return r??=Date.now(),i??=n[6]<<23|n[7]<<16|n[8]<<8|n[9],a[o++]=r/1099511627776&255,a[o++]=r/4294967296&255,a[o++]=r/16777216&255,a[o++]=r/65536&255,a[o++]=r/256&255,a[o++]=r&255,a[o++]=112|i>>>28&15,a[o++]=i>>>20&255,a[o++]=128|i>>>14&63,a[o++]=i>>>6&255,a[o++]=i<<2&255|n[10]&3,a[o++]=n[11],a[o++]=n[12],a[o++]=n[13],a[o++]=n[14],a[o++]=n[15],a}function d(e,t,n){let r;if(e)r=u(e.random??i(),e.msecs,e.seq,t??c,t?n:0);else{let e=Date.now(),a=i();e>l.msecs?(l.seq=a[6]<<23|a[7]<<16|a[8]<<8|a[9],l.msecs=e):(l.seq=l.seq+1|0,l.seq===0&&l.msecs++),r=u(a,l.msecs,l.seq,t??c,t?n:0)}return t?r:o(r)}function f(e){let t=a(e),n=0;for(let e=0;e<6;e+=1)n=n*256+t[e];return n}function p(e){return typeof e==`string`&&s.test(e)}const m=Object.assign(d,{toBytes:a,fromBytes:o,timestamp:f,isValid:p,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{e as BufferError,t as InvalidInputError,n as ParseError,r as UniqueIdError,m as uuidv7};
1
+ import{n as e}from"../random-CGMm8owG.mjs";import{BufferError as t,InvalidInputError as n,ParseError as r,UniqueIdError as i}from"../errors.mjs";import{n as a,t as o}from"../uuid-Ub6ladEr.mjs";const s=/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,c=new Uint8Array(16),l={msecs:-1/0,seq:0};function u(e,r,i,a,o=0){if(e.length<16)throw new n(`UUID_RANDOM_BYTES_TOO_SHORT`,`Random bytes length must be >= 16`);if(o<0||o+16>a.length)throw new t(`UUID_BUFFER_OUT_OF_BOUNDS`,`UUID byte range ${o}:${o+15} is out of buffer bounds`);return r??=Date.now(),i??=e[6]<<23|e[7]<<16|e[8]<<8|e[9],a[o++]=r/1099511627776&255,a[o++]=r/4294967296&255,a[o++]=r/16777216&255,a[o++]=r/65536&255,a[o++]=r/256&255,a[o++]=r&255,a[o++]=112|i>>>28&15,a[o++]=i>>>20&255,a[o++]=128|i>>>14&63,a[o++]=i>>>6&255,a[o++]=i<<2&255|e[10]&3,a[o++]=e[11],a[o++]=e[12],a[o++]=e[13],a[o++]=e[14],a[o++]=e[15],a}function d(t,n,r){let i;if(t)i=u(t.random??e(),t.msecs,t.seq,n??c,n?r:0);else{let t=Date.now(),a=e();t>l.msecs?(l.seq=a[6]<<23|a[7]<<16|a[8]<<8|a[9],l.msecs=t):(l.seq=l.seq+1|0,l.seq<0&&(l.seq=0,l.msecs++)),i=u(a,l.msecs,l.seq,n??c,n?r:0)}return n?i:o(i)}function f(e){let t=a(e),n=0;for(let e=0;e<6;e+=1)n=n*256+t[e];return n}function p(e){return typeof e==`string`&&s.test(e)}const m=Object.assign(d,{toBytes:a,fromBytes:o,timestamp:f,isValid:p,NIL:`00000000-0000-0000-0000-000000000000`,MAX:`ffffffff-ffff-ffff-ffff-ffffffffffff`});export{t as BufferError,n as InvalidInputError,r as ParseError,i as UniqueIdError,m as uuidv7};
2
2
  //# sourceMappingURL=v7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"v7.mjs","names":["state: V7State","bytes: Uint8Array","uuidv7: UuidV7"],"sources":["../../src/uuid/v7.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, 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 msecs?: number\n seq?: number\n}\n\nexport type UuidV7 = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\n (options?: UuidV7Options, 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 /** 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\n\n// Reusable buffer for string output path - avoids allocation per call.\n// Safe because bytes are consumed synchronously by formatUuid().\nconst reusableBuf = new Uint8Array(16)\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 v7Bytes(\n rnds: Uint8Array,\n msecs: number | undefined,\n seq: number | undefined,\n buf: Uint8Array,\n offset = 0,\n): Uint8Array {\n if (rnds.length < 16) {\n throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16')\n }\n\n if (offset < 0 || offset + 16 > buf.length) {\n throw new BufferError(\n 'UUID_BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${offset}:${offset + 15} is out of buffer bounds`,\n )\n }\n\n msecs ??= Date.now()\n // Derive a 31-bit sequence if not provided by the caller.\n // Uses same formula as hot path (line 130) for consistency.\n seq ??= (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n\n // Timestamp (48-bit big-endian milliseconds since Unix epoch).\n // byte 0-5: timestamp (48 bits)\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 return buf\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 let bytes: Uint8Array\n\n if (options) {\n bytes = v7Bytes(options.random ?? rng(), options.msecs, options.seq, buf ?? reusableBuf, buf ? offset : 0)\n } else {\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.msecs++\n }\n }\n\n bytes = v7Bytes(rnds, state.msecs, state.seq, buf ?? reusableBuf, buf ? offset : 0)\n }\n\n return buf ? (bytes as TBuf) : formatUuid(bytes)\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":"iMA4BA,MAAM,EAAgB,yEAIhB,EAAc,IAAI,WAAW,GAAG,CAehCA,EAAiB,CAAE,MAAO,KAAW,IAAK,EAAG,CAEnD,SAAS,EACP,EACA,EACA,EACA,EACA,EAAS,EACG,CACZ,GAAI,EAAK,OAAS,GAChB,MAAM,IAAI,EAAkB,8BAA+B,oCAAoC,CAGjG,GAAI,EAAS,GAAK,EAAS,GAAK,EAAI,OAClC,MAAM,IAAI,EACR,4BACA,mBAAmB,EAAO,GAAG,EAAS,GAAG,0BAC1C,CA8BH,MA3BA,KAAU,KAAK,KAAK,CAGpB,IAAS,EAAK,IAAM,GAAO,EAAK,IAAM,GAAO,EAAK,IAAM,EAAK,EAAK,GAIlE,EAAI,KAAa,EAAQ,cAAiB,IAC1C,EAAI,KAAa,EAAQ,WAAe,IACxC,EAAI,KAAa,EAAQ,SAAa,IACtC,EAAI,KAAa,EAAQ,MAAW,IACpC,EAAI,KAAa,EAAQ,IAAS,IAClC,EAAI,KAAY,EAAQ,IAGxB,EAAI,KAAY,IAAS,IAAQ,GAAM,GACvC,EAAI,KAAa,IAAQ,GAAM,IAC/B,EAAI,KAAY,IAAS,IAAQ,GAAM,GACvC,EAAI,KAAa,IAAQ,EAAK,IAE9B,EAAI,KAAc,GAAO,EAAK,IAAS,EAAK,IAAM,EAClD,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IAEd,EAWT,SAAS,EAAyC,EAAyB,EAAY,EAAgC,CACrH,IAAIC,EAEJ,GAAI,EACF,EAAQ,EAAQ,EAAQ,QAAU,GAAK,CAAE,EAAQ,MAAO,EAAQ,IAAK,GAAO,EAAa,EAAM,EAAS,EAAE,KACrG,CAEL,IAAM,EAAM,KAAK,KAAK,CAChB,EAAO,GAAK,CAGd,EAAM,EAAM,OACd,EAAM,IAAO,EAAK,IAAM,GAAO,EAAK,IAAM,GAAO,EAAK,IAAM,EAAK,EAAK,GACtE,EAAM,MAAQ,IAEd,EAAM,IAAO,EAAM,IAAM,EAAK,EAC1B,EAAM,MAAQ,GAChB,EAAM,SAIV,EAAQ,EAAQ,EAAM,EAAM,MAAO,EAAM,IAAK,GAAO,EAAa,EAAM,EAAS,EAAE,CAGrF,OAAO,EAAO,EAAiB,EAAW,EAAM,CAGlD,SAAS,EAAU,EAAoB,CACrC,IAAM,EAAQ,EAAU,EAAG,CACvB,EAAQ,EACZ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,GAAK,EAC1B,EAAQ,EAAQ,IAAM,EAAM,GAE9B,OAAO,EAGT,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAc,KAAK,EAAG,CA6BzD,MAAaC,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,YACA,UACA,IAAK,uCACL,IAAK,uCACN,CAAC"}
1
+ {"version":3,"file":"v7.mjs","names":["state: V7State","bytes: Uint8Array","uuidv7: UuidV7"],"sources":["../../src/uuid/v7.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, 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 msecs?: number\n seq?: number\n}\n\nexport type UuidV7 = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf\n (options?: UuidV7Options, 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 /** 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\n\n// Reusable buffer for string output path - avoids allocation per call.\n// Safe because bytes are consumed synchronously by formatUuid().\nconst reusableBuf = new Uint8Array(16)\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 v7Bytes(\n rnds: Uint8Array,\n msecs: number | undefined,\n seq: number | undefined,\n buf: Uint8Array,\n offset = 0,\n): Uint8Array {\n if (rnds.length < 16) {\n throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16')\n }\n\n if (offset < 0 || offset + 16 > buf.length) {\n throw new BufferError(\n 'UUID_BUFFER_OUT_OF_BOUNDS',\n `UUID byte range ${offset}:${offset + 15} is out of buffer bounds`,\n )\n }\n\n msecs ??= Date.now()\n // Derive a 31-bit sequence if not provided by the caller.\n // Uses the same formula as the hot path for consistency.\n seq ??= (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n\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 return buf\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 let bytes: Uint8Array\n\n if (options) {\n bytes = v7Bytes(options.random ?? rng(), options.msecs, options.seq, buf ?? reusableBuf, buf ? offset : 0)\n } else {\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 bytes = v7Bytes(rnds, state.msecs, state.seq, buf ?? reusableBuf, buf ? offset : 0)\n }\n\n return buf ? (bytes as TBuf) : formatUuid(bytes)\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":"iMA4BA,MAAM,EAAgB,yEAIhB,EAAc,IAAI,WAAW,GAAG,CAehCA,EAAiB,CAAE,MAAO,KAAW,IAAK,EAAG,CAEnD,SAAS,EACP,EACA,EACA,EACA,EACA,EAAS,EACG,CACZ,GAAI,EAAK,OAAS,GAChB,MAAM,IAAI,EAAkB,8BAA+B,oCAAoC,CAGjG,GAAI,EAAS,GAAK,EAAS,GAAK,EAAI,OAClC,MAAM,IAAI,EACR,4BACA,mBAAmB,EAAO,GAAG,EAAS,GAAG,0BAC1C,CA8BH,MA3BA,KAAU,KAAK,KAAK,CAGpB,IAAS,EAAK,IAAM,GAAO,EAAK,IAAM,GAAO,EAAK,IAAM,EAAK,EAAK,GAIlE,EAAI,KAAa,EAAQ,cAAiB,IAC1C,EAAI,KAAa,EAAQ,WAAe,IACxC,EAAI,KAAa,EAAQ,SAAa,IACtC,EAAI,KAAa,EAAQ,MAAW,IACpC,EAAI,KAAa,EAAQ,IAAS,IAClC,EAAI,KAAY,EAAQ,IAGxB,EAAI,KAAY,IAAS,IAAQ,GAAM,GACvC,EAAI,KAAa,IAAQ,GAAM,IAC/B,EAAI,KAAY,IAAS,IAAQ,GAAM,GACvC,EAAI,KAAa,IAAQ,EAAK,IAE9B,EAAI,KAAc,GAAO,EAAK,IAAS,EAAK,IAAM,EAClD,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IACrB,EAAI,KAAY,EAAK,IAEd,EAWT,SAAS,EAAyC,EAAyB,EAAY,EAAgC,CACrH,IAAIC,EAEJ,GAAI,EACF,EAAQ,EAAQ,EAAQ,QAAU,GAAK,CAAE,EAAQ,MAAO,EAAQ,IAAK,GAAO,EAAa,EAAM,EAAS,EAAE,KACrG,CAEL,IAAM,EAAM,KAAK,KAAK,CAChB,EAAO,GAAK,CAGd,EAAM,EAAM,OACd,EAAM,IAAO,EAAK,IAAM,GAAO,EAAK,IAAM,GAAO,EAAK,IAAM,EAAK,EAAK,GACtE,EAAM,MAAQ,IAEd,EAAM,IAAO,EAAM,IAAM,EAAK,EAC1B,EAAM,IAAM,IACd,EAAM,IAAM,EACZ,EAAM,UAIV,EAAQ,EAAQ,EAAM,EAAM,MAAO,EAAM,IAAK,GAAO,EAAa,EAAM,EAAS,EAAE,CAGrF,OAAO,EAAO,EAAiB,EAAW,EAAM,CAGlD,SAAS,EAAU,EAAoB,CACrC,IAAM,EAAQ,EAAU,EAAG,CACvB,EAAQ,EACZ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,GAAK,EAC1B,EAAQ,EAAQ,IAAM,EAAM,GAE9B,OAAO,EAGT,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAc,KAAK,EAAG,CA6BzD,MAAaC,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,YACA,UACA,IAAK,uCACL,IAAK,uCACN,CAAC"}
@@ -1,2 +1,2 @@
1
1
  import{ParseError as e}from"./errors.mjs";function t(e){return e>=48&&e<=57?e-48:e>=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:-1}const n=[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],r=[!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],i=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,`0`));function a(e){return i[e[0]]+i[e[1]]+i[e[2]]+i[e[3]]+`-`+i[e[4]]+i[e[5]]+`-`+i[e[6]]+i[e[7]]+`-`+i[e[8]]+i[e[9]]+`-`+i[e[10]]+i[e[11]]+i[e[12]]+i[e[13]]+i[e[14]]+i[e[15]]}function o(i){if(i.length!==36)throw new e(`UUID_INVALID_LENGTH`,`UUID string must be 36 characters, got ${i.length}`);if(i[8]!==`-`||i[13]!==`-`||i[18]!==`-`||i[23]!==`-`)throw new e(`UUID_INVALID_SEPARATORS`,`UUID string has invalid separators at positions 8, 13, 18, 23. Received: "${i}"`);let a=new Uint8Array(16);for(let o=0;o<36;o+=1){let s=n[o];if(s===-1)continue;let c=t(i.charCodeAt(o));if(c===-1)throw new e(`UUID_INVALID_HEX_CHAR`,`UUID string contains invalid hex character at position ${o}`);r[o]?a[s]=c<<4:a[s]|=c}return a}export{o as n,a as t};
2
- //# sourceMappingURL=uuid-QysI8pWE.mjs.map
2
+ //# sourceMappingURL=uuid-Ub6ladEr.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"uuid-QysI8pWE.mjs","names":["UUID_CHAR_TO_BYTE: number[]","UUID_CHAR_IS_HIGH: boolean[]","HEX_TABLE: string[]"],"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 { 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 // 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":"0CAYA,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,GCnBT,MAMMA,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,GACD,CAGKC,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,GACD,CAMKC,EAAsB,MAAM,KAAK,CAAE,OAAQ,IAAK,EAAG,EAAG,IAAM,EAAE,SAAS,GAAG,CAAC,SAAS,EAAG,IAAI,CAAC,CAElG,SAAgB,EAAW,EAA2B,CAIpD,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,KAIpB,SAAgB,EAAU,EAA2B,CACnD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAW,sBAAuB,0CAA0C,EAAM,SAAS,CAIvG,GAAI,EAAM,KAAO,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,IAC9E,MAAM,IAAI,EACR,0BACA,6EAA6E,EAAM,GACpF,CAKH,IAAM,EAAQ,IAAI,WAAW,GAAiB,CAE9C,IAAK,IAAI,EAAI,EAAG,EAAI,GAAoB,GAAK,EAAG,CAC9C,IAAM,EAAU,EAAkB,GAClC,GAAI,IAAY,GAAI,SAEpB,IAAM,EAAS,EAAS,EAAM,WAAW,EAAE,CAAC,CAC5C,GAAI,IAAW,GACb,MAAM,IAAI,EAAW,wBAAyB,0DAA0D,IAAI,CAG1G,EAAkB,GACpB,EAAM,GAAW,GAAU,EAE3B,EAAM,IAAY,EAItB,OAAO"}
1
+ {"version":3,"file":"uuid-Ub6ladEr.mjs","names":["UUID_CHAR_TO_BYTE: number[]","UUID_CHAR_IS_HIGH: boolean[]","HEX_TABLE: string[]"],"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 { 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 // 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":"0CAYA,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,GCnBT,MAMMA,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,GACD,CAGKC,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,GACD,CAMKC,EAAsB,MAAM,KAAK,CAAE,OAAQ,IAAK,EAAG,EAAG,IAAM,EAAE,SAAS,GAAG,CAAC,SAAS,EAAG,IAAI,CAAC,CAElG,SAAgB,EAAW,EAA2B,CAIpD,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,KAIpB,SAAgB,EAAU,EAA2B,CACnD,GAAI,EAAM,SAAW,GACnB,MAAM,IAAI,EAAW,sBAAuB,0CAA0C,EAAM,SAAS,CAIvG,GAAI,EAAM,KAAO,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,KAAO,EAAM,MAAQ,IAC9E,MAAM,IAAI,EACR,0BACA,6EAA6E,EAAM,GACpF,CAKH,IAAM,EAAQ,IAAI,WAAW,GAAiB,CAE9C,IAAK,IAAI,EAAI,EAAG,EAAI,GAAoB,GAAK,EAAG,CAC9C,IAAM,EAAU,EAAkB,GAClC,GAAI,IAAY,GAAI,SAEpB,IAAM,EAAS,EAAS,EAAM,WAAW,EAAE,CAAC,CAC5C,GAAI,IAAW,GACb,MAAM,IAAI,EAAW,wBAAyB,0DAA0D,IAAI,CAG1G,EAAkB,GACpB,EAAM,GAAW,GAAU,EAE3B,EAAM,IAAY,EAItB,OAAO"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "uniku",
4
- "version": "0.0.12",
5
- "description": "Minimal, tree-shakeable UUID utilities for every JavaScript runtime",
4
+ "version": "0.1.0",
5
+ "description": "Minimal, tree-shakeable unique ID generators for every JavaScript runtime",
6
6
  "author": {
7
7
  "name": "Alberto Schiabel",
8
8
  "email": "alberto.schiabel@gmail.com",
@@ -23,6 +23,7 @@
23
23
  "uuidv4",
24
24
  "uuidv7",
25
25
  "ulid",
26
+ "typeid",
26
27
  "cuid2",
27
28
  "nanoid",
28
29
  "ksuid",
@@ -45,69 +46,54 @@
45
46
  "access": "public"
46
47
  },
47
48
  "engines": {
48
- "node": ">=24.13.0"
49
+ "node": ">=20.19.0"
49
50
  },
50
51
  "type": "module",
51
52
  "sideEffects": false,
52
53
  "files": [
54
+ "src/**/*.ts",
53
55
  "build",
54
56
  "README.md"
55
57
  ],
56
58
  "exports": {
57
59
  "./uuid/v4": {
58
60
  "types": "./build/uuid/v4.d.mts",
59
- "import": {
60
- "@jkomyno/source": "./src/uuid/v4.ts",
61
- "default": "./build/uuid/v4.mjs"
62
- },
61
+ "import": "./build/uuid/v4.mjs",
63
62
  "default": "./build/uuid/v4.mjs"
64
63
  },
65
64
  "./uuid/v7": {
66
65
  "types": "./build/uuid/v7.d.mts",
67
- "import": {
68
- "@jkomyno/source": "./src/uuid/v7.ts",
69
- "default": "./build/uuid/v7.mjs"
70
- },
66
+ "import": "./build/uuid/v7.mjs",
71
67
  "default": "./build/uuid/v7.mjs"
72
68
  },
73
69
  "./ulid": {
74
70
  "types": "./build/ulid/ulid.d.mts",
75
- "import": {
76
- "@jkomyno/source": "./src/ulid/ulid.ts",
77
- "default": "./build/ulid/ulid.mjs"
78
- },
71
+ "import": "./build/ulid/ulid.mjs",
79
72
  "default": "./build/ulid/ulid.mjs"
80
73
  },
74
+ "./typeid": {
75
+ "types": "./build/typeid/typeid.d.mts",
76
+ "import": "./build/typeid/typeid.mjs",
77
+ "default": "./build/typeid/typeid.mjs"
78
+ },
81
79
  "./cuid2": {
82
80
  "types": "./build/cuid2/cuid2.d.mts",
83
- "import": {
84
- "@jkomyno/source": "./src/cuid2/cuid2.ts",
85
- "default": "./build/cuid2/cuid2.mjs"
86
- },
81
+ "import": "./build/cuid2/cuid2.mjs",
87
82
  "default": "./build/cuid2/cuid2.mjs"
88
83
  },
89
84
  "./nanoid": {
90
85
  "types": "./build/nanoid/nanoid.d.mts",
91
- "import": {
92
- "@jkomyno/source": "./src/nanoid/nanoid.ts",
93
- "default": "./build/nanoid/nanoid.mjs"
94
- },
86
+ "import": "./build/nanoid/nanoid.mjs",
95
87
  "default": "./build/nanoid/nanoid.mjs"
96
88
  },
97
89
  "./ksuid": {
98
90
  "types": "./build/ksuid/ksuid.d.mts",
99
- "import": {
100
- "@jkomyno/source": "./src/ksuid/ksuid.ts",
101
- "default": "./build/ksuid/ksuid.mjs"
102
- },
91
+ "import": "./build/ksuid/ksuid.mjs",
103
92
  "default": "./build/ksuid/ksuid.mjs"
104
93
  },
105
94
  "./errors": {
106
95
  "types": "./build/errors.d.mts",
107
- "import": {
108
- "@jkomyno/source": "./src/errors.ts",
109
- "default": "./build/errors.mjs"
110
- },
96
+ "import": "./build/errors.mjs",
111
97
  "default": "./build/errors.mjs"
112
98
  },
113
99
  "./package.json": "./package.json"
@@ -120,6 +106,7 @@
120
106
  "@paralleldrive/cuid2": "^3.3.0",
121
107
  "@types/bun": "^1.3.8",
122
108
  "nanoid": "^5.1.6",
109
+ "typeid-js": "1.2.0",
123
110
  "ulid": "3.0.2",
124
111
  "uuid": "13.0.0"
125
112
  },
@@ -132,6 +119,9 @@
132
119
  "test:integration": "vitest --project integration run",
133
120
  "test:e2e": "pnpm --filter @uniku/e2e-cloudflare test:e2e",
134
121
  "test:e2e:cloudflare": "pnpm --filter @uniku/e2e-cloudflare test:e2e:cloudflare",
122
+ "smoke:publish": "node scripts/publish-smoke.mjs",
123
+ "smoke:runtime:bun": "bun scripts/runtime-smoke.mjs",
124
+ "smoke:runtime:deno": "deno run --node-modules-dir=manual scripts/runtime-smoke.mjs",
135
125
  "bench": "vitest bench --run --project unit",
136
126
  "bench:compat": "vitest bench ./__tests__/bench/compat.bench.ts --run --project unit",
137
127
  "bench:summary": "bun scripts/bench-summary.ts",
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Common byte manipulation utilities shared across ID generators.
3
+ */
4
+
5
+ /**
6
+ * Increment a byte array by 1 in-place, propagating carry from LSB to MSB.
7
+ * Mutates the input array directly - no allocation.
8
+ *
9
+ * Used by ULID and KSUID for monotonic ordering within the same time unit.
10
+ *
11
+ * @returns true if increment succeeded, false if all bytes overflowed to 0
12
+ */
13
+ export function incrementBytesInPlace(bytes: Uint8Array): boolean {
14
+ for (let i = bytes.length - 1; i >= 0; i -= 1) {
15
+ if (bytes[i] < 255) {
16
+ bytes[i] += 1
17
+ return true
18
+ }
19
+ bytes[i] = 0
20
+ }
21
+
22
+ // All bytes overflowed to 0 - astronomically unlikely (1 in 2^80 for ULID, 1 in 2^128 for KSUID)
23
+ return false
24
+ }
25
+
26
+ /**
27
+ * Write a 48-bit timestamp as big-endian bytes.
28
+ * Used by UUID v7 and ULID for millisecond-precision timestamps.
29
+ *
30
+ * @param buf - Target buffer
31
+ * @param offset - Starting byte offset
32
+ * @param msecs - Milliseconds since Unix epoch (must fit in 48 bits)
33
+ */
34
+ export function writeTimestamp48(buf: Uint8Array, offset: number, msecs: number): void {
35
+ buf[offset] = (msecs / 0x10000000000) & 0xff
36
+ buf[offset + 1] = (msecs / 0x100000000) & 0xff
37
+ buf[offset + 2] = (msecs / 0x1000000) & 0xff
38
+ buf[offset + 3] = (msecs / 0x10000) & 0xff
39
+ buf[offset + 4] = (msecs / 0x100) & 0xff
40
+ buf[offset + 5] = msecs & 0xff
41
+ }
42
+
43
+ /**
44
+ * Write a 32-bit timestamp as big-endian bytes.
45
+ * Used by KSUID for second-precision timestamps.
46
+ *
47
+ * `writeTimestamp32(buf, offset, timestamp)` is equivalent to `new DataView(buf.buffer, offset, 4).setUint32(offset, timestamp, false)`,
48
+ * but it's faster because it doesn't require creating a DataView object.
49
+ *
50
+ * @param buf - Target buffer
51
+ * @param offset - Starting byte offset
52
+ * @param secs - Seconds (must fit in 32 bits)
53
+ */
54
+ export function writeTimestamp32(buf: Uint8Array, offset: number, secs: number): void {
55
+ buf[offset] = (secs >>> 24) & 0xff
56
+ buf[offset + 1] = (secs >>> 16) & 0xff
57
+ buf[offset + 2] = (secs >>> 8) & 0xff
58
+ buf[offset + 3] = secs & 0xff
59
+ }
@@ -0,0 +1,66 @@
1
+ const randomFill = /*@__PURE__*/ globalThis.crypto.getRandomValues.bind(globalThis.crypto)
2
+
3
+ /**
4
+ * Simple random byte pool for ID generation.
5
+ *
6
+ * Module-level state is per JavaScript isolate, so SharedArrayBuffer and Atomics
7
+ * only add overhead here. Returned views are consumed synchronously by callers.
8
+ */
9
+
10
+ const POOL_SIZE = 256
11
+ const pool = new Uint8Array(POOL_SIZE)
12
+ let poolOffset = POOL_SIZE
13
+
14
+ function refillPool(): void {
15
+ randomFill(pool)
16
+ poolOffset = 0
17
+ }
18
+
19
+ /**
20
+ * Return a view of `count` random bytes from the pool.
21
+ */
22
+ export function randomBytes(count: number): Uint8Array {
23
+ if (count > POOL_SIZE) {
24
+ return randomFill(new Uint8Array(count))
25
+ }
26
+
27
+ if (poolOffset + count > POOL_SIZE) {
28
+ refillPool()
29
+ }
30
+
31
+ const start = poolOffset
32
+ poolOffset += count
33
+ return pool.subarray(start, poolOffset)
34
+ }
35
+
36
+ /**
37
+ * Generate a random unsigned 32-bit integer from the shared pool.
38
+ */
39
+ export function randomUint32(): number {
40
+ if (poolOffset > POOL_SIZE - 4) {
41
+ refillPool()
42
+ }
43
+
44
+ const value =
45
+ (pool[poolOffset] * 0x1000000 +
46
+ pool[poolOffset + 1] * 0x10000 +
47
+ pool[poolOffset + 2] * 0x100 +
48
+ pool[poolOffset + 3]) >>>
49
+ 0
50
+ poolOffset += 4
51
+ return value
52
+ }
53
+
54
+ /**
55
+ * Generate 16 bytes of cryptographically strong random data.
56
+ * Uses a pre-filled pool to minimize crypto API calls.
57
+ */
58
+ export function rng(): Uint8Array {
59
+ if (poolOffset > POOL_SIZE - 16) {
60
+ refillPool()
61
+ }
62
+
63
+ const start = poolOffset
64
+ poolOffset += 16
65
+ return pool.subarray(start, poolOffset)
66
+ }