@typed/id 1.0.0-beta.3 → 1.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +171 -65
  2. package/dist/Cuid.d.ts +128 -13
  3. package/dist/Cuid.d.ts.map +1 -1
  4. package/dist/Cuid.js +135 -41
  5. package/dist/DateTimes.d.ts +66 -3
  6. package/dist/DateTimes.d.ts.map +1 -1
  7. package/dist/DateTimes.js +72 -5
  8. package/dist/Ids.d.ts +173 -30
  9. package/dist/Ids.d.ts.map +1 -1
  10. package/dist/Ids.js +162 -19
  11. package/dist/Ksuid.d.ts +51 -1
  12. package/dist/Ksuid.d.ts.map +1 -1
  13. package/dist/Ksuid.js +59 -7
  14. package/dist/NanoId.d.ts +47 -0
  15. package/dist/NanoId.d.ts.map +1 -1
  16. package/dist/NanoId.js +48 -1
  17. package/dist/RandomValues.d.ts +63 -4
  18. package/dist/RandomValues.d.ts.map +1 -1
  19. package/dist/RandomValues.js +74 -10
  20. package/dist/Ulid.d.ts +49 -1
  21. package/dist/Ulid.d.ts.map +1 -1
  22. package/dist/Ulid.js +54 -4
  23. package/dist/Uuid4.d.ts +47 -0
  24. package/dist/Uuid4.d.ts.map +1 -1
  25. package/dist/Uuid4.js +48 -1
  26. package/dist/Uuid5.d.ts +178 -6
  27. package/dist/Uuid5.d.ts.map +1 -1
  28. package/dist/Uuid5.js +152 -15
  29. package/dist/Uuid7.d.ts +121 -15
  30. package/dist/Uuid7.d.ts.map +1 -1
  31. package/dist/Uuid7.js +124 -16
  32. package/dist/__tests__/helpers.d.ts +7 -0
  33. package/dist/__tests__/helpers.d.ts.map +1 -0
  34. package/dist/__tests__/helpers.js +19 -0
  35. package/dist/__tests__/public-contract.type-test.d.ts +2 -0
  36. package/dist/__tests__/public-contract.type-test.d.ts.map +1 -0
  37. package/dist/__tests__/public-contract.type-test.js +3 -0
  38. package/dist/_sha.d.ts +32 -0
  39. package/dist/_sha.d.ts.map +1 -1
  40. package/dist/_sha.js +32 -0
  41. package/dist/_uuid-stringify.d.ts +15 -0
  42. package/dist/_uuid-stringify.d.ts.map +1 -1
  43. package/dist/_uuid-stringify.js +15 -0
  44. package/package.json +65 -11
  45. package/src/Cuid.ts +0 -124
  46. package/src/DateTimes.ts +0 -36
  47. package/src/Id.test.ts +0 -230
  48. package/src/Ids.ts +0 -128
  49. package/src/Ksuid.ts +0 -74
  50. package/src/NanoId.ts +0 -33
  51. package/src/RandomValues.ts +0 -33
  52. package/src/Ulid.ts +0 -51
  53. package/src/Uuid4.ts +0 -24
  54. package/src/Uuid5.ts +0 -71
  55. package/src/Uuid7.ts +0 -104
  56. package/src/_sha.ts +0 -11
  57. package/src/_uuid-stringify.ts +0 -30
  58. package/src/index.ts +0 -10
package/README.md CHANGED
@@ -8,6 +8,27 @@
8
8
 
9
9
  - `effect`
10
10
 
11
+ Install both packages in an ESM project:
12
+
13
+ ```sh
14
+ pnpm add @typed/id effect
15
+ ```
16
+
17
+ `@typed/id` publishes ES modules; use `import` rather than CommonJS `require`.
18
+
19
+ ## Runtime requirements
20
+
21
+ The default layers target runtimes with the standard Web Crypto and encoding globals:
22
+
23
+ - `crypto.getRandomValues` supplies entropy for `RandomValues.Default`.
24
+ - `crypto.subtle.digest` is used by CUID and UUID v5 generation.
25
+ - `TextEncoder` and `BigInt` are used by the string and time encoders.
26
+
27
+ These globals are available in modern browsers and current Node.js releases. Runtimes without the
28
+ encoding or digest globals must install equivalents. Custom `RandomValues` and `DateTimes` services
29
+ can replace the default entropy and clock sources, but they do not replace `crypto.subtle.digest`
30
+ for CUID or UUID v5 generation.
31
+
11
32
  ## API overview
