@typed/id 0.15.0 → 0.17.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.
package/dist/Cuid.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { Effect, Layer, Schema } from 'effect';
2
+ import { DateTimes } from './DateTimes.js';
3
+ import { GetRandomValues } from './GetRandomValues.js';
4
+ export declare const Cuid: Schema.brand<Schema.filter<Schema.Schema<string, string, never>>, "@typed/id/CUID">;
5
+ export type Cuid = Schema.Schema.Type<typeof Cuid>;
6
+ export declare const isCuid: (value: string) => value is Cuid;
7
+ export type CuidSeed = {
8
+ readonly timestamp: number;
9
+ readonly counter: number;
10
+ readonly random: Uint8Array;
11
+ readonly fingerprint: string;
12
+ };
13
+ declare const CuidState_base: import("effect/Context").TagClass<CuidState, "CuidState", {
14
+ readonly next: Effect.Effect<CuidSeed>;
15
+ }> & Effect.Tag.Proxy<CuidState, {
16
+ readonly next: Effect.Effect<CuidSeed>;
17
+ }> & {
18
+ use: <X>(body: (_: {
19
+ readonly next: Effect.Effect<CuidSeed>;
20
+ }) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, R | CuidState> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, import("effect/Cause").UnknownException, CuidState> : Effect.Effect<X, never, CuidState>;
21
+ };
22
+ export declare class CuidState extends CuidState_base {
23
+ static readonly layer: (envData: string) => Layer.Layer<CuidState, never, DateTimes | GetRandomValues>;
24
+ static readonly Default: Layer.Layer<CuidState, never, DateTimes | GetRandomValues>;
25
+ }
26
+ export declare const makeCuid: Effect.Effect<Cuid, never, DateTimes | GetRandomValues | CuidState>;
27
+ export {};
package/dist/Cuid.js ADDED
@@ -0,0 +1,86 @@
1
+ import { Effect, Layer, Schema } from 'effect';
2
+ import { DateTimes } from './DateTimes.js';
3
+ import { GetRandomValues } from './GetRandomValues.js';
4
+ // Constants
5
+ const DEFAULT_LENGTH = 24;
6
+ const BIG_LENGTH = 32;
7
+ const INITIAL_COUNT_MAX = 476782367;
8
+ // Schema
9
+ export const Cuid = Schema.String.pipe(Schema.pattern(/^[a-z][0-9a-z]+$/), Schema.brand('@typed/id/CUID'));
10
+ export const isCuid = Schema.is(Cuid);
11
+ // Utilities
12
+ const ALPHABET = Array.from({ length: 26 }, (_, i) => String.fromCharCode(i + 97));
13
+ const encoder = new TextEncoder();
14
+ function createEntropy(length, random) {
15
+ let entropy = '';
16
+ let offset = 0;
17
+ while (entropy.length < length) {
18
+ const value = random[offset];
19
+ entropy += Math.floor(value % 36).toString(36);
20
+ offset = (offset + 1) % random.length;
21
+ }
22
+ return entropy;
23
+ }
24
+ function hash(input) {
25
+ // Convert string to bytes
26
+ const data = encoder.encode(input);
27
+ // Create a hash using the Web Crypto API
28
+ return crypto.subtle.digest('SHA-512', data).then((buffer) => {
29
+ const view = new Uint8Array(buffer);
30
+ let value = 0n;
31
+ for (const byte of view) {
32
+ value = (value << 8n) + BigInt(byte);
33
+ }
34
+ // Drop the first character because it will bias the histogram to the left
35
+ return value.toString(36).slice(1);
36
+ });
37
+ }
38
+ // State Management
39
+ export class CuidState extends Effect.Tag('CuidState')() {
40
+ static layer = (envData) => Layer.effect(this, Effect.gen(function* () {
41
+ const { now } = yield* DateTimes;
42
+ const getRandomValues = yield* GetRandomValues;
43
+ const initialBytes = yield* getRandomValues(4);
44
+ const initialValue = Math.abs((initialBytes[0] << 24) |
45
+ (initialBytes[1] << 16) |
46
+ (initialBytes[2] << 8) |
47
+ initialBytes[3]) % INITIAL_COUNT_MAX;
48
+ // Create fingerprint from environment data
49
+ const fingerprint = yield* Effect.promise(() => hash(envData).then((h) => h.substring(0, BIG_LENGTH)));
50
+ let counter = initialValue;
51
+ return {
52
+ next: Effect.gen(function* () {
53
+ const timestamp = yield* now;
54
+ const random = yield* getRandomValues(32);
55
+ return {
56
+ timestamp,
57
+ counter: counter++,
58
+ random,
59
+ fingerprint,
60
+ };
61
+ }),
62
+ };
63
+ }));
64
+ static Default = this.layer('node');
65
+ }
66
+ // Core Functions
67
+ function cuidFromSeed({ timestamp, counter, random, fingerprint }) {
68
+ return Effect.gen(function* () {
69
+ // First letter is always a random lowercase letter from the seed
70
+ const firstLetter = ALPHABET[random[0] % ALPHABET.length];
71
+ // Convert components to base36
72
+ const time = timestamp.toString(36);
73
+ const count = counter.toString(36);
74
+ // Create entropy from remaining random bytes
75
+ const salt = createEntropy(4, random.slice(1));
76
+ // Hash all components together
77
+ const hashInput = `${time}${salt}${count}${fingerprint}`;
78
+ const hashed = yield* Effect.promise(() => hash(hashInput));
79
+ // Construct the final CUID
80
+ const id = `${firstLetter}${hashed.substring(0, DEFAULT_LENGTH - 1)}`;
81
+ return Cuid.make(id);
82
+ });
83
+ }
84
+ // Public API
85
+ export const makeCuid = Effect.flatMap(CuidState.next, cuidFromSeed);
86
+ //# sourceMappingURL=Cuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cuid.js","sourceRoot":"","sources":["../src/Cuid.ts"],"names":[],"mappings":"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"}
package/dist/DateTimes.js CHANGED
@@ -7,10 +7,11 @@ export class DateTimes extends Effect.Tag('DateTimes')() {
7
7
  static Default = this.make(Effect.clockWith((clock) => clock.currentTimeMillis));
8
8
  static Fixed = (base) => Layer.effect(DateTimes, Effect.gen(function* () {
9
9
  const clock = yield* Effect.clock;
10
+ const baseN = BigInt(base.getTime());
10
11
  const startMillis = yield* clock.currentTimeMillis;
11
12
  const now = clock.currentTimeMillis.pipe(Effect.map((millis) =>
12
13
  // Use BigInt to avoid floating point precision issues which can break deterministic testing
13
- Number(BigInt(base.getTime()) + BigInt(millis) - BigInt(startMillis))));
14
+ Number(baseN + BigInt(millis) - BigInt(startMillis))));
14
15
  return {
15
16
  now,
16
17
  date: now.pipe(Effect.map((millis) => new Date(millis))),
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimes.js","sourceRoot":"","sources":["../src/DateTimes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAqB,MAAM,QAAQ,CAAA;AAEzD,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAMnD;IACD,MAAM,CAAU,IAAI,GAAG,CAAC,GAA0B,EAA0B,EAAE,CAC5E,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;QAClB,GAAG;QACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;KACzD,CAAC,CAAA;IAEJ,MAAM,CAAU,OAAO,GAA2B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEjH,MAAM,CAAU,KAAK,GAAG,CAAC,IAAU,EAA0B,EAAE,CAC7D,KAAK,CAAC,MAAM,CACV,SAAS,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CACtC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACpB,4FAA4F;QAC5F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CACtE,CACF,CAAA;QAED,OAAO;YACL,GAAG;YACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;SACzD,CAAA;IACH,CAAC,CAAC,CACH,CAAA"}
1
+ {"version":3,"file":"DateTimes.js","sourceRoot":"","sources":["../src/DateTimes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAqB,MAAM,QAAQ,CAAA;AAEzD,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,EAMnD;IACD,MAAM,CAAU,IAAI,GAAG,CAAC,GAA0B,EAA0B,EAAE,CAC5E,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;QAClB,GAAG;QACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;KACzD,CAAC,CAAA;IAEJ,MAAM,CAAU,OAAO,GAA2B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEjH,MAAM,CAAU,KAAK,GAAG,CAAC,IAAU,EAA0B,EAAE,CAC7D,KAAK,CAAC,MAAM,CACV,SAAS,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CACtC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACpB,4FAA4F;QAC5F,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CACrD,CACF,CAAA;QAED,OAAO;YACL,GAAG;YACH,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;SACzD,CAAA;IACH,CAAC,CAAC,CACH,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { Effect, Schema } from 'effect';
2
+ import { DateTimes } from './DateTimes.js';
3
+ import { GetRandomValues } from './GetRandomValues.js';
4
+ export declare const Ksuid: Schema.brand<Schema.filter<Schema.Schema<string, string, never>>, "@typed/id/KSUID">;
5
+ export type Ksuid = Schema.Schema.Type<typeof Ksuid>;
6
+ export declare const isKsuid: (value: string) => value is Ksuid;
7
+ export declare const makeKsuid: Effect.Effect<Ksuid, never, DateTimes | GetRandomValues>;
package/dist/Ksuid.js ADDED
@@ -0,0 +1,56 @@
1
+ import { Effect, Schema } from 'effect';
2
+ import { DateTimes } from './DateTimes.js';
3
+ import { GetRandomValues } from './GetRandomValues.js';
4
+ // Constants
5
+ const EPOCH = 14e11; // 2014-03-01T00:00:00Z
6
+ const TIMESTAMP_BYTES = 4;
7
+ const PAYLOAD_BYTES = 16;
8
+ const TOTAL_BYTES = TIMESTAMP_BYTES + PAYLOAD_BYTES;
9
+ const STRING_LENGTH = 27;
10
+ // Schema
11
+ export const Ksuid = Schema.String.pipe(Schema.pattern(/^[0-9a-zA-Z]{27}$/), Schema.brand('@typed/id/KSUID'));
12
+ export const isKsuid = Schema.is(Ksuid);
13
+ // Utilities
14
+ const base62Chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
15
+ const base = BigInt(base62Chars.length);
16
+ function base62Encode(bytes) {
17
+ let number = 0n;
18
+ for (const byte of bytes) {
19
+ number = (number << 8n) + BigInt(byte);
20
+ }
21
+ const chars = new Array(STRING_LENGTH);
22
+ let i = chars.length;
23
+ while (i > 0) {
24
+ i--;
25
+ const remainder = Number(number % base);
26
+ chars[i] = base62Chars[remainder];
27
+ number = number / base;
28
+ }
29
+ return chars.join('');
30
+ }
31
+ // Core Functions
32
+ function ksuidFromSeed({ timestamp, payload }) {
33
+ // Create the combined bytes
34
+ const bytes = new Uint8Array(TOTAL_BYTES);
35
+ // Support for timestamps before the epoch, usually for testing
36
+ if (timestamp < EPOCH) {
37
+ timestamp += EPOCH;
38
+ }
39
+ // Write timestamp (4 bytes, big-endian)
40
+ const seconds = Math.floor((timestamp - EPOCH) / 1000);
41
+ bytes[0] = (seconds >>> 24) & 0xff;
42
+ bytes[1] = (seconds >>> 16) & 0xff;
43
+ bytes[2] = (seconds >>> 8) & 0xff;
44
+ bytes[3] = seconds & 0xff;
45
+ // Copy payload
46
+ bytes.set(payload, TIMESTAMP_BYTES);
47
+ // Encode as base62
48
+ return Ksuid.make(base62Encode(bytes));
49
+ }
50
+ // Public API
51
+ export const makeKsuid = Effect.gen(function* () {
52
+ const timestamp = yield* DateTimes.now;
53
+ const payload = yield* GetRandomValues.apply(PAYLOAD_BYTES);
54
+ return ksuidFromSeed({ timestamp, payload });
55
+ });
56
+ //# sourceMappingURL=Ksuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ksuid.js","sourceRoot":"","sources":["../src/Ksuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,YAAY;AACZ,MAAM,KAAK,GAAG,KAAK,CAAA,CAAC,uBAAuB;AAC3C,MAAM,eAAe,GAAG,CAAC,CAAA;AACzB,MAAM,aAAa,GAAG,EAAE,CAAA;AACxB,MAAM,WAAW,GAAG,eAAe,GAAG,aAAa,CAAA;AACnD,MAAM,aAAa,GAAG,EAAE,CAAA;AAExB,SAAS;AACT,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CACrC,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EACnC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAChC,CAAA;AAGD,MAAM,CAAC,MAAM,OAAO,GAAsC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;AAQ1E,YAAY;AACZ,MAAM,WAAW,GAAG,gEAAgE,CAAA;AACpF,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;AAEvC,SAAS,YAAY,CAAC,KAAiB;IACrC,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,KAAK,GAAa,IAAI,KAAK,CAAC,aAAa,CAAC,CAAA;IAChD,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAA;IAEpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,CAAC,EAAE,CAAA;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;QACjC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACxB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACvB,CAAC;AAED,iBAAiB;AACjB,SAAS,aAAa,CAAC,EAAE,SAAS,EAAE,OAAO,EAAa;IACtD,4BAA4B;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAA;IAEzC,+DAA+D;IAC/D,IAAI,SAAS,GAAG,KAAK,EAAE,CAAC;QACtB,SAAS,IAAI,KAAK,CAAA;IACpB,CAAC;IAED,wCAAwC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;IACtD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;IACjC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAA;IAEzB,eAAe;IACf,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAEnC,mBAAmB;IACnB,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,aAAa;AACb,MAAM,CAAC,MAAM,SAAS,GAA6D,MAAM,CAAC,GAAG,CAC3F,QAAQ,CAAC;IACP,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,CAAA;IACtC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IAC3D,OAAO,aAAa,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;AAC9C,CAAC,CACF,CAAA"}
package/dist/Uuid4.js CHANGED
@@ -9,6 +9,6 @@ function uuid4FromSeed(seed) {
9
9
  // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
10
10
  seed[6] = (seed[6] & 0x0f) | 0x40;
11
11
  seed[8] = (seed[8] & 0x3f) | 0x80;
12
- return uuidStringify(seed);
12
+ return Uuid4.make(uuidStringify(seed));
13
13
  }
14
14
  //# sourceMappingURL=Uuid4.js.map
package/dist/Uuid4.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid4.js","sourceRoot":"","sources":["../src/Uuid4.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAGtE,MAAM,CAAC,MAAM,OAAO,GAAsC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;AAE1E,MAAM,CAAC,MAAM,SAAS,GAAiD,MAAM,CAAC,GAAG,CAC/E,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,EACzB,aAAa,CACd,CAAA;AAED,SAAS,aAAa,CAAC,IAAgB;IACrC,gEAAgE;IAChE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;IACjC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;IAEjC,OAAO,aAAa,CAAC,IAAI,CAAU,CAAA;AACrC,CAAC"}
1
+ {"version":3,"file":"Uuid4.js","sourceRoot":"","sources":["../src/Uuid4.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAGtE,MAAM,CAAC,MAAM,OAAO,GAAsC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;AAE1E,MAAM,CAAC,MAAM,SAAS,GAAiD,MAAM,CAAC,GAAG,CAC/E,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,EACzB,aAAa,CACd,CAAA;AAED,SAAS,aAAa,CAAC,IAAgB;IACrC,gEAAgE;IAChE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;IACjC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;IAEjC,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;AACxC,CAAC"}
package/dist/Uuid5.js CHANGED
@@ -42,7 +42,7 @@ export function makeUuid5(namespace, name) {
42
42
  // Set version (5) and variant bits
43
43
  result[6] = (result[6] & 0x0f) | 0x50; // version 5
44
44
  result[8] = (result[8] & 0x3f) | 0x80; // variant 1
45
- return uuidStringify(result);
45
+ return Uuid5.make(uuidStringify(result));
46
46
  });
47
47
  }
48
48
  //# sourceMappingURL=Uuid5.js.map
package/dist/Uuid5.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid5.js","sourceRoot":"","sources":["../src/Uuid5.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Uuid5.js","sourceRoot":"","sources":["../src/Uuid5.ts"],"names":[],"mappings":"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"}
package/dist/Uuid7.js CHANGED
@@ -66,6 +66,6 @@ function uuid7FromSeed({ timestamp, seq, randomBytes }) {
66
66
  result[13] = randomBytes[13];
67
67
  result[14] = randomBytes[14];
68
68
  result[15] = randomBytes[15];
69
- return uuidStringify(result);
69
+ return Uuid7.make(uuidStringify(result));
70
70
  }
71
71
  //# sourceMappingURL=Uuid7.js.map
package/dist/Uuid7.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Uuid7.js","sourceRoot":"","sources":["../src/Uuid7.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Uuid7.js","sourceRoot":"","sources":["../src/Uuid7.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ export * from './Cuid.js';
1
2
  export * from './DateTimes.js';
2
3
  export * from './GetRandomValues.js';
4
+ export * from './Ksuid.js';
3
5
  export * from './NanoId.js';
4
6
  export * from './Ulid.js';
5
7
  export * from './Uuid4.js';
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
+ export * from './Cuid.js';
1
2
  export * from './DateTimes.js';
2
3
  export * from './GetRandomValues.js';
4
+ export * from './Ksuid.js';
3
5
  export * from './NanoId.js';
4
6
  export * from './Ulid.js';
5
7
  export * from './Uuid4.js';
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;AAC1B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,YAAY,CAAA;AAC1B,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.15.0",
3
+ "version": "0.17.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
@@ -1,6 +1,6 @@
1
1
  # @typed/id
2
2
 
3
- A TypeScript library providing common ID format generation using [Effect](https://effect.website/). This package includes implementations for UUID, NanoID, and ULID generation with a focus on type safety and functional programming principles.
3
+ A TypeScript library providing common ID format generation using [Effect](https://effect.website/). This package includes implementations for UUID, NanoID, ULID, CUID2, and KSUID generation with a focus on type safety and functional programming principles.
4
4
 
5
5
  ## Installation
6
6
 
@@ -17,9 +17,11 @@ 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, v5, v6, v7)
20
+ - UUID (v4, v5, v7)
21
21
  - NanoID
22
22
  - ULID
23
+ - CUID2
24
+ - KSUID
23
25
  - ⚡ Efficient and secure random value generation
24
26
  - 📦 Zero dependencies (except Effect)
25
27
 
@@ -37,7 +39,10 @@ import {
37
39
  Uuid5Namespace,
38
40
  Sha1,
39
41
  makeNanoId,
40
- makeUlid
42
+ makeUlid,
43
+ makeCuid,
44
+ CuidState,
45
+ makeKsuid,
41
46
  } from '@typed/id'
42
47
 
43
48
  // Generate a UUID v4 (random)
@@ -80,6 +85,23 @@ await makeUlid.pipe(
80
85
  Effect.runPromise
81
86
  )
82
87
  // Output: "01ARZ3NDEKTSV4RRFFQ69G5FAV"
88
+
89
+ // Generate a CUID
90
+ await makeCuid.pipe(
91
+ Effect.provide(CuidState.layer('my-environment')), // Provide environment fingerprint
92
+ Effect.provide([GetRandomValues.CryptoRandom, DateTimes.Default]),
93
+ Effect.flatMap(Effect.log),
94
+ Effect.runPromise
95
+ )
96
+ // Output: "clh3aqnd900003b64zpka3df"
97
+
98
+ // Generate a KSUID
99
+ await makeKsuid.pipe(
100
+ Effect.provide([GetRandomValues.CryptoRandom, DateTimes.Default]),
101
+ Effect.flatMap(Effect.log),
102
+ Effect.runPromise
103
+ )
104
+ // Output: "1jIGxyVFPeR4GkCcDPQU2bXhxy9"
83
105
  ```
84
106
 
85
107
  ## API
@@ -88,7 +110,6 @@ await makeUlid.pipe(
88
110
 
89
111
  - `makeUuid4`: Generates a v4 UUID (random)
90
112
  - `makeUuid5`: Generates a v5 UUID (SHA-1 hash of namespace + name)
91
- - `makeUuid6`: Generates a v6 UUID (reordered time-based for better sorting)
92
113
  - `makeUuid7`: Generates a v7 UUID (time-sortable)
93
114
 
94
115
  ### UUID v5 Namespaces
@@ -107,6 +128,36 @@ Pre-defined namespaces for UUID v5 generation:
107
128
 
108
129
  - `makeUlid`: Generates a ULID (Universally Unique Lexicographically Sortable Identifier)
109
130
 
131
+ ### CUID
132
+
133
+ - `makeCuid`: Generates a CUID2 (Collision-resistant Unique IDentifier)
134
+ - `CuidState.layer(envData)`: Creates a CUID state layer with environment fingerprint
135
+ - `envData`: A string identifying the environment (e.g., 'browser', 'node', 'mobile-ios')
136
+ - Used to help prevent collisions in distributed systems
137
+ - Cached and reused for efficiency
138
+ - Format: 24 characters, starting with a lowercase letter, followed by numbers and lowercase letters
139
+ - Properties:
140
+ - Sequential for database performance
141
+ - Secure from enumeration
142
+ - URL-safe
143
+ - Horizontally scalable
144
+ - Includes timestamp for time-based sorting
145
+
146
+ ### KSUID
147
+
148
+ - `makeKsuid`: Generates a KSUID (K-Sortable Unique IDentifier)
149
+ - Format: 27 characters of base62 (0-9A-Za-z)
150
+ - Components:
151
+ - 32-bit timestamp (seconds since 2014-03-01)
152
+ - 128-bit random payload
153
+ - Properties:
154
+ - Time-sortable (lexicographically ordered by time)
155
+ - URL-safe (base62 encoded)
156
+ - Includes entropy for uniqueness
157
+ - Fixed size (27 characters)
158
+ - ~136 years of timestamp space from 2014
159
+ - No special character dependencies
160
+
110
161
  ## License
111
162
 
112
163
  MIT
package/src/Cuid.ts ADDED
@@ -0,0 +1,135 @@
1
+ import { Effect, Layer, Schema } from 'effect'
2
+ import { DateTimes } from './DateTimes.js'
3
+ import { GetRandomValues } from './GetRandomValues.js'
4
+
5
+ // Constants
6
+ const DEFAULT_LENGTH = 24
7
+ const BIG_LENGTH = 32
8
+ const INITIAL_COUNT_MAX = 476782367
9
+
10
+ // Schema
11
+ export const Cuid = Schema.String.pipe(
12
+ Schema.pattern(/^[a-z][0-9a-z]+$/),
13
+ Schema.brand('@typed/id/CUID'),
14
+ )
15
+ export type Cuid = Schema.Schema.Type<typeof Cuid>
16
+
17
+ export const isCuid: (value: string) => value is Cuid = Schema.is(Cuid)
18
+
19
+ // Types
20
+ export type CuidSeed = {
21
+ readonly timestamp: number
22
+ readonly counter: number
23
+ readonly random: Uint8Array
24
+ readonly fingerprint: string
25
+ }
26
+
27
+ // Utilities
28
+ const ALPHABET = Array.from({ length: 26 }, (_, i) => String.fromCharCode(i + 97))
29
+ const encoder = new TextEncoder()
30
+
31
+ function createEntropy(length: number, random: Uint8Array): string {
32
+ let entropy = ''
33
+ let offset = 0
34
+
35
+ while (entropy.length < length) {
36
+ const value = random[offset]
37
+ entropy += Math.floor(value % 36).toString(36)
38
+ offset = (offset + 1) % random.length
39
+ }
40
+
41
+ return entropy
42
+ }
43
+
44
+ function hash(input: string): Promise<string> {
45
+ // Convert string to bytes
46
+ const data = encoder.encode(input)
47
+
48
+ // Create a hash using the Web Crypto API
49
+ return crypto.subtle.digest('SHA-512', data).then((buffer) => {
50
+ const view = new Uint8Array(buffer)
51
+ let value = 0n
52
+ for (const byte of view) {
53
+ value = (value << 8n) + BigInt(byte)
54
+ }
55
+ // Drop the first character because it will bias the histogram to the left
56
+ return value.toString(36).slice(1)
57
+ })
58
+ }
59
+
60
+ // State Management
61
+ export class CuidState extends Effect.Tag('CuidState')<
62
+ CuidState,
63
+ {
64
+ readonly next: Effect.Effect<CuidSeed>
65
+ }
66
+ >() {
67
+ static readonly layer = (
68
+ envData: string,
69
+ ): Layer.Layer<CuidState, never, DateTimes | GetRandomValues> =>
70
+ Layer.effect(
71
+ this,
72
+ Effect.gen(function* () {
73
+ const { now } = yield* DateTimes
74
+ const getRandomValues = yield* GetRandomValues
75
+ const initialBytes = yield* getRandomValues(4)
76
+ const initialValue =
77
+ Math.abs(
78
+ (initialBytes[0] << 24) |
79
+ (initialBytes[1] << 16) |
80
+ (initialBytes[2] << 8) |
81
+ initialBytes[3],
82
+ ) % INITIAL_COUNT_MAX
83
+
84
+ // Create fingerprint from environment data
85
+ const fingerprint = yield* Effect.promise(() =>
86
+ hash(envData).then((h) => h.substring(0, BIG_LENGTH)),
87
+ )
88
+
89
+ let counter = initialValue
90
+
91
+ return {
92
+ next: Effect.gen(function* () {
93
+ const timestamp = yield* now
94
+ const random = yield* getRandomValues(32)
95
+ return {
96
+ timestamp,
97
+ counter: counter++,
98
+ random,
99
+ fingerprint,
100
+ }
101
+ }),
102
+ }
103
+ }),
104
+ )
105
+
106
+ static readonly Default = this.layer('node')
107
+ }
108
+
109
+ // Core Functions
110
+ function cuidFromSeed({ timestamp, counter, random, fingerprint }: CuidSeed): Effect.Effect<Cuid> {
111
+ return Effect.gen(function* () {
112
+ // First letter is always a random lowercase letter from the seed
113
+ const firstLetter = ALPHABET[random[0] % ALPHABET.length]
114
+
115
+ // Convert components to base36
116
+ const time = timestamp.toString(36)
117
+ const count = counter.toString(36)
118
+
119
+ // Create entropy from remaining random bytes
120
+ const salt = createEntropy(4, random.slice(1))
121
+
122
+ // Hash all components together
123
+ const hashInput = `${time}${salt}${count}${fingerprint}`
124
+ const hashed = yield* Effect.promise(() => hash(hashInput))
125
+
126
+ // Construct the final CUID
127
+ const id = `${firstLetter}${hashed.substring(0, DEFAULT_LENGTH - 1)}`
128
+
129
+ return Cuid.make(id)
130
+ })
131
+ }
132
+
133
+ // Public API
134
+ export const makeCuid: Effect.Effect<Cuid, never, DateTimes | GetRandomValues | CuidState> =
135
+ Effect.flatMap(CuidState.next, cuidFromSeed)
package/src/DateTimes.ts CHANGED
@@ -20,11 +20,12 @@ export class DateTimes extends Effect.Tag('DateTimes')<
20
20
  DateTimes,
21
21
  Effect.gen(function* () {
22
22
  const clock = yield* Effect.clock
23
+ const baseN = BigInt(base.getTime())
23
24
  const startMillis = yield* clock.currentTimeMillis
24
25
  const now = clock.currentTimeMillis.pipe(
25
26
  Effect.map((millis) =>
26
27
  // Use BigInt to avoid floating point precision issues which can break deterministic testing
27
- Number(BigInt(base.getTime()) + BigInt(millis) - BigInt(startMillis)),
28
+ Number(baseN + BigInt(millis) - BigInt(startMillis)),
28
29
  ),
29
30
  )
30
31
 
@@ -35,3 +36,4 @@ export class DateTimes extends Effect.Tag('DateTimes')<
35
36
  }),
36
37
  )
37
38
  }
39
+
package/src/Ksuid.ts ADDED
@@ -0,0 +1,81 @@
1
+ import { Effect, Schema } from 'effect'
2
+ import { DateTimes } from './DateTimes.js'
3
+ import { GetRandomValues } from './GetRandomValues.js'
4
+
5
+ // Constants
6
+ const EPOCH = 14e11 // 2014-03-01T00:00:00Z
7
+ const TIMESTAMP_BYTES = 4
8
+ const PAYLOAD_BYTES = 16
9
+ const TOTAL_BYTES = TIMESTAMP_BYTES + PAYLOAD_BYTES
10
+ const STRING_LENGTH = 27
11
+
12
+ // Schema
13
+ export const Ksuid = Schema.String.pipe(
14
+ Schema.pattern(/^[0-9a-zA-Z]{27}$/),
15
+ Schema.brand('@typed/id/KSUID'),
16
+ )
17
+ export type Ksuid = Schema.Schema.Type<typeof Ksuid>
18
+
19
+ export const isKsuid: (value: string) => value is Ksuid = Schema.is(Ksuid)
20
+
21
+ // Types
22
+ type KsuidSeed = {
23
+ readonly timestamp: number
24
+ readonly payload: Uint8Array
25
+ }
26
+
27
+ // Utilities
28
+ const base62Chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
29
+ const base = BigInt(base62Chars.length)
30
+
31
+ function base62Encode(bytes: Uint8Array): string {
32
+ let number = 0n
33
+ for (const byte of bytes) {
34
+ number = (number << 8n) + BigInt(byte)
35
+ }
36
+
37
+ const chars: string[] = new Array(STRING_LENGTH)
38
+ let i = chars.length
39
+
40
+ while (i > 0) {
41
+ i--
42
+ const remainder = Number(number % base)
43
+ chars[i] = base62Chars[remainder]
44
+ number = number / base
45
+ }
46
+
47
+ return chars.join('')
48
+ }
49
+
50
+ // Core Functions
51
+ function ksuidFromSeed({ timestamp, payload }: KsuidSeed): Ksuid {
52
+ // Create the combined bytes
53
+ const bytes = new Uint8Array(TOTAL_BYTES)
54
+
55
+ // Support for timestamps before the epoch, usually for testing
56
+ if (timestamp < EPOCH) {
57
+ timestamp += EPOCH
58
+ }
59
+
60
+ // Write timestamp (4 bytes, big-endian)
61
+ const seconds = Math.floor((timestamp - EPOCH) / 1000)
62
+ bytes[0] = (seconds >>> 24) & 0xff
63
+ bytes[1] = (seconds >>> 16) & 0xff
64
+ bytes[2] = (seconds >>> 8) & 0xff
65
+ bytes[3] = seconds & 0xff
66
+
67
+ // Copy payload
68
+ bytes.set(payload, TIMESTAMP_BYTES)
69
+
70
+ // Encode as base62
71
+ return Ksuid.make(base62Encode(bytes))
72
+ }
73
+
74
+ // Public API
75
+ export const makeKsuid: Effect.Effect<Ksuid, never, DateTimes | GetRandomValues> = Effect.gen(
76
+ function* () {
77
+ const timestamp = yield* DateTimes.now
78
+ const payload = yield* GetRandomValues.apply(PAYLOAD_BYTES)
79
+ return ksuidFromSeed({ timestamp, payload })
80
+ },
81
+ )
package/src/Uuid4.ts CHANGED
@@ -18,5 +18,5 @@ function uuid4FromSeed(seed: Uint8Array): Uuid4 {
18
18
  seed[6] = (seed[6] & 0x0f) | 0x40
19
19
  seed[8] = (seed[8] & 0x3f) | 0x80
20
20
 
21
- return uuidStringify(seed) as Uuid4
21
+ return Uuid4.make(uuidStringify(seed))
22
22
  }
package/src/Uuid5.ts CHANGED
@@ -72,6 +72,6 @@ export function makeUuid5(
72
72
  result[6] = (result[6] & 0x0f) | 0x50 // version 5
73
73
  result[8] = (result[8] & 0x3f) | 0x80 // variant 1
74
74
 
75
- return uuidStringify(result) as Uuid5
75
+ return Uuid5.make(uuidStringify(result))
76
76
  })
77
77
  }
package/src/Uuid7.ts CHANGED
@@ -100,5 +100,5 @@ function uuid7FromSeed({ timestamp, seq, randomBytes }: Uuid7Seed): Uuid7 {
100
100
  result[14] = randomBytes[14]
101
101
  result[15] = randomBytes[15]
102
102
 
103
- return uuidStringify(result) as Uuid7
103
+ return Uuid7.make(uuidStringify(result))
104
104
  }
package/src/id.test.ts CHANGED
@@ -1,46 +1,48 @@
1
1
  import { describe, expect, it } from '@effect/vitest'
2
- import { Effect, flow } from 'effect'
2
+ import { Effect, flow, TestClock } from 'effect'
3
3
  import {
4
4
  DateTimes,
5
5
  GetRandomValues,
6
6
  isUuid4,
7
7
  isUuid5,
8
- isUuid6,
9
8
  isUuid7,
10
9
  makeNanoId,
11
10
  makeUlid,
12
11
  makeUuid4,
13
12
  makeUuid5,
14
- makeUuid6,
15
13
  makeUuid7,
16
14
  Sha1,
17
15
  Uuid5Namespace,
18
- Uuid6State,
19
16
  Uuid7State,
17
+ makeCuid,
18
+ isCuid,
19
+ CuidState,
20
+ makeKsuid,
21
+ isKsuid,
20
22
  } from './index.js'
21
23
 
24
+
22
25
  const makeTestValues = (length: number) => {
23
26
  const values = new Uint8Array(length)
24
27
  for (let i = 0; i < length; ++i) {
25
- values[i] = i
28
+ values[i] = i % 256
26
29
  }
27
30
  return values
28
31
  }
29
32
 
30
33
  const provideTestValues = flow(
31
- Effect.provide([Uuid7State.Default, Uuid6State.Default]),
34
+ Effect.provide(CuidState.layer('test')),
35
+ Effect.provide(Uuid7State.Default),
32
36
  Effect.provide(Sha1.Default),
33
- Effect.provide([
34
- GetRandomValues.layer((length) => Effect.succeed(makeTestValues(length))),
35
- DateTimes.Fixed(new Date(0)),
36
- ]),
37
+ Effect.provide(GetRandomValues.layer((length) => Effect.succeed(makeTestValues(length)))),
38
+ Effect.provide(DateTimes.Fixed(new Date(0))),
37
39
  )
38
40
 
39
41
  describe(__filename, () => {
40
42
  describe('Uuid4', () => {
41
43
  it.effect('generates a UUID v4', () =>
42
- Effect.gen(function* (_) {
43
- const id = yield* _(makeUuid4)
44
+ Effect.gen(function* () {
45
+ const id = yield* makeUuid4
44
46
  expect(id).toMatchInlineSnapshot(`"00010203-0405-4607-8809-0a0b0c0d0e0f"`)
45
47
  expect(id.length).toEqual(36)
46
48
  expect(isUuid4(id)).toEqual(true)
@@ -50,8 +52,8 @@ describe(__filename, () => {
50
52
 
51
53
  describe('Uuid5', () => {
52
54
  it.effect('generates a UUID v5', () =>
53
- Effect.gen(function* (_) {
54
- const id = yield* _(makeUuid5(Uuid5Namespace.DNS, 'example.com'))
55
+ Effect.gen(function* () {
56
+ const id = yield* makeUuid5(Uuid5Namespace.DNS, 'example.com')
55
57
  expect(id).toMatchInlineSnapshot(`"cfbff0d1-9375-5685-968c-48ce8b15ae17"`)
56
58
  expect(id.length).toEqual(36)
57
59
  expect(isUuid5(id)).toEqual(true)
@@ -59,21 +61,10 @@ describe(__filename, () => {
59
61
  )
60
62
  })
61
63
 
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
-
73
64
  describe('Uuid7', () => {
74
65
  it.effect('generates a UUID v7', () =>
75
- Effect.gen(function* (_) {
76
- const id = yield* _(makeUuid7)
66
+ Effect.gen(function* () {
67
+ const id = yield* makeUuid7
77
68
  expect(id).toMatchInlineSnapshot(`"00000000-0000-7030-9c20-260b0c0d0e0f"`)
78
69
  expect(id.length).toEqual(36)
79
70
  expect(isUuid7(id)).toEqual(true)
@@ -83,8 +74,8 @@ describe(__filename, () => {
83
74
 
84
75
  describe('NanoId', () => {
85
76
  it.effect('generates a NanoId', () =>
86
- Effect.gen(function* (_) {
87
- const id = yield* _(makeNanoId)
77
+ Effect.gen(function* () {
78
+ const id = yield* makeNanoId
88
79
  expect(id).toMatchInlineSnapshot(`"0123456789abcdefghijk"`)
89
80
  expect(id.length).toEqual(21)
90
81
  }).pipe(provideTestValues),
@@ -93,11 +84,50 @@ describe(__filename, () => {
93
84
 
94
85
  describe('Ulid', () => {
95
86
  it.effect('generates a Ulid', () =>
96
- Effect.gen(function* (_) {
97
- const id = yield* _(makeUlid)
87
+ Effect.gen(function* () {
88
+ const id = yield* makeUlid
98
89
  expect(id).toMatchInlineSnapshot(`"00000000000123456789ABCDEF"`)
99
90
  expect(id.length).toEqual(26)
100
91
  }).pipe(provideTestValues),
101
92
  )
102
93
  })
94
+
95
+ describe('Cuid', () => {
96
+ it.effect('generates a CUID', () =>
97
+ Effect.gen(function* () {
98
+ const id = yield* makeCuid
99
+ expect(id.length).toEqual(24)
100
+ expect(isCuid(id)).toEqual(true)
101
+ expect(id).toMatchInlineSnapshot(`"ai17q5mkkp8w5f2cey3lyzu5"`)
102
+
103
+ // Generate another to ensure uniqueness
104
+ const id2 = yield* makeCuid
105
+ expect(id2).not.toEqual(id)
106
+ expect(isCuid(id2)).toEqual(true)
107
+ expect(id2).toMatchInlineSnapshot(`"abeo5wmlmnjxjrnjiidlfvzp"`)
108
+ }).pipe(provideTestValues),
109
+ )
110
+ })
111
+
112
+ describe('Ksuid', () => {
113
+ it.effect('generates a KSUID', () =>
114
+ Effect.gen(function* () {
115
+ console.log(yield* DateTimes.now)
116
+ const id = yield* makeKsuid
117
+ expect(id.length).toEqual(27)
118
+ expect(isKsuid(id)).toEqual(true)
119
+ expect(id).toMatchInlineSnapshot(`"00000000SYW7RiJxkEgOGusQGwp"`)
120
+
121
+ yield* TestClock.adjust(1000)
122
+
123
+ console.log(yield* DateTimes.now)
124
+
125
+ // Generate another to ensure uniqueness
126
+ const id2 = yield* makeKsuid
127
+ expect(id2).not.toEqual(id)
128
+ expect(isKsuid(id2)).toEqual(true)
129
+ expect(id2).toMatchInlineSnapshot(`"000007n4UlmTXBzjUOTX3nzfyYx"`)
130
+ }).pipe(provideTestValues),
131
+ )
132
+ })
103
133
  })
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
+ export * from './Cuid.js'
1
2
  export * from './DateTimes.js'
2
3
  export * from './GetRandomValues.js'
4
+ export * from './Ksuid.js'
3
5
  export * from './NanoId.js'
4
6
  export * from './Ulid.js'
5
7
  export * from './Uuid4.js'