uniku 0.0.7 → 0.0.10

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 (41) hide show
  1. package/README.md +107 -20
  2. package/build/bytes-BBjKLOBR.mjs +2 -0
  3. package/build/bytes-BBjKLOBR.mjs.map +1 -0
  4. package/build/cuid2/cuid2.d.mts +3 -1
  5. package/build/cuid2/cuid2.d.mts.map +1 -1
  6. package/build/cuid2/cuid2.mjs +1 -1
  7. package/build/cuid2/cuid2.mjs.map +1 -1
  8. package/build/errors.d.mts +38 -0
  9. package/build/errors.d.mts.map +1 -0
  10. package/build/errors.mjs +2 -0
  11. package/build/errors.mjs.map +1 -0
  12. package/build/ksuid/ksuid.d.mts +8 -2
  13. package/build/ksuid/ksuid.d.mts.map +1 -1
  14. package/build/ksuid/ksuid.mjs +1 -1
  15. package/build/ksuid/ksuid.mjs.map +1 -1
  16. package/build/nanoid/nanoid.d.mts +46 -1
  17. package/build/nanoid/nanoid.d.mts.map +1 -1
  18. package/build/nanoid/nanoid.mjs +1 -1
  19. package/build/nanoid/nanoid.mjs.map +1 -1
  20. package/build/random-DcKA4vF7.mjs +2 -0
  21. package/build/random-DcKA4vF7.mjs.map +1 -0
  22. package/build/ulid/ulid.d.mts +8 -6
  23. package/build/ulid/ulid.d.mts.map +1 -1
  24. package/build/ulid/ulid.mjs +1 -1
  25. package/build/ulid/ulid.mjs.map +1 -1
  26. package/build/uuid/v4.d.mts +30 -6
  27. package/build/uuid/v4.d.mts.map +1 -1
  28. package/build/uuid/v4.mjs +1 -1
  29. package/build/uuid/v4.mjs.map +1 -1
  30. package/build/uuid/v7.d.mts +34 -6
  31. package/build/uuid/v7.d.mts.map +1 -1
  32. package/build/uuid/v7.mjs +1 -1
  33. package/build/uuid/v7.mjs.map +1 -1
  34. package/build/uuid-QysI8pWE.mjs +2 -0
  35. package/build/uuid-QysI8pWE.mjs.map +1 -0
  36. package/package.json +15 -6
  37. package/build/random-CPlgK_62.mjs +0 -2
  38. package/build/random-CPlgK_62.mjs.map +0 -1
  39. package/build/tsconfig.tsbuildinfo +0 -1
  40. package/build/uuid-DcbjGX9x.mjs +0 -2
  41. package/build/uuid-DcbjGX9x.mjs.map +0 -1
@@ -0,0 +1,2 @@
1
+ const e=globalThis.crypto.getRandomValues.bind(globalThis.crypto),t=new Uint8Array(256);let n=256;function r(){n>240&&(e(t),n=0);let r=n;return n+=16,t.subarray(r,n)}export{r as t};
2
+ //# sourceMappingURL=random-DcKA4vF7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random-DcKA4vF7.mjs","names":[],"sources":["../src/common/random.ts"],"sourcesContent":["const randomFill = /*@__PURE__*/ globalThis.crypto.getRandomValues.bind(globalThis.crypto)\n\n/**\n * Simple, fast random byte pool for ID generation.\n * Uses plain JavaScript for maximum performance - no Atomics overhead.\n * Thread safety is not needed for typical ID generation use cases.\n */\n\nconst POOL_SIZE = 256\nconst rnds8Pool = new Uint8Array(POOL_SIZE)\nlet poolPtr = POOL_SIZE // Start exhausted to trigger first fill\n\n/**\n * Generate 16 bytes of cryptographically strong random data.\n * Uses a pre-filled pool to minimize crypto API calls.\n */\nexport function rng(): Uint8Array {\n if (poolPtr > POOL_SIZE - 16) {\n randomFill(rnds8Pool)\n poolPtr = 0\n }\n // Return a view - consumed synchronously within the same call\n const start = poolPtr\n poolPtr += 16\n return rnds8Pool.subarray(start, poolPtr)\n}\n"],"mappings":"AAAA,MAAM,EAA2B,WAAW,OAAO,gBAAgB,KAAK,WAAW,OAAO,CASpF,EAAY,IAAI,WAAW,IAAU,CAC3C,IAAI,EAAU,IAMd,SAAgB,GAAkB,CAC5B,EAAU,MACZ,EAAW,EAAU,CACrB,EAAU,GAGZ,IAAM,EAAQ,EAEd,MADA,IAAW,GACJ,EAAU,SAAS,EAAO,EAAQ"}
@@ -1,3 +1,5 @@
1
+ import { BufferError, InvalidInputError, ParseError, UniqueIdError } from "../errors.mjs";
2
+
1
3
  //#region src/ulid/ulid.d.ts
2
4
  type UlidOptions = {
3
5
  /**
@@ -18,13 +20,13 @@ type Ulid = {
18
20
  toBytes(id: string): Uint8Array;
19
21
  fromBytes(bytes: Uint8Array): string;
20
22
  timestamp(id: string): number;
21
- isValid(id: string): boolean;
23
+ isValid(id: unknown): id is string;
24
+ /** The nil ULID (all zeros) */
25
+ NIL: string;
26
+ /** The max ULID (maximum valid value) */
27
+ MAX: string;
22
28
  };