12
33
 
13
34
  - **Cuid** — Schema + type; `CuidState` service; Effect to generate Cuid.
@@ -23,39 +44,117 @@
23
44
 
24
45
  ```ts
25
46
  import { Ids, Uuid5Namespace } from "@typed/id";
47
+ import * as Effect from "effect/Effect";
48
+
49
+ const program = Effect.gen(function* () {
50
+ const cuid = yield* Ids.cuid;
51
+ const ksuid = yield* Ids.ksuid;
52
+ const nanoId = yield* Ids.nanoId;
53
+ const ulid = yield* Ids.ulid;
54
+ const uuid4 = yield* Ids.uuid4;
55
+ const uuid5 = yield* Ids.uuid5("https://effect.website", Uuid5Namespace.URL);
56
+ const uuid7 = yield* Ids.uuid7;
57
+
58
+ return { cuid, ksuid, nanoId, ulid, uuid4, uuid5, uuid7 };
59
+ });
60
+
61
+ const ids = await Effect.runPromise(Effect.provide(program, Ids.Default));
62
+ console.log(ids);
63
+ ```
64
+
65
+ Use `Ids.Test()` instead of `Ids.Default` when the same program needs deterministic test data.
66
+
67
+ ## Values and serialization
68
+
69
+ Generated IDs are branded strings: the brand exists only in TypeScript, while runtime equality,
70
+ `Map`/`Set` keys, JSON, and structured clone use ordinary string semantics. Store and transmit the
71
+ string directly. Deserialization or structured clone does not restore the TypeScript brand;
72
+ validate untrusted or persisted strings with the matching exported Schema or `is*` predicate
73
+ before treating them as branded values.
74
+
75
+ | Generator | Serialized output from this package |
76
+ | --------- | ---------------------------------------------------------------- |
77
+ | CUID | 24 lowercase base36 characters; the first character is a letter. |
78
+ | KSUID | 27 base62 characters. |
79
+ | Nano ID | 21 characters from `0-9a-zA-Z_-`. |
80
+ | ULID | 26 uppercase Crockford base32 characters. |
81
+ | UUID | Canonical lowercase hyphenated UUID text. |
26
82
 
