@uniku/cli 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @uniku/cli
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@uniku/cli.svg)](https://www.npmjs.com/package/@uniku/cli)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Command-line tool for generating, validating, and inspecting unique identifiers.
7
+
8
+ Supports UUID v4/v7, ULID, CUID2, Nanoid, and KSUID.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ # pnpm (recommended)
14
+ pnpm add -g @uniku/cli
15
+
16
+ # npm
17
+ npm install -g @uniku/cli
18
+
19
+ # bun
20
+ bun add -g @uniku/cli
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Generate IDs
26
+
27
+ ```bash
28
+ # UUID v4 (default)
29
+ uniku uuid
30
+ # => 550e8400-e29b-41d4-a716-446655440000
31
+
32
+ # UUID v7 (time-ordered)
33
+ uniku uuid --version 7
34
+ # => 018e5e5c-7c8a-7000-8000-000000000000
35
+
36
+ # Generate multiple IDs
37
+ uniku uuid --count 5
38
+
39
+ # ULID
40
+ uniku ulid
41
+ # => 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
42
+
43
+ # Monotonically increasing ULIDs
44
+ uniku ulid --monotonic --count 3
45
+
46
+ # Nanoid (custom size and alphabet)
47
+ uniku nanoid --size 12 --alphabet hex
48
+
49
+ # CUID2 (custom length)
50
+ uniku cuid --length 16
51
+
52
+ # KSUID
53
+ uniku ksuid
54
+
55
+ # Output as JSON
56
+ uniku uuid --count 3 --json
57
+ ```
58
+
59
+ All generate commands also work under `uniku generate <type>` (e.g., `uniku generate uuid`).
60
+
61
+ ### Validate IDs
62
+
63
+ ```bash
64
+ # Validate a single ID (type auto-detected)
65
+ uniku validate 018e5e5c-7c8a-7000-8000-000000000000
66
+
67
+ # Validate with explicit type
68
+ uniku validate --type ulid 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
69
+
70
+ # Batch validate from stdin
71
+ echo -e "018e5e5c-7c8a-7000-8000-000000000000\ninvalid-id" | uniku validate --stdin
72
+
73
+ # Quiet mode (exit code only: 0 = valid, 2 = invalid)
74
+ uniku validate --quiet 018e5e5c-7c8a-7000-8000-000000000000
75
+
76
+ # JSON output
77
+ uniku validate --json 018e5e5c-7c8a-7000-8000-000000000000
78
+ ```
79
+
80
+ ### Inspect IDs
81
+
82
+ ```bash
83
+ # Decode metadata from an ID (type auto-detected)
84
+ uniku inspect 018e5e5c-7c8a-7000-8000-000000000000
85
+
86
+ # Inspect with explicit type
87
+ uniku inspect --type ulid 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
88
+
89
+ # JSON output
90
+ uniku inspect --json 018e5e5c-7c8a-7000-8000-000000000000
91
+ ```
92
+
93
+ For time-ordered IDs (UUID v7, ULID, KSUID), inspect extracts the embedded timestamp. For random-only IDs (UUID v4, CUID2, Nanoid), it reports that no decodable metadata is available.
94
+
95
+ ## Commands Reference
96
+
97
+ | Command | Description |
98
+ |---------|-------------|
99
+ | `uniku uuid` | Generate UUIDs (v4 or v7) |
100
+ | `uniku ulid` | Generate ULIDs |
101
+ | `uniku nanoid` | Generate Nanoids |
102
+ | `uniku cuid` | Generate CUIDs (v2) |
103
+ | `uniku ksuid` | Generate KSUIDs |
104
+ | `uniku validate <id>` | Check if an ID is valid |
105
+ | `uniku inspect <id>` | Decode and inspect an ID |
106
+
107
+ ### Common Options
108
+
109
+ | Option | Alias | Description |
110
+ |--------|-------|-------------|
111
+ | `--count` | `-n` | Number of IDs to generate (default: 1) |
112
+ | `--json` | | Output as JSON |
113
+ | `--help` | | Show help |
114
+ | `--version` | `-V` | Show version |
115
+
116
+ ### Generator-Specific Options
117
+
118
+ | Command | Option | Alias | Description |
119
+ |---------|--------|-------|-------------|
120
+ | `uuid` | `--version` | `-v` | UUID version: 4 or 7 (default: 4) |
121
+ | `uuid` | `--lowercase` | `-l` | Output in lowercase |
122
+ | `ulid` | `--monotonic` | | Generate monotonically increasing ULIDs |
123
+ | `ulid` | `--timestamp` | | Unix timestamp in ms or "now" |
124
+ | `ulid` | `--lowercase` | `-l` | Output in lowercase |
125
+ | `nanoid` | `--size` | `-s` | Length of ID, 1-256 (default: 21) |
126
+ | `nanoid` | `--alphabet` | `-a` | Custom alphabet or preset: hex, numeric, alpha |
127
+ | `cuid` | `--length` | `-l` | Length of ID, 2-32 (default: 24) |
128
+ | `ksuid` | `--timestamp` | | Unix timestamp in seconds or "now" |
129
+
130
+ ### Validate Options
131
+
132
+ | Option | Description |
133
+ |--------|-------------|
134
+ | `--type` | Expected ID type: uuid, ulid, nanoid, cuid, ksuid (auto-detected if omitted) |
135
+ | `--stdin` | Read IDs from stdin (one per line) |
136
+ | `--quiet` | No output, exit code only (0 = valid, 2 = invalid) |
137
+ | `--json` | Output as JSON |
138
+
139
+ ### Inspect Options
140
+
141
+ | Option | Description |
142
+ |--------|-------------|
143
+ | `--type` | ID type: uuid, ulid, nanoid, cuid, ksuid (auto-detected if omitted) |
144
+ | `--json` | Output as JSON |
145
+
146
+ ## Tech Stack
147
+
148
+ - [Effect](https://effect.website/) — functional effect system for TypeScript
149
+ - [@effect/cli](https://github.com/Effect-TS/effect/tree/main/packages/cli) — CLI framework built on Effect
150
+ - [@effect/platform](https://github.com/Effect-TS/effect/tree/main/packages/platform) — platform abstraction layer
151
+ - [Bun](https://bun.sh/) — JavaScript runtime
152
+ - [uniku](https://github.com/jkomyno/uniku) — core ID generation library
153
+
154
+ ## License
155
+
156
+ MIT — see [LICENSE](https://github.com/jkomyno/uniku/blob/main/LICENSE)
@@ -0,0 +1,5 @@
1
+ //#region src/bin.d.ts
2
+ declare function preprocessArgs(argv: readonly string[]): string[];
3
+ //#endregion
4
+ export { preprocessArgs };
5
+ //# sourceMappingURL=bin.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.mts","names":[],"sources":["../src/bin.ts"],"sourcesContent":[],"mappings":";iBAegB,cAAA"}
package/build/bin.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import{BunContext as e,BunRuntime as t}from"@effect/platform-bun";import*as n from"effect/Effect";import*as r from"effect/Layer";import{Args as i,Command as a,Options as o}from"@effect/cli";import*as s from"effect/Option";import{cuid2 as c}from"uniku/cuid2";import{UniqueIdError as l}from"uniku/errors";import{ksuid as u}from"uniku/ksuid";import{nanoid as d}from"uniku/nanoid";import{ulid as f}from"uniku/ulid";import{uuidv4 as p}from"uniku/uuid/v4";import{uuidv7 as m}from"uniku/uuid/v7";import*as h from"effect/Context";const ee={hex:`0123456789abcdef`,numeric:`0123456789`,alpha:`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`};var g=class extends Error{constructor(e,t,n,r=1){super(t),this.code=e,this.hint=n,this.exitCode=r,this.name=`CliError`}},te=class extends g{constructor(e){super(`VALIDATION_FAILED`,e,void 0,2),this.name=`ValidationFailedError`}};function _(e){return new g(e.code,e.message)}function v(e){let t={error:e.message,code:e.code};return e.hint&&(t.hint=e.hint),t}function y(e){return n.try({try:()=>{let t=[];for(let n=0;n<e.count;n++)t.push(c({length:e.length}));return t},catch:e=>e instanceof l?_(e):new g(`GENERATE_FAILED`,String(e))})}function b(e){return n.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=e.timestamp==null?void 0:{secs:e.timestamp};t.push(u(n))}return t},catch:e=>e instanceof l?_(e):new g(`GENERATE_FAILED`,String(e))})}function x(e){if(e)return ee[e]??e}function S(e){return n.try({try:()=>{let t=x(e.alphabet),n=[];for(let r=0;r<e.count;r++)n.push(d({size:e.size,alphabet:t}));return n},catch:e=>e instanceof l?_(e):new g(`GENERATE_FAILED`,String(e))})}function C(e){return e.monotonic&&e.timestamp!=null?n.fail(new g(`INVALID_OPTIONS`,`--monotonic and --timestamp are mutually exclusive`,`Use --monotonic for monotonically increasing ULIDs, or --timestamp to specify a fixed timestamp`)):n.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=f(e.timestamp==null?void 0:{msecs:e.timestamp});e.lowercase&&(n=n.toLowerCase()),t.push(n)}return t},catch:e=>e instanceof l?_(e):new g(`GENERATE_FAILED`,String(e))})}function w(e){return n.try({try:()=>{let t=e.version===7?m:p,n=[];for(let r=0;r<e.count;r++){let r=t();e.lowercase&&(r=r.toLowerCase()),n.push(r)}return n},catch:e=>e instanceof l?_(e):new g(`GENERATE_FAILED`,String(e))})}var T=class extends h.Tag(`OutputService`)(){};function ne(e){if(e.valid){let t=[`valid (${e.type}`];return e.version!=null&&t.push(` v${e.version}`),t.push(`)`),t.join(``)}return`invalid: ${e.error??`malformed identifier`}`}function re(e){let t=[],n=e.version==null?e.type:`${e.type} (v${e.version})`;return t.push(`Type: ${n}`),e.timestamp&&t.push(`Timestamp: ${e.timestamp}`),e.random&&t.push(`Random: ${e.random}`),e.note&&t.push(`Note: ${e.note}`),t.join(`
2
+ `)}const ie=T.of({writeIds(e,t){return n.sync(()=>{if(t.json){let t=e.length===1?JSON.stringify(e[0]):JSON.stringify(e);process.stdout.write(`${t}\n`)}else for(let t of e)process.stdout.write(`${t}\n`)})},writeValidation(e,t){return n.sync(()=>{if(!t.quiet)if(t.json){let t=e.length===1?JSON.stringify(e[0]):JSON.stringify(e);process.stdout.write(`${t}\n`)}else for(let t of e)process.stdout.write(`${ne(t)}\n`)})},writeInspect(e,t){return n.sync(()=>{t.json?process.stdout.write(`${JSON.stringify(e)}\n`):process.stdout.write(`${re(e)}\n`)})},writeError(e,t){return n.sync(()=>{if(t.json)process.stderr.write(`${JSON.stringify(v(e))}\n`);else{let t=`Error: ${e.message}`;e.hint&&(t+=`\n ${e.hint}`),process.stderr.write(`${t}\n`)}})}}),E=o.integer(`count`).pipe(o.withAlias(`n`),o.withDescription(`Number of IDs to generate`),o.withDefault(1)),D=o.boolean(`json`).pipe(o.withDescription(`Output as JSON`),o.withDefault(!1)),O=o.choiceWithValue(`version`,[[`4`,4],[`7`,7]]).pipe(o.withAlias(`v`),o.withDescription(`UUID version: 4, 7`),o.withDefault(4)),k=o.boolean(`lowercase`).pipe(o.withAlias(`l`),o.withDescription(`Output in lowercase`),o.withDefault(!1)),A=a.make(`uuid`,{count:E,json:D,version:O,lowercase:k},({count:e,json:t,version:r,lowercase:i})=>n.gen(function*(){let n=yield*T,a=yield*w({count:e,version:r,lowercase:i});yield*n.writeIds(a,{json:t})})).pipe(a.withDescription(`Generate UUIDs (v4 or v7)`)),j=o.boolean(`monotonic`).pipe(o.withDescription(`Generate monotonically increasing ULIDs`),o.withDefault(!1)),M=o.text(`timestamp`).pipe(o.withDescription(`Unix timestamp in milliseconds (or "now")`),o.optional),N=a.make(`ulid`,{count:E,json:D,monotonic:j,timestamp:M,lowercase:k},({count:e,json:t,monotonic:r,timestamp:i,lowercase:a})=>n.gen(function*(){let n=yield*T,o=yield*C({count:e,monotonic:r,timestamp:s.isSome(i)?q(s.getOrThrow(i)):void 0,lowercase:a});yield*n.writeIds(o,{json:t})})).pipe(a.withDescription(`Generate ULIDs`)),P=o.integer(`size`).pipe(o.withAlias(`s`),o.withDescription(`Length of ID (1-256)`),o.withDefault(21)),F=o.text(`alphabet`).pipe(o.withAlias(`a`),o.withDescription(`Custom alphabet or preset: hex, numeric, alpha`),o.optional),I=a.make(`nanoid`,{count:E,json:D,size:P,alphabet:F},({count:e,json:t,size:r,alphabet:i})=>n.gen(function*(){let n=yield*T,a=yield*S({count:e,size:r,alphabet:s.isSome(i)?s.getOrThrow(i):void 0});yield*n.writeIds(a,{json:t})})).pipe(a.withDescription(`Generate Nanoids`)),L=o.integer(`length`).pipe(o.withAlias(`l`),o.withDescription(`Length of ID (2-32)`),o.withDefault(24)),R=a.make(`cuid`,{count:E,json:D,length:L},({count:e,json:t,length:r})=>n.gen(function*(){let n=yield*T,i=yield*y({count:e,length:r});yield*n.writeIds(i,{json:t})})).pipe(a.withDescription(`Generate CUIDs (v2)`)),z=o.text(`timestamp`).pipe(o.withDescription(`Unix timestamp in seconds (or "now")`),o.optional),B=a.make(`ksuid`,{count:E,json:D,timestamp:z},({count:e,json:t,timestamp:r})=>n.gen(function*(){let n=yield*T,i=yield*b({count:e,timestamp:s.isSome(r)?J(s.getOrThrow(r)):void 0});yield*n.writeIds(i,{json:t})})).pipe(a.withDescription(`Generate KSUIDs`)),V=a.make(`generate`).pipe(a.withDescription(`Generate new IDs`),a.withSubcommands([A,N,I,R,B])),H=A,U=N,W=I,G=R,K=B;function q(e){if(e===`now`)return Date.now();let t=Number(e);if(!Number.isFinite(t)||t<0)throw new g(`INVALID_TIMESTAMP`,`Invalid timestamp: "${e}"`,`Provide a Unix timestamp in milliseconds or "now"`);return t}function J(e){if(e===`now`)return Math.floor(Date.now()/1e3);let t=Number(e);if(!Number.isFinite(t)||t<0)throw new g(`INVALID_TIMESTAMP`,`Invalid timestamp: "${e}"`,`Provide a Unix timestamp in seconds or "now"`);return t}function Y(e,t){switch(t){case`uuid`:return ae(e);case`ulid`:return oe(e);case`ksuid`:return se(e);case`cuid`:return ce(e);case`nanoid`:return le(e)}}function X(e){return m.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:p.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:f.isValid(e)?{id:e,valid:!0,type:`ulid`}:u.isValid(e)?{id:e,valid:!0,type:`ksuid`}:c.isValid(e)?{id:e,valid:!0,type:`cuid`}:d.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,error:`malformed identifier`}}function ae(e){return m.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:p.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:{id:e,valid:!1,type:`uuid`,error:`invalid UUID format`}}function oe(e){return f.isValid(e)?{id:e,valid:!0,type:`ulid`}:{id:e,valid:!1,type:`ulid`,error:`invalid ULID format`}}function se(e){return u.isValid(e)?{id:e,valid:!0,type:`ksuid`}:{id:e,valid:!1,type:`ksuid`,error:`invalid KSUID format`}}function ce(e){return c.isValid(e)?{id:e,valid:!0,type:`cuid`}:{id:e,valid:!1,type:`cuid`,error:`invalid CUID format`}}function le(e){return d.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,type:`nanoid`,error:`invalid Nanoid format`}}function ue(e,t){let n=t??de(e);if(!n)return null;switch(n){case`uuid`:return fe(e);case`ulid`:return pe(e);case`ksuid`:return me(e);case`cuid`:return he(e);case`nanoid`:return ge(e)}}function de(e){let t=X(e);return t.valid?t.type??null:null}function fe(e){if(m.isValid(e)){let t=m.timestamp(e),n=m.toBytes(e),r=Buffer.from(n.slice(10)).toString(`hex`);return{id:e,type:`uuid`,version:7,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:r}}return p.isValid(e)?{id:e,type:`uuid`,version:4,note:`This ID type contains no decodable metadata.`}:{id:e,type:`uuid`,note:`Unrecognized UUID version.`}}function pe(e){let t=f.timestamp(e),n=e.slice(10);return{id:e,type:`ulid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:n}}function me(e){let t=u.timestamp(e),n=u.toBytes(e),r=Buffer.from(n.slice(4)).toString(`hex`);return{id:e,type:`ksuid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:r}}function he(e){return{id:e,type:`cuid`,note:`This ID type contains no decodable metadata.`}}function ge(e){return{id:e,type:`nanoid`,note:`This ID type contains no decodable metadata.`}}const _e=i.text({name:`id`}).pipe(i.withDescription(`The ID to inspect`)),ve=o.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(o.withDescription(`ID type (auto-detected if omitted)`),o.optional),ye=o.boolean(`json`).pipe(o.withDescription(`Output as JSON`),o.withDefault(!1)),be=a.make(`inspect`,{id:_e,type:ve,json:ye},({id:e,type:t,json:r})=>n.gen(function*(){let i=yield*T,a=ue(e,s.isSome(t)?s.getOrThrow(t):void 0);if(!a){yield*n.fail(new g(`UNKNOWN_ID_TYPE`,`Could not identify ID type for: "${e}"`,`Use --type to specify the ID type`));return}yield*i.writeInspect(a,{json:r})})).pipe(a.withDescription(`Decode and inspect an ID`));var Z=class extends h.Tag(`StdinService`)(){};const xe=Z.of({readLines(){return n.async(e=>{let t=[];process.stdin.on(`data`,e=>{t.push(e)}),process.stdin.on(`end`,()=>{let r=Buffer.concat(t).toString(`utf-8`).split(`
3
+ `).map(e=>e.trim()).filter(e=>e.length>0);e(n.succeed(r))}),process.stdin.on(`error`,t=>{e(n.fail(new g(`STDIN_ERROR`,t.message)))}),process.stdin.resume()})}}),Q=i.text({name:`id`}).pipe(i.withDescription(`The ID to validate`),i.optional),Se=o.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(o.withDescription(`Expected ID type (auto-detected if omitted)`),o.optional),Ce=o.boolean(`stdin`).pipe(o.withDescription(`Read IDs from stdin (one per line)`),o.withDefault(!1)),we=o.boolean(`json`).pipe(o.withDescription(`Output validation results as JSON`),o.withDefault(!1)),Te=o.boolean(`quiet`).pipe(o.withDescription(`No output, exit code only`),o.withDefault(!1)),Ee=a.make(`validate`,{id:Q,type:Se,stdin:Ce,json:we,quiet:Te},({id:e,type:t,stdin:r,json:i,quiet:a})=>n.gen(function*(){let o=yield*T,c=yield*Z,l=s.isSome(t)?s.getOrThrow(t):void 0,u;if(r){if(u=yield*c.readLines(),u.length===0){yield*n.fail(new g(`NO_INPUT`,`No IDs provided on stdin`));return}}else if(s.isSome(e))u=[s.getOrThrow(e)];else{yield*n.fail(new g(`NO_INPUT`,`No ID provided`,`Pass an ID as argument or use --stdin`));return}let d=u.map(e=>l?Y(e,l):X(e));yield*o.writeValidation(d,{json:i,quiet:a}),d.some(e=>!e.valid)&&(yield*n.fail(new te(`One or more IDs are invalid`)))})).pipe(a.withDescription(`Check if an ID is valid`)),De=a.make(`uniku`).pipe(a.withDescription(`Generate and validate unique identifiers`),a.withSubcommands([V,Ee,be,H,U,W,G,K])),Oe=(e=>a.run(De,{name:`uniku`,version:e}))(`0.0.11`);function $(e){let t=[...e];for(let e=2;e<t.length;e++)t[e]===`-V`&&(t[e]=`--version`);return t.length<=2&&t.push(`--help`),t}const ke=r.mergeAll(r.succeed(T,ie),r.succeed(Z,xe)),Ae=r.mergeAll(ke,e.layer);n.suspend(()=>Oe($(process.argv))).pipe(n.catchAll(e=>n.sync(()=>{e instanceof g?(process.stderr.write(`Error: ${e.message}\n`),e.hint&&process.stderr.write(` ${e.hint}\n`),process.exitCode=e.exitCode):(process.stderr.write(`Error: ${String(e)}\n`),process.exitCode=1)})),n.provide(Ae),t.runMain);export{$ as preprocessArgs};
4
+ //# sourceMappingURL=bin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.mjs","names":["NANOID_ALPHABET_PRESETS: Record<string, string>","code: string","hint?: string","exitCode: number","obj: { error: string; code: string; hint?: string }","ids: string[]","ids: string[]","ids: string[]","ids: string[]","ids: string[]","lines: string[]","jsonOption","idArg","typeOption","jsonOption","chunks: Buffer[]","type: IdType | undefined","ids: readonly string[]","results: ValidationResult[]","pkg.version"],"sources":["../src/domain/constants.ts","../src/domain/errors.ts","../src/generators/cuid.ts","../src/generators/ksuid.ts","../src/generators/nanoid.ts","../src/generators/ulid.ts","../src/generators/uuid.ts","../src/services/OutputService.ts","../src/commands/generate.cmd.ts","../src/validators/validate.ts","../src/inspectors/inspect.ts","../src/commands/inspect.cmd.ts","../src/services/StdinService.ts","../src/commands/validate.cmd.ts","../src/commands/index.ts","../package.json","../src/bin.ts"],"sourcesContent":["/** Default count for ID generation. */\nexport const COUNT_DEFAULT = 1\n\n/** Valid UUID versions. */\nexport const UUID_VERSIONS = [4, 7] as const\n\n/** Default UUID version. */\nexport const UUID_VERSION_DEFAULT = 4\n\n/** Default nanoid size. */\nexport const NANOID_SIZE_DEFAULT = 21\n\n/** Nanoid size range. */\nexport const NANOID_SIZE_MIN = 1\nexport const NANOID_SIZE_MAX = 256\n\n/** Default CUID2 length. */\nexport const CUID_LENGTH_DEFAULT = 24\n\n/** CUID2 length range. */\nexport const CUID_LENGTH_MIN = 2\nexport const CUID_LENGTH_MAX = 32\n\n/** Nanoid alphabet presets. */\nexport const NANOID_ALPHABET_PRESETS: Record<string, string> = {\n hex: '0123456789abcdef',\n numeric: '0123456789',\n alpha: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n}\n\n/** Environment variable for default generate type. */\nexport const ENV_DEFAULT_TYPE = 'UNIKU_DEFAULT_TYPE'\n","import type { UniqueIdError } from 'uniku/errors'\n\n/**\n * Structured CLI error with optional hint and exit code.\n */\nexport class CliError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly hint?: string,\n readonly exitCode: number = 1,\n ) {\n super(message)\n this.name = 'CliError'\n }\n}\n\n/**\n * Error indicating validation failure (exit code 2).\n */\nexport class ValidationFailedError extends CliError {\n constructor(message: string) {\n super('VALIDATION_FAILED', message, undefined, 2)\n this.name = 'ValidationFailedError'\n }\n}\n\n/**\n * Maps a uniku library error into a CliError, preserving code and message.\n */\nexport function fromUnikuError(err: UniqueIdError): CliError {\n return new CliError(err.code, err.message)\n}\n\n/**\n * Converts a CliError to a JSON-serializable object for stderr output.\n */\nexport function errorToJson(err: CliError): { error: string; code: string; hint?: string } {\n const obj: { error: string; code: string; hint?: string } = {\n error: err.message,\n code: err.code,\n }\n if (err.hint) {\n obj.hint = err.hint\n }\n return obj\n}\n","import * as Effect from 'effect/Effect'\nimport { cuid2 } from 'uniku/cuid2'\nimport { UniqueIdError } from 'uniku/errors'\nimport { CliError, fromUnikuError } from '@/src/domain/errors'\n\nexport type CuidGenerateOptions = {\n readonly count: number\n readonly length: number\n}\n\nexport function generateCuid(options: CuidGenerateOptions): Effect.Effect<string[], CliError> {\n return Effect.try({\n try: () => {\n const ids: string[] = []\n for (let i = 0; i < options.count; i++) {\n ids.push(cuid2({ length: options.length }))\n }\n return ids\n },\n catch: (err) => {\n if (err instanceof UniqueIdError) return fromUnikuError(err)\n return new CliError('GENERATE_FAILED', String(err))\n },\n })\n}\n","import * as Effect from 'effect/Effect'\nimport { UniqueIdError } from 'uniku/errors'\nimport { ksuid } from 'uniku/ksuid'\nimport { CliError, fromUnikuError } from '@/src/domain/errors'\n\nexport type KsuidGenerateOptions = {\n readonly count: number\n readonly timestamp?: number\n}\n\nexport function generateKsuid(options: KsuidGenerateOptions): Effect.Effect<string[], CliError> {\n return Effect.try({\n try: () => {\n const ids: string[] = []\n for (let i = 0; i < options.count; i++) {\n const ksuidOpts = options.timestamp != null ? { secs: options.timestamp } : undefined\n ids.push(ksuid(ksuidOpts))\n }\n return ids\n },\n catch: (err) => {\n if (err instanceof UniqueIdError) return fromUnikuError(err)\n return new CliError('GENERATE_FAILED', String(err))\n },\n })\n}\n","import * as Effect from 'effect/Effect'\nimport { UniqueIdError } from 'uniku/errors'\nimport { nanoid } from 'uniku/nanoid'\nimport { NANOID_ALPHABET_PRESETS } from '@/src/domain/constants'\nimport { CliError, fromUnikuError } from '@/src/domain/errors'\n\nexport type NanoidGenerateOptions = {\n readonly count: number\n readonly size: number\n readonly alphabet?: string\n}\n\nfunction resolveAlphabet(input?: string): string | undefined {\n if (!input) return undefined\n return NANOID_ALPHABET_PRESETS[input] ?? input\n}\n\nexport function generateNanoid(options: NanoidGenerateOptions): Effect.Effect<string[], CliError> {\n return Effect.try({\n try: () => {\n const alphabet = resolveAlphabet(options.alphabet)\n const ids: string[] = []\n for (let i = 0; i < options.count; i++) {\n ids.push(nanoid({ size: options.size, alphabet }))\n }\n return ids\n },\n catch: (err) => {\n if (err instanceof UniqueIdError) return fromUnikuError(err)\n return new CliError('GENERATE_FAILED', String(err))\n },\n })\n}\n","import * as Effect from 'effect/Effect'\nimport { UniqueIdError } from 'uniku/errors'\nimport { ulid } from 'uniku/ulid'\nimport { CliError, fromUnikuError } from '@/src/domain/errors'\n\nexport type UlidGenerateOptions = {\n readonly count: number\n readonly monotonic: boolean\n readonly timestamp?: number\n readonly lowercase: boolean\n}\n\nexport function generateUlid(options: UlidGenerateOptions): Effect.Effect<string[], CliError> {\n if (options.monotonic && options.timestamp != null) {\n return Effect.fail(\n new CliError(\n 'INVALID_OPTIONS',\n '--monotonic and --timestamp are mutually exclusive',\n 'Use --monotonic for monotonically increasing ULIDs, or --timestamp to specify a fixed timestamp',\n ),\n )\n }\n\n return Effect.try({\n try: () => {\n const ids: string[] = []\n for (let i = 0; i < options.count; i++) {\n const ulidOpts = options.timestamp != null ? { msecs: options.timestamp } : undefined\n let id = ulid(ulidOpts)\n if (options.lowercase) {\n id = id.toLowerCase()\n }\n ids.push(id)\n }\n return ids\n },\n catch: (err) => {\n if (err instanceof UniqueIdError) return fromUnikuError(err)\n return new CliError('GENERATE_FAILED', String(err))\n },\n })\n}\n","import * as Effect from 'effect/Effect'\nimport { UniqueIdError } from 'uniku/errors'\nimport { uuidv4 } from 'uniku/uuid/v4'\nimport { uuidv7 } from 'uniku/uuid/v7'\nimport { CliError, fromUnikuError } from '@/src/domain/errors'\n\nexport type UuidGenerateOptions = {\n readonly count: number\n readonly version: number\n readonly lowercase: boolean\n}\n\nexport function generateUuid(options: UuidGenerateOptions): Effect.Effect<string[], CliError> {\n return Effect.try({\n try: () => {\n const gen = options.version === 7 ? uuidv7 : uuidv4\n const ids: string[] = []\n for (let i = 0; i < options.count; i++) {\n let id = gen()\n if (options.lowercase) {\n id = id.toLowerCase()\n }\n ids.push(id)\n }\n return ids\n },\n catch: (err) => {\n if (err instanceof UniqueIdError) return fromUnikuError(err)\n return new CliError('GENERATE_FAILED', String(err))\n },\n })\n}\n","import * as Context from 'effect/Context'\nimport * as Effect from 'effect/Effect'\nimport { type CliError, errorToJson } from '@/src/domain/errors'\nimport type { InspectResult, ValidationResult } from '@/src/domain/types'\n\nexport type OutputOptions = {\n readonly json?: boolean\n readonly quiet?: boolean\n}\n\nexport class OutputService extends Context.Tag('OutputService')<\n OutputService,\n {\n readonly writeIds: (ids: readonly string[], options: OutputOptions) => Effect.Effect<void>\n readonly writeValidation: (results: readonly ValidationResult[], options: OutputOptions) => Effect.Effect<void>\n readonly writeInspect: (result: InspectResult, options: OutputOptions) => Effect.Effect<void>\n readonly writeError: (error: CliError, options: OutputOptions) => Effect.Effect<void>\n }\n>() {}\n\nfunction formatValidationHuman(result: ValidationResult): string {\n if (result.valid) {\n const parts = [`valid (${result.type}`]\n if (result.version != null) {\n parts.push(` v${result.version}`)\n }\n parts.push(')')\n return parts.join('')\n }\n return `invalid: ${result.error ?? 'malformed identifier'}`\n}\n\nfunction formatInspectHuman(result: InspectResult): string {\n const lines: string[] = []\n const typeLabel = result.version != null ? `${result.type} (v${result.version})` : result.type\n lines.push(`Type: ${typeLabel}`)\n if (result.timestamp) {\n lines.push(`Timestamp: ${result.timestamp}`)\n }\n if (result.random) {\n lines.push(`Random: ${result.random}`)\n }\n if (result.note) {\n lines.push(`Note: ${result.note}`)\n }\n return lines.join('\\n')\n}\n\n/**\n * Default implementation writing to process.stdout / process.stderr.\n */\nexport const OutputServiceLive = OutputService.of({\n writeIds(ids, options) {\n return Effect.sync(() => {\n if (options.json) {\n const out = ids.length === 1 ? JSON.stringify(ids[0]) : JSON.stringify(ids)\n process.stdout.write(`${out}\\n`)\n } else {\n for (const id of ids) {\n process.stdout.write(`${id}\\n`)\n }\n }\n })\n },\n\n writeValidation(results, options) {\n return Effect.sync(() => {\n if (options.quiet) return\n\n if (options.json) {\n const out = results.length === 1 ? JSON.stringify(results[0]) : JSON.stringify(results)\n process.stdout.write(`${out}\\n`)\n } else {\n for (const result of results) {\n process.stdout.write(`${formatValidationHuman(result)}\\n`)\n }\n }\n })\n },\n\n writeInspect(result, options) {\n return Effect.sync(() => {\n if (options.json) {\n process.stdout.write(`${JSON.stringify(result)}\\n`)\n } else {\n process.stdout.write(`${formatInspectHuman(result)}\\n`)\n }\n })\n },\n\n writeError(error, options) {\n return Effect.sync(() => {\n if (options.json) {\n process.stderr.write(`${JSON.stringify(errorToJson(error))}\\n`)\n } else {\n let msg = `Error: ${error.message}`\n if (error.hint) {\n msg += `\\n ${error.hint}`\n }\n process.stderr.write(`${msg}\\n`)\n }\n })\n },\n})\n","import { Command, Options } from '@effect/cli'\nimport * as Effect from 'effect/Effect'\nimport * as Option from 'effect/Option'\nimport { COUNT_DEFAULT, CUID_LENGTH_DEFAULT, NANOID_SIZE_DEFAULT, UUID_VERSION_DEFAULT } from '@/src/domain/constants'\nimport { CliError } from '@/src/domain/errors'\nimport { generateCuid } from '@/src/generators/cuid'\nimport { generateKsuid } from '@/src/generators/ksuid'\nimport { generateNanoid } from '@/src/generators/nanoid'\nimport { generateUlid } from '@/src/generators/ulid'\nimport { generateUuid } from '@/src/generators/uuid'\nimport { OutputService } from '@/src/services/OutputService'\n\n// ── Common options ──────────────────────────────────────────────────\n\nconst countOption = Options.integer('count').pipe(\n Options.withAlias('n'),\n Options.withDescription('Number of IDs to generate'),\n Options.withDefault(COUNT_DEFAULT),\n)\n\nconst jsonOption = Options.boolean('json').pipe(Options.withDescription('Output as JSON'), Options.withDefault(false))\n\n// ── UUID subcommand ─────────────────────────────────────────────────\n\nconst uuidVersionOption = Options.choiceWithValue('version', [\n ['4', 4],\n ['7', 7],\n] as const).pipe(\n Options.withAlias('v'),\n Options.withDescription('UUID version: 4, 7'),\n Options.withDefault(UUID_VERSION_DEFAULT as 4 | 7),\n)\n\nconst lowercaseOption = Options.boolean('lowercase').pipe(\n Options.withAlias('l'),\n Options.withDescription('Output in lowercase'),\n Options.withDefault(false),\n)\n\nconst uuidSubcommand = Command.make(\n 'uuid',\n {\n count: countOption,\n json: jsonOption,\n version: uuidVersionOption,\n lowercase: lowercaseOption,\n },\n ({ count, json, version, lowercase }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const ids = yield* generateUuid({ count, version, lowercase })\n yield* output.writeIds(ids, { json })\n }),\n).pipe(Command.withDescription('Generate UUIDs (v4 or v7)'))\n\n// ── ULID subcommand ─────────────────────────────────────────────────\n\nconst monotonicOption = Options.boolean('monotonic').pipe(\n Options.withDescription('Generate monotonically increasing ULIDs'),\n Options.withDefault(false),\n)\n\nconst ulidTimestampOption = Options.text('timestamp').pipe(\n Options.withDescription('Unix timestamp in milliseconds (or \"now\")'),\n Options.optional,\n)\n\nconst ulidSubcommand = Command.make(\n 'ulid',\n {\n count: countOption,\n json: jsonOption,\n monotonic: monotonicOption,\n timestamp: ulidTimestampOption,\n lowercase: lowercaseOption,\n },\n ({ count, json, monotonic, timestamp: timestampOpt, lowercase }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const timestamp = Option.isSome(timestampOpt) ? parseTimestampMs(Option.getOrThrow(timestampOpt)) : undefined\n const ids = yield* generateUlid({ count, monotonic, timestamp, lowercase })\n yield* output.writeIds(ids, { json })\n }),\n).pipe(Command.withDescription('Generate ULIDs'))\n\n// ── Nanoid subcommand ───────────────────────────────────────────────\n\nconst sizeOption = Options.integer('size').pipe(\n Options.withAlias('s'),\n Options.withDescription('Length of ID (1-256)'),\n Options.withDefault(NANOID_SIZE_DEFAULT),\n)\n\nconst alphabetOption = Options.text('alphabet').pipe(\n Options.withAlias('a'),\n Options.withDescription('Custom alphabet or preset: hex, numeric, alpha'),\n Options.optional,\n)\n\nconst nanoidSubcommand = Command.make(\n 'nanoid',\n {\n count: countOption,\n json: jsonOption,\n size: sizeOption,\n alphabet: alphabetOption,\n },\n ({ count, json, size, alphabet: alphabetOpt }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const alphabet = Option.isSome(alphabetOpt) ? Option.getOrThrow(alphabetOpt) : undefined\n const ids = yield* generateNanoid({ count, size, alphabet })\n yield* output.writeIds(ids, { json })\n }),\n).pipe(Command.withDescription('Generate Nanoids'))\n\n// ── CUID subcommand ─────────────────────────────────────────────────\n\nconst lengthOption = Options.integer('length').pipe(\n Options.withAlias('l'),\n Options.withDescription('Length of ID (2-32)'),\n Options.withDefault(CUID_LENGTH_DEFAULT),\n)\n\nconst cuidSubcommand = Command.make(\n 'cuid',\n {\n count: countOption,\n json: jsonOption,\n length: lengthOption,\n },\n ({ count, json, length }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const ids = yield* generateCuid({ count, length })\n yield* output.writeIds(ids, { json })\n }),\n).pipe(Command.withDescription('Generate CUIDs (v2)'))\n\n// ── KSUID subcommand ────────────────────────────────────────────────\n\nconst ksuidTimestampOption = Options.text('timestamp').pipe(\n Options.withDescription('Unix timestamp in seconds (or \"now\")'),\n Options.optional,\n)\n\nconst ksuidSubcommand = Command.make(\n 'ksuid',\n {\n count: countOption,\n json: jsonOption,\n timestamp: ksuidTimestampOption,\n },\n ({ count, json, timestamp: timestampOpt }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const timestamp = Option.isSome(timestampOpt) ? parseTimestampSecs(Option.getOrThrow(timestampOpt)) : undefined\n const ids = yield* generateKsuid({ count, timestamp })\n yield* output.writeIds(ids, { json })\n }),\n).pipe(Command.withDescription('Generate KSUIDs'))\n\n// ── Generate parent command ─────────────────────────────────────────\n\nexport const generateCommand = Command.make('generate').pipe(\n Command.withDescription('Generate new IDs'),\n Command.withSubcommands([uuidSubcommand, ulidSubcommand, nanoidSubcommand, cuidSubcommand, ksuidSubcommand]),\n)\n\n// ── Shorthand commands (top-level: `uniku uuid`, `uniku ulid`, etc.) ─\n\nexport const uuidShorthand = uuidSubcommand\nexport const ulidShorthand = ulidSubcommand\nexport const nanoidShorthand = nanoidSubcommand\nexport const cuidShorthand = cuidSubcommand\nexport const ksuidShorthand = ksuidSubcommand\n\n// ── Helpers ─────────────────────────────────────────────────────────\n\nfunction parseTimestampMs(input: string): number {\n if (input === 'now') return Date.now()\n const n = Number(input)\n if (!Number.isFinite(n) || n < 0) {\n throw new CliError(\n 'INVALID_TIMESTAMP',\n `Invalid timestamp: \"${input}\"`,\n 'Provide a Unix timestamp in milliseconds or \"now\"',\n )\n }\n return n\n}\n\nfunction parseTimestampSecs(input: string): number {\n if (input === 'now') return Math.floor(Date.now() / 1000)\n const n = Number(input)\n if (!Number.isFinite(n) || n < 0) {\n throw new CliError(\n 'INVALID_TIMESTAMP',\n `Invalid timestamp: \"${input}\"`,\n 'Provide a Unix timestamp in seconds or \"now\"',\n )\n }\n return n\n}\n","import { cuid2 } from 'uniku/cuid2'\nimport { ksuid } from 'uniku/ksuid'\nimport { nanoid } from 'uniku/nanoid'\nimport { ulid } from 'uniku/ulid'\nimport { uuidv4 } from 'uniku/uuid/v4'\nimport { uuidv7 } from 'uniku/uuid/v7'\nimport type { IdType, ValidationResult } from '@/src/domain/types'\n\n/**\n * Validate a single ID against a specific type.\n */\nexport function validateAs(id: string, type: IdType): ValidationResult {\n switch (type) {\n case 'uuid':\n return validateUuid(id)\n case 'ulid':\n return validateUlid(id)\n case 'ksuid':\n return validateKsuid(id)\n case 'cuid':\n return validateCuid(id)\n case 'nanoid':\n return validateNanoid(id)\n }\n}\n\n/**\n * Auto-detect ID type and validate.\n * Detection order: UUID > ULID > KSUID > CUID > Nanoid.\n */\nexport function validateAutoDetect(id: string): ValidationResult {\n // 1. UUID (36 chars, 8-4-4-4-12 format with hyphens)\n if (uuidv7.isValid(id)) {\n return { id, valid: true, type: 'uuid', version: 7 }\n }\n if (uuidv4.isValid(id)) {\n return { id, valid: true, type: 'uuid', version: 4 }\n }\n\n // 2. ULID (26 chars, Crockford Base32)\n if (ulid.isValid(id)) {\n return { id, valid: true, type: 'ulid' }\n }\n\n // 3. KSUID (27 chars, Base62)\n if (ksuid.isValid(id)) {\n return { id, valid: true, type: 'ksuid' }\n }\n\n // 4. CUID (starts with letter, Base36)\n if (cuid2.isValid(id)) {\n return { id, valid: true, type: 'cuid' }\n }\n\n // 5. Nanoid (fallback: URL-safe A-Za-z0-9_- and length 1-256)\n if (nanoid.isValid(id)) {\n return { id, valid: true, type: 'nanoid' }\n }\n\n return { id, valid: false, error: 'malformed identifier' }\n}\n\nfunction validateUuid(id: string): ValidationResult {\n if (uuidv7.isValid(id)) {\n return { id, valid: true, type: 'uuid', version: 7 }\n }\n if (uuidv4.isValid(id)) {\n return { id, valid: true, type: 'uuid', version: 4 }\n }\n return { id, valid: false, type: 'uuid', error: 'invalid UUID format' }\n}\n\nfunction validateUlid(id: string): ValidationResult {\n if (ulid.isValid(id)) {\n return { id, valid: true, type: 'ulid' }\n }\n return { id, valid: false, type: 'ulid', error: 'invalid ULID format' }\n}\n\nfunction validateKsuid(id: string): ValidationResult {\n if (ksuid.isValid(id)) {\n return { id, valid: true, type: 'ksuid' }\n }\n return { id, valid: false, type: 'ksuid', error: 'invalid KSUID format' }\n}\n\nfunction validateCuid(id: string): ValidationResult {\n if (cuid2.isValid(id)) {\n return { id, valid: true, type: 'cuid' }\n }\n return { id, valid: false, type: 'cuid', error: 'invalid CUID format' }\n}\n\nfunction validateNanoid(id: string): ValidationResult {\n if (nanoid.isValid(id)) {\n return { id, valid: true, type: 'nanoid' }\n }\n return { id, valid: false, type: 'nanoid', error: 'invalid Nanoid format' }\n}\n","import { ksuid } from 'uniku/ksuid'\nimport { ulid } from 'uniku/ulid'\nimport { uuidv4 } from 'uniku/uuid/v4'\nimport { uuidv7 } from 'uniku/uuid/v7'\nimport type { IdType, InspectResult } from '@/src/domain/types'\nimport { validateAutoDetect } from '@/src/validators/validate'\n\n/**\n * Inspect an ID and extract metadata.\n * If type is not provided, auto-detect is used.\n */\nexport function inspectId(id: string, type?: IdType): InspectResult | null {\n const resolvedType = type ?? detectType(id)\n if (!resolvedType) return null\n\n switch (resolvedType) {\n case 'uuid':\n return inspectUuid(id)\n case 'ulid':\n return inspectUlid(id)\n case 'ksuid':\n return inspectKsuid(id)\n case 'cuid':\n return inspectCuid(id)\n case 'nanoid':\n return inspectNanoid(id)\n }\n}\n\nfunction detectType(id: string): IdType | null {\n const result = validateAutoDetect(id)\n return result.valid ? (result.type ?? null) : null\n}\n\nfunction inspectUuid(id: string): InspectResult {\n if (uuidv7.isValid(id)) {\n const ms = uuidv7.timestamp(id)\n const bytes = uuidv7.toBytes(id)\n // Random component: last 6 bytes (bytes 10-15)\n const random = Buffer.from(bytes.slice(10)).toString('hex')\n return {\n id,\n type: 'uuid',\n version: 7,\n timestamp: new Date(ms).toISOString(),\n timestamp_ms: ms,\n random,\n }\n }\n\n if (uuidv4.isValid(id)) {\n return {\n id,\n type: 'uuid',\n version: 4,\n note: 'This ID type contains no decodable metadata.',\n }\n }\n\n return {\n id,\n type: 'uuid',\n note: 'Unrecognized UUID version.',\n }\n}\n\nfunction inspectUlid(id: string): InspectResult {\n const ms = ulid.timestamp(id)\n // Random component: last 16 chars of the 26-char ULID\n const random = id.slice(10)\n return {\n id,\n type: 'ulid',\n timestamp: new Date(ms).toISOString(),\n timestamp_ms: ms,\n random,\n }\n}\n\nfunction inspectKsuid(id: string): InspectResult {\n const ms = ksuid.timestamp(id)\n const bytes = ksuid.toBytes(id)\n // Random payload: last 16 bytes (bytes 4-19)\n const random = Buffer.from(bytes.slice(4)).toString('hex')\n return {\n id,\n type: 'ksuid',\n timestamp: new Date(ms).toISOString(),\n timestamp_ms: ms,\n random,\n }\n}\n\nfunction inspectCuid(id: string): InspectResult {\n return {\n id,\n type: 'cuid',\n note: 'This ID type contains no decodable metadata.',\n }\n}\n\nfunction inspectNanoid(id: string): InspectResult {\n return {\n id,\n type: 'nanoid',\n note: 'This ID type contains no decodable metadata.',\n }\n}\n","import { Args, Command, Options } from '@effect/cli'\nimport * as Effect from 'effect/Effect'\nimport * as Option from 'effect/Option'\nimport { CliError } from '@/src/domain/errors'\nimport type { IdType } from '@/src/domain/types'\nimport { inspectId } from '@/src/inspectors/inspect'\nimport { OutputService } from '@/src/services/OutputService'\n\nconst idArg = Args.text({ name: 'id' }).pipe(Args.withDescription('The ID to inspect'))\n\nconst typeOption = Options.choice('type', ['uuid', 'ulid', 'nanoid', 'cuid', 'ksuid'] as const).pipe(\n Options.withDescription('ID type (auto-detected if omitted)'),\n Options.optional,\n)\n\nconst jsonOption = Options.boolean('json').pipe(Options.withDescription('Output as JSON'), Options.withDefault(false))\n\nexport const inspectCommand = Command.make(\n 'inspect',\n {\n id: idArg,\n type: typeOption,\n json: jsonOption,\n },\n ({ id, type: typeOpt, json }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const type: IdType | undefined = Option.isSome(typeOpt) ? Option.getOrThrow(typeOpt) : undefined\n\n const result = inspectId(id, type)\n if (!result) {\n yield* Effect.fail(\n new CliError(\n 'UNKNOWN_ID_TYPE',\n `Could not identify ID type for: \"${id}\"`,\n 'Use --type to specify the ID type',\n ),\n )\n return\n }\n\n yield* output.writeInspect(result, { json })\n }),\n).pipe(Command.withDescription('Decode and inspect an ID'))\n","import * as Context from 'effect/Context'\nimport * as Effect from 'effect/Effect'\nimport { CliError } from '@/src/domain/errors'\n\nexport class StdinService extends Context.Tag('StdinService')<\n StdinService,\n {\n readonly readLines: () => Effect.Effect<readonly string[], CliError>\n }\n>() {}\n\n/**\n * Reads all lines from process.stdin until EOF.\n * Filters out empty lines.\n */\nexport const StdinServiceLive = StdinService.of({\n readLines() {\n return Effect.async<readonly string[], CliError>((resume) => {\n const chunks: Buffer[] = []\n\n process.stdin.on('data', (chunk: Buffer) => {\n chunks.push(chunk)\n })\n\n process.stdin.on('end', () => {\n const text = Buffer.concat(chunks).toString('utf-8')\n const lines = text\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n resume(Effect.succeed(lines))\n })\n\n process.stdin.on('error', (err) => {\n resume(Effect.fail(new CliError('STDIN_ERROR', err.message)))\n })\n\n process.stdin.resume()\n })\n },\n})\n","import { Args, Command, Options } from '@effect/cli'\nimport * as Effect from 'effect/Effect'\nimport * as Option from 'effect/Option'\nimport { CliError, ValidationFailedError } from '@/src/domain/errors'\nimport type { IdType, ValidationResult } from '@/src/domain/types'\nimport { OutputService } from '@/src/services/OutputService'\nimport { StdinService } from '@/src/services/StdinService'\nimport { validateAs, validateAutoDetect } from '@/src/validators/validate'\n\nconst idArg = Args.text({ name: 'id' }).pipe(Args.withDescription('The ID to validate'), Args.optional)\n\nconst typeOption = Options.choice('type', ['uuid', 'ulid', 'nanoid', 'cuid', 'ksuid'] as const).pipe(\n Options.withDescription('Expected ID type (auto-detected if omitted)'),\n Options.optional,\n)\n\nconst stdinOption = Options.boolean('stdin').pipe(\n Options.withDescription('Read IDs from stdin (one per line)'),\n Options.withDefault(false),\n)\n\nconst jsonOption = Options.boolean('json').pipe(\n Options.withDescription('Output validation results as JSON'),\n Options.withDefault(false),\n)\n\nconst quietOption = Options.boolean('quiet').pipe(\n Options.withDescription('No output, exit code only'),\n Options.withDefault(false),\n)\n\nexport const validateCommand = Command.make(\n 'validate',\n {\n id: idArg,\n type: typeOption,\n stdin: stdinOption,\n json: jsonOption,\n quiet: quietOption,\n },\n ({ id: idOpt, type: typeOpt, stdin, json, quiet }) =>\n Effect.gen(function* () {\n const output = yield* OutputService\n const stdinService = yield* StdinService\n const type: IdType | undefined = Option.isSome(typeOpt) ? Option.getOrThrow(typeOpt) : undefined\n\n let ids: readonly string[]\n\n if (stdin) {\n ids = yield* stdinService.readLines()\n if (ids.length === 0) {\n yield* Effect.fail(new CliError('NO_INPUT', 'No IDs provided on stdin'))\n return\n }\n } else if (Option.isSome(idOpt)) {\n ids = [Option.getOrThrow(idOpt)]\n } else {\n yield* Effect.fail(new CliError('NO_INPUT', 'No ID provided', 'Pass an ID as argument or use --stdin'))\n return\n }\n\n const results: ValidationResult[] = ids.map((id) => (type ? validateAs(id, type) : validateAutoDetect(id)))\n\n yield* output.writeValidation(results, { json, quiet })\n\n const hasInvalid = results.some((r) => !r.valid)\n if (hasInvalid) {\n yield* Effect.fail(new ValidationFailedError('One or more IDs are invalid'))\n }\n }),\n).pipe(Command.withDescription('Check if an ID is valid'))\n","import { Command } from '@effect/cli'\nimport {\n cuidShorthand,\n generateCommand,\n ksuidShorthand,\n nanoidShorthand,\n ulidShorthand,\n uuidShorthand,\n} from '@/src/commands/generate.cmd'\nimport { inspectCommand } from '@/src/commands/inspect.cmd'\nimport { validateCommand } from '@/src/commands/validate.cmd'\n\n// ── Root command ────────────────────────────────────────────────────\n\nexport const rootCommand = Command.make('uniku').pipe(\n Command.withDescription('Generate and validate unique identifiers'),\n Command.withSubcommands([\n generateCommand,\n validateCommand,\n inspectCommand,\n // Shorthand commands: `uniku uuid` = `uniku generate uuid`\n uuidShorthand,\n ulidShorthand,\n nanoidShorthand,\n cuidShorthand,\n ksuidShorthand,\n ]),\n)\n\n// ── CLI runner (reusable for testing) ───────────────────────────────\n\nexport const makeCliRunner = (version: string) =>\n Command.run(rootCommand, {\n name: 'uniku',\n version,\n })\n","","import { BunContext, BunRuntime } from '@effect/platform-bun'\nimport * as Effect from 'effect/Effect'\nimport * as Layer from 'effect/Layer'\nimport { makeCliRunner } from '@/src/commands'\nimport { CliError } from '@/src/domain/errors'\nimport { OutputService, OutputServiceLive } from '@/src/services/OutputService'\nimport { StdinService, StdinServiceLive } from '@/src/services/StdinService'\nimport pkg from '../package.json' with { type: 'json' }\n\n// ── CLI runner ──────────────────────────────────────────────────────\n\nconst cli = makeCliRunner(pkg.version)\n\n// ── Arg preprocessing ───────────────────────────────────────────────\n\nexport function preprocessArgs(argv: readonly string[]): string[] {\n const args = [...argv]\n\n // Replace -V with --version (Effect CLI doesn't alias -V by default)\n for (let i = 2; i < args.length; i++) {\n if (args[i] === '-V') {\n args[i] = '--version'\n }\n }\n\n // If no command args beyond the executable path, inject --help\n // argv is typically: [bun, script.ts, ...userArgs]\n if (args.length <= 2) {\n args.push('--help')\n }\n\n return args\n}\n\n// ── Service layers ──────────────────────────────────────────────────\n\nconst ServicesLayer = Layer.mergeAll(\n Layer.succeed(OutputService, OutputServiceLive),\n Layer.succeed(StdinService, StdinServiceLive),\n)\n\nconst MainLayer = Layer.mergeAll(ServicesLayer, BunContext.layer)\n\n// ── Run ─────────────────────────────────────────────────────────────\n\nEffect.suspend(() => cli(preprocessArgs(process.argv))).pipe(\n // Handle our CLI errors (CliError, ValidationFailedError) — these\n // are the only non-ValidationError errors our commands can produce.\n Effect.catchAll((err) =>\n Effect.sync(() => {\n if (err instanceof CliError) {\n process.stderr.write(`Error: ${err.message}\\n`)\n if (err.hint) {\n process.stderr.write(` ${err.hint}\\n`)\n }\n process.exitCode = err.exitCode\n } else {\n // @effect/cli ValidationError variants are already handled\n // by Command.run internally (it prints help/usage).\n // This catches any remaining unexpected errors.\n process.stderr.write(`Error: ${String(err)}\\n`)\n process.exitCode = 1\n }\n }),\n ),\n Effect.provide(MainLayer),\n BunRuntime.runMain,\n)\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "private": false,
3
+ "name": "@uniku/cli",
4
+ "version": "0.0.11",
5
+ "description": "CLI tool for generating and validating unique identifiers",
6
+ "author": {
7
+ "name": "Alberto Schiabel",
8
+ "email": "alberto.schiabel@gmail.com",
9
+ "url": "https://github.com/jkomyno"
10
+ },
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/jkomyno/uniku.git",
15
+ "directory": "packages/cli"
16
+ },
17
+ "type": "module",
18
+ "bin": {
19
+ "uniku": "./build/bin.mjs"
20
+ },
21
+ "publishConfig": {
22
+ "registry": "https://registry.npmjs.org/",
23
+ "access": "public"
24
+ },
25
+ "files": [
26
+ "build",
27
+ "README.md"
28
+ ],
29
+ "scripts": {
30
+ "clean": "rimraf build .turbo",
31
+ "build": "tsdown --config-loader unrun",
32
+ "build:binary": "bun scripts/build-binary.ts",
33
+ "install:binary": "bun scripts/install-binary.ts",
34
+ "typecheck": "tsc --noEmit",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest"
37
+ },
38
+ "dependencies": {
39
+ "effect": "3.19.16",
40
+ "@effect/cli": "0.73.2",
41
+ "@effect/platform": "0.94.3",
42
+ "@effect/platform-bun": "0.87.1",
43
+ "uniku": "workspace:*"
44
+ },
45
+ "devDependencies": {
46
+ "@types/bun": "^1.3.8",
47
+ "@effect/vitest": "0.27.0",
48
+ "vitest": "~3.2.0"
49
+ }
50
+ }