@typed/id 1.0.0-beta.1 → 1.0.0-beta.11

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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +175 -67
  3. package/dist/Cuid.d.ts +128 -13
  4. package/dist/Cuid.d.ts.map +1 -1
  5. package/dist/Cuid.js +135 -41
  6. package/dist/DateTimes.d.ts +66 -3
  7. package/dist/DateTimes.d.ts.map +1 -1
  8. package/dist/DateTimes.js +72 -5
  9. package/dist/Ids.d.ts +140 -36
  10. package/dist/Ids.d.ts.map +1 -1
  11. package/dist/Ids.js +121 -22
  12. package/dist/IdsTest.d.ts +34 -0
  13. package/dist/IdsTest.d.ts.map +1 -0
  14. package/dist/IdsTest.js +44 -0
  15. package/dist/Ksuid.d.ts +51 -1
  16. package/dist/Ksuid.d.ts.map +1 -1
  17. package/dist/Ksuid.js +59 -7
  18. package/dist/NanoId.d.ts +47 -0
  19. package/dist/NanoId.d.ts.map +1 -1
  20. package/dist/NanoId.js +48 -1
  21. package/dist/RandomValues.d.ts +63 -4
  22. package/dist/RandomValues.d.ts.map +1 -1
  23. package/dist/RandomValues.js +74 -10
  24. package/dist/Ulid.d.ts +49 -1
  25. package/dist/Ulid.d.ts.map +1 -1
  26. package/dist/Ulid.js +54 -4
  27. package/dist/Uuid4.d.ts +47 -0
  28. package/dist/Uuid4.d.ts.map +1 -1
  29. package/dist/Uuid4.js +48 -1
  30. package/dist/Uuid5.d.ts +178 -6
  31. package/dist/Uuid5.d.ts.map +1 -1
  32. package/dist/Uuid5.js +152 -15
  33. package/dist/Uuid7.d.ts +121 -15
  34. package/dist/Uuid7.d.ts.map +1 -1
  35. package/dist/Uuid7.js +124 -16
  36. package/dist/__tests__/helpers.d.ts +7 -0
  37. package/dist/__tests__/helpers.d.ts.map +1 -0
  38. package/dist/__tests__/helpers.js +19 -0
  39. package/dist/__tests__/public-contract.type-test.d.ts +2 -0
  40. package/dist/__tests__/public-contract.type-test.d.ts.map +1 -0
  41. package/dist/__tests__/public-contract.type-test.js +3 -0
  42. package/dist/_sha.d.ts +32 -0
  43. package/dist/_sha.d.ts.map +1 -1
  44. package/dist/_sha.js +32 -0
  45. package/dist/_uuid-stringify.d.ts +15 -0
  46. package/dist/_uuid-stringify.d.ts.map +1 -1
  47. package/dist/_uuid-stringify.js +15 -0
  48. package/dist/internal/Ids.d.ts +23 -0
  49. package/dist/internal/Ids.d.ts.map +1 -0
  50. package/dist/internal/Ids.js +29 -0
  51. package/package.json +75 -16
  52. package/src/Cuid.ts +0 -124
  53. package/src/DateTimes.ts +0 -36
  54. package/src/Id.test.ts +0 -231
  55. package/src/Ids.ts +0 -128
  56. package/src/Ksuid.ts +0 -74
  57. package/src/NanoId.ts +0 -33
  58. package/src/RandomValues.ts +0 -33
  59. package/src/Ulid.ts +0 -51
  60. package/src/Uuid4.ts +0 -24
  61. package/src/Uuid5.ts +0 -71
  62. package/src/Uuid7.ts +0 -104
  63. package/src/_sha.ts +0 -11
  64. package/src/_uuid-stringify.ts +0 -30
  65. package/src/index.ts +0 -10
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023-present The Contributors
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 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,119 @@
23
44
 