27
- const id = yield * Ids.cuid;
28
- const id = yield * Ids.ksuid;
29
- const id = yield * Ids.nanoId;
30
- const id = yield * Ids.ulid;
31
- const id = yield * Ids.uuid4;
32
- const id = yield * Ids.uuid5("https://effect.website", Uuid5Namespace.URL);
33
- const id = yield * Ids.uuid7;
34
-
35
- // Provide Ids services
36
- Effect.provide(Ids.Default);
37
- Effect.provide(Ids.Test());
83
+ UUID v5 is deterministic for the same UTF-8 name and namespace bytes. The other default
84
+ generators incorporate time, entropy, or state and should not be treated as reproducible values.
85
+
86
+ ## Service and seed lifecycle
87
+
88
+ `Ids.Default` is the usual production layer. It wires the clock, secure randomness, and the
89
+ stateful CUID and UUID v7 generators into the `Ids` facade. Build and share that layer at the
90
+ application scope where IDs must belong to one sequence; rebuilding a state layer resets its
91
+ in-memory counter.
92
+
93
+ The standalone generators have narrower requirements:
94
+
95
+ | Generator | Required services |
96
+ | ----------------- | ------------------------------ |
97
+ | `cuid` | `CuidState` |
98
+ | `uuid7` | `Uuid7State` |
99
+ | `ksuid`, `ulid` | `DateTimes` and `RandomValues` |
100
+ | `nanoId`, `uuid4` | `RandomValues` |
101
+ | `uuid5` | None |
102
+
103
+ `RandomValues.Default` uses Web Crypto and is the production entropy source. `RandomValues.Random`
104
+ derives bytes from Effect's current `Random` service and is intended for controlled tests or
105
+ simulations, not as a cryptographic entropy source. `Ids.Test()` supplies fixed internal entropy
106
+ and a controllable clock; its output is for repeatable tests, not production IDs. Service state is
107
+ process-local and is not a serialization format or a persistence mechanism.
108
+
109
+ `CuidSeed` and `Uuid7Seed` describe one generation step; they are not serialized IDs or snapshots
110
+ of the state service. `CuidState` and `Uuid7State` are themselves Effect-valued services that yield
111
+ the next seed. When assembling one manually, construct the service with `Layer.effect` and provide
112
+ its clock and entropy dependencies to that layer:
113
+
114
+ ```ts
115
+ import { CuidState, DateTimes, RandomValues, cuid } from "@typed/id";
116
+ import * as Effect from "effect/Effect";
117
+ import * as Layer from "effect/Layer";
118
+ import * as Random from "effect/Random";
119
+
120
+ const deterministicRandomValues = Layer.effect(
121
+ RandomValues,
122
+ RandomValues.pipe(Effect.provide(RandomValues.Random), Random.withSeed("documentation-example")),
123
+ );
124
+
125
+ const deterministicCuidState = Layer.effect(
126
+ CuidState,
127
+ CuidState.make("documentation-example"),
128
+ ).pipe(Layer.provide([DateTimes.Fixed(1_700_000_000_000), deterministicRandomValues]));
129
+
130
+ const id = await Effect.runPromise(Effect.provide(cuid, deterministicCuidState));
38
131
  ```
39
132
 
133
+ This provider is deterministic and is therefore test-only. Application code normally uses
134
+ `Ids.Default` or `CuidState.Default`.
135
+
40
136
  ## API reference
41
137
 
42
138
  ### Ids
43
139
 
44
140
  Unified service for generating all ID types. Requires `DateTimes`, `RandomValues`, `CuidState`, and `Uuid7State` (use `Ids.Default` or `Ids.Test()` to provide them).
45
141
 
46
- | Member | Type | Description |
47
- | -------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
48
- | `Ids.cuid` | `Effect<Cuid, never, Ids>` | Generate a Cuid. |
49
- | `Ids.ksuid` | `Effect<Ksuid, never, Ids>` | Generate a Ksuid. |
50
- | `Ids.nanoId` | `Effect<NanoId, never, Ids>` | Generate a NanoId. |
51
- | `Ids.ulid` | `Effect<Ulid, never, Ids>` | Generate a ULID. |
52
- | `Ids.uuid4` | `Effect<Uuid4, never, Ids>` | Generate a UUID v4. |
53
- | `Ids.uuid5` | `(name, namespace) => Effect<Uuid5, never, Ids>` | Generate a UUID v5 from a name and namespace. Also has `Ids.uuid5.dns`, `.url`, `.oid`, `.x500` taking a single `name`. |
54
- | `Ids.uuid7` | `Effect<Uuid7, never, Ids>` | Generate a UUID v7. |
55
- | `Ids.Default` | `Layer<Ids \| DateTimes \| RandomValues>` | Layer that provides `Ids` with default Cuid/Uuid7/DateTimes/RandomValues. |
56
- | `Ids.Test(options?)` | `Layer<Ids \| DateTimes \| RandomValues>` | Layer for tests; optional `currentTime` and `envData`. |
142
+ | Member | Type | Description |
143
+ | -------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
144
+ | `Ids.cuid` | `Effect<Cuid, never, Ids>` | Generate a Cuid. |
145
+ | `Ids.ksuid` | `Effect<Ksuid, IllegalArgumentError, Ids>` | Generate a Ksuid; invalid service timestamps fail. |
146
+ | `Ids.nanoId` | `Effect<NanoId, never, Ids>` | Generate a NanoId. |
147
+ | `Ids.ulid` | `Effect<Ulid, IllegalArgumentError, Ids>` | Generate a ULID; invalid service timestamps fail. |
148
+ | `Ids.uuid4` | `Effect<Uuid4, never, Ids>` | Generate a UUID v4. |
149
+ | `Ids.uuid5` | `(name, namespace) => Effect<Uuid5, IllegalArgumentError, Ids>` | Generate a UUID v5; namespaces not exactly 16 bytes fail. Also has `.dns`, `.url`, `.oid`, and `.x500`. |
150
+ | `Ids.uuid7` | `Effect<Uuid7, IllegalArgumentError, Ids>` | Generate a UUID v7; timestamps outside its 48-bit field fail before state mutation. |
151
+ | `Ids.Default` | `Layer<Ids \| DateTimes \| RandomValues>` | Layer that provides `Ids` with default Cuid/Uuid7/DateTimes/RandomValues. |
152
+ | `Ids.Test(options?)` | `Layer<Ids \| DateTimes \| RandomValues, IllegalArgumentError>` | Reproducible test layer; invalid `currentTime` values fail. |
57
153
 
