@typed/id 0.13.0 → 0.15.0

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.
@@ -0,0 +1,26 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { Layer, Schema } from 'effect';
3
+ export declare const Uuid5: Schema.brand<typeof Schema.UUID, "@typed/id/UUID5">;
4
+ export type Uuid5 = Schema.Schema.Type<typeof Uuid5>;
5
+ export declare const isUuid5: (value: string) => value is Uuid5;
6
+ declare const Sha1_base: import("effect/Context").TagClass<Sha1, "Sha1", {
7
+ readonly hash: (data: Uint8Array) => Effect.Effect<Uint8Array, never>;
8
+ }> & Effect.Tag.Proxy<Sha1, {
9
+ readonly hash: (data: Uint8Array) => Effect.Effect<Uint8Array, never>;
10
+ }> & {
11
+ use: <X>(body: (_: {
12
+ readonly hash: (data: Uint8Array) => Effect.Effect<Uint8Array, never>;
13
+ }) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, R | Sha1> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, import("effect/Cause").UnknownException, Sha1> : Effect.Effect<X, never, Sha1>;
14
+ };
15
+ export declare class Sha1 extends Sha1_base {
16
+ static readonly Default: Layer.Layer<Sha1, never, never>;
17
+ }
18
+ export type Uuid5Namespace = Uint8Array;
19
+ export declare const Uuid5Namespace: {
20
+ readonly DNS: Uint8Array<ArrayBuffer>;
21
+ readonly URL: Uint8Array<ArrayBuffer>;
22
+ readonly OID: Uint8Array<ArrayBuffer>;
23
+ readonly X500: Uint8Array<ArrayBuffer>;
24
+ };
25
+ export declare function makeUuid5(namespace: Uuid5Namespace, name: string): Effect.Effect<Uuid5, never, Sha1>;
26
+ export {};
package/dist/Uuid5.js ADDED
@@ -0,0 +1,48 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { Layer, Schema } from 'effect';
3
+ import { uuidStringify } from './UuidStringify.js';
4
+ export const Uuid5 = Schema.UUID.pipe(Schema.brand('@typed/id/UUID5'));
5
+ export const isUuid5 = Schema.is(Uuid5);
6
+ export class Sha1 extends Effect.Tag('Sha1')() {
7
+ static Default = Layer.succeed(this, {
8
+ hash: (data) => Effect.promise(() => crypto.subtle.digest('SHA-1', data).then((hash) => new Uint8Array(hash))),
9
+ });
10
+ }
11
+ const textEncoder = new TextEncoder();
12
+ // Pre-defined namespaces from RFC 4122
13
+ export const Uuid5Namespace = {
14
+ DNS: new Uint8Array([
15
+ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
16
+ ]),
17
+ URL: new Uint8Array([
18
+ 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
19
+ ]),
20
+ OID: new Uint8Array([
21
+ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
22
+ ]),
23
+ X500: new Uint8Array([
24
+ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
25
+ ]),
26
+ };
27
+ export function makeUuid5(namespace, name) {
28
+ return Effect.gen(function* () {
29
+ const sha1 = yield* Sha1;
30
+ // Convert name to UTF-8 bytes
31
+ const nameBytes = textEncoder.encode(name);
32
+ // Concatenate namespace and name
33
+ const buffer = new Uint8Array(namespace.length + nameBytes.length);
34
+ buffer.set(namespace);
35
+ buffer.set(nameBytes, namespace.length);
36
+ // Hash the concatenated bytes
37
+ const hash = yield* sha1.hash(buffer);
38
+ // Format as UUID v5
39
+ const result = new Uint8Array(16);
40
+ // Copy first 16 bytes of the hash
41
+ result.set(hash.subarray(0, 16));
42
+ // Set version (5) and variant bits
43
+ result[6] = (result[6] & 0x0f) | 0x50; // version 5
44
+ result[8] = (result[8] & 0x3f) | 0x80; // variant 1
45
+ return uuidStringify(result);
46
+ });
47
+ }
48
+ //# sourceMappingURL=Uuid5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Uuid5.js","sourceRoot":"","sources":["../src/Uuid5.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { GetRandomValues } from './GetRandomValues.js';
3
+ import { Layer, Schema } from 'effect';
4
+ import { DateTimes } from './DateTimes.js';
5
+ export declare const Uuid6: Schema.brand<typeof Schema.UUID, "@typed/id/UUID6">;
6
+ export type Uuid6 = Schema.Schema.Type<typeof Uuid6>;
7
+ export declare const isUuid6: (value: string) => value is Uuid6;
8
+ export type Uuid6Seed = {
9
+ readonly msecs: number;
10
+ readonly nsecs: number;
11
+ readonly clockSeq: number;
12
+ readonly nodeId: Uint8Array;
13
+ };
14
+ declare const Uuid6State_base: import("effect/Context").TagClass<Uuid6State, "Uuid6State", {
15
+ readonly next: Effect.Effect<Uuid6Seed>;
16
+ }> & Effect.Tag.Proxy<Uuid6State, {
17
+ readonly next: Effect.Effect<Uuid6Seed>;
18
+ }> & {
19
+ use: <X>(body: (_: {
20
+ readonly next: Effect.Effect<Uuid6Seed>;
21
+ }) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, R | Uuid6State> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, import("effect/Cause").UnknownException, Uuid6State> : Effect.Effect<X, never, Uuid6State>;
22
+ };
23
+ export declare class Uuid6State extends Uuid6State_base {
24
+ static Default: Layer.Layer<Uuid6State, never, GetRandomValues | DateTimes>;
25
+ }
26
+ export declare const makeUuid6: Effect.Effect<Uuid6, never, Uuid6State>;
27
+ export {};
package/dist/Uuid6.js ADDED
@@ -0,0 +1,104 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { GetRandomValues } from './GetRandomValues.js';
3
+ import { Layer, Schema } from 'effect';
4
+ import { DateTimes } from './DateTimes.js';
5
+ import { uuidStringify } from './UuidStringify.js';
6
+ export const Uuid6 = Schema.UUID.pipe(Schema.brand('@typed/id/UUID6'));
7
+ export const isUuid6 = Schema.is(Uuid6);
8
+ export class Uuid6State extends Effect.Tag('Uuid6State')() {
9
+ static Default = Layer.effect(this, Effect.gen(function* () {
10
+ const { now } = yield* DateTimes;
11
+ const getRandomValues = yield* GetRandomValues;
12
+ const state = {
13
+ msecs: Number.NEGATIVE_INFINITY,
14
+ nsecs: 0,
15
+ clockSeq: -1,
16
+ nodeId: undefined,
17
+ };
18
+ function updateState(currentTime, randomBytes) {
19
+ if (currentTime === state.msecs) {
20
+ // Same msec-interval = simulate higher clock resolution by bumping `nsecs`
21
+ state.nsecs++;
22
+ // Check for `nsecs` overflow (nsecs is capped at 10K intervals / msec)
23
+ if (state.nsecs >= 10000) {
24
+ state.nodeId = undefined;
25
+ state.nsecs = 0;
26
+ }
27
+ }
28
+ else if (currentTime > state.msecs) {
29
+ // Reset nsec counter when clock advances to a new msec interval
30
+ state.nsecs = 0;
31
+ }
32
+ else if (currentTime < state.msecs) {
33
+ // Handle clock regression
34
+ state.nodeId = undefined;
35
+ }
36
+ // Init node and clock sequence if needed
37
+ if (!state.nodeId) {
38
+ state.nodeId = randomBytes.slice(10, 16);
39
+ // Set multicast bit
40
+ state.nodeId[0] |= 0x01;
41
+ // Clock sequence must be randomized
42
+ state.clockSeq = ((randomBytes[8] << 8) | randomBytes[9]) & 0x3fff;
43
+ }
44
+ state.msecs = currentTime;
45
+ return {
46
+ msecs: state.msecs,
47
+ nsecs: state.nsecs,
48
+ clockSeq: state.clockSeq,
49
+ nodeId: state.nodeId,
50
+ };
51
+ }
52
+ return {
53
+ next: Effect.gen(function* () {
54
+ const timestamp = yield* now;
55
+ const randomBytes = yield* getRandomValues(16);
56
+ return updateState(timestamp, randomBytes);
57
+ }),
58
+ };
59
+ }));
60
+ }
61
+ export const makeUuid6 = Effect.map(Uuid6State.next, uuid6FromSeed);
62
+ function uuid6FromSeed({ msecs, nsecs, clockSeq, nodeId }) {
63
+ // First generate the fields as they would be in a v1 UUID
64
+ const result = new Uint8Array(16);
65
+ // Offset to Gregorian epoch
66
+ msecs += 12219292800000;
67
+ // `time_low`
68
+ const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
69
+ const time_low_bytes = new Uint8Array([
70
+ (tl >>> 24) & 0xff,
71
+ (tl >>> 16) & 0xff,
72
+ (tl >>> 8) & 0xff,
73
+ tl & 0xff,
74
+ ]);
75
+ // `time_mid` and `time_high`
76
+ const tmh = ((msecs / 0x100000000) * 10000) & 0xfffffff;
77
+ const time_mid_high_bytes = new Uint8Array([
78
+ (tmh >>> 8) & 0xff,
79
+ tmh & 0xff,
80
+ ((tmh >>> 24) & 0xf) | 0x10, // include version 1
81
+ (tmh >>> 16) & 0xff,
82
+ ]);
83
+ result[0] = ((time_mid_high_bytes[2] & 0x0f) << 4) | ((time_mid_high_bytes[3] >> 4) & 0x0f);
84
+ result[1] = ((time_mid_high_bytes[3] & 0x0f) << 4) | ((time_mid_high_bytes[0] & 0xf0) >> 4);
85
+ result[2] = ((time_mid_high_bytes[0] & 0x0f) << 4) | ((time_mid_high_bytes[1] & 0xf0) >> 4);
86
+ result[3] = ((time_mid_high_bytes[1] & 0x0f) << 4) | ((time_low_bytes[0] & 0xf0) >> 4);
87
+ result[4] = ((time_low_bytes[0] & 0x0f) << 4) | ((time_low_bytes[1] & 0xf0) >> 4);
88
+ result[5] = ((time_low_bytes[1] & 0x0f) << 4) | ((time_low_bytes[2] & 0xf0) >> 4);
89
+ result[6] = 0x60 | (time_low_bytes[2] & 0x0f);
90
+ result[7] = time_low_bytes[3];
91
+ // clock_seq_hi_and_reserved
92
+ result[8] = (clockSeq >>> 8) | 0x80; // variant bits
93
+ // clock_seq_low
94
+ result[9] = clockSeq & 0xff;
95
+ // node
96
+ result[10] = nodeId[0];
97
+ result[11] = nodeId[1];
98
+ result[12] = nodeId[2];
99
+ result[13] = nodeId[3];
100
+ result[14] = nodeId[4];
101
+ result[15] = nodeId[5];
102
+ return uuidStringify(result);
103
+ }
104
+ //# sourceMappingURL=Uuid6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Uuid6.js","sourceRoot":"","sources":["../src/Uuid6.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from './GetRandomValues.js';
3
3
  export * from './NanoId.js';
4
4
  export * from './Ulid.js';
5
5
  export * from './Uuid4.js';
6
+ export * from './Uuid5.js';
6
7
  export * from './Uuid7.js';
package/dist/index.js CHANGED
@@ -3,5 +3,6 @@ export * from './GetRandomValues.js';
3
3
  export * from './NanoId.js';
4
4
  export * from './Ulid.js';
5
5
  export * from './Uuid4.js';
6
+ export * from './Uuid5.js';
6
7
  export * from './Uuid7.js';
7
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed/id",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "Common ID format generation for Effect",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/readme.md CHANGED
@@ -17,7 +17,7 @@ yarn add @typed/id effect
17
17
  - 🎯 Type-safe ID generation
18
18
  - 🔧 Built on top of Effect
19
19
  - 🎨 Multiple ID format support:
20
- - UUID (v4)
20
+ - UUID (v4, v5, v6, v7)
21
21
  - NanoID
22
22
  - ULID
23
23
  - ⚡ Efficient and secure random value generation
@@ -30,24 +30,44 @@ import { Effect } from 'effect'
30
30
  import {
31
31
  DateTimes,
32
32
  GetRandomValues,
33
- makeUuid,
33
+ makeUuid4,
34
+ makeUuid5,
35
+ makeUuid7,
36
+ Uuid7State,
37
+ Uuid5Namespace,
38
+ Sha1,
34
39
  makeNanoId,
35
40
  makeUlid
36
41
  } from '@typed/id'
37
42
 
38
- // Generate a UUID
39
- await makeUuid.pipe(
43
+ // Generate a UUID v4 (random)
44
+ await makeUuid4.pipe(
40
45
  Effect.provide(GetRandomValues.CryptoRandom),
41
- // Effect.provide(GetRandomValues.PseudoRandom),
42
46
  Effect.flatMap(Effect.log),
43
47
  Effect.runPromise
44
48
  )
45
49
  // Output: "550e8400-e29b-41d4-a716-446655440000"
46
50
 
51
+ // Generate a UUID v5 (namespace + name based)
52
+ await makeUuid5(Uuid5Namespace.URL, 'https://example.com').pipe(
53
+ Effect.provide(Sha1.Default),
54
+ Effect.flatMap(Effect.log),
55
+ Effect.runPromise
56
+ )
57
+ // Output: "2ed6657d-e927-568b-95e1-2665a8aea6a2"
58
+
59
+ // Generate a UUID v7 (time-sortable)
60
+ await makeUuid7.pipe(
61
+ Effect.provide(Uuid7State.Default),
62
+ Effect.provide([GetRandomValues.CryptoRandom, DateTimes.Default]),
63
+ Effect.flatMap(Effect.log),
64
+ Effect.runPromise
65
+ )
66
+ // Output: "018e7768-c0b3-7000-8000-123456789abc"
67
+
47
68
  // Generate a NanoID
48
69
  await makeNanoId.pipe(
49
70
  Effect.provide(GetRandomValues.CryptoRandom),
50
- // Effect.provide(GetRandomValues.PseudoRandom),
51
71
  Effect.flatMap(Effect.log),
52
72
  Effect.runPromise
53
73
  )
@@ -55,12 +75,7 @@ await makeNanoId.pipe(
55
75
 
56
76
  // Generate a ULID
57
77
  await makeUlid.pipe(
58
- Effect.provide([
59
- GetRandomValues.CryptoRandom,
60
- // GetRandomValues.PseudoRandom,
61
- DateTimes.Default
62
- // DateTimes.Fixed(new Date(0))
63
- ]),
78
+ Effect.provide([GetRandomValues.CryptoRandom, DateTimes.Default]),
64
79
  Effect.flatMap(Effect.log),
65
80
  Effect.runPromise
66
81
  )
@@ -71,7 +86,18 @@ await makeUlid.pipe(
71
86
 
72
87
  ### UUID
73
88
 
74
- - `makeUuid`: Generates a v4 UUID
89
+ - `makeUuid4`: Generates a v4 UUID (random)
90
+ - `makeUuid5`: Generates a v5 UUID (SHA-1 hash of namespace + name)
91
+ - `makeUuid6`: Generates a v6 UUID (reordered time-based for better sorting)
92
+ - `makeUuid7`: Generates a v7 UUID (time-sortable)
93
+
94
+ ### UUID v5 Namespaces
95
+
96
+ Pre-defined namespaces for UUID v5 generation:
97
+ - `Uuid5Namespace.DNS`: For DNS-based UUIDs
98
+ - `Uuid5Namespace.URL`: For URL-based UUIDs
99
+ - `Uuid5Namespace.OID`: For OID-based UUIDs
100
+ - `Uuid5Namespace.X500`: For X.500 DN-based UUIDs
75
101
 
76
102
  ### NanoID
77
103
 
package/src/Uuid5.ts ADDED
@@ -0,0 +1,77 @@
1
+ import * as Effect from 'effect/Effect'
2
+ import { Layer, Schema } from 'effect'
3
+ import { uuidStringify } from './UuidStringify.js'
4
+
5
+ export const Uuid5 = Schema.UUID.pipe(Schema.brand('@typed/id/UUID5'))
6
+ export type Uuid5 = Schema.Schema.Type<typeof Uuid5>
7
+
8
+ export const isUuid5: (value: string) => value is Uuid5 = Schema.is(Uuid5)
9
+
10
+ export class Sha1 extends Effect.Tag('Sha1')<
11
+ Sha1,
12
+ {
13
+ readonly hash: (data: Uint8Array) => Effect.Effect<Uint8Array, never>
14
+ }
15
+ >() {
16
+ static readonly Default = Layer.succeed(this, {
17
+ hash: (data: Uint8Array) =>
18
+ Effect.promise(() =>
19
+ crypto.subtle.digest('SHA-1', data).then((hash) => new Uint8Array(hash)),
20
+ ),
21
+ })
22
+ }
23
+
24
+ export type Uuid5Namespace = Uint8Array
25
+
26
+ const textEncoder = new TextEncoder()
27
+
28
+ // Pre-defined namespaces from RFC 4122
29
+ export const Uuid5Namespace = {
30
+ DNS: new Uint8Array([
31
+ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
32
+ ]),
33
+
34
+ URL: new Uint8Array([
35
+ 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
36
+ ]),
37
+
38
+ OID: new Uint8Array([
39
+ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
40
+ ]),
41
+
42
+ X500: new Uint8Array([
43
+ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
44
+ ]),
45
+ } as const
46
+
47
+ export function makeUuid5(
48
+ namespace: Uuid5Namespace,
49
+ name: string,
50
+ ): Effect.Effect<Uuid5, never, Sha1> {
51
+ return Effect.gen(function* () {
52
+ const sha1 = yield* Sha1
53
+
54
+ // Convert name to UTF-8 bytes
55
+ const nameBytes = textEncoder.encode(name)
56
+
57
+ // Concatenate namespace and name
58
+ const buffer = new Uint8Array(namespace.length + nameBytes.length)
59
+ buffer.set(namespace)
60
+ buffer.set(nameBytes, namespace.length)
61
+
62
+ // Hash the concatenated bytes
63
+ const hash = yield* sha1.hash(buffer)
64
+
65
+ // Format as UUID v5
66
+ const result = new Uint8Array(16)
67
+
68
+ // Copy first 16 bytes of the hash
69
+ result.set(hash.subarray(0, 16))
70
+
71
+ // Set version (5) and variant bits
72
+ result[6] = (result[6] & 0x0f) | 0x50 // version 5
73
+ result[8] = (result[8] & 0x3f) | 0x80 // variant 1
74
+
75
+ return uuidStringify(result) as Uuid5
76
+ })
77
+ }
package/src/id.test.ts CHANGED
@@ -4,11 +4,18 @@ import {
4
4
  DateTimes,
5
5
  GetRandomValues,
6
6
  isUuid4,
7
+ isUuid5,
8
+ isUuid6,
7
9
  isUuid7,
8
10
  makeNanoId,
9
11
  makeUlid,
10
12
  makeUuid4,
13
+ makeUuid5,
14
+ makeUuid6,
11
15
  makeUuid7,
16
+ Sha1,
17
+ Uuid5Namespace,
18
+ Uuid6State,
12
19
  Uuid7State,
13
20
  } from './index.js'
14
21
 
@@ -21,7 +28,8 @@ const makeTestValues = (length: number) => {
21
28
  }
22
29
 
23
30
  const provideTestValues = flow(
24
- Effect.provide(Uuid7State.Default),
31
+ Effect.provide([Uuid7State.Default, Uuid6State.Default]),
32
+ Effect.provide(Sha1.Default),
25
33
  Effect.provide([
26
34
  GetRandomValues.layer((length) => Effect.succeed(makeTestValues(length))),
27
35
  DateTimes.Fixed(new Date(0)),
@@ -40,6 +48,28 @@ describe(__filename, () => {
40
48
  )
41
49
  })
42
50
 
51
+ describe('Uuid5', () => {
52
+ it.effect('generates a UUID v5', () =>
53
+ Effect.gen(function* (_) {
54
+ const id = yield* _(makeUuid5(Uuid5Namespace.DNS, 'example.com'))
55
+ expect(id).toMatchInlineSnapshot(`"cfbff0d1-9375-5685-968c-48ce8b15ae17"`)
56
+ expect(id.length).toEqual(36)
57
+ expect(isUuid5(id)).toEqual(true)
58
+ }).pipe(provideTestValues),
59
+ )
60
+ })
61
+
62
+ describe('Uuid6', () => {
63
+ it.effect('generates a UUID v6', () =>
64
+ Effect.gen(function* (_) {
65
+ const id = yield* _(makeUuid6)
66
+ expect(id).toMatchInlineSnapshot(`"1b21dd21-3814-6000-8809-0b0b0c0d0e0f"`)
67
+ expect(id.length).toEqual(36)
68
+ expect(isUuid6(id)).toEqual(true)
69
+ }).pipe(provideTestValues),
70
+ )
71
+ })
72
+
43
73
  describe('Uuid7', () => {
44
74
  it.effect('generates a UUID v7', () =>
45
75
  Effect.gen(function* (_) {
package/src/index.ts CHANGED
@@ -3,4 +3,5 @@ export * from './GetRandomValues.js'
3
3
  export * from './NanoId.js'
4
4
  export * from './Ulid.js'
5
5
  export * from './Uuid4.js'
6
+ export * from './Uuid5.js'
6
7
  export * from './Uuid7.js'