@typed/id 1.0.0-beta.4 → 1.0.0-beta.6
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 +171 -65
- package/dist/Cuid.d.ts +127 -12
- package/dist/Cuid.d.ts.map +1 -1
- package/dist/Cuid.js +133 -39
- package/dist/DateTimes.d.ts +64 -1
- package/dist/DateTimes.d.ts.map +1 -1
- package/dist/DateTimes.js +70 -3
- package/dist/Ids.d.ts +171 -28
- package/dist/Ids.d.ts.map +1 -1
- package/dist/Ids.js +159 -16
- package/dist/Ksuid.d.ts +51 -1
- package/dist/Ksuid.d.ts.map +1 -1
- package/dist/Ksuid.js +58 -6
- package/dist/NanoId.d.ts +47 -0
- package/dist/NanoId.d.ts.map +1 -1
- package/dist/NanoId.js +47 -0
- package/dist/RandomValues.d.ts +62 -3
- package/dist/RandomValues.d.ts.map +1 -1
- package/dist/RandomValues.js +72 -8
- package/dist/Ulid.d.ts +49 -1
- package/dist/Ulid.d.ts.map +1 -1
- package/dist/Ulid.js +53 -3
- package/dist/Uuid4.d.ts +47 -0
- package/dist/Uuid4.d.ts.map +1 -1
- package/dist/Uuid4.js +47 -0
- package/dist/Uuid5.d.ts +178 -6
- package/dist/Uuid5.d.ts.map +1 -1
- package/dist/Uuid5.js +151 -14
- package/dist/Uuid7.d.ts +120 -14
- package/dist/Uuid7.d.ts.map +1 -1
- package/dist/Uuid7.js +121 -13
- package/dist/__tests__/helpers.d.ts +7 -0
- package/dist/__tests__/helpers.d.ts.map +1 -0
- package/dist/__tests__/helpers.js +19 -0
- package/dist/__tests__/public-contract.type-test.d.ts +2 -0
- package/dist/__tests__/public-contract.type-test.d.ts.map +1 -0
- package/dist/__tests__/public-contract.type-test.js +3 -0
- package/dist/_sha.d.ts +32 -0
- package/dist/_sha.d.ts.map +1 -1
- package/dist/_sha.js +32 -0
- package/dist/_uuid-stringify.d.ts +15 -0
- package/dist/_uuid-stringify.d.ts.map +1 -1
- package/dist/_uuid-stringify.js +15 -0
- package/package.json +68 -14
- package/src/Cuid.ts +0 -124
- package/src/DateTimes.ts +0 -36
- package/src/Id.test.ts +0 -230
- package/src/Ids.ts +0 -128
- package/src/Ksuid.ts +0 -74
- package/src/NanoId.ts +0 -33
- package/src/RandomValues.ts +0 -33
- package/src/Ulid.ts +0 -51
- package/src/Uuid4.ts +0 -24
- package/src/Uuid5.ts +0 -71
- package/src/Uuid7.ts +0 -104
- package/src/_sha.ts +0 -11
- package/src/_uuid-stringify.ts +0 -30
- package/src/index.ts +0 -10
package/dist/Cuid.js
CHANGED
|
@@ -9,9 +9,56 @@ import { RandomValues } from "./RandomValues.js";
|
|
|
9
9
|
const DEFAULT_LENGTH = 24;
|
|
10
10
|
const BIG_LENGTH = 32;
|
|
11
11
|
const INITIAL_COUNT_MAX = 476782367;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Effect Schema and branded string type for 24-character CUID values.
|
|
14
|
+
* @remarks
|
|
15
|
+
* ## Why
|
|
16
|
+
* The schema validates transport or persisted strings before restoring the compile-time brand; generating a new client ID is not hydration identity.
|
|
17
|
+
* ## Ownership and lifetime
|
|
18
|
+
* This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { Cuid } from "@typed/id/Cuid"
|
|
22
|
+
* const id = Cuid.make("a00000000000000000000000")
|
|
23
|
+
* ```
|
|
24
|
+
* See [Effect Schema](https://effect.website/docs/schema/introduction/).
|
|
25
|
+
* @category Schemas
|
|
26
|
+
* @since 1.0.0
|
|
27
|
+
*/
|
|
28
|
+
export const Cuid = Schema.String.pipe(Schema.check(Schema.isPattern(/^[a-z][0-9a-z]{23}$/)), Schema.brand("@typed/id/CUID"));
|
|
29
|
+
/**
|
|
30
|
+
* Tests whether a string is a valid branded CUID.
|
|
31
|
+
* @remarks
|
|
32
|
+
* ## Why
|
|
33
|
+
* Runtime refinement restores trust after JSON, structured clone, or other transport has erased the TypeScript brand.
|
|
34
|
+
* ## Ownership and lifetime
|
|
35
|
+
* This pure predicate acquires no resources and retains no input.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { isCuid } from "@typed/id/Cuid"
|
|
39
|
+
* isCuid("a00000000000000000000000")
|
|
40
|
+
* ```
|
|
41
|
+
* @category Refinements
|
|
42
|
+
* @since 1.0.0
|
|
43
|
+
*/
|
|
14
44
|
export const isCuid = Schema.is(Cuid);
|
|
45
|
+
/**
|
|
46
|
+
* Process-local Effect service that supplies sequential CUID seeds.
|
|
47
|
+
* @remarks
|
|
48
|
+
* ## Why
|
|
49
|
+
* Counter state and caller-provided `envData` live in an explicit service so tests and applications choose the sharing boundary instead of relying on hidden globals.
|
|
50
|
+
* ## Ownership and lifetime
|
|
51
|
+
* Each Layer instance owns its mutable counter and captured fingerprint. A new process, worker, or Layer resets that sequence; exact SSR identity must be serialized and reused.
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { cuid, CuidState } from "@typed/id/Cuid"
|
|
55
|
+
* import { Effect } from "effect"
|
|
56
|
+
* const program = Effect.provide(cuid, CuidState.Default)
|
|
57
|
+
* ```
|
|
58
|
+
* See [Effect services](https://effect.website/docs/requirements-management/services/) and [Layers](https://effect.website/docs/requirements-management/layers/).
|
|
59
|
+
* @category Services
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
*/
|
|
15
62
|
export class CuidState extends Context.Service()("@typed/id/CuidState", {
|
|
16
63
|
make: (envData) => Effect.gen(function* () {
|
|
17
64
|
const { now } = yield* DateTimes;
|
|
@@ -21,38 +68,72 @@ export class CuidState extends Context.Service()("@typed/id/CuidState", {
|
|
|
21
68
|
(initialBytes[1] << 16) |
|
|
22
69
|
(initialBytes[2] << 8) |
|
|
23
70
|
initialBytes[3]) % INITIAL_COUNT_MAX;
|
|
24
|
-
//
|
|
71
|
+
// Derive a stable discriminator from caller-provided environment data
|
|
25
72
|
const fingerprint = (yield* hash(envData)).substring(0, BIG_LENGTH);
|
|
26
73
|
let counter = initialValue;
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
74
|
+
return {
|
|
75
|
+
next: Effect.gen(function* () {
|
|
76
|
+
const timestamp = yield* now;
|
|
77
|
+
const random = yield* getRandomValues(32);
|
|
78
|
+
return {
|
|
79
|
+
timestamp,
|
|
80
|
+
counter: counter++,
|
|
81
|
+
random,
|
|
82
|
+
fingerprint,
|
|
83
|
+
};
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
37
86
|
}),
|
|
38
87
|
}) {
|
|
39
|
-
|
|
40
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Reads one seed from the current CuidState service.
|
|
90
|
+
* @remarks
|
|
91
|
+
* ## Why
|
|
92
|
+
* The accessor exposes stateful sequencing through Effect's service channel rather than a module-global counter.
|
|
93
|
+
* ## Ownership and lifetime
|
|
94
|
+
* The Effect requires `CuidState`; its Layer owns the counter for the Layer lifetime.
|
|
95
|
+
* @category Services
|
|
96
|
+
* @since 1.0.0
|
|
97
|
+
*/
|
|
98
|
+
static next = Effect.gen(function* () {
|
|
99
|
+
const { next } = yield* CuidState;
|
|
100
|
+
return yield* next;
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* Provides a default CuidState backed by system time and Web Crypto entropy.
|
|
104
|
+
* @remarks
|
|
105
|
+
* ## Why
|
|
106
|
+
* The explicit Layer gives production code a standard service while keeping test and environment-specific alternatives replaceable.
|
|
107
|
+
* ## Ownership and lifetime
|
|
108
|
+
* Layer acquisition creates one counter state; the surrounding Layer Scope owns it. Web Crypto must be available in the runtime.
|
|
109
|
+
* @category Layers
|
|
110
|
+
* @since 1.0.0
|
|
111
|
+
*/
|
|
112
|
+
static Default = Layer.effect(CuidState, CuidState.make("node")).pipe(Layer.provide([DateTimes.Default, RandomValues.Default]));
|
|
41
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Generates one CUID from the current CuidState service.
|
|
116
|
+
* @remarks
|
|
117
|
+
* ## Why
|
|
118
|
+
* Generation is an Effect so sequencing and entropy dependencies remain explicit and replaceable; `envData` is only a caller discriminator, not a machine fingerprint guarantee. Missing Web Crypto or rejected SHA-512 work is a defect because the typed error channel is `never`.
|
|
119
|
+
* ## Ownership and lifetime
|
|
120
|
+
* The Effect acquires no resources itself and uses the CuidState owned by its provided Layer.
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { cuid, CuidState } from "@typed/id/Cuid"
|
|
124
|
+
* import { Effect } from "effect"
|
|
125
|
+
* const id = Effect.provide(cuid, CuidState.Default)
|
|
126
|
+
* ```
|
|
127
|
+
* @category Generators
|
|
128
|
+
* @since 1.0.0
|
|
129
|
+
*/
|
|
42
130
|
export const cuid = Effect.flatMap(CuidState.next, cuidFromSeed);
|
|
43
131
|
// Utilities
|
|
44
|
-
const
|
|
132
|
+
const LETTER_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
|
|
133
|
+
const BODY_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
134
|
+
const LETTER_DOMAIN = "@typed/id/cuid/letter";
|
|
135
|
+
const BODY_DOMAIN = "@typed/id/cuid/body";
|
|
45
136
|
const encoder = new TextEncoder();
|
|
46
|
-
function createEntropy(length, random) {
|
|
47
|
-
let entropy = "";
|
|
48
|
-
let offset = 0;
|
|
49
|
-
while (entropy.length < length) {
|
|
50
|
-
const value = random[offset];
|
|
51
|
-
entropy += Math.floor(value % 36).toString(36);
|
|
52
|
-
offset = (offset + 1) % random.length;
|
|
53
|
-
}
|
|
54
|
-
return entropy;
|
|
55
|
-
}
|
|
56
137
|
function hash(input) {
|
|
57
138
|
return Effect.map(sha512(encoder.encode(input)), (buffer) => {
|
|
58
139
|
const view = new Uint8Array(buffer);
|
|
@@ -64,20 +145,33 @@ function hash(input) {
|
|
|
64
145
|
return value.toString(36).slice(1);
|
|
65
146
|
});
|
|
66
147
|
}
|
|
148
|
+
function sample(domain, alphabet, length, canonicalInput) {
|
|
149
|
+
return Effect.gen(function* () {
|
|
150
|
+
const limit = Math.floor(256 / alphabet.length) * alphabet.length;
|
|
151
|
+
let value = "";
|
|
152
|
+
for (let block = 0; value.length < length; block++) {
|
|
153
|
+
const prefix = encoder.encode(`${domain}\0${block.toString(10)}\0`);
|
|
154
|
+
const input = new Uint8Array(prefix.length + canonicalInput.length);
|
|
155
|
+
input.set(prefix);
|
|
156
|
+
input.set(canonicalInput, prefix.length);
|
|
157
|
+
const digest = new Uint8Array(yield* sha512(input));
|
|
158
|
+
for (const byte of digest) {
|
|
159
|
+
if (byte >= limit)
|
|
160
|
+
continue;
|
|
161
|
+
value += alphabet[byte % alphabet.length];
|
|
162
|
+
if (value.length === length)
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
67
169
|
function cuidFromSeed({ counter, fingerprint, random, timestamp }) {
|
|
68
170
|
return Effect.gen(function* () {
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
// Create entropy from remaining random bytes
|
|
75
|
-
const salt = createEntropy(4, random.slice(1));
|
|
76
|
-
// Hash all components together
|
|
77
|
-
const hashInput = `${time}${salt}${count}${fingerprint}`;
|
|
78
|
-
const hashed = yield* hash(hashInput);
|
|
79
|
-
// Construct the final CUID
|
|
80
|
-
const id = `${firstLetter}${hashed.substring(0, DEFAULT_LENGTH - 1)}`;
|
|
81
|
-
return Cuid.make(id);
|
|
171
|
+
const randomHex = Array.from(random, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
172
|
+
const canonicalInput = encoder.encode([timestamp.toString(36), counter.toString(36), fingerprint, randomHex].join("\0"));
|
|
173
|
+
const firstLetter = yield* sample(LETTER_DOMAIN, LETTER_ALPHABET, 1, canonicalInput);
|
|
174
|
+
const body = yield* sample(BODY_DOMAIN, BODY_ALPHABET, DEFAULT_LENGTH - 1, canonicalInput);
|
|
175
|
+
return Cuid.make(firstLetter + body);
|
|
82
176
|
});
|
|
83
177
|
}
|
package/dist/DateTimes.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Layer from "effect/Layer";
|
|
3
4
|
import * as Context from "effect/Context";
|
|
@@ -10,11 +11,73 @@ declare const DateTimes_base: Context.ServiceClass<DateTimes, "@typed/id/DateTim
|
|
|
10
11
|
date: Effect.Effect<Date, never, never>;
|
|
11
12
|
}, never, never>;
|
|
12
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Effect service for current epoch milliseconds and Date values.
|
|
16
|
+
* @remarks
|
|
17
|
+
* ## Why
|
|
18
|
+
* Making time a service keeps time-based ID generators deterministic under tests and explicit under server or browser runtimes.
|
|
19
|
+
* ## Ownership and lifetime
|
|
20
|
+
* A DateTimes Layer owns its time source for the Layer lifetime; individual reads acquire no resources.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { DateTimes } from "@typed/id/DateTimes"
|
|
24
|
+
* import { Effect } from "effect"
|
|
25
|
+
* const now = Effect.provide(DateTimes.now, DateTimes.Default)
|
|
26
|
+
* ```
|
|
27
|
+
* See [Effect Clock](https://effect.website/docs/testing/testclock/).
|
|
28
|
+
* @category Services
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
*/
|
|
13
31
|
export declare class DateTimes extends DateTimes_base {
|
|
32
|
+
/**
|
|
33
|
+
* Reads epoch milliseconds from the current DateTimes service.
|
|
34
|
+
* @remarks
|
|
35
|
+
* ## Why
|
|
36
|
+
* A service-backed read avoids hard-wiring `Date.now` into generators and tests.
|
|
37
|
+
* ## Ownership and lifetime
|
|
38
|
+
* This Effect acquires no resources and uses the DateTimes service for one invocation.
|
|
39
|
+
* @category Services
|
|
40
|
+
* @since 1.0.0
|
|
41
|
+
*/
|
|
14
42
|
static readonly now: Effect.Effect<number, never, DateTimes>;
|
|
43
|
+
/**
|
|
44
|
+
* Reads a Date from the current DateTimes service.
|
|
45
|
+
* @remarks
|
|
46
|
+
* ## Why
|
|
47
|
+
* The Date view stays aligned with the same replaceable time source as epoch-millisecond reads.
|
|
48
|
+
* ## Ownership and lifetime
|
|
49
|
+
* This Effect acquires no resources and uses the DateTimes service for one invocation.
|
|
50
|
+
* @category Services
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
*/
|
|
15
53
|
static readonly date: Effect.Effect<Date, never, DateTimes>;
|
|
54
|
+
/**
|
|
55
|
+
* Provides DateTimes using the runtime wall clock.
|
|
56
|
+
* @remarks
|
|
57
|
+
* ## Why
|
|
58
|
+
* The production default is explicit and replaceable rather than hidden in each generator.
|
|
59
|
+
* ## Ownership and lifetime
|
|
60
|
+
* The surrounding Layer Scope owns the service; reads allocate only their returned Date values.
|
|
61
|
+
* @category Layers
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
*/
|
|
16
64
|
static readonly Default: Layer.Layer<DateTimes, never, never>;
|
|
17
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Provides DateTimes anchored to a base date and advanced by Effect Clock.
|
|
67
|
+
* @remarks
|
|
68
|
+
* ## Why
|
|
69
|
+
* Clock-relative time supports deterministic tests while still allowing controlled advancement; invalid bases fail with `IllegalArgumentError`.
|
|
70
|
+
* ## Ownership and lifetime
|
|
71
|
+
* Layer acquisition captures the base and current Clock reading; the surrounding Layer Scope owns that state.
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* import { DateTimes } from "@typed/id/DateTimes"
|
|
75
|
+
* const fixed = DateTimes.Fixed("2026-01-01T00:00:00Z")
|
|
76
|
+
* ```
|
|
77
|
+
* @category Layers
|
|
78
|
+
* @since 1.0.0
|
|
79
|
+
*/
|
|
80
|
+
static readonly Fixed: (baseDate: number | string | Date) => Layer.Layer<DateTimes, Cause.IllegalArgumentError, never>;
|
|
18
81
|
}
|
|
19
82
|
export {};
|
|
20
83
|
//# sourceMappingURL=DateTimes.d.ts.map
|
package/dist/DateTimes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimes.d.ts","sourceRoot":"","sources":["../src/DateTimes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;;;;;;;;;;AAE1C,qBAAa,SAAU,SAAQ,cAK7B;IACA,MAAM,CAAC,QAAQ,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"DateTimes.d.ts","sourceRoot":"","sources":["../src/DateTimes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;;;;;;;;;;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAU,SAAQ,cAK7B;IACA;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,0CAA+C;IAClE;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,wCAAiD;IAErE;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,uCAA2C;IAElE;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,aAAc,MAAM,GAAG,MAAM,GAAG,IAAI,+DAsBrD;CACL"}
|
package/dist/DateTimes.js
CHANGED
|
@@ -1,20 +1,87 @@
|
|
|
1
1
|
import * as Clock from "effect/Clock";
|
|
2
|
+
import * as Cause from "effect/Cause";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Layer from "effect/Layer";
|
|
4
5
|
import * as Context from "effect/Context";
|
|
6
|
+
/**
|
|
7
|
+
* Effect service for current epoch milliseconds and Date values.
|
|
8
|
+
* @remarks
|
|
9
|
+
* ## Why
|
|
10
|
+
* Making time a service keeps time-based ID generators deterministic under tests and explicit under server or browser runtimes.
|
|
11
|
+
* ## Ownership and lifetime
|
|
12
|
+
* A DateTimes Layer owns its time source for the Layer lifetime; individual reads acquire no resources.
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { DateTimes } from "@typed/id/DateTimes"
|
|
16
|
+
* import { Effect } from "effect"
|
|
17
|
+
* const now = Effect.provide(DateTimes.now, DateTimes.Default)
|
|
18
|
+
* ```
|
|
19
|
+
* See [Effect Clock](https://effect.website/docs/testing/testclock/).
|
|
20
|
+
* @category Services
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
5
23
|
export class DateTimes extends Context.Service()("@typed/id/DateTimes", {
|
|
6
24
|
make: Effect.succeed({
|
|
7
25
|
now: Effect.sync(() => Date.now()),
|
|
8
26
|
date: Effect.sync(() => new Date()),
|
|
9
27
|
}),
|
|
10
28
|
}) {
|
|
11
|
-
|
|
12
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Reads epoch milliseconds from the current DateTimes service.
|
|
31
|
+
* @remarks
|
|
32
|
+
* ## Why
|
|
33
|
+
* A service-backed read avoids hard-wiring `Date.now` into generators and tests.
|
|
34
|
+
* ## Ownership and lifetime
|
|
35
|
+
* This Effect acquires no resources and uses the DateTimes service for one invocation.
|
|
36
|
+
* @category Services
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
*/
|
|
39
|
+
static now = Effect.flatMap(DateTimes, ({ now }) => now);
|
|
40
|
+
/**
|
|
41
|
+
* Reads a Date from the current DateTimes service.
|
|
42
|
+
* @remarks
|
|
43
|
+
* ## Why
|
|
44
|
+
* The Date view stays aligned with the same replaceable time source as epoch-millisecond reads.
|
|
45
|
+
* ## Ownership and lifetime
|
|
46
|
+
* This Effect acquires no resources and uses the DateTimes service for one invocation.
|
|
47
|
+
* @category Services
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
static date = Effect.flatMap(DateTimes, ({ date }) => date);
|
|
51
|
+
/**
|
|
52
|
+
* Provides DateTimes using the runtime wall clock.
|
|
53
|
+
* @remarks
|
|
54
|
+
* ## Why
|
|
55
|
+
* The production default is explicit and replaceable rather than hidden in each generator.
|
|
56
|
+
* ## Ownership and lifetime
|
|
57
|
+
* The surrounding Layer Scope owns the service; reads allocate only their returned Date values.
|
|
58
|
+
* @category Layers
|
|
59
|
+
* @since 1.0.0
|
|
60
|
+
*/
|
|
13
61
|
static Default = Layer.effect(DateTimes, DateTimes.make);
|
|
62
|
+
/**
|
|
63
|
+
* Provides DateTimes anchored to a base date and advanced by Effect Clock.
|
|
64
|
+
* @remarks
|
|
65
|
+
* ## Why
|
|
66
|
+
* Clock-relative time supports deterministic tests while still allowing controlled advancement; invalid bases fail with `IllegalArgumentError`.
|
|
67
|
+
* ## Ownership and lifetime
|
|
68
|
+
* Layer acquisition captures the base and current Clock reading; the surrounding Layer Scope owns that state.
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { DateTimes } from "@typed/id/DateTimes"
|
|
72
|
+
* const fixed = DateTimes.Fixed("2026-01-01T00:00:00Z")
|
|
73
|
+
* ```
|
|
74
|
+
* @category Layers
|
|
75
|
+
* @since 1.0.0
|
|
76
|
+
*/
|
|
14
77
|
static Fixed = (baseDate) => Layer.effect(DateTimes, Effect.gen(function* () {
|
|
15
78
|
const clock = yield* Clock.Clock;
|
|
16
79
|
const base = new Date(baseDate);
|
|
17
|
-
const
|
|
80
|
+
const baseMillis = base.getTime();
|
|
81
|
+
if (!Number.isFinite(baseMillis)) {
|
|
82
|
+
return yield* new Cause.IllegalArgumentError(`Invalid base date: ${String(baseDate)}`);
|
|
83
|
+
}
|
|
84
|
+
const baseN = BigInt(baseMillis);
|
|
18
85
|
const startMillis = yield* clock.currentTimeMillis;
|
|
19
86
|
const now = clock.currentTimeMillis.pipe(Effect.map((millis) =>
|
|
20
87
|
// Use BigInt to avoid floating point precision issues which can break deterministic testing
|
package/dist/Ids.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Cause from "effect/Cause";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Layer from "effect/Layer";
|
|
3
4
|
import * as Context from "effect/Context";
|
|
@@ -15,57 +16,199 @@ import { Uuid7State } from "./Uuid7.js";
|
|
|
15
16
|
import { TestClock } from "effect/testing";
|
|
16
17
|
declare const Ids_base: Context.ServiceClass<Ids, "@typed/id/Ids", {
|
|
17
18
|
cuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/CUID">, never, never>;
|
|
18
|
-
ksuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/KSUID">,
|
|
19
|
+
ksuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/KSUID">, Cause.IllegalArgumentError, never>;
|
|
19
20
|
nanoId: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/NanoId">, never, never>;
|
|
20
|
-
ulid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/ULID">,
|
|
21
|
+
ulid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/ULID">, Cause.IllegalArgumentError, never>;
|
|
21
22
|
uuid4: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID4">, never, never>;
|
|
22
23
|
uuid5: {
|
|
23
|
-
(namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5>;
|
|
24
|
-
(name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5>;
|
|
25
|
-
readonly dns: (name: string) => Effect.Effect<Uuid5>;
|
|
26
|
-
readonly url: (name: string) => Effect.Effect<Uuid5>;
|
|
27
|
-
readonly oid: (name: string) => Effect.Effect<Uuid5>;
|
|
28
|
-
readonly x500: (name: string) => Effect.Effect<Uuid5>;
|
|
24
|
+
(namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
25
|
+
(name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
26
|
+
readonly dns: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
27
|
+
readonly url: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
28
|
+
readonly oid: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
29
|
+
readonly x500: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
29
30
|
};
|
|
30
|
-
uuid7: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID7">,
|
|
31
|
+
uuid7: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID7">, Cause.IllegalArgumentError, never>;
|
|
31
32
|
}> & {
|
|
32
33
|
readonly make: Effect.Effect<{
|
|
33
34
|
cuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/CUID">, never, never>;
|
|
34
|
-
ksuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/KSUID">,
|
|
35
|
+
ksuid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/KSUID">, Cause.IllegalArgumentError, never>;
|
|
35
36
|
nanoId: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/NanoId">, never, never>;
|
|
36
|
-
ulid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/ULID">,
|
|
37
|
+
ulid: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/ULID">, Cause.IllegalArgumentError, never>;
|
|
37
38
|
uuid4: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID4">, never, never>;
|
|
38
39
|
uuid5: {
|
|
39
|
-
(namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5>;
|
|
40
|
-
(name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5>;
|
|
41
|
-
readonly dns: (name: string) => Effect.Effect<Uuid5>;
|
|
42
|
-
readonly url: (name: string) => Effect.Effect<Uuid5>;
|
|
43
|
-
readonly oid: (name: string) => Effect.Effect<Uuid5>;
|
|
44
|
-
readonly x500: (name: string) => Effect.Effect<Uuid5>;
|
|
40
|
+
(namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
41
|
+
(name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
42
|
+
readonly dns: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
43
|
+
readonly url: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
44
|
+
readonly oid: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
45
|
+
readonly x500: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
|
|
45
46
|
};
|
|
46
|
-
uuid7: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID7">,
|
|
47
|
+
uuid7: Effect.Effect<string & import("effect/Brand").Brand<"@typed/id/UUID7">, Cause.IllegalArgumentError, never>;
|
|
47
48
|
}, never, CuidState | DateTimes | RandomValues | Uuid7State>;
|
|
48
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Unified Effect service for every Typed ID generator.
|
|
52
|
+
* @remarks
|
|
53
|
+
* ## Why
|
|
54
|
+
* One facade captures time, entropy, and state services once, so application code composes generators through a single explicit dependency without hiding their behavior.
|
|
55
|
+
* ## Ownership and lifetime
|
|
56
|
+
* Each Ids Layer owns its captured services plus lazy CUID and UUIDv7 state. Recreating the Layer resets process-local sequences; serialize server IDs when identity must survive hydration.
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { Ids } from "@typed/id/Ids"
|
|
60
|
+
* import { Effect } from "effect"
|
|
61
|
+
* const program = Effect.gen(function* () { return yield* Ids.uuid7 }).pipe(Effect.provide(Ids.Default))
|
|
62
|
+
* ```
|
|
63
|
+
* See [Effect services](https://effect.website/docs/requirements-management/services/) and [Layers](https://effect.website/docs/requirements-management/layers/).
|
|
64
|
+
* @category Services
|
|
65
|
+
* @since 1.0.0
|
|
66
|
+
*/
|
|
49
67
|
export declare class Ids extends Ids_base {
|
|
68
|
+
/**
|
|
69
|
+
* Generates a CUID using the current Ids service.
|
|
70
|
+
* @remarks
|
|
71
|
+
* ## Why
|
|
72
|
+
* The facade shares the Ids-owned CuidState instead of allocating a new sequence for every call.
|
|
73
|
+
* ## Ownership and lifetime
|
|
74
|
+
* This Effect acquires no resources and uses state owned by the provided Ids Layer.
|
|
75
|
+
* @category Generators
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
*/
|
|
50
78
|
static readonly cuid: Effect.Effect<Cuid, never, Ids>;
|
|
51
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Generates a KSUID using the current Ids service.
|
|
81
|
+
* @remarks
|
|
82
|
+
* ## Why
|
|
83
|
+
* The facade reuses captured time and entropy while retaining `IllegalArgumentError` for invalid KSUID timestamps.
|
|
84
|
+
* ## Ownership and lifetime
|
|
85
|
+
* This Effect acquires no persistent resource and uses services owned by the provided Ids Layer.
|
|
86
|
+
* @category Generators
|
|
87
|
+
* @since 1.0.0
|
|
88
|
+
*/
|
|
89
|
+
static readonly ksuid: Effect.Effect<Ksuid, Cause.IllegalArgumentError, Ids>;
|
|
90
|
+
/**
|
|
91
|
+
* Generates a NanoId using the current Ids service.
|
|
92
|
+
* @remarks
|
|
93
|
+
* ## Why
|
|
94
|
+
* The facade makes the selected entropy implementation available through one application dependency.
|
|
95
|
+
* ## Ownership and lifetime
|
|
96
|
+
* This Effect acquires no persistent resource and uses entropy owned by the provided Ids Layer.
|
|
97
|
+
* @category Generators
|
|
98
|
+
* @since 1.0.0
|
|
99
|
+
*/
|
|
52
100
|
static readonly nanoId: Effect.Effect<NanoId, never, Ids>;
|
|
53
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Generates a ULID using the current Ids service.
|
|
103
|
+
* @remarks
|
|
104
|
+
* ## Why
|
|
105
|
+
* The facade reuses captured time and entropy while retaining `IllegalArgumentError` for invalid 48-bit timestamps.
|
|
106
|
+
* ## Ownership and lifetime
|
|
107
|
+
* This Effect acquires no persistent resource and uses services owned by the provided Ids Layer.
|
|
108
|
+
* @category Generators
|
|
109
|
+
* @since 1.0.0
|
|
110
|
+
*/
|
|
111
|
+
static readonly ulid: Effect.Effect<Ulid, Cause.IllegalArgumentError, Ids>;
|
|
112
|
+
/**
|
|
113
|
+
* Generates a random UUID version 4 using the current Ids service.
|
|
114
|
+
* @remarks
|
|
115
|
+
* ## Why
|
|
116
|
+
* The facade keeps entropy selection replaceable while preserving UUID version and variant semantics.
|
|
117
|
+
* ## Ownership and lifetime
|
|
118
|
+
* This Effect acquires no persistent resource and uses entropy owned by the provided Ids Layer.
|
|
119
|
+
* @category Generators
|
|
120
|
+
* @since 1.0.0
|
|
121
|
+
*/
|
|
54
122
|
static readonly uuid4: Effect.Effect<Uuid4, never, Ids>;
|
|
123
|
+
/**
|
|
124
|
+
* Derives deterministic UUID version 5 values through the current Ids service, with DNS, URL, OID, and X.500 helpers.
|
|
125
|
+
* @remarks
|
|
126
|
+
* ## Why
|
|
127
|
+
* The facade supports data-first and namespace-first calls while keeping namespace choice and `IllegalArgumentError` explicit.
|
|
128
|
+
* ## Ownership and lifetime
|
|
129
|
+
* Each Effect acquires no persistent resources and reads the Ids service for one invocation; helper namespaces are stable captured copies.
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { Ids } from "@typed/id/Ids"
|
|
133
|
+
* import { Effect } from "effect"
|
|
134
|
+
* const program = Ids.uuid5.dns("example.com").pipe(Effect.provide(Ids.Default))
|
|
135
|
+
* ```
|
|
136
|
+
* @category Generators
|
|
137
|
+
* @since 1.0.0
|
|
138
|
+
*/
|
|
55
139
|
static readonly uuid5: {
|
|
56
|
-
|
|
57
|
-
(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
readonly
|
|
140
|
+
/** Binds a namespace first, then derives UUIDv5 values for names. @since 1.0.0 */
|
|
141
|
+
(namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
142
|
+
/** Derives a UUIDv5 from a name and namespace through the current Ids service. @since 1.0.0 */
|
|
143
|
+
(name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
144
|
+
/** Derives a UUIDv5 in the standard DNS namespace. @since 1.0.0 */
|
|
145
|
+
readonly dns: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
146
|
+
/** Derives a UUIDv5 in the standard URL namespace. @since 1.0.0 */
|
|
147
|
+
readonly url: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
148
|
+
/** Derives a UUIDv5 in the standard OID namespace. @since 1.0.0 */
|
|
149
|
+
readonly oid: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
150
|
+
/** Derives a UUIDv5 in the standard X.500 namespace. @since 1.0.0 */
|
|
151
|
+
readonly x500: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError, Ids>;
|
|
62
152
|
};
|
|
63
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Generates a UUID version 7 using the current Ids service.
|
|
155
|
+
* @remarks
|
|
156
|
+
* ## Why
|
|
157
|
+
* The facade shares one lazy Uuid7State per Ids Layer, preserving local monotonicity and typed timestamp errors.
|
|
158
|
+
* ## Ownership and lifetime
|
|
159
|
+
* This Effect acquires no resources and uses sequence state owned by the provided Ids Layer.
|
|
160
|
+
* @category Generators
|
|
161
|
+
* @since 1.0.0
|
|
162
|
+
*/
|
|
163
|
+
static readonly uuid7: Effect.Effect<Uuid7, Cause.IllegalArgumentError, Ids>;
|
|
164
|
+
/**
|
|
165
|
+
* Provides production Ids, DateTimes, and RandomValues services.
|
|
166
|
+
* @remarks
|
|
167
|
+
* ## Why
|
|
168
|
+
* The standard Layer uses system time and Web Crypto while lazily creating sequence state only when CUID or UUIDv7 is first requested.
|
|
169
|
+
* ## Ownership and lifetime
|
|
170
|
+
* The surrounding Layer Scope owns captured services and lazy sequence state; Web Crypto must exist in the runtime.
|
|
171
|
+
* @category Layers
|
|
172
|
+
* @since 1.0.0
|
|
173
|
+
*/
|
|
64
174
|
static readonly Default: Layer.Layer<Ids | DateTimes | RandomValues, never, never>;
|
|
65
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Provides deterministic Ids, time, entropy, and TestClock services.
|
|
177
|
+
* @remarks
|
|
178
|
+
* ## Why
|
|
179
|
+
* Reproducible generators make exact sequences testable; the deterministic entropy is for tests and simulations, not security.
|
|
180
|
+
* ## Ownership and lifetime
|
|
181
|
+
* Each Layer construction owns an independent clock, random sequence, and lazy CUID/UUIDv7 state for its Scope.
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import { Ids } from "@typed/id/Ids"
|
|
185
|
+
* import { Effect } from "effect"
|
|
186
|
+
* const deterministic = Ids.uuid7.pipe(Effect.provide(Ids.Test({ currentTime: 0 })))
|
|
187
|
+
* ```
|
|
188
|
+
* @category Testing
|
|
189
|
+
* @since 1.0.0
|
|
190
|
+
*/
|
|
191
|
+
static readonly Test: (options?: TestOptions) => Layer.Layer<Ids | DateTimes | RandomValues | TestClock.TestClock, Cause.IllegalArgumentError>;
|
|
66
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Configuration for the deterministic Ids test Layer.
|
|
195
|
+
* @remarks
|
|
196
|
+
* ## Why
|
|
197
|
+
* Explicit initial time and CUID environment data let tests reproduce generator sequences without ambient process state.
|
|
198
|
+
* ## Ownership and lifetime
|
|
199
|
+
* This plain configuration acquires no resources and is read only by Layer acquisition; TypeScript `readonly` does not freeze it at runtime.
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* import type { TestOptions } from "@typed/id/Ids"
|
|
203
|
+
* const options: TestOptions = { currentTime: "2026-01-01T00:00:00Z", envData: "test-worker" }
|
|
204
|
+
* ```
|
|
205
|
+
* @category Testing
|
|
206
|
+
* @since 1.0.0
|
|
207
|
+
*/
|
|
67
208
|
export type TestOptions = {
|
|
209
|
+
/** Base time passed to `DateTimes.Fixed`; invalid dates fail Layer acquisition. @since 1.0.0 */
|
|
68
210
|
readonly currentTime?: number | string | Date;
|
|
211
|
+
/** CUID caller discriminator used when the test CuidState is created. @since 1.0.0 */
|
|
69
212
|
readonly envData?: string;
|
|
70
213
|
};
|
|
71
214
|
export {};
|
package/dist/Ids.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Ids.d.ts","sourceRoot":"","sources":["../src/Ids.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Ids.d.ts","sourceRoot":"","sources":["../src/Ids.ts"],"names":[],"mappings":"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"}
|