24
45
  ```ts
25
46
  import { Ids, Uuid5Namespace } from "@typed/id";
47
+ import { IdsTest } from "@typed/id/IdsTest";
48
+ import * as Effect from "effect/Effect";
49
+
50
+ const program = Effect.gen(function* () {
51
+ const cuid = yield* Ids.cuid;
52
+ const ksuid = yield* Ids.ksuid;
53
+ const nanoId = yield* Ids.nanoId;
54
+ const ulid = yield* Ids.ulid;
55
+ const uuid4 = yield* Ids.uuid4;
56
+ const uuid5 = yield* Ids.uuid5("https://effect.website", Uuid5Namespace.URL);
57
+ const uuid7 = yield* Ids.uuid7;
58
+
59
+ return { cuid, ksuid, nanoId, ulid, uuid4, uuid5, uuid7 };
60
+ });
61
+
62
+ const ids = await Effect.runPromise(Effect.provide(program, Ids.Default));
63
+ console.log(ids);
64
+ ```
65
+
66
+ Use `IdsTest()` from `@typed/id/IdsTest` instead of `Ids.Default` when the same program needs
67
+ deterministic test data.
68
+
69
+ ## Values and serialization
70
+
71
+ Generated IDs are branded strings: the brand exists only in TypeScript, while runtime equality,
72
+ `Map`/`Set` keys, JSON, and structured clone use ordinary string semantics. Store and transmit the
73
+ string directly. Deserialization or structured clone does not restore the TypeScript brand;
74
+ validate untrusted or persisted strings with the matching exported Schema or `is*` predicate
75
+ before treating them as branded values.
76
+
77
+ | Generator | Serialized output from this package |
78
+ | --------- | ---------------------------------------------------------------- |
79
+ | CUID | 24 lowercase base36 characters; the first character is a letter. |
80
+ | KSUID | 27 base62 characters. |
81
+ | Nano ID | 21 characters from `0-9a-zA-Z_-`. |
82
+ | ULID | 26 uppercase Crockford base32 characters. |
83
+ | UUID | Canonical lowercase hyphenated UUID text. |
26
84
 
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());
85
+ UUID v5 is deterministic for the same UTF-8 name and namespace bytes. The other default
86
+ generators incorporate time, entropy, or state and should not be treated as reproducible values.
87
+
88
+ ## Service and seed lifecycle
89
+
90
+ `Ids.Default` is the usual production layer. It wires the clock, secure randomness, and the
91
+ stateful CUID and UUID v7 generators into the `Ids` facade. Build and share that layer at the
92
+ application scope where IDs must belong to one sequence; rebuilding a state layer resets its
93
+ in-memory counter.
94
+
95
+ The standalone generators have narrower requirements:
96
+
97
+ | Generator | Required services |
98
+ | ----------------- | ------------------------------ |
99
+ | `cuid` | `CuidState` |
100
+ | `uuid7` | `Uuid7State` |
101
+ | `ksuid`, `ulid` | `DateTimes` and `RandomValues` |
102
+ | `nanoId`, `uuid4` | `RandomValues` |
103
+ | `uuid5` | None |
104
+
105
+ `RandomValues.Default` uses Web Crypto and is the production entropy source. `RandomValues.Random`
106
+ derives bytes from Effect's current `Random` service and is intended for controlled tests or
107
+ simulations, not as a cryptographic entropy source. `IdsTest()` supplies fixed internal entropy
108
+ and a controllable clock; its output is for repeatable tests, not production IDs. Service state is
109
+ process-local and is not a serialization format or a persistence mechanism.
110
+
111
+ `CuidSeed` and `Uuid7Seed` describe one generation step; they are not serialized IDs or snapshots
112
+ of the state service. `CuidState` and `Uuid7State` are themselves Effect-valued services that yield
113
+ the next seed. When assembling one manually, construct the service with `Layer.effect` and provide
114
+ its clock and entropy dependencies to that layer:
115
+
116
+ ```ts
117
+ import { CuidState, DateTimes, RandomValues, cuid } from "@typed/id";
118
+ import * as Effect from "effect/Effect";
119
+ import * as Layer from "effect/Layer";
120
+ import * as Random from "effect/Random";
121
+
122
+ const deterministicRandomValues = Layer.effect(
123
+ RandomValues,
124
+ RandomValues.pipe(Effect.provide(RandomValues.Random), Random.withSeed("documentation-example")),
125
+ );
126
+
127
+ const deterministicCuidState = Layer.effect(
128
+ CuidState,
129
+ CuidState.make("documentation-example"),
130
+ ).pipe(Layer.provide([DateTimes.Fixed(1_700_000_000_000), deterministicRandomValues]));
131
+
132
+ const id = await Effect.runPromise(Effect.provide(cuid, deterministicCuidState));
38
133
  ```
39
134
 