58
- **TestOptions:** `{ currentTime?: number | string | Date; envData?: string }`
154
+ **TestOptions:**
155
+ `{ currentTime?: number | string | Date; envData?: string }`
156
+
157
+ `Ids.Test()` defaults to time `1_400_000_000_000` and uses fixed internal test entropy.
59
158
 
60
159
  ---
61
160
 
@@ -63,23 +162,30 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
63
162
 
64
163
  | Export | Type | Description |
65
164
  | ------------------- | ---------------------------------- | -------------------------------------------------- |
66
- | `Cuid` | `Schema<string, Cuid>` | Branded schema for Cuid strings. |
165
+ | `Cuid` | `Schema<string, Cuid>` | Branded schema for 24-character Cuid strings. |
67
166
  | `Cuid` (type) | `string` | Branded Cuid type. |
68
167
  | `isCuid` | `(value: string) => value is Cuid` | Type guard. |
69
168
  | `CuidState` | Service | Provides `next: Effect<CuidSeed>`. Used by `cuid`. |
70
169
  | `CuidState.Default` | `Layer<CuidState>` | Default CuidState (uses `"node"` envData). |
71
170
  | `cuid` | `Effect<Cuid, never, CuidState>` | Generate a Cuid. |
72
171
 
172
+ `envData` is a caller-provided discriminator incorporated into CUID generation. It is not a
173
+ detected machine fingerprint and does not provide a uniqueness guarantee by itself.
174
+
175
+ > **Beta migration:** CUID generation now consumes the complete seed with domain-separated,
176
+ > unbiased sampling. The 24-character serialized shape is unchanged, but fixed fixtures,
177
+ > persisted expected values, and cross-version deterministic snapshots must be updated.
178
+
73
179
  ---
74
180
 
75
181
  ### Ksuid
76
182
 
77
- | Export | Type | Description |
78
- | -------------- | ------------------------------------------------- | ----------------------------------------- |
79
- | `Ksuid` | `Schema<string, Ksuid>` | Branded schema for 27-char base62 Ksuids. |
80
- | `Ksuid` (type) | `string` | Branded Ksuid type. |
81
- | `isKsuid` | `(value: string) => value is Ksuid` | Type guard. |
82
- | `ksuid` | `Effect<Ksuid, never, DateTimes \| RandomValues>` | Generate a Ksuid. |
183
+ | Export | Type | Description |
184
+ | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------ |
185
+ | `Ksuid` | `Schema<string, Ksuid>` | Branded schema for 27-char base62 Ksuids. |
186
+ | `Ksuid` (type) | `string` | Branded Ksuid type. |
187
+ | `isKsuid` | `(value: string) => value is Ksuid` | Type guard. |
188
+ | `ksuid` | `Effect<Ksuid, IllegalArgumentError, DateTimes \| RandomValues>` | Generate a Ksuid; timestamps must fit its unsigned 32-bit seconds field. |
83
189
 
84
190
  ---
85
191
 
@@ -96,12 +202,12 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
96
202
 
97
203
  ### Ulid
98
204
 