23
- /**
24
- * Generate a ULID string or write the bytes into a buffer.
25
- * It also includes helpers to convert to and from byte arrays.
26
- */
27
29
  declare const ulid: Ulid;
28
30
  //#endregion
29
- export { Ulid, UlidOptions, ulid };
31
+ export { BufferError, InvalidInputError, ParseError, Ulid, UlidOptions, UniqueIdError, ulid };
30
32
  //# sourceMappingURL=ulid.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ulid.d.mts","names":["ulid: Ulid"],"sources":["../../src/ulid/ulid.ts"],"sourcesContent":[],"mappings":";KAGY,WAAA;EAAZ;AAaA;;;EAEkD,MAAA,CAAA,EAVvC,UAUuC;EAA8B;;;;EAG7D,KAAA,CAAA,EAAA,MAAA;CAAA;AA4HNA,KAjID,IAAA,GAiIO;;gBA/HH,aAAa,qBAAqB,8BAA8B,wBAAwB;aAC3F;uBACU;mBACJ;;;;;;;;cA4HNA,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;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,2 +1,2 @@
1
- import{t as e}from"../random-CPlgK_62.mjs";const t=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,n=new Uint8Array(128);n.fill(255);for(let e=0;e<32;e+=1){let r=t.charCodeAt(e),i=t[e].toLowerCase().charCodeAt(0);n[r]=e,n[i]=e}function r(e){return t[Math.floor(e/35184372088832)&31]+t[Math.floor(e/1099511627776)&31]+t[Math.floor(e/34359738368)&31]+t[Math.floor(e/1073741824)&31]+t[Math.floor(e/33554432)&31]+t[Math.floor(e/1048576)&31]+t[Math.floor(e/32768)&31]+t[Math.floor(e/1024)&31]+t[Math.floor(e/32)&31]+t[e&31]}function i(e){return t[e[0]>>3&31]+t[(e[0]<<2|e[1]>>6)&31]+t[e[1]>>1&31]+t[(e[1]<<4|e[2]>>4)&31]+t[(e[2]<<1|e[3]>>7)&31]+t[e[3]>>2&31]+t[(e[3]<<3|e[4]>>5)&31]+t[e[4]&31]+t[e[5]>>3&31]+t[(e[5]<<2|e[6]>>6)&31]+t[e[6]>>1&31]+t[(e[6]<<4|e[7]>>4)&31]+t[(e[7]<<1|e[8]>>7)&31]+t[e[8]>>2&31]+t[(e[8]<<3|e[9]>>5)&31]+t[e[9]&31]}function a(e){let t=0;for(let r=0;r<10;r+=1){let i=n[e.charCodeAt(r)];if(i===255)throw Error(`Invalid ULID character: ${e[r]}`);t=t*32+i}return t}function o(e){if(e.length!==26)throw Error(`ULID string must be 26 characters`);let t=new Uint8Array(16),r=n[e.charCodeAt(0)],i=n[e.charCodeAt(1)],a=n[e.charCodeAt(2)],o=n[e.charCodeAt(3)],s=n[e.charCodeAt(4)],c=n[e.charCodeAt(5)],l=n[e.charCodeAt(6)],u=n[e.charCodeAt(7)],d=n[e.charCodeAt(8)],f=n[e.charCodeAt(9)],p=n[e.charCodeAt(10)],m=n[e.charCodeAt(11)],h=n[e.charCodeAt(12)],g=n[e.charCodeAt(13)],_=n[e.charCodeAt(14)],v=n[e.charCodeAt(15)],y=n[e.charCodeAt(16)],b=n[e.charCodeAt(17)],x=n[e.charCodeAt(18)],S=n[e.charCodeAt(19)],C=n[e.charCodeAt(20)],w=n[e.charCodeAt(21)],T=n[e.charCodeAt(22)],E=n[e.charCodeAt(23)],D=n[e.charCodeAt(24)],O=n[e.charCodeAt(25)];if((r|i|a|o|s|c|l|u|d|f|p|m|h|g|_|v|y|b|x|S|C|w|T|E|D|O)&128){for(let t=0;t<26;t+=1)if(n[e.charCodeAt(t)]===255)throw Error(`Invalid ULID character: ${e[t]}`)}return t[0]=r<<5|i,t[1]=a<<3|o>>2,t[2]=o<<6|s<<1|c>>4,t[3]=c<<4|l>>1,t[4]=l<<7|u<<2|d>>3,t[5]=d<<5|f,t[6]=p<<3|m>>2,t[7]=m<<6|h<<1|g>>4,t[8]=g<<4|_>>1,t[9]=_<<7|v<<2|y>>3,t[10]=y<<5|b,t[11]=x<<3|S>>2,t[12]=S<<6|C<<1|w>>4,t[13]=w<<4|T>>1,t[14]=T<<7|E<<2|D>>3,t[15]=D<<5|O,t}function s(e){if(e.length<16)throw Error(`Byte array must be at least 16 bytes`);let t=0;for(let n=0;n<6;n+=1)t=t*256+e[n];return r(t)+i(e.subarray(6,16))}const c=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i,l={msecs:-1/0,lastRandom:new Uint8Array(10)};function u(e){let t=new Uint8Array(e);for(let e=t.length-1;e>=0;--e){if(t[e]<255)return t[e]+=1,t;t[e]=0}return t}function d(e,t,n,r=0){if(!n)n=new Uint8Array(16),r=0;else if(r<0||r+16>n.length)throw RangeError(`ULID byte range ${r}:${r+15} is out of buffer bounds`);n[r]=e/1099511627776&255,n[r+1]=e/4294967296&255,n[r+2]=e/16777216&255,n[r+3]=e/65536&255,n[r+4]=e/256&255,n[r+5]=e&255;for(let e=0;e<10;e+=1)n[r+6+e]=t[e];return n}function f(t,n,a=0){let o,s,c=Date.now();return t?(o=t.msecs??c,s=t.random??e()):(o=c,o>l.msecs?(s=e(),l.msecs=o,l.lastRandom.set(s.subarray(0,10))):(s=u(l.lastRandom),l.lastRandom=s)),n?(d(o,s,n,a),n):r(o)+i(s)}const p=Object.assign(f,{toBytes:e=>o(e),fromBytes:e=>s(e),timestamp:e=>a(e.slice(0,10)),isValid:e=>c.test(e)});export{p as ulid};
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};
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/common/crockford.ts","../../src/ulid/ulid.ts"],"sourcesContent":["// Crockford's Base32 alphabet (excludes I, L, O, U to avoid confusion)\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 Error(`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 Error('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 Error(`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 Error('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 { rng } from '../uuid/common/random'\nimport { bytesToUlid, decodeTime, decodeToBytes, encodeRandom, encodeTime } from './common/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: string): boolean\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\n/**\n * Increment a byte array by 1, propagating carry from LSB to MSB.\n * Returns a new array (does not modify input).\n */\nfunction incrementBytes(bytes: Uint8Array): Uint8Array {\n const result = new Uint8Array(bytes)\n for (let i = result.length - 1; i >= 0; i -= 1) {\n if (result[i] < 255) {\n result[i] += 1\n return result\n }\n result[i] = 0\n }\n return result\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 RangeError(`ULID byte range ${offset}:${offset + 15} is out of buffer bounds`)\n }\n\n // Timestamp (48-bit big-endian milliseconds since Unix epoch) -> bytes 0-5\n buf[offset] = (time / 0x10000000000) & 0xff\n buf[offset + 1] = (time / 0x100000000) & 0xff\n buf[offset + 2] = (time / 0x1000000) & 0xff\n buf[offset + 3] = (time / 0x10000) & 0xff\n buf[offset + 4] = (time / 0x100) & 0xff\n buf[offset + 5] = time & 0xff\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 random = options.random ?? rng()\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 random = incrementBytes(state.lastRandom)\n state.lastRandom = random\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 * It also includes helpers to convert to and from byte arrays.\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: (id: string) => ULID_REGEX.test(id),\n})\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 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,5 +1,7 @@
1
+ import { BufferError, InvalidInputError, ParseError, UniqueIdError } from "../errors.mjs";
2
+
1
3
  //#region src/uuid/v4.d.ts
