@typed/id 1.0.0-beta.4 → 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 +127 -12
  3. package/dist/Cuid.d.ts.map +1 -1
  4. package/dist/Cuid.js +133 -39
  5. package/dist/DateTimes.d.ts +64 -1
  6. package/dist/DateTimes.d.ts.map +1 -1
  7. package/dist/DateTimes.js +70 -3
  8. package/dist/Ids.d.ts +171 -28
  9. package/dist/Ids.d.ts.map +1 -1
  10. package/dist/Ids.js +159 -16
  11. package/dist/Ksuid.d.ts +51 -1
  12. package/dist/Ksuid.d.ts.map +1 -1
  13. package/dist/Ksuid.js +58 -6
  14. package/dist/NanoId.d.ts +47 -0
  15. package/dist/NanoId.d.ts.map +1 -1
  16. package/dist/NanoId.js +47 -0
  17. package/dist/RandomValues.d.ts +62 -3
  18. package/dist/RandomValues.d.ts.map +1 -1
  19. package/dist/RandomValues.js +72 -8
  20. package/dist/Ulid.d.ts +49 -1
  21. package/dist/Ulid.d.ts.map +1 -1
  22. package/dist/Ulid.js +53 -3
  23. package/dist/Uuid4.d.ts +47 -0
  24. package/dist/Uuid4.d.ts.map +1 -1
  25. package/dist/Uuid4.js +47 -0
  26. package/dist/Uuid5.d.ts +178 -6
  27. package/dist/Uuid5.d.ts.map +1 -1
  28. package/dist/Uuid5.js +151 -14
  29. package/dist/Uuid7.d.ts +120 -14
  30. package/dist/Uuid7.d.ts.map +1 -1
  31. package/dist/Uuid7.js +121 -13
  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 +68 -14
  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/dist/Uuid7.d.ts CHANGED
@@ -1,44 +1,150 @@
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 Schema from "effect/Schema";
4
5
  import * as Context from "effect/Context";
5
6
  import { DateTimes } from "./DateTimes.js";
6
7
  import { RandomValues } from "./RandomValues.js";
8
+ /**
9
+ * Effect Schema and branded string type for RFC UUID version 7 values.
10
+ * @remarks
11
+ * ## Why
12
+ * The schema verifies version and variant at transport boundaries; generated ordering is local to one Uuid7State, not a distributed total order.
13
+ * ## Ownership and lifetime
14
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
15
+ * @example
16
+ * ```ts
17
+ * import { Uuid7 } from "@typed/id/Uuid7"
18
+ * import { Schema } from "effect"
19
+ * const id = Schema.decodeUnknownSync(Uuid7)("01890f2e-7d6c-7cc0-98c4-dc0c0c07398f")
20
+ * ```
21
+ * @category Schemas
22
+ * @since 1.0.0
23
+ */
7
24
  export declare const Uuid7: Schema.brand<Schema.String, "@typed/id/UUID7">;
8
25
  export type Uuid7 = typeof Uuid7.Type;
26
+ /**
27
+ * Tests whether a string is an RFC UUID version 7 value.
28
+ * @remarks
29
+ * ## Why
30
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
31
+ * ## Ownership and lifetime
32
+ * This pure predicate acquires no resources and retains no input.
33
+ * @example
34
+ * ```ts
35
+ * import { isUuid7 } from "@typed/id/Uuid7"
36
+ * const valid = isUuid7("01890f2e-7d6c-7cc0-98c4-dc0c0c07398f")
37
+ * ```
38
+ * @category Refinements
39
+ * @since 1.0.0
40
+ */
9
41
  export declare const isUuid7: (value: string) => value is Uuid7;