99
- | Export | Type | Description |
100
- | ------------- | ------------------------------------------------ | -------------------------------- |
101
- | `Ulid` | `Schema<string, Ulid>` | Branded schema for ULID strings. |
102
- | `Ulid` (type) | `string` | Branded Ulid type. |
103
- | `isUlid` | `(value: string) => value is Ulid` | Type guard. |
104
- | `ulid` | `Effect<Ulid, never, DateTimes \| RandomValues>` | Generate a ULID. |
205
+ | Export | Type | Description |
206
+ | ------------- | --------------------------------------------------------------- | ------------------------------------------------------------------ |
207
+ | `Ulid` | `Schema<string, Ulid>` | Branded schema for ULID strings. |
208
+ | `Ulid` (type) | `string` | Branded Ulid type. |
209
+ | `isUlid` | `(value: string) => value is Ulid` | Type guard. |
210
+ | `ulid` | `Effect<Ulid, IllegalArgumentError, DateTimes \| RandomValues>` | Generate a ULID; timestamps must fit its 48-bit millisecond field. |
105
211
 
106
212
  ---
107
213
 
@@ -118,47 +224,47 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
118
224
 
119
225
  ### Uuid5
120
226
 
121
- | Export | Type | Description |
122
- | ----------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------ |
123
- | `Uuid5` | `Schema<string, Uuid5>` | Branded schema for UUID v5. |
124
- | `Uuid5` (type) | `string` | Branded Uuid5 type. |
125
- | `Uuid5Namespace` | `Uint8Array` (type) + const object | Namespace type; const has `DNS`, `URL`, `OID`, `X500`. |
126
- | `isUuid5` | `(value: string) => value is Uuid5` | Type guard. |
127
- | `uuid5` | `(name, namespace) => Effect<Uuid5>` or `(namespace) => (name) => Effect<Uuid5>` | Generate UUID v5 from name + namespace. |
128
- | `dnsUuid5`, `urlUuid5`, `oidUuid5`, `x500Uuid5` | `(name: string) => Effect<Uuid5>` | Pre-bound effects for standard namespaces. |
227
+ | Export | Type | Description |
228
+ | ----------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
229
+ | `Uuid5` | `Schema<string, Uuid5>` | Branded schema for UUID v5. |
230
+ | `Uuid5` (type) | `string` | Branded Uuid5 type. |
231
+ | `Uuid5Namespace` | `Uint8Array` (type) + const object | Namespace type; `DNS`, `URL`, `OID`, and `X500` each return a fresh canonical copy. |
232
+ | `isUuid5` | `(value: string) => value is Uuid5` | Type guard. |
233
+ | `uuid5` | `(name, namespace) => Effect<Uuid5, IllegalArgumentError>` or curried | Generate UUID v5; the namespace must contain exactly 16 bytes. |
234
+ | `dnsUuid5`, `urlUuid5`, `oidUuid5`, `x500Uuid5` | `(name: string) => Effect<Uuid5, IllegalArgumentError>` | Pre-bound effects for standard namespaces. |
129
235
 
130
236
  ---
131
237
 
132
238
  ### Uuid7
133
239
 
134
- | Export | Type | Description |
135
- | -------------------- | ----------------------------------- | ---------------------------------------------------- |
136
- | `Uuid7` | `Schema<string, Uuid7>` | Branded schema for UUID v7. |
137
- | `Uuid7` (type) | `string` | Branded Uuid7 type. |
138
- | `isUuid7` | `(value: string) => value is Uuid7` | Type guard. |
139
- | `Uuid7State` | Service | Provides `next: Effect<Uuid7Seed>`. Used by `uuid7`. |
140
- | `Uuid7State.Default` | `Layer<Uuid7State>` | Default Uuid7State. |
141
- | `uuid7` | `Effect<Uuid7, never, Uuid7State>` | Generate a UUID v7. |
240
+ | Export | Type | Description |
241
+ | -------------------- | ------------------------------------------------- | -------------------------------------------------------------------------- |
242
+ | `Uuid7` | `Schema<string, Uuid7>` | Branded schema for UUID v7. |
243
+ | `Uuid7` (type) | `string` | Branded Uuid7 type. |
244
+ | `isUuid7` | `(value: string) => value is Uuid7` | Type guard. |
245
+ | `Uuid7State` | Service | Provides `next: Effect<Uuid7Seed, IllegalArgumentError>`. Used by `uuid7`. |
246
+ | `Uuid7State.Default` | `Layer<Uuid7State>` | Default Uuid7State. |
247
+ | `uuid7` | `Effect<Uuid7, IllegalArgumentError, Uuid7State>` | Generate a UUID v7; invalid or exhausted timestamps fail. |
142
248
 
