@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/Ulid.d.ts CHANGED
@@ -1,9 +1,57 @@
1
+ import * as Cause from "effect/Cause";
1
2
  import * as Effect from "effect/Effect";
2
3
  import * as Schema from "effect/Schema";
3
4
  import { DateTimes } from "./DateTimes.js";
4
5
  import { RandomValues } from "./RandomValues.js";
6
+ /**
7
+ * Effect Schema and branded string type for canonical ULID values.
8
+ * @remarks
9
+ * ## Why
10
+ * The schema validates values at transport boundaries; encoded time does not imply a total order across independent generators.
11
+ * ## Ownership and lifetime
12
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
13
+ * @example
14
+ * ```ts
15
+ * import { Ulid } from "@typed/id/Ulid"
16
+ * const id = Ulid.make("01ARZ3NDEKTSV4RRFFQ69G5FAV")
17
+ * ```
18
+ * @category Schemas
19
+ * @since 1.0.0
20
+ */
5
21
  export declare const Ulid: Schema.brand<Schema.String, "@typed/id/ULID">;
6
22
  export type Ulid = typeof Ulid.Type;
23
+ /**
24
+ * Tests whether a string is a canonical ULID.
25
+ * @remarks
26
+ * ## Why
27
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
28
+ * ## Ownership and lifetime
29
+ * This pure predicate acquires no resources and retains no input.
30
+ * @example
31
+ * ```ts
32
+ * import { isUlid } from "@typed/id/Ulid"
33
+ * isUlid("01ARZ3NDEKTSV4RRFFQ69G5FAV")
34
+ * ```
35
+ * @category Refinements
36
+ * @since 1.0.0
37
+ */
7
38
  export declare const isUlid: (value: string) => value is Ulid;
8
- export declare const ulid: Effect.Effect<Ulid, never, RandomValues | DateTimes>;
39
+ /**
40
+ * Generates a ULID from the current millisecond time and random bytes.
41
+ * @remarks
42
+ * ## Why
43
+ * Time and entropy remain explicit services; unsafe, negative, or out-of-range 48-bit timestamps fail with `IllegalArgumentError`.
44
+ * ## Ownership and lifetime
45
+ * The Effect acquires no persistent resources and uses DateTimes and RandomValues only for the invocation.
46
+ * @example
47
+ * ```ts
48
+ * import { ulid } from "@typed/id/Ulid"
49
+ * import { Ids } from "@typed/id/Ids"
50
+ * import { Effect } from "effect"
51
+ * const id = Effect.provide(ulid, Ids.Default)
52
+ * ```
53
+ * @category Generators
54
+ * @since 1.0.0
55
+ */
56
+ export declare const ulid: Effect.Effect<Ulid, Cause.IllegalArgumentError, RandomValues | DateTimes>;
9
57
  //# sourceMappingURL=Ulid.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Ulid.d.ts","sourceRoot":"","sources":["../src/Ulid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,eAAO,MAAM,IAAI,+CAGhB,CAAC;AACF,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC;AAEpC,eAAO,MAAM,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,IAAsB,CAAC;AAWxE,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAUrE,CAAC"}