42
+ /**
43
+ * The validated time, sequence, and entropy used to format one UUID version 7.
44
+ * @remarks
45
+ * ## Why
46
+ * An explicit seed documents the exact inputs to version and variant bit layout and makes generator state testable.
47
+ * ## Ownership and lifetime
48
+ * This data acquires no resources; the producing service owns sequence state and transfers a fresh random byte array.
49
+ * @example
50
+ * ```ts
51
+ * import type { Uuid7Seed } from "@typed/id/Uuid7"
52
+ * const seed: Uuid7Seed = { timestamp: 0, seq: 0, randomBytes: new Uint8Array(16) as Uuid7Seed["randomBytes"] }
53
+ * ```
54
+ * @category Models
55
+ * @since 1.0.0
56
+ */
10
57
  export type Uuid7Seed = {
58
+ /** Validated millisecond timestamp encoded into the UUID. @since 1.0.0 */
11
59
  readonly timestamp: number;
60
+ /** Unsigned 32-bit sequence integer in the range [0, 0xffffffff]. @since 1.0.0 */
12
61
  readonly seq: number;
62
+ /** Fresh entropy buffer whose final bytes complete the UUID payload. @since 1.0.0 */
13
63
  readonly randomBytes: Uint8Array & {
14
64
  length: 16;
15
65
  };
16
66
  };
17
- declare const Uuid7State_base: Context.ServiceClass<Uuid7State, "@typed/id/Uuid7State", Effect.Effect<{
18
- timestamp: number;
19
- seq: number;
20
- randomBytes: Uint8Array<ArrayBufferLike> & {
21
- length: 16;
22
- };
23
- }, never, never>> & {
24
- readonly make: Effect.Effect<Effect.Effect<{
67
+ declare const Uuid7State_base: Context.ServiceClass<Uuid7State, "@typed/id/Uuid7State", {
68
+ next: Effect.Effect<{
25
69
  timestamp: number;
26
70
  seq: number;
27
71
  randomBytes: Uint8Array<ArrayBufferLike> & {
28
- length: 16;
72
+ readonly length: 16;
29
73
  };
30
- }, never, never>, never, DateTimes | RandomValues>;
74
+ }, Cause.IllegalArgumentError, never>;
75
+ }> & {
76
+ readonly make: Effect.Effect<{
77
+ next: Effect.Effect<{
78
+ timestamp: number;
79
+ seq: number;
80
+ randomBytes: Uint8Array<ArrayBufferLike> & {
81
+ readonly length: 16;
82
+ };
83
+ }, Cause.IllegalArgumentError, never>;
84
+ }, never, DateTimes | RandomValues>;
31
85
  };
86
+ /**
87
+ * Process-local Effect service that produces monotonic UUID version 7 seeds.
88
+ * @remarks
89
+ * ## Why
90
+ * Clock rollback and 32-bit sequence rollover are handled inside an explicit service, guaranteeing monotonicity only for one shared service instance.
91
+ * ## Ownership and lifetime
92
+ * Each Layer instance owns mutable timestamp and sequence state. A new process, worker, deployment, or Layer resets it; exact hydration identity must be serialized.
93
+ * @example
94
+ * ```ts
95
+ * import { uuid7, Uuid7State } from "@typed/id/Uuid7"
96
+ * import { Effect } from "effect"
97
+ * const id = Effect.provide(uuid7, Uuid7State.Default)
98
+ * ```
99
+ * @category Services
100
+ * @since 1.0.0
101
+ */
32
102
  export declare class Uuid7State extends Uuid7State_base {
103
+ /**
104
+ * Reads the next validated seed from the current Uuid7State.
105
+ * @remarks
106
+ * ## Why
107
+ * The accessor exposes ordered state through Effect's service channel and reports timestamp exhaustion as `IllegalArgumentError`.
108
+ * ## Ownership and lifetime
109
+ * The Effect uses the state owned by its provided Layer and acquires no separate persistent resource.
110
+ * @category Services
111
+ * @since 1.0.0
112
+ */
33
113
  static readonly next: Effect.Effect<{
34
114
  timestamp: number;
35
115
  seq: number;
36
116
  randomBytes: Uint8Array<ArrayBufferLike> & {
37
- length: 16;
117
+ readonly length: 16;
38
118
  };
39
- }, never, Uuid7State>;
40
- static readonly Default: Layer.Layer<DateTimes | RandomValues | Uuid7State, never, never>;
119
+ }, Cause.IllegalArgumentError, Uuid7State>;
120
+ /**
121
+ * Provides Uuid7State from system time and Web Crypto entropy.
122
+ * @remarks
123
+ * ## Why
124
+ * The production default is explicit while remaining replaceable by deterministic service layers.
125
+ * ## Ownership and lifetime
126
+ * Layer acquisition creates one mutable sequence state owned by the surrounding Layer Scope.
127
+ * @category Layers
128
+ * @since 1.0.0
129
+ */
130
+ static readonly Default: Layer.Layer<Uuid7State, never, never>;
41
131
  }