2
- type Version4Options = {
4
+ type UuidV4Options = {
3
5
  /**
4
6
  * 16 bytes of random data to use for UUID generation.
5
7
  * Note: Bytes at index 6 and 8 will be modified in-place to set version/variant bits.
@@ -8,17 +10,39 @@ type Version4Options = {
8
10
  };
9
11
  type UuidV4 = {
10
12
  (): string;
11
- <TBuf extends Uint8Array = Uint8Array>(options: Version4Options | undefined, buf: TBuf, offset?: number): TBuf;
12
- (options?: Version4Options, buf?: undefined, offset?: number): string;
13
+ <TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf;
14
+ (options?: UuidV4Options, buf?: undefined, offset?: number): string;
13
15
  toBytes(id: string): Uint8Array;
14
16
  fromBytes(bytes: Uint8Array): string;
15
- isValid(id: string): boolean;
17
+ isValid(id: unknown): id is string;
18
+ /** The nil UUID (all zeros) */
19
+ NIL: string;
20
+ /** The max UUID (all ones) */
21
+ MAX: string;
16
22
  };
17
23
  /**
18
24
  * Generate a UUID v4 string or write the bytes into a buffer.
19
- * It also includes helpers to convert to and from byte arrays.
25
+ *
26
+ * UUID v4 is a purely random UUID with 122 bits of entropy. It's the most
27
+ * widely compatible UUID format, supported by virtually all databases and systems.
28
+ * Use when you need maximum compatibility and don't require time-ordering.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { uuidv4 } from 'uniku/uuid/v4'
33
+ *
34
+ * const id = uuidv4()
35
+ * // => "550e8400-e29b-41d4-a716-446655440000"
36
+ *
37
+ * // Validate
38
+ * uuidv4.isValid(id) // true
39
+ *
40
+ * // Convert to/from bytes (16 bytes)
41
+ * const bytes = uuidv4.toBytes(id)
42
+ * const restored = uuidv4.fromBytes(bytes)
43
+ * ```
20
44
  */
21
45
  declare const uuidv4: UuidV4;
22
46
  //#endregion
23
- export { UuidV4, Version4Options, uuidv4 };
47
+ export { BufferError, InvalidInputError, ParseError, UniqueIdError, UuidV4, UuidV4Options, uuidv4 };
24
48
  //# sourceMappingURL=v4.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v4.d.mts","names":["uuidv4: UuidV4"],"sources":["../../src/uuid/v4.ts"],"sourcesContent":[],"mappings":";KAGY,eAAA;EAAZ;AAQA;;;EAEkD,MAAA,CAAA,EALvC,UAKuC;CAAkC;AAAwB,KAFhG,MAAA,GAEgG;EAC/F,EAAA,EAAA,MAAA;EACU,CAAA,aAFP,UAEO,GAFM,UAEN,CAAA,CAAA,OAAA,EAF2B,eAE3B,GAAA,SAAA,EAAA,GAAA,EAF6D,IAE7D,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAFqF,IAErF;EACJ,CAAA,OAAA,CAAA,EAFN,eAEM,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EADI,UACJ;EAkEnB,SAAaA,CAAAA,KAAQ,EAlEF,UAkEE,CAAA,EAAA,MAAA;;;;;;;cAARA,QAAQ"}
1
+ {"version":3,"file":"v4.d.mts","names":["uuidv4: UuidV4"],"sources":["../../src/uuid/v4.ts"],"sourcesContent":[],"mappings":";;;KAMY,aAAA;;;AAAZ;AAQA;EAEgB,MAAA,CAAA,EALL,UAKK;CAAa;AAAqB,KAFtC,MAAA,GAEsC;EAAgC,EAAA,EAAA,MAAA;EAAwB,CAAA,aAA1F,UAA0F,GAA7E,UAA6E,CAAA,CAAA,OAAA,EAAxD,aAAwD,GAAA,SAAA,EAAA,GAAA,EAAxB,IAAwB,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAC7F,CAAA,OAAA,CAAA,EAAA,aAAA,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EACU,OAAA,CAAA,EAAA,EAAA,MAAA,CAAA,EAAA,UAAA;EACJ,SAAA,CAAA,KAAA,EAAA,UAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,EAAA,OAAA,CAAA,EAAA,EAAA,IAAA,MAAA;EA2FnB;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAaA,QAAQ"}
package/build/uuid/v4.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{t as e}from"../random-CPlgK_62.mjs";import{n as t,t as n}from"../uuid-DcbjGX9x.mjs";const r=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function i(e,t,n=0){if(e.length<16)throw Error(`Random bytes length must be >= 16`);if(e[6]=e[6]&15|64,e[8]=e[8]&63|128,!t)return e;if(n<0||n+16>t.length)throw RangeError(`UUID byte range ${n}:${n+15} is out of buffer bounds`);for(let r=0;r<16;r+=1)t[n+r]=e[r];return t}function a(t,r,a){if(globalThis.crypto?.randomUUID&&!r&&!t)return globalThis.crypto.randomUUID();let o=i(t?.random??e(),r,a);return r??n(o)}function o(e){return r.test(e)}const s=Object.assign(a,{toBytes:t,fromBytes:n,isValid:o});export{s as uuidv4};
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};
2
2
  //# sourceMappingURL=v4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"v4.mjs","names":["uuidv4: UuidV4"],"sources":["../../src/uuid/v4.ts"],"sourcesContent":["import { rng } from './common/random'\nimport { formatUuid, parseUuid } from './common/uuid'\n\nexport type Version4Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n * Note: Bytes at index 6 and 8 will be modified in-place to set version/variant bits.\n */\n random?: Uint8Array\n}\n\nexport type UuidV4 = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: Version4Options | undefined, buf: TBuf, offset?: number): TBuf\n (options?: Version4Options, buf?: undefined, offset?: number): string\n toBytes(id: string): Uint8Array\n fromBytes(bytes: Uint8Array): string\n isValid(id: string): boolean\n}\n\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction v4Bytes(rnds: Uint8Array, buf?: Uint8Array, offset = 0): Uint8Array {\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16')\n }\n\n // Set RFC 4122 version (4) and variant (10xx) bits.\n // Note: This modifies the input array in-place.\n rnds[6] = (rnds[6] & 0x0f) | 0x40\n rnds[8] = (rnds[8] & 0x3f) | 0x80\n\n if (!buf) {\n // No output buffer provided - return the modified random bytes directly\n return rnds\n }\n\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`)\n }\n\n // Copy 16 UUID bytes into the provided buffer slice.\n for (let i = 0; i < 16; i += 1) {\n buf[offset + i] = rnds[i]\n }\n\n return buf\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v4(options?: Version4Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v4<TBuf extends Uint8Array = Uint8Array>(\n options: Version4Options | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction v4<TBuf extends Uint8Array = Uint8Array>(\n options?: Version4Options,\n buf?: TBuf,\n offset?: number,\n): string | TBuf {\n if (globalThis.crypto?.randomUUID && !buf && !options) {\n return globalThis.crypto.randomUUID()\n }\n\n const bytes = v4Bytes(options?.random ?? rng(), buf, offset)\n return buf ?? formatUuid(bytes)\n}\n\nfunction isValid(id: string): boolean {\n return UUID_V4_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v4 string or write the bytes into a buffer.\n * It also includes helpers to convert to and from byte arrays.\n */\nexport const uuidv4: UuidV4 = Object.assign(v4, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n isValid,\n})\n"],"mappings":"2FAoBA,MAAM,EAAgB,yEAEtB,SAAS,EAAQ,EAAkB,EAAkB,EAAS,EAAe,CAC3E,GAAI,EAAK,OAAS,GAChB,MAAU,MAAM,oCAAoC,CAQtD,GAHA,EAAK,GAAM,EAAK,GAAK,GAAQ,GAC7B,EAAK,GAAM,EAAK,GAAK,GAAQ,IAEzB,CAAC,EAEH,OAAO,EAGT,GAAI,EAAS,GAAK,EAAS,GAAK,EAAI,OAClC,MAAU,WAAW,mBAAmB,EAAO,GAAG,EAAS,GAAG,0BAA0B,CAI1F,IAAK,IAAI,EAAI,EAAG,EAAI,GAAI,GAAK,EAC3B,EAAI,EAAS,GAAK,EAAK,GAGzB,OAAO,EAeT,SAAS,EACP,EACA,EACA,EACe,CACf,GAAI,WAAW,QAAQ,YAAc,CAAC,GAAO,CAAC,EAC5C,OAAO,WAAW,OAAO,YAAY,CAGvC,IAAM,EAAQ,EAAQ,GAAS,QAAU,GAAK,CAAE,EAAK,EAAO,CAC5D,OAAO,GAAO,EAAW,EAAM,CAGjC,SAAS,EAAQ,EAAqB,CACpC,OAAO,EAAc,KAAK,EAAG,CAO/B,MAAaA,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,UACD,CAAC"}