1
+ {"version":3,"file":"Ulid.d.ts","sourceRoot":"","sources":["../src/Ulid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,+CAGhB,CAAC;AACF,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC;AAEpC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,IAAI,IAAsB,CAAC;AAWxE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,oBAAoB,EAAE,YAAY,GAAG,SAAS,CAWvF,CAAC"}
package/dist/Ulid.js CHANGED
@@ -1,8 +1,39 @@
1
+ import * as Cause from "effect/Cause";
1
2
  import * as Effect from "effect/Effect";
2
3
  import * as Schema from "effect/Schema";
3
4
  import { DateTimes } from "./DateTimes.js";
4
5
  import { RandomValues } from "./RandomValues.js";
6
+ /**
7
+ * Effect Schema and branded string type for canonical ULID values.
8
+ * @remarks
9
+ * ## Why
10
+ * The schema validates values at transport boundaries; encoded time does not imply a total order across independent generators.
11
+ * ## Ownership and lifetime
12
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
13
+ * @example
14
+ * ```ts
15
+ * import { Ulid } from "@typed/id/Ulid"
16
+ * const id = Ulid.make("01ARZ3NDEKTSV4RRFFQ69G5FAV")
17
+ * ```
18
+ * @category Schemas
19
+ * @since 1.0.0
20
+ */
5
21
  export const Ulid = Schema.String.pipe(Schema.check(Schema.isULID()), Schema.brand("@typed/id/ULID"));
22
+ /**
23
+ * Tests whether a string is a canonical ULID.
24
+ * @remarks
25
+ * ## Why
26
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
27
+ * ## Ownership and lifetime
28
+ * This pure predicate acquires no resources and retains no input.
29
+ * @example
30
+ * ```ts
31
+ * import { isUlid } from "@typed/id/Ulid"
32
+ * isUlid("01ARZ3NDEKTSV4RRFFQ69G5FAV")
33
+ * ```
34
+ * @category Refinements
35
+ * @since 1.0.0
36
+ */
6
37
  export const isUlid = Schema.is(Ulid);
7
38
  // Crockford's Base32
8
39
  const ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
@@ -10,10 +41,29 @@ const ENCODING_LEN = ENCODING.length;
10
41
  const TIME_MAX = 2 ** 48 - 1;
11
42
  const TIME_LEN = 10;
12
43
  const RANDOM_LEN = 16;
13
- export const ulid = Effect.zipWith(DateTimes.now, RandomValues.call(16), (now, seed) => {
14
- if (now > TIME_MAX) {
15
- throw new Error("Cannot generate ULID due to timestamp overflow");
44
+ /**
45
+ * Generates a ULID from the current millisecond time and random bytes.
46
+ * @remarks
47
+ * ## Why
48
+ * Time and entropy remain explicit services; unsafe, negative, or out-of-range 48-bit timestamps fail with `IllegalArgumentError`.
49
+ * ## Ownership and lifetime
50
+ * The Effect acquires no persistent resources and uses DateTimes and RandomValues only for the invocation.
51
+ * @example
52
+ * ```ts
53
+ * import { ulid } from "@typed/id/Ulid"
54
+ * import { Ids } from "@typed/id/Ids"
55
+ * import { Effect } from "effect"
56
+ * const id = Effect.provide(ulid, Ids.Default)
57
+ * ```
58
+ * @category Generators
59
+ * @since 1.0.0
60
+ */
61
+ export const ulid = Effect.gen(function* () {
62
+ const now = yield* DateTimes.now;
63
+ if (!Number.isSafeInteger(now) || now < 0 || now > TIME_MAX) {
64
+ return yield* new Cause.IllegalArgumentError(`ULID timestamp must be a safe integer between 0 and ${TIME_MAX}, received ${now}`);
16
65
  }
66
+ const seed = yield* RandomValues.call(16);
17
67
  return Ulid.make(encodeTime(now, TIME_LEN) + encodeRandom(seed));
18
68
  });
19
69
  function encodeTime(now, len) {
package/dist/Uuid4.d.ts CHANGED
@@ -1,8 +1,55 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import * as Schema from "effect/Schema";
3
3
  import { RandomValues } from "./RandomValues.js";
4
+ /**
5
+ * Effect Schema and branded string type for RFC UUID version 4 values.
6
+ * @remarks
7
+ * ## Why
8
+ * The schema verifies version and variant bits before restoring the compile-time brand after transport.
9
+ * ## Ownership and lifetime
10
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
11
+ * @example
12
+ * ```ts
13
+ * import { Uuid4 } from "@typed/id/Uuid4"
14
+ * const id = Uuid4.make("550e8400-e29b-41d4-a716-446655440000")
15
+ * ```
16
+ * @category Schemas
17
+ * @since 1.0.0
18
+ */
4
19
  export declare const Uuid4: Schema.brand<Schema.String, "@typed/id/UUID4">;
5
20
  export type Uuid4 = typeof Uuid4.Type;
21
+ /**
22
+ * Tests whether a string is an RFC UUID version 4 value.
23
+ * @remarks
24
+ * ## Why
25
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
26
+ * ## Ownership and lifetime
27
+ * This pure predicate acquires no resources and retains no input.
28
+ * @example
29
+ * ```ts
30
+ * import { isUuid4 } from "@typed/id/Uuid4"
31
+ * isUuid4("550e8400-e29b-41d4-a716-446655440000")
32
+ * ```
33
+ * @category Refinements
34
+ * @since 1.0.0
35
+ */
6
36
  export declare const isUuid4: (value: string) => value is Uuid4;
37
+ /**
38
+ * Generates an RFC UUID version 4 from 16 fresh random bytes.
39
+ * @remarks
40
+ * ## Why
41
+ * Effectful generation exposes entropy as a service and explicitly sets version and variant bits; custom services must return a usable fresh buffer.
42
+ * ## Ownership and lifetime
43
+ * The invocation mutates only its fresh byte buffer, acquires no persistent resource, and returns an immutable string.
44
+ * @example
45
+ * ```ts
46
+ * import { uuid4 } from "@typed/id/Uuid4"
47
+ * import { RandomValues } from "@typed/id/RandomValues"
48
+ * import { Effect } from "effect"
49
+ * const id = Effect.provide(uuid4, RandomValues.Default)
50
+ * ```
51
+ * @category Generators
52
+ * @since 1.0.0
53
+ */
7
54
  export declare const uuid4: Effect.Effect<Uuid4, never, RandomValues>;
8
55
  //# sourceMappingURL=Uuid4.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid4.d.ts","sourceRoot":"","sources":["../src/Uuid4.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,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;AAI3E,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,CAQ3D,CAAC"}
1
+ {"version":3,"file":"Uuid4.d.ts","sourceRoot":"","sources":["../src/Uuid4.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;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;AAI3E;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,CAQ3D,CAAC"}
package/dist/Uuid4.js CHANGED
@@ -2,8 +2,55 @@ import * as Effect from "effect/Effect";
2
2
  import * as Schema from "effect/Schema";
3
3
  import { uuidStringify } from "./_uuid-stringify.js";
4
4
  import { RandomValues } from "./RandomValues.js";
5
+ /**
6
+ * Effect Schema and branded string type for RFC UUID version 4 values.
7
+ * @remarks
8
+ * ## Why
9
+ * The schema verifies version and variant bits before restoring the compile-time brand after transport.
10
+ * ## Ownership and lifetime
11
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
12
+ * @example
13
+ * ```ts
14
+ * import { Uuid4 } from "@typed/id/Uuid4"
15
+ * const id = Uuid4.make("550e8400-e29b-41d4-a716-446655440000")
16
+ * ```
17
+ * @category Schemas
18
+ * @since 1.0.0
19
+ */
5
20
  export const Uuid4 = Schema.String.pipe(Schema.check(Schema.isUUID(4)), Schema.brand("@typed/id/UUID4"));
21
+ /**
22
+ * Tests whether a string is an RFC UUID version 4 value.
23
+ * @remarks
24
+ * ## Why
25
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
26
+ * ## Ownership and lifetime
27
+ * This pure predicate acquires no resources and retains no input.
28
+ * @example
29
+ * ```ts
30
+ * import { isUuid4 } from "@typed/id/Uuid4"
31
+ * isUuid4("550e8400-e29b-41d4-a716-446655440000")
32
+ * ```
33
+ * @category Refinements
34
+ * @since 1.0.0
35
+ */
6
36
  export const isUuid4 = Schema.is(Uuid4);
37
+ /**
38
+ * Generates an RFC UUID version 4 from 16 fresh random bytes.
39
+ * @remarks
40
+ * ## Why
41
+ * Effectful generation exposes entropy as a service and explicitly sets version and variant bits; custom services must return a usable fresh buffer.
42
+ * ## Ownership and lifetime
43
+ * The invocation mutates only its fresh byte buffer, acquires no persistent resource, and returns an immutable string.
44
+ * @example
45
+ * ```ts
46
+ * import { uuid4 } from "@typed/id/Uuid4"
47
+ * import { RandomValues } from "@typed/id/RandomValues"
48
+ * import { Effect } from "effect"
49
+ * const id = Effect.provide(uuid4, RandomValues.Default)
50
+ * ```
51
+ * @category Generators
52
+ * @since 1.0.0
53
+ */
7
54
  export const uuid4 = Effect.map(RandomValues.call(16), (seed) => {
8
55
  // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
9
56
  seed[6] = (seed[6] & 0x0f) | 0x40;
package/dist/Uuid5.d.ts CHANGED
@@ -1,21 +1,193 @@
1
+ import * as Cause from "effect/Cause";
1
2
  import * as Effect from "effect/Effect";
2
3
  import * as Schema from "effect/Schema";
4
+ /**
5
+ * Effect Schema and branded string type for RFC UUID version 5 values.
6
+ * @remarks
7
+ * ## Why
8
+ * The schema verifies UUID version and variant at transport boundaries before restoring the compile-time brand.
9
+ * ## Ownership and lifetime
10
+ * This module-level schema value acquires no resources and is shared; no runtime freezing guarantee is implied.
11
+ * @example
12
+ * ```ts
13
+ * import { Uuid5 } from "@typed/id/Uuid5"
14
+ * import { Schema } from "effect"
15
+ * const id = Schema.decodeUnknownSync(Uuid5)("21f7f8de-8051-5b89-8680-0195ef798b6a")
16
+ * ```
17
+ * @category Schemas
18
+ * @since 1.0.0
19
+ */
3
20
  export declare const Uuid5: Schema.brand<Schema.String, "@typed/id/UUID5">;
4
21
  export type Uuid5 = typeof Uuid5.Type;
22
+ /**
23
+ * Tests whether a string is an RFC UUID version 5 value.
24
+ * @remarks
25
+ * ## Why
26
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
27
+ * ## Ownership and lifetime
28
+ * This pure predicate acquires no resources and retains no input.
29
+ * @example
30
+ * ```ts
31
+ * import { isUuid5 } from "@typed/id/Uuid5"
32
+ * isUuid5("21f7f8de-8051-5b89-8680-0195ef798b6a")
33
+ * ```
34
+ * @category Refinements
35
+ * @since 1.0.0
36
+ */
5
37
  export declare const isUuid5: (value: string) => value is Uuid5;
38
+ /**
39
+ * The exact 16 namespace bytes used in UUID version 5 hashing.
40
+ * @remarks
41
+ * ## Why
42
+ * Namespace bytes are part of deterministic identity; caller canonicalization of names and namespace selection must remain explicit.
43
+ * ## Ownership and lifetime
44
+ * This type acquires no resources. Callers own and may mutate their byte array; generation reads exactly 16 bytes.
45
+ * @category Models
46
+ * @since 1.0.0
47
+ */
6
48
  export type Uuid5Namespace = Uint8Array;
49
+ /**
50
+ * Standard RFC UUID version 5 namespaces, returned as fresh mutable copies.
51
+ * @remarks
52
+ * ## Why
53
+ * Copy-on-access protects canonical constants while allowing callers to own and safely modify their selected namespace bytes.
54
+ * ## Ownership and lifetime
55
+ * The module owns canonical bytes for its lifetime; every property access transfers a fresh 16-byte copy to the caller.
56
+ * @example
57
+ * ```ts
58
+ * import { Uuid5Namespace } from "@typed/id/Uuid5"
59
+ * const namespace = Uuid5Namespace.DNS
60
+ * ```
61
+ * @category Namespaces
62
+ * @since 1.0.0
63
+ */
7
64
  export declare const Uuid5Namespace: {
65
+ /**
66
+ * Returns a fresh copy of the RFC DNS namespace bytes.
67
+ * @remarks
68
+ * ## Why
69
+ * DNS names need a stable namespace distinct from URLs, OIDs, and X.500 names.
70
+ * ## Ownership and lifetime
71
+ * Each access allocates a mutable byte array owned by the caller.
72
+ * @category Namespaces
73
+ * @since 1.0.0
74
+ */
8
75
  readonly DNS: Uint8Array<ArrayBuffer>;
76
+ /**
77
+ * Returns a fresh copy of the RFC URL namespace bytes.
78
+ * @remarks
79
+ * ## Why
80
+ * URL names need a stable namespace distinct from DNS, OID, and X.500 names.
81
+ * ## Ownership and lifetime
82
+ * Each access allocates a mutable byte array owned by the caller.
83
+ * @category Namespaces
84
+ * @since 1.0.0
85
+ */
9
86
  readonly URL: Uint8Array<ArrayBuffer>;
87
+ /**
88
+ * Returns a fresh copy of the RFC OID namespace bytes.
89
+ * @remarks
90
+ * ## Why
91
+ * Object identifiers need a stable namespace distinct from DNS, URL, and X.500 names.
92
+ * ## Ownership and lifetime
93
+ * Each access allocates a mutable byte array owned by the caller.
94
+ * @category Namespaces
95
+ * @since 1.0.0
96
+ */
10
97
  readonly OID: Uint8Array<ArrayBuffer>;
98
+ /**
99
+ * Returns a fresh copy of the RFC X.500 namespace bytes.
100
+ * @remarks
101
+ * ## Why
102
+ * X.500 names need a stable namespace distinct from DNS, URL, and OID names.
103
+ * ## Ownership and lifetime
104
+ * Each access allocates a mutable byte array owned by the caller.
105
+ * @category Namespaces
106
+ * @since 1.0.0
107
+ */
11
108
  readonly X500: Uint8Array<ArrayBuffer>;
12
109
  };
110
+ /**
111
+ * Derives a deterministic UUID version 5 from a UTF-8 name and 16-byte namespace.
112
+ * @remarks
113
+ * ## Why
114
+ * Determinism is exact for the same name bytes and namespace. Invalid namespace length fails in the typed channel with `IllegalArgumentError`; missing Web Crypto or a rejected SHA-1 digest is an Effect defect, not a typed error.
115
+ * ## Ownership and lifetime
116
+ * Each Effect acquires no persistent resources, reads but does not retain the namespace, and uses Web Crypto `subtle.digest` for the invocation.
117
+ * @example
118
+ * ```ts
119
+ * import { uuid5, Uuid5Namespace } from "@typed/id/Uuid5"
120
+ * const id = uuid5("example.com", Uuid5Namespace.DNS)
121
+ * ```
122
+ * @category Generators
123
+ * @since 1.0.0
124
+ */
13
125
  export declare const uuid5: {
14
- (namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5>;
15
- (name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5>;
126
+ (namespace: Uuid5Namespace): (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
127
+ (name: string, namespace: Uuid5Namespace): Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
16
128
  };
17
- export declare const dnsUuid5: (name: string) => Effect.Effect<Uuid5>;
18
- export declare const urlUuid5: (name: string) => Effect.Effect<Uuid5>;
19
- export declare const oidUuid5: (name: string) => Effect.Effect<Uuid5>;
20
- export declare const x500Uuid5: (name: string) => Effect.Effect<Uuid5>;
129
+ /**
130
+ * Derives deterministic UUID version 5 values in the standard DNS namespace.
131
+ * @remarks
132
+ * ## Why
133
+ * The pre-bound helper prevents accidental namespace selection drift for DNS identities.
134
+ * ## Ownership and lifetime
135
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
136
+ * @example
137
+ * ```ts
138
+ * import { dnsUuid5 } from "@typed/id/Uuid5"
139
+ * const id = dnsUuid5("example.com")
140
+ * ```
141
+ * @category Generators
142
+ * @since 1.0.0
143
+ */
144
+ export declare const dnsUuid5: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
145
+ /**
146
+ * Derives deterministic UUID version 5 values in the standard URL namespace.
147
+ * @remarks
148
+ * ## Why
149
+ * The pre-bound helper prevents accidental namespace selection drift for URL identities.
150
+ * ## Ownership and lifetime
151
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
152
+ * @example
153
+ * ```ts
154
+ * import { urlUuid5 } from "@typed/id/Uuid5"
155
+ * const id = urlUuid5("https://example.com")
156
+ * ```
157
+ * @category Generators
158
+ * @since 1.0.0
159
+ */
160
+ export declare const urlUuid5: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
161
+ /**
162
+ * Derives deterministic UUID version 5 values in the standard OID namespace.
163
+ * @remarks
164
+ * ## Why
165
+ * The pre-bound helper prevents accidental namespace selection drift for object identifiers.
166
+ * ## Ownership and lifetime
167
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
168
+ * @example
169
+ * ```ts
170
+ * import { oidUuid5 } from "@typed/id/Uuid5"
171
+ * const id = oidUuid5("1.3.6.1.4.1")
172
+ * ```
173
+ * @category Generators
174
+ * @since 1.0.0
175
+ */
176
+ export declare const oidUuid5: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
177
+ /**
178
+ * Derives deterministic UUID version 5 values in the standard X.500 namespace.
179
+ * @remarks
180
+ * ## Why
181
+ * The pre-bound helper prevents accidental namespace selection drift for X.500 identities.
182
+ * ## Ownership and lifetime
183
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
184
+ * @example
185
+ * ```ts
186
+ * import { x500Uuid5 } from "@typed/id/Uuid5"
187
+ * const id = x500Uuid5("CN=example")
188
+ * ```
189
+ * @category Generators
190
+ * @since 1.0.0
191
+ */
192
+ export declare const x500Uuid5: (name: string) => Effect.Effect<Uuid5, Cause.IllegalArgumentError>;
21
193
  //# sourceMappingURL=Uuid5.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid5.d.ts","sourceRoot":"","sources":["../src/Uuid5.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,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,cAAc,GAAG,UAAU,CAAC;AAKxC,eAAO,MAAM,cAAc;;;;;CAgBjB,CAAC;AAEX,eAAO,MAAM,KAAK,EAAE;IAClB,CAAC,SAAS,EAAE,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CA0BhE,CAAC;AAEH,eAAO,MAAM,QAAQ,SA7BiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CA6BnB,CAAC;AAClD,eAAO,MAAM,QAAQ,SA9BiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CA8BnB,CAAC;AAClD,eAAO,MAAM,QAAQ,SA/BiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CA+BnB,CAAC;AAClD,eAAO,MAAM,SAAS,SAhCgB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAgCjB,CAAC"}
1
+ {"version":3,"file":"Uuid5.d.ts","sourceRoot":"","sources":["../src/Uuid5.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC;;;;;;;;;;;;;;;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;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC;AAkBxC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,EAAE;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;CAcvC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK,EAAE;IAClB,CAAC,SAAS,EAAE,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAChG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;CAmC5F,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,SArDiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAqD/C,CAAC;AAClD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,SArEiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAqE/C,CAAC;AAClD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,SArFiB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAqF/C,CAAC;AAClD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,SArGgB,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAqG7C,CAAC"}
package/dist/Uuid5.js CHANGED
@@ -1,28 +1,105 @@
1
+ import * as Cause from "effect/Cause";
1
2
  import * as Effect from "effect/Effect";
2
3
  import { dual } from "effect/Function";
3
4
  import * as Schema from "effect/Schema";
4
5
  import { sha1 } from "./_sha.js";
5
6
  import { uuidStringify } from "./_uuid-stringify.js";
7
+ /**
8
+ * Effect Schema and branded string type for RFC UUID version 5 values.
9
+ * @remarks
10
+ * ## Why
11
+ * The schema verifies UUID version and variant at transport boundaries before restoring the compile-time brand.
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 { Uuid5 } from "@typed/id/Uuid5"
17
+ * import { Schema } from "effect"
18
+ * const id = Schema.decodeUnknownSync(Uuid5)("21f7f8de-8051-5b89-8680-0195ef798b6a")
19
+ * ```
20
+ * @category Schemas
21
+ * @since 1.0.0
22
+ */
6
23
  export const Uuid5 = Schema.String.pipe(Schema.check(Schema.isUUID(5)), Schema.brand("@typed/id/UUID5"));
24
+ /**
25
+ * Tests whether a string is an RFC UUID version 5 value.
26
+ * @remarks
27
+ * ## Why
28
+ * Runtime refinement restores trust after serialization has erased the TypeScript brand.
29
+ * ## Ownership and lifetime
30
+ * This pure predicate acquires no resources and retains no input.
31
+ * @example
32
+ * ```ts
33
+ * import { isUuid5 } from "@typed/id/Uuid5"
34
+ * isUuid5("21f7f8de-8051-5b89-8680-0195ef798b6a")
35
+ * ```
36
+ * @category Refinements
37
+ * @since 1.0.0
38
+ */
7
39
  export const isUuid5 = Schema.is(Uuid5);
8
40
  const textEncoder = new TextEncoder();
9
41
  // Pre-defined namespaces from RFC 4122
10
- export const Uuid5Namespace = {
11
- DNS: new Uint8Array([
12
- 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
13
- ]),
14
- URL: new Uint8Array([
15
- 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
16
- ]),
17
- OID: new Uint8Array([
18
- 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
19
- ]),
20
- X500: new Uint8Array([
21
- 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
22
- ]),
23
- };
42
+ const DNS = new Uint8Array([
43
+ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
44
+ ]);
45
+ const URL = new Uint8Array([
46
+ 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
47
+ ]);
48
+ const OID = new Uint8Array([
49
+ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
50
+ ]);
51
+ const X500 = new Uint8Array([
52
+ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
53
+ ]);
54
+ /**
55
+ * Standard RFC UUID version 5 namespaces, returned as fresh mutable copies.
56
+ * @remarks
57
+ * ## Why
58
+ * Copy-on-access protects canonical constants while allowing callers to own and safely modify their selected namespace bytes.
59
+ * ## Ownership and lifetime
60
+ * The module owns canonical bytes for its lifetime; every property access transfers a fresh 16-byte copy to the caller.
61
+ * @example
62
+ * ```ts
63
+ * import { Uuid5Namespace } from "@typed/id/Uuid5"
64
+ * const namespace = Uuid5Namespace.DNS
65
+ * ```
66
+ * @category Namespaces
67
+ * @since 1.0.0
68
+ */
69
+ export const Uuid5Namespace = Object.freeze({
70
+ get DNS() {
71
+ return DNS.slice(0);
72
+ },
73
+ get URL() {
74
+ return URL.slice(0);
75
+ },
76
+ get OID() {
77
+ return OID.slice(0);
78
+ },
79
+ get X500() {
80
+ return X500.slice(0);
81
+ },
82
+ });
83
+ /**
84
+ * Derives a deterministic UUID version 5 from a UTF-8 name and 16-byte namespace.
85
+ * @remarks
86
+ * ## Why
87
+ * Determinism is exact for the same name bytes and namespace. Invalid namespace length fails in the typed channel with `IllegalArgumentError`; missing Web Crypto or a rejected SHA-1 digest is an Effect defect, not a typed error.
88
+ * ## Ownership and lifetime
89
+ * Each Effect acquires no persistent resources, reads but does not retain the namespace, and uses Web Crypto `subtle.digest` for the invocation.
90
+ * @example
91
+ * ```ts
92
+ * import { uuid5, Uuid5Namespace } from "@typed/id/Uuid5"
93
+ * const id = uuid5("example.com", Uuid5Namespace.DNS)
94
+ * ```
95
+ * @category Generators
96
+ * @since 1.0.0
97
+ */
24
98
  export const uuid5 = dual(2, function uuid5(name, namespace) {
25
99
  return Effect.gen(function* () {
100
+ if (namespace.length !== 16) {
101
+ return yield* new Cause.IllegalArgumentError(`UUIDv5 namespace must contain exactly 16 bytes, received ${namespace.length}`);
102
+ }
26
103
  // Convert name to UTF-8 bytes
27
104
  const nameBytes = textEncoder.encode(name);
28
105
  // Concatenate namespace and name
@@ -41,7 +118,67 @@ export const uuid5 = dual(2, function uuid5(name, namespace) {
41
118
  return Uuid5.make(uuidStringify(result));
42
119
  });
43
120
  });
121
+ /**
122
+ * Derives deterministic UUID version 5 values in the standard DNS namespace.
123
+ * @remarks
124
+ * ## Why
125
+ * The pre-bound helper prevents accidental namespace selection drift for DNS identities.
126
+ * ## Ownership and lifetime
127
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
128
+ * @example
129
+ * ```ts
130
+ * import { dnsUuid5 } from "@typed/id/Uuid5"
131
+ * const id = dnsUuid5("example.com")
132
+ * ```
133
+ * @category Generators
134
+ * @since 1.0.0
135
+ */
44
136
  export const dnsUuid5 = uuid5(Uuid5Namespace.DNS);
137
+ /**
138
+ * Derives deterministic UUID version 5 values in the standard URL namespace.
139
+ * @remarks
140
+ * ## Why
141
+ * The pre-bound helper prevents accidental namespace selection drift for URL identities.
142
+ * ## Ownership and lifetime
143
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
144
+ * @example
145
+ * ```ts
146
+ * import { urlUuid5 } from "@typed/id/Uuid5"
147
+ * const id = urlUuid5("https://example.com")
148
+ * ```
149
+ * @category Generators
150
+ * @since 1.0.0
151
+ */
45
152
  export const urlUuid5 = uuid5(Uuid5Namespace.URL);
153
+ /**
154
+ * Derives deterministic UUID version 5 values in the standard OID namespace.
155
+ * @remarks
156
+ * ## Why
157
+ * The pre-bound helper prevents accidental namespace selection drift for object identifiers.
158
+ * ## Ownership and lifetime
159
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
160
+ * @example
161
+ * ```ts
162
+ * import { oidUuid5 } from "@typed/id/Uuid5"
163
+ * const id = oidUuid5("1.3.6.1.4.1")
164
+ * ```
165
+ * @category Generators
166
+ * @since 1.0.0
167
+ */
46
168
  export const oidUuid5 = uuid5(Uuid5Namespace.OID);
169
+ /**
170
+ * Derives deterministic UUID version 5 values in the standard X.500 namespace.
171
+ * @remarks
172
+ * ## Why
173
+ * The pre-bound helper prevents accidental namespace selection drift for X.500 identities.
174
+ * ## Ownership and lifetime
175
+ * This function acquires no persistent resources and uses a captured namespace copy for module lifetime.
176
+ * @example
177
+ * ```ts
178
+ * import { x500Uuid5 } from "@typed/id/Uuid5"
179
+ * const id = x500Uuid5("CN=example")
180
+ * ```
181
+ * @category Generators
182
+ * @since 1.0.0
183
+ */
47
184
  export const x500Uuid5 = uuid5(Uuid5Namespace.X500);