135
+ This provider is deterministic and is therefore test-only. Application code normally uses
136
+ `Ids.Default` or `CuidState.Default`.
137
+
40
138
  ## API reference
41
139
 
42
- ### Ids
140
+ ### Ids and IdsTest
43
141
 
44
- Unified service for generating all ID types. Requires `DateTimes`, `RandomValues`, `CuidState`, and `Uuid7State` (use `Ids.Default` or `Ids.Test()` to provide them).
142
+ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues`, `CuidState`, and `Uuid7State` (use `Ids.Default` or `IdsTest()` to provide them).
45
143
 
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`. |
144
+ | Member | Type | Description |
145
+ | -------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
146
+ | `Ids.cuid` | `Effect<Cuid, never, Ids>` | Generate a Cuid. |
147
+ | `Ids.ksuid` | `Effect<Ksuid, IllegalArgumentError, Ids>` | Generate a Ksuid; invalid service timestamps fail. |
148
+ | `Ids.nanoId` | `Effect<NanoId, never, Ids>` | Generate a NanoId. |
149
+ | `Ids.ulid` | `Effect<Ulid, IllegalArgumentError, Ids>` | Generate a ULID; invalid service timestamps fail. |
150
+ | `Ids.uuid4` | `Effect<Uuid4, never, Ids>` | Generate a UUID v4. |
151
+ | `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`. |
152
+ | `Ids.uuid7` | `Effect<Uuid7, IllegalArgumentError, Ids>` | Generate a UUID v7; timestamps outside its 48-bit field fail before state mutation. |
153
+ | `Ids.Default` | `Layer<Ids \| DateTimes \| RandomValues>` | Layer that provides `Ids` with default Cuid/Uuid7/DateTimes/RandomValues. |
154
+ | `IdsTest(options?)` | `Layer<Ids \| DateTimes \| RandomValues, IllegalArgumentError>` | Reproducible test layer; invalid `currentTime` values fail. |
57
155
 
58
- **TestOptions:** `{ currentTime?: number | string | Date; envData?: string }`
156
+ **IdsTestOptions:**
157
+ `{ currentTime?: number | string | Date; envData?: string }`
158
+
159
+ `IdsTest()` defaults to time `1_400_000_000_000` and uses fixed internal test entropy.
59
160
 
60
161
  ---
61
162
 
@@ -63,23 +164,30 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
63
164
 
64
165
  | Export | Type | Description |
65
166
  | ------------------- | ---------------------------------- | -------------------------------------------------- |
66
- | `Cuid` | `Schema<string, Cuid>` | Branded schema for Cuid strings. |
167
+ | `Cuid` | `Schema<string, Cuid>` | Branded schema for 24-character Cuid strings. |
67
168
  | `Cuid` (type) | `string` | Branded Cuid type. |
68
169
  | `isCuid` | `(value: string) => value is Cuid` | Type guard. |
69
170
  | `CuidState` | Service | Provides `next: Effect<CuidSeed>`. Used by `cuid`. |
70
171
  | `CuidState.Default` | `Layer<CuidState>` | Default CuidState (uses `"node"` envData). |
71
172
  | `cuid` | `Effect<Cuid, never, CuidState>` | Generate a Cuid. |
72
173
 
174
+ `envData` is a caller-provided discriminator incorporated into CUID generation. It is not a
175
+ detected machine fingerprint and does not provide a uniqueness guarantee by itself.
176
+
177
+ > **Beta migration:** CUID generation now consumes the complete seed with domain-separated,
178
+ > unbiased sampling. The 24-character serialized shape is unchanged, but fixed fixtures,
179
+ > persisted expected values, and cross-version deterministic snapshots must be updated.
180
+
73
181
  ---
74
182
 
75
183
  ### Ksuid
76
184
 
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. |
185
+ | Export | Type | Description |
186
+ | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------ |
187
+ | `Ksuid` | `Schema<string, Ksuid>` | Branded schema for 27-char base62 Ksuids. |
188
+ | `Ksuid` (type) | `string` | Branded Ksuid type. |
189
+ | `isKsuid` | `(value: string) => value is Ksuid` | Type guard. |
190
+ | `ksuid` | `Effect<Ksuid, IllegalArgumentError, DateTimes \| RandomValues>` | Generate a Ksuid; timestamps must fit its unsigned 32-bit seconds field. |
83
191
 
84
192
  ---
85
193
 
@@ -96,12 +204,12 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
96
204
 