1
+ {"version":3,"file":"v4.mjs","names":["uuidv4: UuidV4"],"sources":["../../src/uuid/v4.ts"],"sourcesContent":["import { rng } from '../common/random'\nimport { BufferError, InvalidInputError } from '../errors'\nimport { formatUuid, parseUuid } from './common/uuid'\n\nconst randomUUID = /*@__PURE__*/ globalThis.crypto.randomUUID.bind(globalThis.crypto)\n\nexport type UuidV4Options = {\n /**\n * 16 bytes of random data to use for UUID generation.\n * Note: Bytes at index 6 and 8 will be modified in-place to set version/variant bits.\n */\n random?: Uint8Array\n}\n\nexport type UuidV4 = {\n (): string\n <TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\n (options?: UuidV4Options, buf?: undefined, offset?: number): string\n toBytes(id: string): Uint8Array\n fromBytes(bytes: Uint8Array): string\n isValid(id: unknown): id is string\n /** The nil UUID (all zeros) */\n NIL: string\n /** The max UUID (all ones) */\n MAX: string\n}\n\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction v4Bytes(rnds: Uint8Array, buf?: Uint8Array, offset = 0): Uint8Array {\n if (rnds.length < 16) {\n throw new InvalidInputError('UUID_RANDOM_BYTES_TOO_SHORT', 'Random bytes length must be >= 16')\n }\n\n // Set RFC 4122 version (4) and variant (10xx) bits.\n // Note: This modifies the input array in-place.\n rnds[6] = (rnds[6] & 0x0f) | 0x40\n rnds[8] = (rnds[8] & 0x3f) | 0x80\n\n if (!buf) {\n // No output buffer provided - return the modified random bytes directly\n return rnds\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 // Copy 16 UUID bytes into the provided buffer slice.\n for (let i = 0; i < 16; i += 1) {\n buf[offset + i] = rnds[i]\n }\n\n return buf\n}\n\n/*\n * Overload: no buffer => return a UUID string.\n */\nfunction v4(options?: UuidV4Options, buf?: undefined, offset?: number): string\n/*\n * Overload: caller provides a buffer slice to fill with UUID bytes.\n */\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options: UuidV4Options | undefined, buf: TBuf, offset?: number): TBuf\nfunction v4<TBuf extends Uint8Array = Uint8Array>(options?: UuidV4Options, buf?: TBuf, offset?: number): string | TBuf {\n if (!buf && !options) {\n return randomUUID()\n }\n\n return _v4(options, buf, offset)\n}\n\nfunction _v4<TBuf extends Uint8Array = Uint8Array>(\n options?: UuidV4Options,\n buf?: TBuf,\n offset?: number,\n): string | TBuf {\n const bytes = v4Bytes(options?.random ?? rng(), buf, offset)\n return buf ?? formatUuid(bytes)\n}\n\nfunction isValid(id: unknown): id is string {\n return typeof id === 'string' && UUID_V4_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v4 string or write the bytes into a buffer.\n *\n * UUID v4 is a purely random UUID with 122 bits of entropy. It's the most\n * widely compatible UUID format, supported by virtually all databases and systems.\n * Use when you need maximum compatibility and don't require time-ordering.\n *\n * @example\n * ```ts\n * import { uuidv4 } from 'uniku/uuid/v4'\n *\n * const id = uuidv4()\n * // => \"550e8400-e29b-41d4-a716-446655440000\"\n *\n * // Validate\n * uuidv4.isValid(id) // true\n *\n * // Convert to/from bytes (16 bytes)\n * const bytes = uuidv4.toBytes(id)\n * const restored = uuidv4.fromBytes(bytes)\n * ```\n */\nexport const uuidv4: UuidV4 = Object.assign(v4, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n isValid,\n NIL: '00000000-0000-0000-0000-000000000000',\n MAX: 'ffffffff-ffff-ffff-ffff-ffffffffffff',\n})\n\nexport { BufferError, InvalidInputError, ParseError, UniqueIdError } from '../errors'\n"],"mappings":"iMAIA,MAAM,EAA2B,WAAW,OAAO,WAAW,KAAK,WAAW,OAAO,CAuB/E,EAAgB,yEAEtB,SAAS,EAAQ,EAAkB,EAAkB,EAAS,EAAe,CAC3E,GAAI,EAAK,OAAS,GAChB,MAAM,IAAI,EAAkB,8BAA+B,oCAAoC,CAQjG,GAHA,EAAK,GAAM,EAAK,GAAK,GAAQ,GAC7B,EAAK,GAAM,EAAK,GAAK,GAAQ,IAEzB,CAAC,EAEH,OAAO,EAGT,GAAI,EAAS,GAAK,EAAS,GAAK,EAAI,OAClC,MAAM,IAAI,EACR,4BACA,mBAAmB,EAAO,GAAG,EAAS,GAAG,0BAC1C,CAIH,IAAK,IAAI,EAAI,EAAG,EAAI,GAAI,GAAK,EAC3B,EAAI,EAAS,GAAK,EAAK,GAGzB,OAAO,EAWT,SAAS,EAAyC,EAAyB,EAAY,EAAgC,CAKrH,MAJI,CAAC,GAAO,CAAC,EACJ,GAAY,CAGd,EAAI,EAAS,EAAK,EAAO,CAGlC,SAAS,EACP,EACA,EACA,EACe,CACf,IAAM,EAAQ,EAAQ,GAAS,QAAU,GAAK,CAAE,EAAK,EAAO,CAC5D,OAAO,GAAO,EAAW,EAAM,CAGjC,SAAS,EAAQ,EAA2B,CAC1C,OAAO,OAAO,GAAO,UAAY,EAAc,KAAK,EAAG,CAyBzD,MAAaA,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,UACA,IAAK,uCACL,IAAK,uCACN,CAAC"}
@@ -1,5 +1,7 @@
1
+ import { BufferError, InvalidInputError, ParseError, UniqueIdError } from "../errors.mjs";
2
+
1
3
  //#region src/uuid/v7.d.ts