143
249
  ---
144
250
 
145
251
  ### DateTimes
146
252
 
147
- | Export | Type | Description |
148
- | --------------------------- | ---------------------------------- | --------------------------------------------------------------- |
149
- | `DateTimes` | Service | Provides `now: Effect<number>`, `date: Effect<Date>`. |
150
- | `DateTimes.now` | `Effect<number, never, DateTimes>` | Current time in ms. |
151
- | `DateTimes.date` | `Effect<Date, never, DateTimes>` | Current date. |
152
- | `DateTimes.Default` | `Layer<DateTimes>` | Real clock. |
153
- | `DateTimes.Fixed(baseDate)` | `Layer<DateTimes>` | Fixed time for tests; `baseDate` is `number \| string \| Date`. |
253
+ | Export | Type | Description |
254
+ | --------------------------- | ---------------------------------------- | --------------------------------------------------------------------- |
255
+ | `DateTimes` | Service | Provides `now: Effect<number>`, `date: Effect<Date>`. |
256
+ | `DateTimes.now` | `Effect<number, never, DateTimes>` | Current time in ms. |
257
+ | `DateTimes.date` | `Effect<Date, never, DateTimes>` | Current date. |
258
+ | `DateTimes.Default` | `Layer<DateTimes>` | Real clock. |
259
+ | `DateTimes.Fixed(baseDate)` | `Layer<DateTimes, IllegalArgumentError>` | Fixed time for tests; invalid `number \| string \| Date` inputs fail. |
154
260
 
155
261
  ---
156
262
 
157
263
  ### RandomValues
158
264
 
159
- | Export | Type | Description |
160
- | --------------------------- | ----------------------------------------- | ----------------------------------------------------- |
161
- | `RandomValues` | Service | Provides a function `(length) => Effect<Uint8Array>`. |
162
- | `RandomValues.call(length)` | `Effect<Uint8Array, never, RandomValues>` | Request `length` cryptographically random bytes. |
163
- | `RandomValues.Default` | `Layer<RandomValues>` | Uses `crypto.getRandomValues`. |
164
- | `RandomValues.Random` | `Layer<RandomValues>` | Uses Effect `Random` (e.g. for tests). |
265
+ | Export | Type | Description |
266
+ | --------------------------- | ------------------------------------------------------------------ | ----------------------------------------- |
267
+ | `RandomValues` | Service | Provides exact-length random bytes. |
268
+ | `RandomValues.call(length)` | `Effect<Uint8Array & { readonly length: N }, never, RandomValues>` | Request exactly `N` random bytes. |
269
+ | `RandomValues.Default` | `Layer<RandomValues>` | Uses `crypto.getRandomValues`. |
270
+ | `RandomValues.Random` | `Layer<RandomValues>` | Uses the current Effect `Random` service. |
package/dist/Cuid.d.ts CHANGED
@@ -1,40 +1,155 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import * as Layer from "effect/Layer";
3
3
  import * as Schema from "effect/Schema";
4
- import * as ServiceMap from "effect/ServiceMap";
4
+ import * as Context from "effect/Context";
5
5
  import { DateTimes } from "./DateTimes.js";
6
6
  import { RandomValues } from "./RandomValues.js";
7
+ /**
8
+ * Effect Schema and branded string type for 24-character CUID values.
9
+ * @remarks
10
+ * ## Why
11
+ * The schema validates transport or persisted strings before restoring the compile-time brand; generating a new client ID is not hydration identity.
12
+ * ## Ownership and lifetime
13
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
14
+ * @example
15
+ * ```ts
16
+ * import { Cuid } from "@typed/id/Cuid"
17
+ * const id = Cuid.make("a00000000000000000000000")
18
+ * ```
19
+ * See [Effect Schema](https://effect.website/docs/schema/introduction/).
20
+ * @category Schemas
21
+ * @since 1.0.0
22
+ */
7
23
  export declare const Cuid: Schema.brand<Schema.String, "@typed/id/CUID">;
