uniku 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +110 -0
- package/build/uuid-DaimLSJD.mjs +64 -0
- package/build/uuid-DaimLSJD.mjs.map +1 -0
- package/build/v4.d.mts +23 -0
- package/build/v4.d.mts.map +1 -0
- package/build/v4.mjs +29 -0
- package/build/v4.mjs.map +1 -0
- package/build/v7.d.mts +25 -0
- package/build/v7.d.mts.map +1 -0
- package/build/v7.mjs +81 -0
- package/build/v7.mjs.map +1 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-current Alberto Schiabel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# uniku
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/uniku)
|
|
4
|
+
[](https://github.com/jkomyno/uniku/actions/workflows/ci.yaml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://bundlephobia.com/package/uniku)
|
|
7
|
+
|
|
8
|
+
Minimal, tree-shakeable UUID utilities for every JavaScript runtime.
|
|
9
|
+
|
|
10
|
+
> *uniku* means "unique" in Maltese.
|
|
11
|
+
|
|
12
|
+
## Why uniku?
|
|
13
|
+
|
|
14
|
+
- **ESM-only** - No CommonJS or legacy support.
|
|
15
|
+
- **Universal runtime support** - Works everywhere: Node.js, Cloudflare Workers, Vercel Edge, Deno, browsers. Uses the WebCrypto API (`globalThis.crypto`), not `node:crypto`.
|
|
16
|
+
- **Truly tree-shakeable** - Separate entry points mean you only bundle what you import. No barrel exports that defeat dead-code elimination.
|
|
17
|
+
- **Byte-level access** - Convert between UUID strings and `Uint8Array` with built-in `toBytes()` and `fromBytes()` helpers.
|
|
18
|
+
- **Modern standards** - Includes UUID v7 (RFC 9562) for time-ordered, sortable identifiers with monotonic sequencing.
|
|
19
|
+
- **Lightweight** - Designed for use in performance-sensitive contexts like ORMs.
|
|
20
|
+
|
|
21
|
+
## Supported ID generation algorithms
|
|
22
|
+
|
|
23
|
+
- UUID v4 ([RFC 4122](./rfcs/rfc4122))
|
|
24
|
+
- UUID v7 ([RFC 9562](./rfcs/rfc9562), time-ordered, monotonic sequencing)
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
With pnpm:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add uniku
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With Bun:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bun install uniku
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
With npm:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install uniku
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### UUID v4 (random)
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { uuidv4 } from 'uniku/uuid/v4'
|
|
52
|
+
|
|
53
|
+
const id = uuidv4()
|
|
54
|
+
// => "550e8400-e29b-41d4-a716-446655440000"
|
|
55
|
+
|
|
56
|
+
// Convert to/from bytes
|
|
57
|
+
const bytes = uuidv4.toBytes(id)
|
|
58
|
+
const str = uuidv4.fromBytes(bytes)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### UUID v7 (time-ordered)
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { uuidv7 } from 'uniku/uuid/v7'
|
|
65
|
+
|
|
66
|
+
const id = uuidv7()
|
|
67
|
+
// => "018e5e5c-7c8a-7000-8000-000000000000"
|
|
68
|
+
|
|
69
|
+
// IDs are lexicographically sortable by creation time
|
|
70
|
+
const ids = [uuidv7(), uuidv7(), uuidv7()]
|
|
71
|
+
ids.sort() // Already in creation order
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## API Reference
|
|
75
|
+
|
|
76
|
+
### `uuidv4` (from `uniku/uuid/v4`)
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
uuidv4(options?: Version4Options): string
|
|
80
|
+
uuidv4(options: Version4Options | undefined, buf: Uint8Array, offset?: number): Uint8Array
|
|
81
|
+
|
|
82
|
+
uuidv4.toBytes(id: string): Uint8Array
|
|
83
|
+
uuidv4.fromBytes(bytes: Uint8Array): string
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Options:**
|
|
87
|
+
- `random?: Uint8Array` - 16 bytes of random data
|
|
88
|
+
|
|
89
|
+
### `uuidv7` (from `uniku/uuid/v7`)
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
uuidv7(options?: Version7Options): string
|
|
93
|
+
uuidv7(options: Version7Options | undefined, buf: Uint8Array, offset?: number): Uint8Array
|
|
94
|
+
|
|
95
|
+
uuidv7.toBytes(id: string): Uint8Array
|
|
96
|
+
uuidv7.fromBytes(bytes: Uint8Array): string
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Options:**
|
|
100
|
+
- `msecs?: number` - Timestamp in milliseconds (defaults to `Date.now()`)
|
|
101
|
+
- `seq?: number` - Sequence number for monotonicity
|
|
102
|
+
- `random?: Uint8Array` - 16 bytes of random data
|
|
103
|
+
|
|
104
|
+
## Documentation
|
|
105
|
+
|
|
106
|
+
For advanced usage, examples, and contributing guidelines, see the [full documentation on GitHub](https://github.com/jkomyno/uniku).
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT - see [LICENSE](https://github.com/jkomyno/uniku/blob/main/LICENSE)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/uuid/common/random.ts
|
|
2
|
+
function randomBytes(out) {
|
|
3
|
+
globalThis.crypto.getRandomValues(out);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Generate 16 bytes of cryptographically strong random data.
|
|
7
|
+
* Used internally by UUID generators.
|
|
8
|
+
*/
|
|
9
|
+
function rng() {
|
|
10
|
+
const bytes = new Uint8Array(16);
|
|
11
|
+
randomBytes(bytes);
|
|
12
|
+
return bytes;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/uuid/common/hex.ts
|
|
17
|
+
const HEX_TABLE = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
18
|
+
function bytesToHex(bytes) {
|
|
19
|
+
let hex = "";
|
|
20
|
+
for (let i = 0; i < bytes.length; i += 1) hex += HEX_TABLE[bytes[i]];
|
|
21
|
+
return hex;
|
|
22
|
+
}
|
|
23
|
+
const ASCII_0 = 48;
|
|
24
|
+
const ASCII_9 = 57;
|
|
25
|
+
const ASCII_A = 65;
|
|
26
|
+
const ASCII_F = 70;
|
|
27
|
+
const ASCII_a = 97;
|
|
28
|
+
const ASCII_f = 102;
|
|
29
|
+
function hexValue(code) {
|
|
30
|
+
if (code >= ASCII_0 && code <= ASCII_9) return code - ASCII_0;
|
|
31
|
+
if (code >= ASCII_A && code <= ASCII_F) return code - ASCII_A + 10;
|
|
32
|
+
if (code >= ASCII_a && code <= ASCII_f) return code - ASCII_a + 10;
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
function hexToBytes(hex, out) {
|
|
36
|
+
if (hex.length !== out.length * 2) throw new Error(`hex string must be ${out.length * 2} chars, got ${hex.length}`);
|
|
37
|
+
for (let i = 0; i < out.length; i += 1) {
|
|
38
|
+
const hi = hexValue(hex.charCodeAt(i * 2));
|
|
39
|
+
const lo = hexValue(hex.charCodeAt(i * 2 + 1));
|
|
40
|
+
if (hi === -1 || lo === -1) throw new Error("hex string contains invalid characters");
|
|
41
|
+
out[i] = hi << 4 | lo;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/uuid/common/uuid.ts
|
|
47
|
+
const UUID_BYTE_LENGTH = 16;
|
|
48
|
+
const UUID_STRING_LENGTH = 36;
|
|
49
|
+
function formatUuid(bytes) {
|
|
50
|
+
const hex = bytesToHex(bytes);
|
|
51
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
52
|
+
}
|
|
53
|
+
function parseUuid(value) {
|
|
54
|
+
if (value.length !== UUID_STRING_LENGTH) throw new Error("uuid string must be 36 characters");
|
|
55
|
+
if (value[8] !== "-" || value[13] !== "-" || value[18] !== "-" || value[23] !== "-") throw new Error("uuid string has invalid separators");
|
|
56
|
+
const hex = value.slice(0, 8) + value.slice(9, 13) + value.slice(14, 18) + value.slice(19, 23) + value.slice(24);
|
|
57
|
+
const bytes = new Uint8Array(UUID_BYTE_LENGTH);
|
|
58
|
+
hexToBytes(hex, bytes);
|
|
59
|
+
return bytes;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { parseUuid as n, rng as r, formatUuid as t };
|
|
64
|
+
//# sourceMappingURL=uuid-DaimLSJD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid-DaimLSJD.mjs","names":[],"sources":["../src/uuid/common/random.ts","../src/uuid/common/hex.ts","../src/uuid/common/uuid.ts"],"sourcesContent":["export function randomBytes(out: Uint8Array): void {\n const crypto = globalThis.crypto\n crypto.getRandomValues(out)\n}\n\n/**\n * Generate 16 bytes of cryptographically strong random data.\n * Used internally by UUID generators.\n */\nexport function rng(): Uint8Array {\n const bytes = new Uint8Array(16)\n randomBytes(bytes)\n return bytes\n}\n","// Pre-computed lookup table for byte-to-hex conversion (0x00 -> \"00\", 0xff -> \"ff\")\nconst HEX_TABLE = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))\n\nexport function bytesToHex(bytes: Uint8Array): string {\n // Build string directly, without intermediate array allocation\n let hex = ''\n for (let i = 0; i < bytes.length; i += 1) {\n hex += HEX_TABLE[bytes[i]]\n }\n return hex\n}\n\n// 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\nfunction 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\nexport function hexToBytes(hex: string, out: Uint8Array): void {\n if (hex.length !== out.length * 2) {\n throw new Error(`hex string must be ${out.length * 2} chars, got ${hex.length}`)\n }\n\n for (let i = 0; i < out.length; i += 1) {\n const hi = hexValue(hex.charCodeAt(i * 2))\n const lo = hexValue(hex.charCodeAt(i * 2 + 1))\n if (hi === -1 || lo === -1) {\n throw new Error('hex string contains invalid characters')\n }\n out[i] = (hi << 4) | lo\n }\n}\n","import { bytesToHex, hexToBytes } from './hex'\n\nconst UUID_BYTE_LENGTH = 16\nconst UUID_STRING_LENGTH = 36\n\nexport function formatUuid(bytes: Uint8Array): string {\n // precondition: bytes.length === UUID_BYTE_LENGTH\n const hex = bytesToHex(bytes)\n\n // Build UUID string with dashes at positions 8, 13, 18, 23\n // Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`\n}\n\nexport function parseUuid(value: string): Uint8Array {\n if (value.length !== UUID_STRING_LENGTH) {\n throw new Error('uuid string must be 36 characters')\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 Error('uuid string has invalid separators')\n }\n\n const hex = value.slice(0, 8) + value.slice(9, 13) + value.slice(14, 18) + value.slice(19, 23) + value.slice(24)\n\n const bytes = new Uint8Array(UUID_BYTE_LENGTH)\n hexToBytes(hex, bytes)\n return bytes\n}\n"],"mappings":";AAAA,SAAgB,YAAY,KAAuB;AAEjD,CADe,WAAW,OACnB,gBAAgB,IAAI;;;;;;AAO7B,SAAgB,MAAkB;CAChC,MAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,aAAY,MAAM;AAClB,QAAO;;;;;ACXT,MAAM,YAAY,MAAM,KAAK,EAAE,QAAQ,KAAK,GAAG,GAAG,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;AAExF,SAAgB,WAAW,OAA2B;CAEpD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,EACrC,QAAO,UAAU,MAAM;AAEzB,QAAO;;AAIT,MAAM,UAAU;AAChB,MAAM,UAAU;AAChB,MAAM,UAAU;AAChB,MAAM,UAAU;AAChB,MAAM,UAAU;AAChB,MAAM,UAAU;AAEhB,SAAS,SAAS,MAAsB;AACtC,KAAI,QAAQ,WAAW,QAAQ,QAC7B,QAAO,OAAO;AAEhB,KAAI,QAAQ,WAAW,QAAQ,QAC7B,QAAO,OAAO,UAAU;AAE1B,KAAI,QAAQ,WAAW,QAAQ,QAC7B,QAAO,OAAO,UAAU;AAE1B,QAAO;;AAGT,SAAgB,WAAW,KAAa,KAAuB;AAC7D,KAAI,IAAI,WAAW,IAAI,SAAS,EAC9B,OAAM,IAAI,MAAM,sBAAsB,IAAI,SAAS,EAAE,cAAc,IAAI,SAAS;AAGlF,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;EACtC,MAAM,KAAK,SAAS,IAAI,WAAW,IAAI,EAAE,CAAC;EAC1C,MAAM,KAAK,SAAS,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;AAC9C,MAAI,OAAO,MAAM,OAAO,GACtB,OAAM,IAAI,MAAM,yCAAyC;AAE3D,MAAI,KAAM,MAAM,IAAK;;;;;;AC1CzB,MAAM,mBAAmB;AACzB,MAAM,qBAAqB;AAE3B,SAAgB,WAAW,OAA2B;CAEpD,MAAM,MAAM,WAAW,MAAM;AAI7B,QAAO,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,MAAM,GAAG;;AAG1G,SAAgB,UAAU,OAA2B;AACnD,KAAI,MAAM,WAAW,mBACnB,OAAM,IAAI,MAAM,oCAAoC;AAItD,KAAI,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAC9E,OAAM,IAAI,MAAM,qCAAqC;CAGvD,MAAM,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,MAAM,IAAI,GAAG,GAAG,MAAM,MAAM,IAAI,GAAG,GAAG,MAAM,MAAM,GAAG;CAEhH,MAAM,QAAQ,IAAI,WAAW,iBAAiB;AAC9C,YAAW,KAAK,MAAM;AACtB,QAAO"}
|
package/build/v4.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/uuid/v4.d.ts
|
|
2
|
+
type Version4Options = {
|
|
3
|
+
/**
|
|
4
|
+
* 16 bytes of random data to use for UUID generation.
|
|
5
|
+
* Note: Bytes at index 6 and 8 will be modified in-place to set version/variant bits.
|
|
6
|
+
*/
|
|
7
|
+
random?: Uint8Array;
|
|
8
|
+
};
|
|
9
|
+
type UuidV4 = {
|
|
10
|
+
(): string;
|
|
11
|
+
<TBuf extends Uint8Array = Uint8Array>(options: Version4Options | undefined, buf: TBuf, offset?: number): TBuf;
|
|
12
|
+
(options?: Version4Options, buf?: undefined, offset?: number): string;
|
|
13
|
+
toBytes(id: string): Uint8Array;
|
|
14
|
+
fromBytes(bytes: Uint8Array): string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Generate a UUID v4 string or write the bytes into a buffer.
|
|
18
|
+
* It also includes helpers to convert to and from byte arrays.
|
|
19
|
+
*/
|
|
20
|
+
declare const uuidv4: UuidV4;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { UuidV4, Version4Options, uuidv4 };
|
|
23
|
+
//# sourceMappingURL=v4.d.mts.map
|
|
@@ -0,0 +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;EA2DnB,SAAaA,CAAAA,KAAQ,EA3DF,UA2DE,CAAA,EAAA,MAAA;;;;;;cAARA,QAAQ"}
|
package/build/v4.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { n as parseUuid, r as rng, t as formatUuid } from "./uuid-DaimLSJD.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/uuid/v4.ts
|
|
4
|
+
function v4Bytes(rnds, buf, offset = 0) {
|
|
5
|
+
if (rnds.length < 16) throw new Error("Random bytes length must be >= 16");
|
|
6
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
7
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
8
|
+
if (!buf) return rnds;
|
|
9
|
+
if (offset < 0 || offset + 16 > buf.length) throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
10
|
+
for (let i = 0; i < 16; i += 1) buf[offset + i] = rnds[i];
|
|
11
|
+
return buf;
|
|
12
|
+
}
|
|
13
|
+
function v4(options, buf, offset) {
|
|
14
|
+
if (globalThis.crypto?.randomUUID && !buf && !options) return globalThis.crypto.randomUUID();
|
|
15
|
+
const bytes = v4Bytes(options?.random ?? rng(), buf, offset);
|
|
16
|
+
return buf ?? formatUuid(bytes);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate a UUID v4 string or write the bytes into a buffer.
|
|
20
|
+
* It also includes helpers to convert to and from byte arrays.
|
|
21
|
+
*/
|
|
22
|
+
const uuidv4 = Object.assign(v4, {
|
|
23
|
+
toBytes: (id) => parseUuid(id),
|
|
24
|
+
fromBytes: (bytes) => formatUuid(bytes)
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { uuidv4 };
|
|
29
|
+
//# sourceMappingURL=v4.mjs.map
|
package/build/v4.mjs.map
ADDED
|
@@ -0,0 +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}\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\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: (id: string) => parseUuid(id),\n fromBytes: (bytes: Uint8Array) => formatUuid(bytes),\n})\n"],"mappings":";;;AAmBA,SAAS,QAAQ,MAAkB,KAAkB,SAAS,GAAe;AAC3E,KAAI,KAAK,SAAS,GAChB,OAAM,IAAI,MAAM,oCAAoC;AAKtD,MAAK,KAAM,KAAK,KAAK,KAAQ;AAC7B,MAAK,KAAM,KAAK,KAAK,KAAQ;AAE7B,KAAI,CAAC,IAEH,QAAO;AAGT,KAAI,SAAS,KAAK,SAAS,KAAK,IAAI,OAClC,OAAM,IAAI,WAAW,mBAAmB,OAAO,GAAG,SAAS,GAAG,0BAA0B;AAI1F,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK,EAC3B,KAAI,SAAS,KAAK,KAAK;AAGzB,QAAO;;AAeT,SAAS,GACP,SACA,KACA,QACe;AACf,KAAI,WAAW,QAAQ,cAAc,CAAC,OAAO,CAAC,QAC5C,QAAO,WAAW,OAAO,YAAY;CAGvC,MAAM,QAAQ,QAAQ,SAAS,UAAU,KAAK,EAAE,KAAK,OAAO;AAC5D,QAAO,OAAO,WAAW,MAAM;;;;;;AAOjC,MAAaA,SAAiB,OAAO,OAAO,IAAI;CAC9C,UAAU,OAAe,UAAU,GAAG;CACtC,YAAY,UAAsB,WAAW,MAAM;CACpD,CAAC"}
|
package/build/v7.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/uuid/v7.d.ts
|
|
2
|
+
type Version7Options = {
|
|
3
|
+
/**
|
|
4
|
+
* 16 bytes of random data to use for UUID generation.
|
|
5
|
+
* Note: Several bytes will be overwritten with timestamp, version, and variant data.
|
|
6
|
+
*/
|
|
7
|
+
random?: Uint8Array;
|
|
8
|
+
msecs?: number;
|
|
9
|
+
seq?: number;
|
|
10
|
+
};
|
|
11
|
+
type UuidV7 = {
|
|
12
|
+
(): string;
|
|
13
|
+
<TBuf extends Uint8Array = Uint8Array>(options: Version7Options | undefined, buf: TBuf, offset?: number): TBuf;
|
|
14
|
+
(options?: Version7Options, buf?: undefined, offset?: number): string;
|
|
15
|
+
toBytes(id: string): Uint8Array;
|
|
16
|
+
fromBytes(bytes: Uint8Array): string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Generate a UUID v7 string or write the bytes into a buffer.
|
|
20
|
+
* It also includes helpers to convert to and from byte arrays.
|
|
21
|
+
*/
|
|
22
|
+
declare const uuidv7: UuidV7;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { UuidV7, Version7Options, uuidv7 };
|
|
25
|
+
//# sourceMappingURL=v7.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v7.d.mts","names":["uuidv7: UuidV7"],"sources":["../src/uuid/v7.ts"],"sourcesContent":[],"mappings":";KAGY,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;EA2HnB,CAAA,OAAqB,CAARA,EA7HA,eA6HQ,EAAA,GAAA,CAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;uBA5HE;mBACJ;;;;;;cA2HNA,QAAQ"}
|
package/build/v7.mjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { n as parseUuid, r as rng, t as formatUuid } from "./uuid-DaimLSJD.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/uuid/v7.ts
|
|
4
|
+
/**
|
|
5
|
+
* Module-level state for maintaining monotonic ordering within the same millisecond.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: This state persists across all uuidv7() calls in the module's lifetime.
|
|
8
|
+
* - In serverless/edge functions with warm starts, state persists between invocations.
|
|
9
|
+
* - For isolated state, pass explicit `msecs` and `seq` via options.
|
|
10
|
+
* - Tests should mock Date.now() or provide explicit options for deterministic behavior.
|
|
11
|
+
*/
|
|
12
|
+
const state = {};
|
|
13
|
+
function updateV7State(current, now, rnds) {
|
|
14
|
+
current.msecs ??= -Infinity;
|
|
15
|
+
current.seq ??= 0;
|
|
16
|
+
if (now > current.msecs) {
|
|
17
|
+
current.seq = rnds[6] << 23 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
|
|
18
|
+
current.msecs = now;
|
|
19
|
+
} else {
|
|
20
|
+
current.seq = current.seq + 1 | 0;
|
|
21
|
+
if (current.seq === 0) current.msecs += 1;
|
|
22
|
+
}
|
|
23
|
+
return current;
|
|
24
|
+
}
|
|
25
|
+
function v7Bytes(rnds, msecs, seq, buf, offset = 0) {
|
|
26
|
+
if (rnds.length < 16) throw new Error("Random bytes length must be >= 16");
|
|
27
|
+
if (!buf) {
|
|
28
|
+
buf = new Uint8Array(16);
|
|
29
|
+
offset = 0;
|
|
30
|
+
} else if (offset < 0 || offset + 16 > buf.length) throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
31
|
+
msecs ??= Date.now();
|
|
32
|
+
seq ??= rnds[6] * 127 << 24 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
|
|
33
|
+
buf[offset++] = msecs / 1099511627776 & 255;
|
|
34
|
+
buf[offset++] = msecs / 4294967296 & 255;
|
|
35
|
+
buf[offset++] = msecs / 16777216 & 255;
|
|
36
|
+
buf[offset++] = msecs / 65536 & 255;
|
|
37
|
+
buf[offset++] = msecs / 256 & 255;
|
|
38
|
+
buf[offset++] = msecs & 255;
|
|
39
|
+
buf[offset++] = 112 | seq >>> 28 & 15;
|
|
40
|
+
buf[offset++] = seq >>> 20 & 255;
|
|
41
|
+
buf[offset++] = 128 | seq >>> 14 & 63;
|
|
42
|
+
buf[offset++] = seq >>> 6 & 255;
|
|
43
|
+
buf[offset++] = seq << 2 & 255 | rnds[10] & 3;
|
|
44
|
+
buf[offset++] = rnds[11];
|
|
45
|
+
buf[offset++] = rnds[12];
|
|
46
|
+
buf[offset++] = rnds[13];
|
|
47
|
+
buf[offset++] = rnds[14];
|
|
48
|
+
buf[offset++] = rnds[15];
|
|
49
|
+
return buf;
|
|
50
|
+
}
|
|
51
|
+
function v7(options, buf, offset) {
|
|
52
|
+
let bytes;
|
|
53
|
+
if (options) bytes = v7Bytes(options.random ?? rng(), options.msecs, options.seq, buf, offset);
|
|
54
|
+
else {
|
|
55
|
+
/**
|
|
56
|
+
* Note: by default, Cloudflare Workers "freezes" time during request handling to prevent
|
|
57
|
+
* side-channel attacks. This means that Date.now() will return the same value for the entire
|
|
58
|
+
* duration of a request.
|
|
59
|
+
* Implications:
|
|
60
|
+
* - all UUIDv7 generated within a single request will have the same timestamp.
|
|
61
|
+
* - the monotonic ordering will rely entirely on the `state.seq` counter
|
|
62
|
+
*/
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
const rnds = rng();
|
|
65
|
+
updateV7State(state, now, rnds);
|
|
66
|
+
bytes = v7Bytes(rnds, state.msecs, state.seq, buf, offset);
|
|
67
|
+
}
|
|
68
|
+
return buf ?? formatUuid(bytes);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generate a UUID v7 string or write the bytes into a buffer.
|
|
72
|
+
* It also includes helpers to convert to and from byte arrays.
|
|
73
|
+
*/
|
|
74
|
+
const uuidv7 = Object.assign(v7, {
|
|
75
|
+
toBytes: (id) => parseUuid(id),
|
|
76
|
+
fromBytes: (bytes) => formatUuid(bytes)
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
export { uuidv7 };
|
|
81
|
+
//# sourceMappingURL=v7.mjs.map
|
package/build/v7.mjs.map
ADDED
|
@@ -0,0 +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 { 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}\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 = {}\n\nfunction updateV7State(current: V7State, now: number, rnds: Uint8Array): V7State {\n // Initialize state on first call (-Infinity ensures any real timestamp is greater)\n current.msecs ??= -Infinity\n current.seq ??= 0\n\n if (now > current.msecs) {\n // New millisecond tick: reseed sequence from random bytes.\n current.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]\n current.msecs = now\n } else {\n // Same millisecond: increment sequence, roll over into the next tick if needed.\n current.seq = (current.seq + 1) | 0\n if (current.seq === 0) {\n current.msecs += 1\n }\n }\n\n return current\n}\n\nfunction v7Bytes(rnds: Uint8Array, msecs?: number, seq?: number, buf?: Uint8Array, offset = 0): Uint8Array {\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16')\n }\n\n if (!buf) {\n buf = new Uint8Array(16)\n offset = 0\n } else 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, offset)\n } else {\n /**\n * Note: by default, Cloudflare Workers \"freezes\" time during request handling to prevent\n * side-channel attacks. This means that Date.now() will return the same value for the entire\n * duration of a request.\n * Implications:\n * - all UUIDv7 generated within a single request will have the same timestamp.\n * - the monotonic ordering will rely entirely on the `state.seq` counter\n */\n const now = Date.now()\n const rnds = rng()\n\n updateV7State(state, now, rnds)\n\n bytes = v7Bytes(rnds, state.msecs, state.seq, buf, offset)\n }\n\n return buf ?? formatUuid(bytes)\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.\n */\nexport const uuidv7: UuidV7 = Object.assign(v7, {\n toBytes: (id: string) => parseUuid(id),\n fromBytes: (bytes: Uint8Array) => formatUuid(bytes),\n})\n"],"mappings":";;;;;;;;;;;AAkCA,MAAMA,QAAiB,EAAE;AAEzB,SAAS,cAAc,SAAkB,KAAa,MAA2B;AAE/E,SAAQ,UAAU;AAClB,SAAQ,QAAQ;AAEhB,KAAI,MAAM,QAAQ,OAAO;AAEvB,UAAQ,MAAO,KAAK,MAAM,KAAO,KAAK,MAAM,KAAO,KAAK,MAAM,IAAK,KAAK;AACxE,UAAQ,QAAQ;QACX;AAEL,UAAQ,MAAO,QAAQ,MAAM,IAAK;AAClC,MAAI,QAAQ,QAAQ,EAClB,SAAQ,SAAS;;AAIrB,QAAO;;AAGT,SAAS,QAAQ,MAAkB,OAAgB,KAAc,KAAkB,SAAS,GAAe;AACzG,KAAI,KAAK,SAAS,GAChB,OAAM,IAAI,MAAM,oCAAoC;AAGtD,KAAI,CAAC,KAAK;AACR,QAAM,IAAI,WAAW,GAAG;AACxB,WAAS;YACA,SAAS,KAAK,SAAS,KAAK,IAAI,OACzC,OAAM,IAAI,WAAW,mBAAmB,OAAO,GAAG,SAAS,GAAG,0BAA0B;AAG1F,WAAU,KAAK,KAAK;AAEpB,SAAU,KAAK,KAAK,OAAS,KAAO,KAAK,MAAM,KAAO,KAAK,MAAM,IAAK,KAAK;AAG3E,KAAI,YAAa,QAAQ,gBAAiB;AAC1C,KAAI,YAAa,QAAQ,aAAe;AACxC,KAAI,YAAa,QAAQ,WAAa;AACtC,KAAI,YAAa,QAAQ,QAAW;AACpC,KAAI,YAAa,QAAQ,MAAS;AAClC,KAAI,YAAY,QAAQ;AAGxB,KAAI,YAAY,MAAS,QAAQ,KAAM;AACvC,KAAI,YAAa,QAAQ,KAAM;AAC/B,KAAI,YAAY,MAAS,QAAQ,KAAM;AACvC,KAAI,YAAa,QAAQ,IAAK;AAE9B,KAAI,YAAc,OAAO,IAAK,MAAS,KAAK,MAAM;AAClD,KAAI,YAAY,KAAK;AACrB,KAAI,YAAY,KAAK;AACrB,KAAI,YAAY,KAAK;AACrB,KAAI,YAAY,KAAK;AACrB,KAAI,YAAY,KAAK;AAErB,QAAO;;AAeT,SAAS,GACP,SACA,KACA,QACe;CACf,IAAIC;AAEJ,KAAI,QACF,SAAQ,QAAQ,QAAQ,UAAU,KAAK,EAAE,QAAQ,OAAO,QAAQ,KAAK,KAAK,OAAO;MAC5E;;;;;;;;;EASL,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,OAAO,KAAK;AAElB,gBAAc,OAAO,KAAK,KAAK;AAE/B,UAAQ,QAAQ,MAAM,MAAM,OAAO,MAAM,KAAK,KAAK,OAAO;;AAG5D,QAAO,OAAO,WAAW,MAAM;;;;;;AAOjC,MAAaC,SAAiB,OAAO,OAAO,IAAI;CAC9C,UAAU,OAAe,UAAU,GAAG;CACtC,YAAY,UAAsB,WAAW,MAAM;CACpD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": false,
|
|
3
|
+
"name": "uniku",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Minimal, tree-shakeable UUID utilities for every JavaScript runtime",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Alberto Schiabel",
|
|
8
|
+
"email": "alberto.schiabel@gmail.com",
|
|
9
|
+
"url": "https://github.com/jkomyno"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/jkomyno/uniku.git",
|
|
15
|
+
"directory": "packages/uniku"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/jkomyno/uniku#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/jkomyno/uniku/issues"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"uuid",
|
|
23
|
+
"uuidv4",
|
|
24
|
+
"uuidv7",
|
|
25
|
+
"unique",
|
|
26
|
+
"id",
|
|
27
|
+
"identifier",
|
|
28
|
+
"random",
|
|
29
|
+
"rfc4122",
|
|
30
|
+
"rfc9562",
|
|
31
|
+
"esm",
|
|
32
|
+
"typescript",
|
|
33
|
+
"tree-shakeable",
|
|
34
|
+
"edge",
|
|
35
|
+
"cloudflare-workers",
|
|
36
|
+
"bun",
|
|
37
|
+
"webcrypto"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"registry": "https://registry.npmjs.org/",
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=24.13.0"
|
|
45
|
+
},
|
|
46
|
+
"type": "module",
|
|
47
|
+
"sideEffects": false,
|
|
48
|
+
"files": [
|
|
49
|
+
"build",
|
|
50
|
+
"README.md"
|
|
51
|
+
],
|
|
52
|
+
"exports": {
|
|
53
|
+
"./uuid/v4": {
|
|
54
|
+
"types": "./build/v4.d.mts",
|
|
55
|
+
"import": {
|
|
56
|
+
"@jkomyno/source": "./src/uuid/v4.ts",
|
|
57
|
+
"default": "./build/v4.mjs"
|
|
58
|
+
},
|
|
59
|
+
"default": "./build/v4.mjs"
|
|
60
|
+
},
|
|
61
|
+
"./uuid/v7": {
|
|
62
|
+
"types": "./build/v7.d.mts",
|
|
63
|
+
"import": {
|
|
64
|
+
"@jkomyno/source": "./src/uuid/v7.ts",
|
|
65
|
+
"default": "./build/v7.mjs"
|
|
66
|
+
},
|
|
67
|
+
"default": "./build/v7.mjs"
|
|
68
|
+
},
|
|
69
|
+
"./package.json": "./package.json"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"clean": "rimraf build .turbo",
|
|
73
|
+
"build": "tsdown --config-loader unrun",
|
|
74
|
+
"build:watch": "tsdown --config-loader unrun --watch",
|
|
75
|
+
"test": "vitest run",
|
|
76
|
+
"test:unit": "vitest --project unit run",
|
|
77
|
+
"bench": "vitest bench"
|
|
78
|
+
}
|
|
79
|
+
}
|