42
- export declare const uuid7: Effect.Effect<Uuid7, never, Uuid7State>;
132
+ /**
133
+ * Generates one UUID version 7 from the current Uuid7State.
134
+ * @remarks
135
+ * ## Why
136
+ * Effectful generation makes the state boundary explicit and preserves `IllegalArgumentError` for invalid or exhausted timestamp space.
137
+ * ## Ownership and lifetime
138
+ * The Effect acquires no persistent resource and uses state owned by the provided Uuid7State Layer.
139
+ * @example
140
+ * ```ts
141
+ * import { uuid7, Uuid7State } from "@typed/id/Uuid7"
142
+ * import { Effect } from "effect"
143
+ * const id = Effect.provide(uuid7, Uuid7State.Default)
144
+ * ```
145
+ * @category Generators
146
+ * @since 1.0.0
147
+ */
148
+ export declare const uuid7: Effect.Effect<Uuid7, Cause.IllegalArgumentError, Uuid7State>;
43
149
  export {};
44
150
  //# sourceMappingURL=Uuid7.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid7.d.ts","sourceRoot":"","sources":["../src/Uuid7.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;AAEjD,eAAO,MAAM,KAAK,gDAGjB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC;AAEtC,eAAO,MAAM,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,KAAwB,CAAC;AAE3E,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,UAAU,GAAG;QAAE,MAAM,EAAE,EAAE,CAAA;KAAE,CAAC;CACnD,CAAC;;;;;gBAD6C,EAAE;;;;;;;oBAAF,EAAE;;;;AAGjD,qBAAa,UAAW,SAAQ,eAkC9B;IACA,MAAM,CAAC,QAAQ,CAAC,IAAI;;;;oBAtCyB,EAAE;;0BAsCc;IAE7D,MAAM,CAAC,QAAQ,CAAC,OAAO,mEAErB;CACH;AAED,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAGzD,CAAC"}