8
24
  export type Cuid = Schema.Schema.Type<typeof Cuid>;
25
+ /**
26
+ * Tests whether a string is a valid branded CUID.
27
+ * @remarks
28
+ * ## Why
29
+ * Runtime refinement restores trust after JSON, structured clone, or other transport has erased the TypeScript brand.
30
+ * ## Ownership and lifetime
31
+ * This pure predicate acquires no resources and retains no input.
32
+ * @example
33
+ * ```ts
34
+ * import { isCuid } from "@typed/id/Cuid"
35
+ * isCuid("a00000000000000000000000")
36
+ * ```
37
+ * @category Refinements
38
+ * @since 1.0.0
39
+ */
9
40
  export declare const isCuid: (value: string) => value is Cuid;
41
+ /**
42
+ * The complete deterministic input used to derive one CUID.
43
+ * @remarks
44
+ * ## Why
45
+ * Keeping time, sequence, entropy, and caller fingerprint explicit makes generator identity rules testable and reviewable.
46
+ * ## Ownership and lifetime
47
+ * This data acquires no resources; callers own the random byte array and state services produce fresh seeds.
48
+ * @example
49
+ * ```ts
50
+ * import type { CuidSeed } from "@typed/id/Cuid"
51
+ * const seed: CuidSeed = { timestamp: 0, counter: 0, random: new Uint8Array(32) as CuidSeed["random"], fingerprint: "test" }
52
+ * ```
53
+ * @category Models
54
+ * @since 1.0.0
55
+ */
10
56
  export type CuidSeed = {
57
+ /** Millisecond timestamp sampled for this seed. Inherits the seed's resource-free lifetime. @since 1.0.0 */
11
58
  readonly timestamp: number;
59
+ /** Process-local sequence value for this seed. Inherits the seed's resource-free lifetime. @since 1.0.0 */
12
60
  readonly counter: number;
13
- readonly random: Uint8Array;
61
+ /** Fresh 32-byte entropy buffer owned by this seed's consumer. @since 1.0.0 */
62
+ readonly random: Uint8Array & {
63
+ readonly length: 32;
64
+ };
65
+ /** Caller-derived discriminator captured by the CuidState instance. @since 1.0.0 */
14
66
  readonly fingerprint: string;
15
67
  };