2
- type Version7Options = {
4
+ type UuidV7Options = {
3
5
  /**
4
6
  * 16 bytes of random data to use for UUID generation.
5
7
  * Note: Several bytes will be overwritten with timestamp, version, and variant data.
@@ -10,18 +12,44 @@ type Version7Options = {
10
12
  };
11
13
  type UuidV7 = {
12
14
  (): string;
13
- <TBuf extends Uint8Array = Uint8Array>(options: Version7Options | undefined, buf: TBuf, offset?: number): TBuf;
14
- (options?: Version7Options, buf?: undefined, offset?: number): string;
15
+ <TBuf extends Uint8Array = Uint8Array>(options: UuidV7Options | undefined, buf: TBuf, offset?: number): TBuf;
16
+ (options?: UuidV7Options, buf?: undefined, offset?: number): string;
15
17
  toBytes(id: string): Uint8Array;
16
18
  fromBytes(bytes: Uint8Array): string;
17
19
  timestamp(id: string): number;
18
- isValid(id: string): boolean;
20
+ isValid(id: unknown): id is string;
21
+ /** The nil UUID (all zeros) */
22
+ NIL: string;
23
+ /** The max UUID (all ones) */
24
+ MAX: string;
19
25
  };
20
26
  /**
21
27
  * Generate a UUID v7 string or write the bytes into a buffer.
22
- * It also includes helpers to convert to and from byte arrays.j
28
+ *
29
+ * UUID v7 is a time-ordered UUID that embeds a Unix timestamp in milliseconds,
30
+ * making IDs naturally sortable by creation time. Ideal for database primary keys
31
+ * where chronological ordering improves index performance.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { uuidv7 } from 'uniku/uuid/v7'
36
+ *
37
+ * const id = uuidv7()
38
+ * // => "018e5e5c-7c8a-7000-8000-000000000000"
39
+ *
40
+ * // Extract timestamp
41
+ * const ts = uuidv7.timestamp(id)
42
+ * console.log(new Date(ts))
43
+ *
44
+ * // Validate
45
+ * uuidv7.isValid(id) // true
46
+ *
47
+ * // Convert to/from bytes
48
+ * const bytes = uuidv7.toBytes(id)
49
+ * const restored = uuidv7.fromBytes(bytes)
50
+ * ```
23
51
  */
24
52
  declare const uuidv7: UuidV7;
25
53
  //#endregion
26
- export { UuidV7, Version7Options, uuidv7 };
54
+ export { BufferError, InvalidInputError, ParseError, UniqueIdError, UuidV7, UuidV7Options, uuidv7 };
27
55
  //# sourceMappingURL=v7.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v7.d.mts","names":["uuidv7: UuidV7"],"sources":["../../src/uuid/v7.ts"],"sourcesContent":[],"mappings":";KAEY,eAAA;EAAZ;AAUA;;;EAEkD,MAAA,CAAA,EAPvC,UAOuC;EAAkC,KAAA,CAAA,EAAA,MAAA;EAAwB,GAAA,CAAA,EAAA,MAAA;CAC/F;AACU,KAJX,MAAA,GAIW;EACJ,EAAA,EAAA,MAAA;EAAA,CAAA,aAHH,UAGG,GAHU,UAGV,CAAA,CAAA,OAAA,EAH+B,eAG/B,GAAA,SAAA,EAAA,GAAA,EAHiE,IAGjE,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAHyF,IAGzF;EAgJnB,CAAA,OAAqB,CAARA,EAlJA,eAkJQ,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;uBAjJE;mBACJ;;;;;;;;cAgJNA,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;EAwJnB,SAAaA,CAAAA,KAAQ,EAxJF,UAwJE,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAARA,QAAQ"}
package/build/uuid/v7.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{n as e,t}from"../uuid-DcbjGX9x.mjs";const n=/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,r=new Uint8Array(256);let i=256;function a(){i>240&&(crypto.getRandomValues(r),i=0);let e=i;return i+=16,r.subarray(e,i)}const o=new Uint8Array(16),s={msecs:-1/0,seq:0};function c(e,t,n,r,i=0){if(e.length<16)throw Error(`Random bytes length must be >= 16`);if(i<0||i+16>r.length)throw RangeError(`UUID byte range ${i}:${i+15} is out of buffer bounds`);return t??=Date.now(),n??=e[6]*127<<24|e[7]<<16|e[8]<<8|e[9],r[i++]=t/1099511627776&255,r[i++]=t/4294967296&255,r[i++]=t/16777216&255,r[i++]=t/65536&255,r[i++]=t/256&255,r[i++]=t&255,r[i++]=112|n>>>28&15,r[i++]=n>>>20&255,r[i++]=128|n>>>14&63,r[i++]=n>>>6&255,r[i++]=n<<2&255|e[10]&3,r[i++]=e[11],r[i++]=e[12],r[i++]=e[13],r[i++]=e[14],r[i++]=e[15],r}function l(e,n,r){let i;if(e)i=c(e.random??a(),e.msecs,e.seq,n??o,n?r:0);else{let e=Date.now(),t=a();e>s.msecs?(s.seq=t[6]<<23|t[7]<<16|t[8]<<8|t[9],s.msecs=e):(s.seq=s.seq+1|0,s.seq===0&&s.msecs++),i=c(t,s.msecs,s.seq,n??o,n?r:0)}return n?i:t(i)}function u(t){let n=e(t),r=0;for(let e=0;e<6;e+=1)r=r*256+n[e];return r}function d(e){return n.test(e)}const f=Object.assign(l,{toBytes:e,fromBytes:t,timestamp:u,isValid:d});export{f as uuidv7};
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};
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 { formatUuid, parseUuid } from './common/uuid'\n\nexport type Version7Options = {\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: Version7Options | undefined, buf: TBuf, offset?: number): TBuf\n (options?: Version7Options, buf?: undefined, offset?: number): string\n toBytes(id: string): Uint8Array\n fromBytes(bytes: Uint8Array): string\n timestamp(id: string): number\n isValid(id: string): boolean\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// Simple random pool (matches uuid npm approach)\nconst POOL_SIZE = 256\nconst rnds8Pool = new Uint8Array(POOL_SIZE)\nlet poolPtr = POOL_SIZE // Start exhausted to trigger first fill\n\nfunction rng(): Uint8Array {\n if (poolPtr > POOL_SIZE - 16) {\n crypto.getRandomValues(rnds8Pool)\n poolPtr = 0\n }\n const start = poolPtr\n poolPtr += 16\n return rnds8Pool.subarray(start, poolPtr)\n}\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 Error('Random bytes length must be >= 16')\n }\n\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`)\n }\n\n msecs ??= Date.now()\n // Derive a 30-bit sequence if not provided by the caller.\n seq ??= ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n\n // Timestamp (48-bit big-endian milliseconds since Unix epoch).\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?: Version7Options, 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>(\n options: Version7Options | undefined,\n buf: TBuf,\n offset?: number,\n): TBuf\nfunction v7<TBuf extends Uint8Array = Uint8Array>(\n options?: Version7Options,\n buf?: TBuf,\n offset?: number,\n): 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: string): boolean {\n return UUID_V7_REGEX.test(id)\n}\n\n/**\n * Generate a UUID v7 string or write the bytes into a buffer.\n * It also includes helpers to convert to and from byte arrays.j\n */\nexport const uuidv7: UuidV7 = Object.assign(v7, {\n toBytes: parseUuid,\n fromBytes: formatUuid,\n timestamp,\n isValid,\n})\n"],"mappings":"2CAsBA,MAAM,EAAgB,yEAIhB,EAAY,IAAI,WAAW,IAAU,CAC3C,IAAI,EAAU,IAEd,SAAS,GAAkB,CACrB,EAAU,MACZ,OAAO,gBAAgB,EAAU,CACjC,EAAU,GAEZ,IAAM,EAAQ,EAEd,MADA,IAAW,GACJ,EAAU,SAAS,EAAO,EAAQ,CAK3C,MAAM,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,MAAU,MAAM,oCAAoC,CAGtD,GAAI,EAAS,GAAK,EAAS,GAAK,EAAI,OAClC,MAAU,WAAW,mBAAmB,EAAO,GAAG,EAAS,GAAG,0BAA0B,CA4B1F,MAzBA,KAAU,KAAK,KAAK,CAEpB,IAAU,EAAK,GAAK,KAAS,GAAO,EAAK,IAAM,GAAO,EAAK,IAAM,EAAK,EAAK,GAG3E,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,EAeT,SAAS,EACP,EACA,EACA,EACe,CACf,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,EAAqB,CACpC,OAAO,EAAc,KAAK,EAAG,CAO/B,MAAaC,EAAiB,OAAO,OAAO,EAAI,CAC9C,QAAS,EACT,UAAW,EACX,YACA,UACD,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 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"}
@@ -0,0 +1,2 @@
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
@@ -0,0 +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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "uniku",
4
- "version": "0.0.7",
4
+ "version": "0.0.10",
5
5
  "description": "Minimal, tree-shakeable UUID utilities for every JavaScript runtime",