1
+ {"version":3,"file":"Uuid7.d.ts","sourceRoot":"","sources":["../src/Uuid7.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,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;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,gDAGjB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,KAAwB,CAAC;AAE3E;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,UAAU,GAAG;QAAE,MAAM,EAAE,EAAE,CAAA;KAAE,CAAC;CACnD,CAAC;;;;;;;;;;;;;;;;;;;;AAIF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAW,SAAQ,eA8D9B;IACA;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI;;;;;;+CAGjB;IAEH;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,wCAErB;CACH;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,EAAE,UAAU,CAG9E,CAAC"}
package/dist/Uuid7.js 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 Schema from "effect/Schema";
@@ -5,8 +6,56 @@ import * as Context from "effect/Context";
5
6
  import { uuidStringify } from "./_uuid-stringify.js";
6
7
  import { DateTimes } from "./DateTimes.js";
7
8
  import { RandomValues } from "./RandomValues.js";
9
+ /**
10
+ * Effect Schema and branded string type for RFC UUID version 7 values.
11
+ * @remarks
12
+ * ## Why
13
+ * The schema verifies version and variant at transport boundaries; generated ordering is local to one Uuid7State, not a distributed total order.
14
+ * ## Ownership and lifetime
15
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
16
+ * @example
17
+ * ```ts
18
+ * import { Uuid7 } from "@typed/id/Uuid7"
19
+ * import { Schema } from "effect"
20
+ * const id = Schema.decodeUnknownSync(Uuid7)("01890f2e-7d6c-7cc0-98c4-dc0c0c07398f")
21
+ * ```
22
+ * @category Schemas
23
+ * @since 1.0.0
24
+ */
8
25
  export const Uuid7 = Schema.String.pipe(Schema.check(Schema.isUUID(7)), Schema.brand("@typed/id/UUID7"));
26
+ /**
27
+ * Tests whether a string is an RFC UUID version 7 value.
28
+ * @remarks
29
+ * ## Why
30
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
31
+ * ## Ownership and lifetime
32
+ * This pure predicate acquires no resources and retains no input.
33
+ * @example
34
+ * ```ts
35
+ * import { isUuid7 } from "@typed/id/Uuid7"
36
+ * const valid = isUuid7("01890f2e-7d6c-7cc0-98c4-dc0c0c07398f")
37
+ * ```
38
+ * @category Refinements
39
+ * @since 1.0.0
40
+ */
9
41
  export const isUuid7 = Schema.is(Uuid7);
42
+ const maximumTimestamp = 2 ** 48 - 1;
43
+ /**
44
+ * Process-local Effect service that produces monotonic UUID version 7 seeds.
45
+ * @remarks
46
+ * ## Why
47
+ * Clock rollback and 32-bit sequence rollover are handled inside an explicit service, guaranteeing monotonicity only for one shared service instance.
48
+ * ## Ownership and lifetime
49
+ * Each Layer instance owns mutable timestamp and sequence state. A new process, worker, deployment, or Layer resets it; exact hydration identity must be serialized.
50
+ * @example
51
+ * ```ts
52
+ * import { uuid7, Uuid7State } from "@typed/id/Uuid7"
53
+ * import { Effect } from "effect"
54
+ * const id = Effect.provide(uuid7, Uuid7State.Default)
55
+ * ```
56
+ * @category Services
57
+ * @since 1.0.0
58
+ */
10
59
  export class Uuid7State extends Context.Service()("@typed/id/Uuid7State", {
11
60
  make: Effect.gen(function* () {
12
61
  const { now } = yield* DateTimes;
@@ -16,33 +65,92 @@ export class Uuid7State extends Context.Service()("@typed/id/Uuid7State", {
16
65
  seq: 0,
17
66
  };
18
67
  function updateV7State(now, randomBytes) {
68
+ let msecs;
69
+ let seq;
19
70
  if (now > state.msecs) {
20
71
  // Time has moved on! Pick a new random sequence number
21
- state.seq =
22
- (randomBytes[6] << 23) | (randomBytes[7] << 16) | (randomBytes[8] << 8) | randomBytes[9];
23
- state.msecs = now;
72
+ seq =
73
+ ((randomBytes[6] << 24) |
74
+ (randomBytes[7] << 16) |
75
+ (randomBytes[8] << 8) |
76
+ randomBytes[9]) >>>
77
+ 0;
78
+ msecs = now;
24
79
  }
25
80
  else {
26
81
  // Bump sequence counter w/ 32-bit rollover
27
- state.seq = (state.seq + 1) | 0;
82
+ seq = (state.seq + 1) >>> 0;
83
+ msecs = state.msecs;
28
84
  // In case of rollover, bump timestamp to preserve monotonicity. This is
29
85
  // allowed by the RFC and should self-correct as the system clock catches
30
86
  // up. See https://www.rfc-editor.org/rfc/rfc9562.html#section-6.2-9.4
31
- if (state.seq === 0) {
32
- state.msecs++;
87
+ if (seq === 0) {
88
+ msecs++;
33
89
  }
34
90
  }
91
+ state.msecs = msecs;
92
+ state.seq = seq;
35
93
  }
36
- return Effect.gen(function* () {
37
- const randomBytes = yield* getRandomValues(16);
38
- updateV7State(yield* now, randomBytes);
39
- return { timestamp: state.msecs, seq: state.seq, randomBytes };
40
- });
94
+ return {
95
+ next: Effect.gen(function* () {
96
+ const timestamp = yield* now;
97
+ if (!Number.isSafeInteger(timestamp) || timestamp < 0 || timestamp > maximumTimestamp) {
98
+ return yield* new Cause.IllegalArgumentError(`UUIDv7 timestamp must be a safe integer between 0 and ${maximumTimestamp}, received ${timestamp}`);
99
+ }
100
+ if (timestamp <= state.msecs &&
101
+ state.msecs === maximumTimestamp &&
102
+ state.seq === 0xffffffff) {
103
+ return yield* new Cause.IllegalArgumentError("UUIDv7 sequence rollover exceeds its 48-bit timestamp field");
104
+ }
105
+ const randomBytes = yield* getRandomValues(16);
106
+ updateV7State(timestamp, randomBytes);
107
+ return { timestamp: state.msecs, seq: state.seq, randomBytes };
108
+ }),
109
+ };
41
110
  }),
42
111
  }) {
43
- static next = Effect.flatten(Uuid7State.asEffect());
44
- static Default = Layer.effect(Uuid7State, Uuid7State.make).pipe(Layer.provideMerge([DateTimes.Default, RandomValues.Default]));
112
+ /**
113
+ * Reads the next validated seed from the current Uuid7State.
114
+ * @remarks
115
+ * ## Why
116
+ * The accessor exposes ordered state through Effect's service channel and reports timestamp exhaustion as `IllegalArgumentError`.
117
+ * ## Ownership and lifetime
118
+ * The Effect uses the state owned by its provided Layer and acquires no separate persistent resource.
119
+ * @category Services
120
+ * @since 1.0.0
121
+ */
122
+ static next = Effect.gen(function* () {
123
+ const { next } = yield* Uuid7State;
124
+ return yield* next;
125
+ });
126
+ /**
127
+ * Provides Uuid7State from system time and Web Crypto entropy.
128
+ * @remarks
129
+ * ## Why
130
+ * The production default is explicit while remaining replaceable by deterministic service layers.
131
+ * ## Ownership and lifetime
132
+ * Layer acquisition creates one mutable sequence state owned by the surrounding Layer Scope.
133
+ * @category Layers
134
+ * @since 1.0.0
135
+ */
136
+ static Default = Layer.effect(Uuid7State, Uuid7State.make).pipe(Layer.provide([DateTimes.Default, RandomValues.Default]));
45
137
  }
138
+ /**
139
+ * Generates one UUID version 7 from the current Uuid7State.
140
+ * @remarks
141
+ * ## Why
142
+ * Effectful generation makes the state boundary explicit and preserves `IllegalArgumentError` for invalid or exhausted timestamp space.
143
+ * ## Ownership and lifetime
144
+ * The Effect acquires no persistent resource and uses state owned by the provided Uuid7State Layer.
145
+ * @example
146
+ * ```ts
147
+ * import { uuid7, Uuid7State } from "@typed/id/Uuid7"
148
+ * import { Effect } from "effect"
149
+ * const id = Effect.provide(uuid7, Uuid7State.Default)
150
+ * ```
151
+ * @category Generators
152
+ * @since 1.0.0
153
+ */
46
154
  export const uuid7 = Effect.map(Uuid7State.next, uuid7FromSeed);
47
155
  function uuid7FromSeed({ randomBytes, seq, timestamp }) {
48
156
  const result = new Uint8Array(16);
@@ -0,0 +1,7 @@
1
+ import * as Exit from "effect/Exit";
2
+ import * as Layer from "effect/Layer";
3
+ import { RandomValues } from "../RandomValues.js";
4
+ export declare const expectIllegalArgument: (exit: Exit.Exit<unknown, unknown>) => void;
5
+ export declare const seededRandomValues: (seed: string | number) => Layer.Layer<RandomValues>;
6
+ export declare const zeroRandomValues: Layer.Layer<RandomValues>;
7
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/__tests__/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,eAAO,MAAM,qBAAqB,SAAU,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,SAStE,CAAC;AAEF,eAAO,MAAM,kBAAkB,SAAU,MAAM,GAAG,MAAM,KAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAIhF,CAAC;AAEJ,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAOtD,CAAC"}
@@ -0,0 +1,19 @@
1
+ import * as Cause from "effect/Cause";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Exit from "effect/Exit";
4
+ import * as Layer from "effect/Layer";
5
+ import * as Random from "effect/Random";
6
+ import { expect } from "vitest";
7
+ import { RandomValues } from "../RandomValues.js";
8
+ export const expectIllegalArgument = (exit) => {
9
+ expect(Exit.isFailure(exit)).toBe(true);
10
+ if (Exit.isFailure(exit)) {
11
+ const failure = Cause.findErrorOption(exit.cause);
12
+ expect(failure._tag).toBe("Some");
13
+ if (failure._tag === "Some") {
14
+ expect(Cause.isIllegalArgumentError(failure.value)).toBe(true);
15
+ }
16
+ }
17
+ };
18
+ export const seededRandomValues = (seed) => Layer.effect(RandomValues, RandomValues.pipe(Effect.provide(RandomValues.Random), Random.withSeed(seed)));
19
+ export const zeroRandomValues = Layer.succeed(RandomValues, RandomValues.of(Effect.fn((length) => Effect.succeed(new Uint8Array(length)))));
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=public-contract.type-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-contract.type-test.d.ts","sourceRoot":"","sources":["../../src/__tests__/public-contract.type-test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import { Ids } from "../Ids.js";
2
+ const curriedUuid5 = Ids.uuid5(namespace);
3
+ const directUuid5 = Ids.uuid5(name, namespace);
package/dist/_sha.d.ts CHANGED
@@ -1,4 +1,36 @@
1
1
  import * as Effect from "effect/Effect";
2
+ /**
3
+ * Digests bytes with Web Crypto SHA-1 and returns a fresh Uint8Array.
4
+ * @remarks
5
+ * ## Why
6
+ * This published low-level helper exposes the exact hash required by UUID version 5; SHA-1 here is identity derivation, not password or signature security. Missing Web Crypto and rejected `subtle.digest` promises are Effect defects because the typed error channel is `never`.
7
+ * ## Ownership and lifetime
8
+ * Each Effect owns one asynchronous Web Crypto request and transfers a fresh result buffer; it retains no input after completion.
9
+ * @example
10
+ * ```ts
11
+ * import { sha1 } from "@typed/id/_sha"
12
+ * import { Effect } from "effect"
13
+ * const digest = Effect.runPromise(sha1(new TextEncoder().encode("name")))
14
+ * ```
15
+ * @category Hashing
16
+ * @since 1.0.0
17
+ */
2
18
  export declare const sha1: (data: BufferSource) => Effect.Effect<Uint8Array<ArrayBuffer>, never, never>;
19
+ /**
20
+ * Digests bytes with Web Crypto SHA-512 and returns a fresh Uint8Array.
21
+ * @remarks
22
+ * ## Why
23
+ * This published low-level helper exposes the exact domain-separated hash used by CUID formatting without hiding platform requirements. Missing Web Crypto and rejected `subtle.digest` promises are Effect defects because the typed error channel is `never`.
24
+ * ## Ownership and lifetime
25
+ * Each Effect owns one asynchronous Web Crypto request and transfers a fresh result buffer; it retains no input after completion.
26
+ * @example
27
+ * ```ts
28
+ * import { sha512 } from "@typed/id/_sha"
29
+ * import { Effect } from "effect"
30
+ * const digest = Effect.runPromise(sha512(new TextEncoder().encode("seed")))
31
+ * ```
32
+ * @category Hashing
33
+ * @since 1.0.0
34
+ */
3
35
  export declare const sha512: (data: BufferSource) => Effect.Effect<Uint8Array<ArrayBuffer>, never, never>;
4
36
  //# sourceMappingURL=_sha.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_sha.d.ts","sourceRoot":"","sources":["../src/_sha.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,eAAO,MAAM,IAAI,GAAI,MAAM,YAAY,yDAGpC,CAAC;AAEJ,eAAO,MAAM,MAAM,GAAI,MAAM,YAAY,yDAGtC,CAAC"}
1
+ {"version":3,"file":"_sha.d.ts","sourceRoot":"","sources":["../src/_sha.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,SAAU,YAAY,yDAGpC,CAAC;AAEJ;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,MAAM,SAAU,YAAY,yDAGtC,CAAC"}
package/dist/_sha.js CHANGED
@@ -1,3 +1,35 @@
1
1
  import * as Effect from "effect/Effect";
2
+ /**
3
+ * Digests bytes with Web Crypto SHA-1 and returns a fresh Uint8Array.
4
+ * @remarks
5
+ * ## Why
6
+ * This published low-level helper exposes the exact hash required by UUID version 5; SHA-1 here is identity derivation, not password or signature security. Missing Web Crypto and rejected `subtle.digest` promises are Effect defects because the typed error channel is `never`.
7
+ * ## Ownership and lifetime
8
+ * Each Effect owns one asynchronous Web Crypto request and transfers a fresh result buffer; it retains no input after completion.
9
+ * @example
10
+ * ```ts
11
+ * import { sha1 } from "@typed/id/_sha"
12
+ * import { Effect } from "effect"
13
+ * const digest = Effect.runPromise(sha1(new TextEncoder().encode("name")))
14
+ * ```
15
+ * @category Hashing
16
+ * @since 1.0.0
17
+ */
2
18
  export const sha1 = (data) => Effect.promise(() => crypto.subtle.digest("SHA-1", data).then((buffer) => new Uint8Array(buffer)));
19
+ /**
20
+ * Digests bytes with Web Crypto SHA-512 and returns a fresh Uint8Array.
21
+ * @remarks
22
+ * ## Why
23
+ * This published low-level helper exposes the exact domain-separated hash used by CUID formatting without hiding platform requirements. Missing Web Crypto and rejected `subtle.digest` promises are Effect defects because the typed error channel is `never`.
24
+ * ## Ownership and lifetime
25
+ * Each Effect owns one asynchronous Web Crypto request and transfers a fresh result buffer; it retains no input after completion.
26
+ * @example
27
+ * ```ts
28
+ * import { sha512 } from "@typed/id/_sha"
29
+ * import { Effect } from "effect"
30
+ * const digest = Effect.runPromise(sha512(new TextEncoder().encode("seed")))
31
+ * ```
32
+ * @category Hashing
33
+ * @since 1.0.0
34
+ */
3
35
  export const sha512 = (data) => Effect.promise(() => crypto.subtle.digest("SHA-512", data).then((buffer) => new Uint8Array(buffer)));
@@ -1,2 +1,17 @@
1
+ /**
2
+ * Formats the first 16 bytes of a seed as a lowercase hyphenated UUID string.
3
+ * @remarks
4
+ * ## Why
5
+ * This published low-level helper centralizes UUID byte layout formatting but deliberately does not validate length, version, or variant bits.
6
+ * ## Ownership and lifetime
7
+ * This pure function acquires no resources, does not mutate or retain the seed, and returns a new string.
8
+ * @example
9
+ * ```ts
10
+ * import { uuidStringify } from "@typed/id/_uuid-stringify"
11
+ * const text = uuidStringify(new Uint8Array(16))
12
+ * ```
13
+ * @category Formatting
14
+ * @since 1.0.0
15
+ */
1
16
  export declare function uuidStringify(seed: Uint8Array): string;
2
17
  //# sourceMappingURL=_uuid-stringify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_uuid-stringify.d.ts","sourceRoot":"","sources":["../src/_uuid-stringify.ts"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAuBtD"}
1
+ {"version":3,"file":"_uuid-stringify.d.ts","sourceRoot":"","sources":["../src/_uuid-stringify.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAuBtD"}
@@ -2,6 +2,21 @@ const byteToHex = [];
2
2
  for (let i = 0; i < 256; ++i) {
3
3
  byteToHex.push((i + 0x100).toString(16).slice(1));
4
4
  }
5
+ /**
6
+ * Formats the first 16 bytes of a seed as a lowercase hyphenated UUID string.
7
+ * @remarks
8
+ * ## Why
9
+ * This published low-level helper centralizes UUID byte layout formatting but deliberately does not validate length, version, or variant bits.
10
+ * ## Ownership and lifetime
11
+ * This pure function acquires no resources, does not mutate or retain the seed, and returns a new string.
12
+ * @example
13
+ * ```ts
14
+ * import { uuidStringify } from "@typed/id/_uuid-stringify"
15
+ * const text = uuidStringify(new Uint8Array(16))
16
+ * ```
17
+ * @category Formatting
18
+ * @since 1.0.0
19
+ */
5
20
  export function uuidStringify(seed) {
6
21
  return [
7
22
  byteToHex[seed[0]],
package/package.json CHANGED
@@ -1,33 +1,87 @@
1
1
  {
2
2
  "name": "@typed/id",
3
- "version": "1.0.0-beta.4",
3
+ "version": "1.0.0-beta.5",
4
+ "description": "Branded ID generators and facades for Typed applications.",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/TylorS/typed-smol/tree/main/packages/id#readme",
7
+ "bugs": "https://github.com/TylorS/typed-smol/issues",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/TylorS/typed-smol.git",
11
+ "directory": "packages/id"
12
+ },
4
13
  "files": [
5
- "dist",
6
- "src"
14
+ "dist"
7
15
  ],
8
16
  "type": "module",
17
+ "sideEffects": false,
9
18
  "exports": {
10
19
  ".": {
11
20
  "types": "./dist/index.d.ts",
12
21
  "import": "./dist/index.js"
13
22
  },
14
- "./*": {
15
- "types": "./dist/*.d.ts",
16
- "import": "./dist/*.js"
23
+ "./Cuid": {
24
+ "types": "./dist/Cuid.d.ts",
25
+ "import": "./dist/Cuid.js"
26
+ },
27
+ "./DateTimes": {
28
+ "types": "./dist/DateTimes.d.ts",
29
+ "import": "./dist/DateTimes.js"
30
+ },
31
+ "./Ids": {
32
+ "types": "./dist/Ids.d.ts",
33
+ "import": "./dist/Ids.js"
34
+ },
35
+ "./Ksuid": {
36
+ "types": "./dist/Ksuid.d.ts",
37
+ "import": "./dist/Ksuid.js"
38
+ },
39
+ "./NanoId": {
40
+ "types": "./dist/NanoId.d.ts",
41
+ "import": "./dist/NanoId.js"
42
+ },
43
+ "./RandomValues": {
44
+ "types": "./dist/RandomValues.d.ts",
45
+ "import": "./dist/RandomValues.js"
46
+ },
47
+ "./Ulid": {
48
+ "types": "./dist/Ulid.d.ts",
49
+ "import": "./dist/Ulid.js"
50
+ },
51
+ "./Uuid4": {
52
+ "types": "./dist/Uuid4.d.ts",
53
+ "import": "./dist/Uuid4.js"
54
+ },
55
+ "./Uuid5": {
56
+ "types": "./dist/Uuid5.d.ts",
57
+ "import": "./dist/Uuid5.js"
58
+ },
59
+ "./Uuid7": {
60
+ "types": "./dist/Uuid7.d.ts",
61
+ "import": "./dist/Uuid7.js"
62
+ },
63
+ "./_sha": {
64
+ "types": "./dist/_sha.d.ts",
65
+ "import": "./dist/_sha.js"
66
+ },
67
+ "./_uuid-stringify": {
68
+ "types": "./dist/_uuid-stringify.d.ts",
69
+ "import": "./dist/_uuid-stringify.js"
17
70
  }
18
71
  },
19
72
  "publishConfig": {
20
73
  "access": "public"
21
74
  },
22
- "scripts": {
23
- "build": "[ -d dist ] || rm -f tsconfig.tsbuildinfo; tsc",
24
- "test": "vitest run --passWithNoTests"
25
- },
26
75
  "dependencies": {
27
- "effect": "catalog:"
76
+ "effect": "4.0.0-rc.112"
28
77
  },
29
78
  "devDependencies": {
30
- "typescript": "catalog:",
31
- "vitest": "catalog:"
79
+ "typescript": "7.0.2",
80
+ "vitest": "5.0.0"
81
+ },
82
+ "scripts": {
83
+ "build": "node -e \"const fs=require('node:fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('tsconfig.tsbuildinfo',{force:true})\" && tsc",
84
+ "test": "vitest run",
85
+ "test:types": "tsc -p tsconfig.type-tests.json && tsc -p tsconfig.tests.json"
32
86
  }
33
- }
87
+ }