@marianmeres/uid 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # @marianmeres/uid
2
+
3
+ [![JSR](https://jsr.io/badges/@marianmeres/uid)](https://jsr.io/@marianmeres/uid)
4
+ [![NPM](https://img.shields.io/npm/v/@marianmeres/uid)](https://www.npmjs.com/package/@marianmeres/uid)
5
+ [![License](https://img.shields.io/npm/l/@marianmeres/uid)](LICENSE)
6
+
7
+ One `uid()` function, many id strategies — UUIDs, sortable ids (UUID v7 / ULID),
8
+ URL-safe random ids (nanoid-style), human-friendly alphabets (base56/58/62/…),
9
+ in-memory counters, reversible integer codecs, and human-readable ids.
10
+
11
+ - **Works everywhere** — browsers, Deno, Node 19+, Bun.
12
+ - **Crypto-backed** — all randomness comes from the Web Crypto API, with
13
+ rejection sampling so non-power-of-two alphabets stay unbiased.
14
+ - **Zero dependencies** in the core (the optional `rhr` strategy is the only
15
+ add-on, and it's opt-in).
16
+ - **Type-safe** — `options` are checked per strategy, and every strategy is also
17
+ a standalone, tree-shakeable named export.
18
+
19
+ > Good-quality randomness, but **not** intended for cryptographic secrets
20
+ > (tokens, keys, password resets). Use a dedicated crypto routine for those.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ # deno
26
+ deno add jsr:@marianmeres/uid
27
+
28
+ # npm (or pnpm / yarn / bun)
29
+ npx jsr add @marianmeres/uid
30
+ ```
31
+
32
+ ## Quick start
33
+
34
+ ```typescript
35
+ import { uid } from "@marianmeres/uid";
36
+
37
+ uid(); // uuid v4 (default)
38
+ uid("uuidv7"); // sortable, UUID-compatible
39
+ uid("ulid"); // sortable, 26-char Crockford base32
40
+ uid("nanoid", { length: 12 }); // "V1StGXR8_Z5j"
41
+ uid("base58", { length: 10 }); // "3kP9xQ2mWz"
42
+ uid("numeric", { length: 6 }); // "048217" (OTP / coupon)
43
+ uid("counter", { prefix: "n" }); // "n0", "n1", "n2", …
44
+ ```
45
+
46
+ Every strategy is also a direct, tree-shakeable named export — handy when you
47
+ want one specific generator without the dispatcher:
48
+
49
+ ```typescript
50
+ import { base62, nanoid, ulid, uuidv7 } from "@marianmeres/uid";
51
+
52
+ uuidv7(); // "0192f6c4-1d2e-7a3b-8c4d-5e6f7a8b9c0d"
53
+ nanoid(); // 21-char URL-safe id
54
+ base62(8); // "aZ09Kp3X"
55
+ ```
56
+
57
+ ## Strategies
58
+
59
+ | Strategy | `uid(...)` | Output |
60
+ | --------------------------------------------------- | -------------------------------------------------- | --------------------------------------- |
61
+ | `uuid` / `uuidv4` | `uid()` / `uid("uuid")` | RFC 9562 UUID v4 |
62
+ | `uuidv7` | `uid("uuidv7", { timestamp? })` | Time-sortable UUID |
63
+ | `ulid` | `uid("ulid", { timestamp? })` | 26-char Crockford base32, sortable |
64
+ | `base56` | `uid("base56", { length?, uuid? })` | No-ambiguous random / reversible uuid |
65
+ | `nanoid` | `uid("nanoid", { length?, alphabet? })` | URL-safe random id |
66
+ | `hex` `base32` `base36` `base58` `base62` `numeric` | `uid("base58", { length? })` | Random string over a named alphabet |
67
+ | `custom` | `uid("custom", { alphabet, length? })` | Random string over your alphabet |
68
+ | `counter` | `uid("counter", { prefix?, start?, step?, pad? })` | In-memory incrementing id |
69
+ | `reversible` | `uid("reversible", { value, salt?, … })` | Short reversible encoding of an integer |
70
+ | `rhr` | `uid("rhr", { … })` _(opt-in, see below)_ | Human-readable id |
71
+
72
+ Default length for random strategies is **21**. A UUID encoded as base56 is
73
+ always **23** characters (128 bits need 23 base56 digits).
74
+
75
+ ### Sortable ids — `uuidv7` vs `ulid`
76
+
77
+ Both embed a 48-bit millisecond timestamp prefix and sort by creation time.
78
+ `uuidv7` is a valid UUID (drops into any `uuid` DB column); `ulid` is shorter,
79
+ dash-free, and case-insensitive but not a valid UUID string.
80
+
81
+ ```typescript
82
+ uid("uuidv7"); // "0192f6c4-1d2e-7a3b-..."
83
+ uid("ulid"); // "01J9Z7Q8K3M4N5P6R7S8T9V0W1"
84
+ uid("uuidv7", { timestamp: 0 }); // back-dated / deterministic time for tests
85
+ ```
86
+
87
+ ### base56 — random or reversible UUID
88
+
89
+ `base56` drops visually ambiguous characters (`0 O o 1 l I`), so it's safe to
90
+ read aloud or retype.
91
+
92
+ ```typescript
93
+ import { base56, base56ToUuid, base56Uuid, uuidToBase56 } from "@marianmeres/uid";
94
+
95
+ base56(10); // random, e.g. "7vNpRmXj4Q"
96
+ base56Uuid(); // fresh uuid, 23-char base56 (reversible)
97
+
98
+ const enc = uuidToBase56("550e8400-e29b-41d4-a716-446655440000");
99
+ base56ToUuid(enc); // back to the original uuid
100
+ ```
101
+
102
+ ### counter — in-memory sequence
103
+
104
+ State lives for the lifetime of the process/page (it resets on reload) and is
105
+ **not** for cross-process uniqueness. Each prefix has its own sequence.
106
+
107
+ ```typescript
108
+ import { createCounter } from "@marianmeres/uid";
109
+
110
+ uid("counter", { prefix: "node_" }); // "node_0", "node_1", …
111
+ uid("counter", { prefix: "x", pad: 4 }); // "x0000", "x0001", …
112
+
113
+ // fully isolated instance (best for tests / multiple independent sequences):
114
+ const next = createCounter({ prefix: "row-", start: 1, pad: 4 });
115
+ next(); // "row-0001"
116
+ next(); // "row-0002"
117
+ ```
118
+
119
+ ### reversible — encode integers ↔ short strings
120
+
121
+ A small "sqids/hashids-lite". With a `salt` the alphabet is deterministically
122
+ shuffled so sequential ids don't look sequential — useful for exposing database
123
+ row ids in URLs without leaking the row count.
124
+
125
+ ```typescript
126
+ import { decodeInt, encodeInt } from "@marianmeres/uid";
127
+
128
+ const code = encodeInt(12345, { salt: "my-secret" }); // e.g. "Yq9"
129
+ decodeInt(code, { salt: "my-secret" }); // 12345
130
+ ```
131
+
132
+ > Like hashids, this is **obfuscation, not encryption** — anyone who knows the
133
+ > salt and alphabet can reverse it. Don't use it to protect data.
134
+
135
+ ### rhr — human-readable ids (opt-in)
136
+
137
+ Human-readable ids are built on
138
+ [`@marianmeres/random-human-readable`](https://jsr.io/@marianmeres/random-human-readable).
139
+ To keep its word lists out of the core bundle, this strategy lives behind a
140
+ subpath you import explicitly:
141
+
142
+ ```typescript
143
+ // register the strategy once (e.g. in your entry file):
144
+ import "@marianmeres/uid/rhr";
145
+ import { uid } from "@marianmeres/uid";
146
+ uid("rhr"); // "happy-blue-otter-canyon"
147
+
148
+ // …or call it directly (tree-shakeable, no registration needed):
149
+ import { rhr } from "@marianmeres/uid/rhr";
150
+ rhr({ nounsCount: 1 });
151
+ ```
152
+
153
+ On npm, install the peer dependency yourself:
154
+ `npm install @marianmeres/random-human-readable`.
155
+
156
+ ## Custom alphabets & strategies
157
+
158
+ ```typescript
159
+ import { randomString, registerStrategy, uid } from "@marianmeres/uid";
160
+
161
+ // arbitrary alphabet, one-off:
162
+ uid("custom", { alphabet: "ABCDEF01", length: 8 });
163
+ randomString(8, "ABCDEF01");
164
+
165
+ // register your own reusable strategy:
166
+ registerStrategy("order", () => "ORD-" + uid("numeric", { length: 8 }));
167
+ uid("order"); // "ORD-40582193"
168
+ ```
169
+
170
+ ## Validation
171
+
172
+ Options are validated rather than coerced: non-positive/fractional lengths,
173
+ out-of-range UUID v7 / ULID timestamps, missing required options (`custom`'s
174
+ `alphabet`, `reversible`'s `value`), duplicate reversible alphabets, and invalid
175
+ counter options all throw `TypeError` / `RangeError`.
176
+
177
+ ## API
178
+
179
+ See [API.md](API.md) for the complete API reference.
180
+
181
+ ## License
182
+
183
+ [MIT](LICENSE)
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Fixed-length random strings over the built-in named alphabets.
3
+ *
4
+ * These are thin, well-named wrappers around {@link randomString} so the most
5
+ * common cases read cleanly: `hex(32)`, `numeric(6)`, `base62()`, …
6
+ */
7
+ /**
8
+ * nanoid-style id: URL-safe (`A–Z a–z 0–9 _ -`), crypto-backed, unbiased.
9
+ *
10
+ * @param length Number of characters (default: {@link DEFAULT_LENGTH}).
11
+ * @param alphabet Override the alphabet (default: URL-safe 64-char set).
12
+ */
13
+ export declare function nanoid(length?: number, alphabet?: string): string;
14
+ /** Random lowercase hex string. */
15
+ export declare function hex(length?: number): string;
16
+ /** Random Crockford base32 string (no I, L, O, U). */
17
+ export declare function base32(length?: number): string;
18
+ /** Random lowercase base36 string. */
19
+ export declare function base36(length?: number): string;
20
+ /** Random Bitcoin base58 string (no 0, O, I, l). */
21
+ export declare function base58(length?: number): string;
22
+ /** Random full base62 string. */
23
+ export declare function base62(length?: number): string;
24
+ /** Random digits-only string — handy for OTPs / numeric coupon codes. */
25
+ export declare function numeric(length?: number): string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Fixed-length random strings over the built-in named alphabets.
3
+ *
4
+ * These are thin, well-named wrappers around {@link randomString} so the most
5
+ * common cases read cleanly: `hex(32)`, `numeric(6)`, `base62()`, …
6
+ */
7
+ import { ALPHABETS, DEFAULT_LENGTH, randomString } from "./random.js";
8
+ /**
9
+ * nanoid-style id: URL-safe (`A–Z a–z 0–9 _ -`), crypto-backed, unbiased.
10
+ *
11
+ * @param length Number of characters (default: {@link DEFAULT_LENGTH}).
12
+ * @param alphabet Override the alphabet (default: URL-safe 64-char set).
13
+ */
14
+ export function nanoid(length = DEFAULT_LENGTH, alphabet = ALPHABETS.nanoid) {
15
+ return randomString(length, alphabet);
16
+ }
17
+ /** Random lowercase hex string. */
18
+ export function hex(length = DEFAULT_LENGTH) {
19
+ return randomString(length, ALPHABETS.hex);
20
+ }
21
+ /** Random Crockford base32 string (no I, L, O, U). */
22
+ export function base32(length = DEFAULT_LENGTH) {
23
+ return randomString(length, ALPHABETS.base32);
24
+ }
25
+ /** Random lowercase base36 string. */
26
+ export function base36(length = DEFAULT_LENGTH) {
27
+ return randomString(length, ALPHABETS.base36);
28
+ }
29
+ /** Random Bitcoin base58 string (no 0, O, I, l). */
30
+ export function base58(length = DEFAULT_LENGTH) {
31
+ return randomString(length, ALPHABETS.base58);
32
+ }
33
+ /** Random full base62 string. */
34
+ export function base62(length = DEFAULT_LENGTH) {
35
+ return randomString(length, ALPHABETS.base62);
36
+ }
37
+ /** Random digits-only string — handy for OTPs / numeric coupon codes. */
38
+ export function numeric(length = DEFAULT_LENGTH) {
39
+ return randomString(length, ALPHABETS.numeric);
40
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Base56 strategy — human-friendly, no ambiguous characters (no 0 O o 1 l I).
3
+ *
4
+ * Two modes:
5
+ * - {@link base56} random fixed-length string (coupon-style)
6
+ * - {@link uuidToBase56} / {@link base56ToUuid} fully reversible 23-char
7
+ * encoding of a UUID
8
+ *
9
+ * Note: 128 bits need ceil(128 / log2(56)) = 23 base56 characters in the worst
10
+ * case (since 56^22 ≈ 2^127.76 < 2^128), so the encoded width is fixed at 23.
11
+ */
12
+ /**
13
+ * Generates a random base56 string.
14
+ *
15
+ * @param length Number of characters (default: {@link DEFAULT_LENGTH}).
16
+ */
17
+ export declare function base56(length?: number): string;
18
+ /**
19
+ * Encodes a UUID into a 23-character base56 string. Fully reversible via
20
+ * {@link base56ToUuid}.
21
+ *
22
+ * @param uuid A UUID string, with or without dashes.
23
+ */
24
+ export declare function uuidToBase56(uuid: string): string;
25
+ /**
26
+ * Decodes a base56 string produced by {@link uuidToBase56} back into a
27
+ * canonical UUID string.
28
+ */
29
+ export declare function base56ToUuid(encoded: string): string;
30
+ /**
31
+ * Generates a fresh UUID and returns its 23-character base56 encoding.
32
+ * Equivalent to `uuidToBase56(uuid())`.
33
+ */
34
+ export declare function base56Uuid(): string;
package/dist/base56.js ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Base56 strategy — human-friendly, no ambiguous characters (no 0 O o 1 l I).
3
+ *
4
+ * Two modes:
5
+ * - {@link base56} random fixed-length string (coupon-style)
6
+ * - {@link uuidToBase56} / {@link base56ToUuid} fully reversible 23-char
7
+ * encoding of a UUID
8
+ *
9
+ * Note: 128 bits need ceil(128 / log2(56)) = 23 base56 characters in the worst
10
+ * case (since 56^22 ≈ 2^127.76 < 2^128), so the encoded width is fixed at 23.
11
+ */
12
+ import { ALPHABETS, DEFAULT_LENGTH, randomString } from "./random.js";
13
+ const BASE56 = ALPHABETS.base56;
14
+ /**
15
+ * Generates a random base56 string.
16
+ *
17
+ * @param length Number of characters (default: {@link DEFAULT_LENGTH}).
18
+ */
19
+ export function base56(length = DEFAULT_LENGTH) {
20
+ return randomString(length, BASE56);
21
+ }
22
+ /**
23
+ * Encodes a UUID into a 23-character base56 string. Fully reversible via
24
+ * {@link base56ToUuid}.
25
+ *
26
+ * @param uuid A UUID string, with or without dashes.
27
+ */
28
+ export function uuidToBase56(uuid) {
29
+ const hex = uuid.replace(/-/g, "").toLowerCase();
30
+ if (!/^[0-9a-f]{32}$/.test(hex)) {
31
+ throw new TypeError(`uuidToBase56: invalid uuid "${uuid}"`);
32
+ }
33
+ let num = BigInt("0x" + hex);
34
+ let result = "";
35
+ while (num > 0n) {
36
+ result = BASE56[Number(num % 56n)] + result;
37
+ num = num / 56n;
38
+ }
39
+ return result.padStart(23, BASE56[0]);
40
+ }
41
+ /**
42
+ * Decodes a base56 string produced by {@link uuidToBase56} back into a
43
+ * canonical UUID string.
44
+ */
45
+ export function base56ToUuid(encoded) {
46
+ let num = 0n;
47
+ for (const ch of encoded) {
48
+ const idx = BASE56.indexOf(ch);
49
+ if (idx < 0) {
50
+ throw new Error(`base56ToUuid: invalid character "${ch}"`);
51
+ }
52
+ num = num * 56n + BigInt(idx);
53
+ }
54
+ const hex = num.toString(16).padStart(32, "0");
55
+ return [
56
+ hex.slice(0, 8),
57
+ hex.slice(8, 12),
58
+ hex.slice(12, 16),
59
+ hex.slice(16, 20),
60
+ hex.slice(20),
61
+ ].join("-");
62
+ }
63
+ /**
64
+ * Generates a fresh UUID and returns its 23-character base56 encoding.
65
+ * Equivalent to `uuidToBase56(uuid())`.
66
+ */
67
+ export function base56Uuid() {
68
+ return uuidToBase56(crypto.randomUUID());
69
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Counter strategy — a simple, monotonically increasing, in-memory counter
3
+ * with an optional prefix. State lives for the lifetime of the running
4
+ * process/page; it is NOT persisted and resets on reload. Suitable for
5
+ * within-process unique ids (tree nodes, DOM ids, test fixtures), not for
6
+ * cross-process uniqueness.
7
+ */
8
+ /** Options shared by {@link counter} and {@link createCounter}. */
9
+ export interface CounterOptions {
10
+ /** String prepended to the number (also the key for the shared counter). */
11
+ prefix?: string;
12
+ /** First value emitted (default: `0`). */
13
+ start?: number;
14
+ /** Increment between successive values (default: `1`). */
15
+ step?: number;
16
+ /** Zero-pad the numeric part to this width (default: `0`, no padding). */
17
+ pad?: number;
18
+ }
19
+ /**
20
+ * Returns the next value of the shared, per-prefix counter.
21
+ *
22
+ * Each distinct `prefix` has its own independent sequence. The **first** call
23
+ * for a given prefix configures it (`start`, `step`, `pad`) and returns `start`;
24
+ * subsequent calls advance it by the captured `step` and reuse the captured
25
+ * `pad`, so option overrides passed to later calls for the same prefix are
26
+ * ignored (and the id width stays stable). Use {@link createCounter} when you
27
+ * want explicit per-instance configuration.
28
+ *
29
+ * Options are still validated on every call, so malformed input throws even when
30
+ * the values would be ignored.
31
+ *
32
+ * @example
33
+ * counter({ prefix: "node_" }); // "node_0"
34
+ * counter({ prefix: "node_" }); // "node_1"
35
+ * counter({ prefix: "x", pad: 3 }); // "x000"
36
+ */
37
+ export declare function counter(options?: CounterOptions): string;
38
+ /**
39
+ * Creates an isolated counter function with its own private state — no sharing
40
+ * with {@link counter} or with other instances. Prefer this when you need
41
+ * several independent sequences or deterministic behavior in tests.
42
+ *
43
+ * @example
44
+ * const next = createCounter({ prefix: "row-", start: 1, pad: 4 });
45
+ * next(); // "row-0001"
46
+ * next(); // "row-0002"
47
+ */
48
+ export declare function createCounter(options?: CounterOptions): () => string;
49
+ /**
50
+ * Clears the shared per-prefix counter state used by {@link counter}.
51
+ * Mainly useful in tests. Does not affect {@link createCounter} instances.
52
+ *
53
+ * @param prefix If given, resets only that prefix; otherwise resets all.
54
+ */
55
+ export declare function resetCounters(prefix?: string): void;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Counter strategy — a simple, monotonically increasing, in-memory counter
3
+ * with an optional prefix. State lives for the lifetime of the running
4
+ * process/page; it is NOT persisted and resets on reload. Suitable for
5
+ * within-process unique ids (tree nodes, DOM ids, test fixtures), not for
6
+ * cross-process uniqueness.
7
+ */
8
+ import { assertNonNegativeInt } from "./random.js";
9
+ function validate(o) {
10
+ const { prefix = "", start = 0, step = 1, pad = 0 } = o;
11
+ if (typeof prefix !== "string") {
12
+ throw new TypeError(`counter: "prefix" must be a string`);
13
+ }
14
+ if (!Number.isInteger(start)) {
15
+ throw new TypeError(`counter: "start" must be an integer`);
16
+ }
17
+ if (!Number.isInteger(step) || step < 1) {
18
+ throw new TypeError(`counter: "step" must be a positive integer`);
19
+ }
20
+ assertNonNegativeInt(pad, "pad");
21
+ return { prefix, start, step, pad };
22
+ }
23
+ function format(prefix, n, pad) {
24
+ const s = pad > 0 ? String(n).padStart(pad, "0") : String(n);
25
+ return prefix + s;
26
+ }
27
+ // One independent counter per prefix, shared across the module. The full config
28
+ // (current value + step + pad) is captured on first use so a prefix's sequence
29
+ // stays consistent regardless of options passed to later calls.
30
+ const _counters = new Map();
31
+ /**
32
+ * Returns the next value of the shared, per-prefix counter.
33
+ *
34
+ * Each distinct `prefix` has its own independent sequence. The **first** call
35
+ * for a given prefix configures it (`start`, `step`, `pad`) and returns `start`;
36
+ * subsequent calls advance it by the captured `step` and reuse the captured
37
+ * `pad`, so option overrides passed to later calls for the same prefix are
38
+ * ignored (and the id width stays stable). Use {@link createCounter} when you
39
+ * want explicit per-instance configuration.
40
+ *
41
+ * Options are still validated on every call, so malformed input throws even when
42
+ * the values would be ignored.
43
+ *
44
+ * @example
45
+ * counter({ prefix: "node_" }); // "node_0"
46
+ * counter({ prefix: "node_" }); // "node_1"
47
+ * counter({ prefix: "x", pad: 3 }); // "x000"
48
+ */
49
+ export function counter(options = {}) {
50
+ const { prefix, start, step, pad } = validate(options);
51
+ const existing = _counters.get(prefix);
52
+ const entry = existing
53
+ ? { ...existing, value: existing.value + existing.step }
54
+ : { value: start, step, pad };
55
+ _counters.set(prefix, entry);
56
+ return format(prefix, entry.value, entry.pad);
57
+ }
58
+ /**
59
+ * Creates an isolated counter function with its own private state — no sharing
60
+ * with {@link counter} or with other instances. Prefer this when you need
61
+ * several independent sequences or deterministic behavior in tests.
62
+ *
63
+ * @example
64
+ * const next = createCounter({ prefix: "row-", start: 1, pad: 4 });
65
+ * next(); // "row-0001"
66
+ * next(); // "row-0002"
67
+ */
68
+ export function createCounter(options = {}) {
69
+ const { prefix, start, step, pad } = validate(options);
70
+ let current = start - step;
71
+ return () => {
72
+ current += step;
73
+ return format(prefix, current, pad);
74
+ };
75
+ }
76
+ /**
77
+ * Clears the shared per-prefix counter state used by {@link counter}.
78
+ * Mainly useful in tests. Does not affect {@link createCounter} instances.
79
+ *
80
+ * @param prefix If given, resets only that prefix; otherwise resets all.
81
+ */
82
+ export function resetCounters(prefix) {
83
+ if (prefix === undefined)
84
+ _counters.clear();
85
+ else
86
+ _counters.delete(prefix);
87
+ }
package/dist/mod.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @marianmeres/uid — one `uid()` function, many id strategies.
3
+ *
4
+ * The core entry point is zero-dependency and works in every modern runtime.
5
+ * The `rhr` strategy (human-readable ids) is opt-in via the `./rhr` subpath to
6
+ * keep its word lists out of the core bundle.
7
+ *
8
+ * @example
9
+ * import { uid, nanoid, uuidv7 } from "@marianmeres/uid";
10
+ * uid(); // uuid v4
11
+ * nanoid(12); // tree-shakeable named export
12
+ * uid("uuidv7"); // sortable database key
13
+ */
14
+ export * from "./random.js";
15
+ export * from "./uuid.js";
16
+ export * from "./base56.js";
17
+ export * from "./alphabet.js";
18
+ export * from "./counter.js";
19
+ export * from "./reversible.js";
20
+ export * from "./uid.js";
package/dist/mod.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @marianmeres/uid — one `uid()` function, many id strategies.
3
+ *
4
+ * The core entry point is zero-dependency and works in every modern runtime.
5
+ * The `rhr` strategy (human-readable ids) is opt-in via the `./rhr` subpath to
6
+ * keep its word lists out of the core bundle.
7
+ *
8
+ * @example
9
+ * import { uid, nanoid, uuidv7 } from "@marianmeres/uid";
10
+ * uid(); // uuid v4
11
+ * nanoid(12); // tree-shakeable named export
12
+ * uid("uuidv7"); // sortable database key
13
+ */
14
+ export * from "./random.js";
15
+ export * from "./uuid.js";
16
+ export * from "./base56.js";
17
+ export * from "./alphabet.js";
18
+ export * from "./counter.js";
19
+ export * from "./reversible.js";
20
+ export * from "./uid.js";
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Crypto-backed randomness primitives shared by every strategy.
3
+ *
4
+ * All randomness goes through the Web Crypto API (`crypto.getRandomValues`),
5
+ * which is available in every modern runtime (browsers, Deno, Node 19+, Bun)
6
+ * without any external dependency. This is good-quality randomness, but the
7
+ * library is NOT intended for cryptographic secrets (tokens, keys, etc.).
8
+ */
9
+ /** Default length for random, fixed-length strategies (nanoid, base*, hex, …). */
10
+ export declare const DEFAULT_LENGTH = 21;
11
+ /**
12
+ * Named alphabets used by the built-in strategies.
13
+ *
14
+ * The "no-ambiguous" alphabets (`base56`, `base58`, `base32`) drop visually
15
+ * confusable characters so the output is safe to read aloud / retype.
16
+ */
17
+ export declare const ALPHABETS: {
18
+ hex: string;
19
+ base32: string;
20
+ base36: string;
21
+ base56: string;
22
+ base58: string;
23
+ base62: string;
24
+ numeric: string;
25
+ alphanumeric: string;
26
+ nanoid: string;
27
+ };
28
+ /** Throws `TypeError` unless `n` is an integer `>= 1`. */
29
+ export declare function assertPositiveInt(n: unknown, label: string): asserts n is number;
30
+ /** Throws `TypeError` unless `n` is an integer `>= 0`. */
31
+ export declare function assertNonNegativeInt(n: unknown, label: string): asserts n is number;
32
+ /**
33
+ * Returns `size` cryptographically-strong random bytes.
34
+ *
35
+ * Transparently chunks calls larger than the 65536-byte `getRandomValues`
36
+ * limit so any `size` is supported.
37
+ */
38
+ export declare function randomBytes(size: number): Uint8Array;
39
+ /**
40
+ * Generates a random string of `length` characters from `alphabet`.
41
+ *
42
+ * Uses rejection sampling (the nanoid algorithm) so the output is unbiased
43
+ * even when `alphabet.length` is not a power of two — no modulo skew.
44
+ *
45
+ * @param length Number of characters to produce (positive integer).
46
+ * @param alphabet Characters to choose from (1–256 chars). Defaults to the
47
+ * URL-safe nanoid alphabet.
48
+ */
49
+ export declare function randomString(length: number, alphabet?: string): string;