97
205
  ### Ulid
98
206
 
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. |
207
+ | Export | Type | Description |
208
+ | ------------- | --------------------------------------------------------------- | ------------------------------------------------------------------ |
209
+ | `Ulid` | `Schema<string, Ulid>` | Branded schema for ULID strings. |
210
+ | `Ulid` (type) | `string` | Branded Ulid type. |
211
+ | `isUlid` | `(value: string) => value is Ulid` | Type guard. |
212
+ | `ulid` | `Effect<Ulid, IllegalArgumentError, DateTimes \| RandomValues>` | Generate a ULID; timestamps must fit its 48-bit millisecond field. |
105
213
 
106
214
  ---
107
215
 
@@ -118,47 +226,47 @@ Unified service for generating all ID types. Requires `DateTimes`, `RandomValues
118
226
 
119
227
  ### Uuid5
120
228
 
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. |
229
+ | Export | Type | Description |
230
+ | ----------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
231
+ | `Uuid5` | `Schema<string, Uuid5>` | Branded schema for UUID v5. |
232
+ | `Uuid5` (type) | `string` | Branded Uuid5 type. |
233
+ | `Uuid5Namespace` | `Uint8Array` (type) + const object | Namespace type; `DNS`, `URL`, `OID`, and `X500` each return a fresh canonical copy. |
234
+ | `isUuid5` | `(value: string) => value is Uuid5` | Type guard. |
235
+ | `uuid5` | `(name, namespace) => Effect<Uuid5, IllegalArgumentError>` or curried | Generate UUID v5; the namespace must contain exactly 16 bytes. |
236
+ | `dnsUuid5`, `urlUuid5`, `oidUuid5`, `x500Uuid5` | `(name: string) => Effect<Uuid5, IllegalArgumentError>` | Pre-bound effects for standard namespaces. |
129
237
 
130
238
  ---
131
239
 
132
240
  ### Uuid7
133
241
 
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. |
242
+ | Export | Type | Description |
243
+ | -------------------- | ------------------------------------------------- | -------------------------------------------------------------------------- |
244
+ | `Uuid7` | `Schema<string, Uuid7>` | Branded schema for UUID v7. |
245
+ | `Uuid7` (type) | `string` | Branded Uuid7 type. |
246
+ | `isUuid7` | `(value: string) => value is Uuid7` | Type guard. |
247
+ | `Uuid7State` | Service | Provides `next: Effect<Uuid7Seed, IllegalArgumentError>`. Used by `uuid7`. |
248
+ | `Uuid7State.Default` | `Layer<Uuid7State>` | Default Uuid7State. |
249
+ | `uuid7` | `Effect<Uuid7, IllegalArgumentError, Uuid7State>` | Generate a UUID v7; invalid or exhausted timestamps fail. |
142
250
 
143
251
  ---
144
252
 
145
253
  ### DateTimes
146
254
 
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`. |
255
+ | Export | Type | Description |
256
+ | --------------------------- | ---------------------------------------- | --------------------------------------------------------------------- |
257
+ | `DateTimes` | Service | Provides `now: Effect<number>`, `date: Effect<Date>`. |
258
+ | `DateTimes.now` | `Effect<number, never, DateTimes>` | Current time in ms. |
259
+ | `DateTimes.date` | `Effect<Date, never, DateTimes>` | Current date. |
260
+ | `DateTimes.Default` | `Layer<DateTimes>` | Real clock. |
261
+ | `DateTimes.Fixed(baseDate)` | `Layer<DateTimes, IllegalArgumentError>` | Fixed time for tests; invalid `number \| string \| Date` inputs fail. |
154
262
 
155
263
  ---
156
264
 
157
265
  ### RandomValues
158
266
 
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). |
267
+ | Export | Type | Description |
268
+ | --------------------------- | ------------------------------------------------------------------ | ----------------------------------------- |
269
+ | `RandomValues` | Service | Provides exact-length random bytes. |
270
+ | `RandomValues.call(length)` | `Effect<Uint8Array & { readonly length: N }, never, RandomValues>` | Request exactly `N` random bytes. |
271
+ | `RandomValues.Default` | `Layer<RandomValues>` | Uses `crypto.getRandomValues`. |
272
+ | `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 ID 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 ID validation
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 ID types
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 Sequence state
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<DateTimes | RandomValues | CuidState, 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 Production 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 ID generation
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"}