6
6
  "author": {
7
7
  "name": "Alberto Schiabel",
@@ -102,6 +102,14 @@
102
102
  },
103
103
  "default": "./build/ksuid/ksuid.mjs"
104
104
  },
105
+ "./errors": {
106
+ "types": "./build/errors.d.mts",
107
+ "import": {
108
+ "@jkomyno/source": "./src/errors.ts",
109
+ "default": "./build/errors.mjs"
110
+ },
111
+ "default": "./build/errors.mjs"
112
+ },
105
113
  "./package.json": "./package.json"
106
114
  },
107
115
  "dependencies": {
@@ -111,9 +119,9 @@
111
119
  "@owpz/ksuid": "^25.7.20",
112
120
  "@paralleldrive/cuid2": "^3.3.0",
113
121
  "@types/bun": "^1.3.8",
114
- "nanoid": "5.0.9",
115
- "ulid": "2.3.0",
116
- "uuid": "11.0.5"
122
+ "nanoid": "^5.1.6",
123
+ "ulid": "3.0.2",
124
+ "uuid": "13.0.0"
117
125
  },
118
126
  "scripts": {
119
127
  "clean": "rimraf build .turbo",
@@ -124,9 +132,10 @@
124
132
  "test:integration": "vitest --project integration run",
125
133
  "test:e2e": "pnpm --filter @uniku/e2e-cloudflare test:e2e",
126
134
  "test:e2e:cloudflare": "pnpm --filter @uniku/e2e-cloudflare test:e2e:cloudflare",
127
- "bench": "vitest bench --run",
128
- "bench:compat": "vitest bench ./__tests__/bench/compat.bench.ts --run",
135
+ "bench": "vitest bench --run --project unit",
136
+ "bench:compat": "vitest bench ./__tests__/bench/compat.bench.ts --run --project unit",
129
137
  "bench:summary": "bun scripts/bench-summary.ts",
138
+ "bench:compare": "git show origin/gh-benchmarks:baseline.json > baseline.json 2>/dev/null && bun scripts/bench-compare.ts || echo 'No baseline found. Run benchmarks on main first.'",
130
139
  "bundle:summary": "bun scripts/bundle-summary.ts",
131
140
  "typecheck": "tsc --noEmit"
132
141
  }