16
- declare const CuidState_base: ServiceMap.ServiceClass<CuidState, "@typed/id/CuidState", Effect.Effect<{
17
- timestamp: number;
18
- counter: number;
19
- random: Uint8Array<ArrayBufferLike>;
20
- fingerprint: string;
21
- }, never, never>> & {
22
- readonly make: (envData: string) => Effect.Effect<Effect.Effect<{
68
+ declare const CuidState_base: Context.ServiceClass<CuidState, "@typed/id/CuidState", {
69
+ next: Effect.Effect<{
23
70
  timestamp: number;
24
71
  counter: number;
25
- random: Uint8Array<ArrayBufferLike>;
72
+ random: Uint8Array<ArrayBufferLike> & {
73
+ readonly length: 32;
74
+ };
26
75
  fingerprint: string;
27
- }, never, never>, never, DateTimes | RandomValues>;
76
+ }, never, never>;
77
+ }> & {
78
+ readonly make: (envData: string) => Effect.Effect<{
79
+ next: Effect.Effect<{
80
+ timestamp: number;
81
+ counter: number;
82
+ random: Uint8Array<ArrayBufferLike> & {
83
+ readonly length: 32;
84
+ };
85
+ fingerprint: string;
86
+ }, never, never>;
87
+ }, never, DateTimes | RandomValues>;
28
88
  };
89
+ /**
90
+ * Process-local Effect service that supplies sequential CUID seeds.
91
+ * @remarks
92
+ * ## Why
93
+ * 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.
94
+ * ## Ownership and lifetime
95
+ * 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.
96
+ * @example
97
+ * ```ts
98
+ * import { cuid, CuidState } from "@typed/id/Cuid"
99
+ * import { Effect } from "effect"
100
+ * const program = Effect.provide(cuid, CuidState.Default)
101
+ * ```
102
+ * See [Effect services](https://effect.website/docs/requirements-management/services/) and [Layers](https://effect.website/docs/requirements-management/layers/).
103
+ * @category Services
104
+ * @since 1.0.0
105
+ */
29
106
  export declare class CuidState extends CuidState_base {
107
+ /**
108
+ * Reads one seed from the current CuidState service.
109
+ * @remarks
110
+ * ## Why
111
+ * The accessor exposes stateful sequencing through Effect's service channel rather than a module-global counter.
112
+ * ## Ownership and lifetime
113
+ * The Effect requires `CuidState`; its Layer owns the counter for the Layer lifetime.
114
+ * @category Services
115
+ * @since 1.0.0
116
+ */
30
117
  static readonly next: Effect.Effect<{
31
118
  timestamp: number;
32
119
  counter: number;
33
- random: Uint8Array<ArrayBufferLike>;
120
+ random: Uint8Array<ArrayBufferLike> & {
121
+ readonly length: 32;
122
+ };
34
123
  fingerprint: string;
35
124
  }, never, CuidState>;
36
- static readonly Default: Layer.Layer<CuidState | DateTimes | RandomValues, never, never>;
125
+ /**
126
+ * Provides a default CuidState backed by system time and Web Crypto entropy.
127
+ * @remarks
128
+ * ## Why
129
+ * The explicit Layer gives production code a standard service while keeping test and environment-specific alternatives replaceable.
130
+ * ## Ownership and lifetime
131
+ * Layer acquisition creates one counter state; the surrounding Layer Scope owns it. Web Crypto must be available in the runtime.
132
+ * @category Layers
133
+ * @since 1.0.0
134
+ */
135
+ static readonly Default: Layer.Layer<CuidState, never, never>;
37
136
  }
137
+ /**
138
+ * Generates one CUID from the current CuidState service.
139
+ * @remarks
140
+ * ## Why
141
+ * 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`.
142
+ * ## Ownership and lifetime
143
+ * The Effect acquires no resources itself and uses the CuidState owned by its provided Layer.
144
+ * @example
145
+ * ```ts
146
+ * import { cuid, CuidState } from "@typed/id/Cuid"
147
+ * import { Effect } from "effect"
148
+ * const id = Effect.provide(cuid, CuidState.Default)
149
+ * ```
150
+ * @category Generators
151
+ * @since 1.0.0
152
+ */
38
153
  export declare const cuid: Effect.Effect<Cuid, never, CuidState>;
39
154
  export {};
40
155
  //# sourceMappingURL=Cuid.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Cuid.d.ts","sourceRoot":"","sources":["../src/Cuid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQjD,eAAO,MAAM,IAAI,+CAGhB,CAAC;AACF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnD,eAAO,MAAM,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,IAAsB,CAAC;AAGxE,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;;;;;;;6BAGgB,MAAM;;;;;;;AADxB,qBAAa,SAAU,SAAQ,cA8B7B;IACA,MAAM,CAAC,QAAQ,CAAC,IAAI;;;;;yBAAwC;IAE5D,MAAM,CAAC,QAAQ,CAAC,OAAO,kEAErB;CACH;AAED,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAGtD,CAAC"}
1
+ {"version":3,"file":"Cuid.d.ts","sourceRoot":"","sources":["../src/Cuid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,+CAGhB,CAAC;AACF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,IAAsB,CAAC;AAGxE;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,4GAA4G;IAC5G,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2GAA2G;IAC3G,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG;QAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAA;KAAE,CAAC;IACtD,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;;;;;;;;;;;6BAoBgB,MAAM;;;;;;;;;;;AAlBxB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAU,SAAQ,cAgC7B;IACA;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI;;;;;;;yBAGjB;IAEH;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,uCAErB;CACH;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAGtD,CAAC"}