@@ -1,2 +0,0 @@
1
- const e=new Uint8Array(256);let t=256;function n(){t>240&&(crypto.getRandomValues(e),t=0);let n=t;return t+=16,e.subarray(n,t)}export{n as t};
2
- //# sourceMappingURL=random-CPlgK_62.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"random-CPlgK_62.mjs","names":[],"sources":["../src/uuid/common/random.ts"],"sourcesContent":["// Simple, fast random byte pool for UUID generation.\n// Uses plain JavaScript for maximum performance - no Atomics overhead.\n// Thread safety is not needed for typical UUID use cases.\n\nconst POOL_SIZE = 256 // uuid npm uses 256 bytes\nconst rnds8Pool = new Uint8Array(POOL_SIZE)\nlet poolPtr = POOL_SIZE // Start exhausted to trigger first fill\n\n/**\n * Generate 16 bytes of cryptographically strong random data.\n * Uses a pre-filled pool to minimize crypto API calls.\n */\nexport function rng(): Uint8Array {\n if (poolPtr > POOL_SIZE - 16) {\n crypto.getRandomValues(rnds8Pool)\n poolPtr = 0\n }\n // Return a view - consumed synchronously within the same v7 call\n const start = poolPtr\n poolPtr += 16\n return rnds8Pool.subarray(start, poolPtr)\n}\n\n/**\n * Fill the provided buffer with random bytes from the pool.\n */\nexport function randomBytes(out: Uint8Array): void {\n const count = out.length\n if (poolPtr > POOL_SIZE - count) {\n crypto.getRandomValues(rnds8Pool)\n poolPtr = 0\n }\n out.set(rnds8Pool.subarray(poolPtr, poolPtr + count))\n poolPtr += count\n}\n"],"mappings":"AAIA,MACM,EAAY,IAAI,WAAW,IAAU,CAC3C,IAAI,EAAU,IAMd,SAAgB,GAAkB,CAC5B,EAAU,MACZ,OAAO,gBAAgB,EAAU,CACjC,EAAU,GAGZ,IAAM,EAAQ,EAEd,MADA,IAAW,GACJ,EAAU,SAAS,EAAO,EAAQ"}