@uniku/cli 0.0.12 → 0.0.13

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 CHANGED
@@ -9,6 +9,26 @@ Supports UUID v4/v7, ULID, CUID2, Nanoid, and KSUID.
9
9
 
10
10
  ## Installation
11
11
 
12
+ ### Pre-built Binary (recommended)
13
+
14
+ Download and install a standalone binary — no Node.js required:
15
+
16
+ ```bash
17
+ curl -fsSL https://raw.githubusercontent.com/jkomyno/uniku/main/install.sh | sh
18
+ ```
19
+
20
+ Supports macOS (Intel & Apple Silicon) and Linux (x64). Override the install location or version with environment variables:
21
+
22
+ ```bash
23
+ # Custom install directory
24
+ UNIKU_INSTALL_DIR=~/.local/bin curl -fsSL https://raw.githubusercontent.com/jkomyno/uniku/main/install.sh | sh
25
+
26
+ # Specific version
27
+ UNIKU_VERSION=0.0.12 curl -fsSL https://raw.githubusercontent.com/jkomyno/uniku/main/install.sh | sh
28
+ ```
29
+
30
+ ### npm
31
+
12
32
  ```bash
13
33
  # pnpm (recommended)
14
34
  pnpm add -g @uniku/cli
@@ -30,7 +50,7 @@ uniku uuid
30
50
  # => 550e8400-e29b-41d4-a716-446655440000
31
51
 
32
52
  # UUID v7 (time-ordered)
33
- uniku uuid --version 7
53
+ uniku uuid --uuid-version 7
34
54
  # => 018e5e5c-7c8a-7000-8000-000000000000
35
55
 
36
56
  # Generate multiple IDs
@@ -117,11 +137,11 @@ For time-ordered IDs (UUID v7, ULID, KSUID), inspect extracts the embedded times
117
137
 
118
138
  | Command | Option | Alias | Description |
119
139
  |---------|--------|-------|-------------|
120
- | `uuid` | `--version` | `-v` | UUID version: 4 or 7 (default: 4) |
121
- | `uuid` | `--lowercase` | `-l` | Output in lowercase |
140
+ | `uuid` | `--uuid-version` | `-v` | UUID version: 4 or 7 (default: 4) |
141
+ | `uuid` | `--lowercase` | | Output in lowercase |
122
142
  | `ulid` | `--monotonic` | | Generate monotonically increasing ULIDs |
123
143
  | `ulid` | `--timestamp` | | Unix timestamp in ms or "now" |
124
- | `ulid` | `--lowercase` | `-l` | Output in lowercase |
144
+ | `ulid` | `--lowercase` | | Output in lowercase |
125
145
  | `nanoid` | `--size` | `-s` | Length of ID, 1-256 (default: 21) |
126
146
  | `nanoid` | `--alphabet` | `-a` | Custom alphabet or preset: hex, numeric, alpha |
127
147
  | `cuid` | `--length` | `-l` | Length of ID, 2-32 (default: 24) |
@@ -1 +1 @@
1
- {"version":3,"file":"bin.d.mts","names":[],"sources":["../src/bin.ts"],"sourcesContent":[],"mappings":";iBAmBgB,cAAA"}
1
+ {"version":3,"file":"bin.d.mts","names":[],"sources":["../src/bin.ts"],"sourcesContent":[],"mappings":";iBAqBgB,cAAA"}
package/build/bin.mjs CHANGED
@@ -1,6 +1,7 @@
1
- import{BunContext as e,BunRuntime as t}from"@effect/platform-bun";import*as n from"effect/Duration";import*as r from"effect/Effect";import*as i from"effect/Fiber";import*as a from"effect/Layer";import*as o from"effect/Option";import{Args as s,Command as c,Options as l}from"@effect/cli";import{cuid2 as u}from"uniku/cuid2";import{UniqueIdError as d}from"uniku/errors";import{ksuid as f}from"uniku/ksuid";import{nanoid as p}from"uniku/nanoid";import{ulid as m}from"uniku/ulid";import{uuidv4 as h}from"uniku/uuid/v4";import{uuidv7 as g}from"uniku/uuid/v7";import*as _ from"effect/Context";import{existsSync as v,mkdirSync as ee,readFileSync as te,renameSync as y,writeFileSync as b}from"node:fs";import{tmpdir as x}from"node:os";import{dirname as S,join as C}from"node:path";const w={hex:`0123456789abcdef`,numeric:`0123456789`,alpha:`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`};var T=class extends Error{constructor(e,t,n,r=1){super(t),this.code=e,this.hint=n,this.exitCode=r,this.name=`CliError`}},ne=class extends T{constructor(e){super(`VALIDATION_FAILED`,e,void 0,2),this.name=`ValidationFailedError`}};function E(e){return new T(e.code,e.message)}function re(e){let t={error:e.message,code:e.code};return e.hint&&(t.hint=e.hint),t}function ie(e){return r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++)t.push(u({length:e.length}));return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function ae(e){return r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=e.timestamp==null?void 0:{secs:e.timestamp};t.push(f(n))}return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function oe(e){if(e)return w[e]??e}function se(e){return r.try({try:()=>{let t=oe(e.alphabet),n=[];for(let r=0;r<e.count;r++)n.push(p({size:e.size,alphabet:t}));return n},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function ce(e){return e.monotonic&&e.timestamp!=null?r.fail(new T(`INVALID_OPTIONS`,`--monotonic and --timestamp are mutually exclusive`,`Use --monotonic for monotonically increasing ULIDs, or --timestamp to specify a fixed timestamp`)):r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=m(e.timestamp==null?void 0:{msecs:e.timestamp});e.lowercase&&(n=n.toLowerCase()),t.push(n)}return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function le(e){return r.try({try:()=>{let t=e.version===7?g:h,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 d?E(e):new T(`GENERATE_FAILED`,String(e))})}var D=class extends _.Tag(`OutputService`)(){};function ue(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 de(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 fe=D.of({writeIds(e,t){return r.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 r.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(`${ue(t)}\n`)})},writeInspect(e,t){return r.sync(()=>{t.json?process.stdout.write(`${JSON.stringify(e)}\n`):process.stdout.write(`${de(e)}\n`)})},writeError(e,t){return r.sync(()=>{if(t.json)process.stderr.write(`${JSON.stringify(re(e))}\n`);else{let t=`Error: ${e.message}`;e.hint&&(t+=`\n ${e.hint}`),process.stderr.write(`${t}\n`)}})}}),O=l.integer(`count`).pipe(l.withAlias(`n`),l.withDescription(`Number of IDs to generate`),l.withDefault(1)),k=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),A=l.choiceWithValue(`version`,[[`4`,4],[`7`,7]]).pipe(l.withAlias(`v`),l.withDescription(`UUID version: 4, 7`),l.withDefault(4)),j=l.boolean(`lowercase`).pipe(l.withAlias(`l`),l.withDescription(`Output in lowercase`),l.withDefault(!1)),M=c.make(`uuid`,{count:O,json:k,version:A,lowercase:j},({count:e,json:t,version:n,lowercase:i})=>r.gen(function*(){let r=yield*D,a=yield*le({count:e,version:n,lowercase:i});yield*r.writeIds(a,{json:t})})).pipe(c.withDescription(`Generate UUIDs (v4 or v7)`)),N=l.boolean(`monotonic`).pipe(l.withDescription(`Generate monotonically increasing ULIDs`),l.withDefault(!1)),P=l.text(`timestamp`).pipe(l.withDescription(`Unix timestamp in milliseconds (or "now")`),l.optional),F=c.make(`ulid`,{count:O,json:k,monotonic:N,timestamp:P,lowercase:j},({count:e,json:t,monotonic:n,timestamp:i,lowercase:a})=>r.gen(function*(){let r=yield*D,s=yield*ce({count:e,monotonic:n,timestamp:o.isSome(i)?ye(o.getOrThrow(i)):void 0,lowercase:a});yield*r.writeIds(s,{json:t})})).pipe(c.withDescription(`Generate ULIDs`)),I=l.integer(`size`).pipe(l.withAlias(`s`),l.withDescription(`Length of ID (1-256)`),l.withDefault(21)),L=l.text(`alphabet`).pipe(l.withAlias(`a`),l.withDescription(`Custom alphabet or preset: hex, numeric, alpha`),l.optional),R=c.make(`nanoid`,{count:O,json:k,size:I,alphabet:L},({count:e,json:t,size:n,alphabet:i})=>r.gen(function*(){let r=yield*D,a=yield*se({count:e,size:n,alphabet:o.isSome(i)?o.getOrThrow(i):void 0});yield*r.writeIds(a,{json:t})})).pipe(c.withDescription(`Generate Nanoids`)),z=l.integer(`length`).pipe(l.withAlias(`l`),l.withDescription(`Length of ID (2-32)`),l.withDefault(24)),B=c.make(`cuid`,{count:O,json:k,length:z},({count:e,json:t,length:n})=>r.gen(function*(){let r=yield*D,i=yield*ie({count:e,length:n});yield*r.writeIds(i,{json:t})})).pipe(c.withDescription(`Generate CUIDs (v2)`)),V=l.text(`timestamp`).pipe(l.withDescription(`Unix timestamp in seconds (or "now")`),l.optional),H=c.make(`ksuid`,{count:O,json:k,timestamp:V},({count:e,json:t,timestamp:n})=>r.gen(function*(){let r=yield*D,i=yield*ae({count:e,timestamp:o.isSome(n)?be(o.getOrThrow(n)):void 0});yield*r.writeIds(i,{json:t})})).pipe(c.withDescription(`Generate KSUIDs`)),pe=c.make(`generate`).pipe(c.withDescription(`Generate new IDs`),c.withSubcommands([M,F,R,B,H])),me=M,he=F,ge=R,_e=B,ve=H;function ye(e){if(e===`now`)return Date.now();let t=Number(e);if(!Number.isFinite(t)||t<0)throw new T(`INVALID_TIMESTAMP`,`Invalid timestamp: "${e}"`,`Provide a Unix timestamp in milliseconds or "now"`);return t}function be(e){if(e===`now`)return Math.floor(Date.now()/1e3);let t=Number(e);if(!Number.isFinite(t)||t<0)throw new T(`INVALID_TIMESTAMP`,`Invalid timestamp: "${e}"`,`Provide a Unix timestamp in seconds or "now"`);return t}function xe(e,t){switch(t){case`uuid`:return Se(e);case`ulid`:return Ce(e);case`ksuid`:return we(e);case`cuid`:return Te(e);case`nanoid`:return Ee(e)}}function U(e){return g.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:h.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:m.isValid(e)?{id:e,valid:!0,type:`ulid`}:f.isValid(e)?{id:e,valid:!0,type:`ksuid`}:u.isValid(e)?{id:e,valid:!0,type:`cuid`}:p.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,error:`malformed identifier`}}function Se(e){return g.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:h.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:{id:e,valid:!1,type:`uuid`,error:`invalid UUID format`}}function Ce(e){return m.isValid(e)?{id:e,valid:!0,type:`ulid`}:{id:e,valid:!1,type:`ulid`,error:`invalid ULID format`}}function we(e){return f.isValid(e)?{id:e,valid:!0,type:`ksuid`}:{id:e,valid:!1,type:`ksuid`,error:`invalid KSUID format`}}function Te(e){return u.isValid(e)?{id:e,valid:!0,type:`cuid`}:{id:e,valid:!1,type:`cuid`,error:`invalid CUID format`}}function Ee(e){return p.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,type:`nanoid`,error:`invalid Nanoid format`}}function De(e,t){let n=t??Oe(e);if(!n)return null;switch(n){case`uuid`:return ke(e);case`ulid`:return Ae(e);case`ksuid`:return je(e);case`cuid`:return Me(e);case`nanoid`:return Ne(e)}}function Oe(e){let t=U(e);return t.valid?t.type??null:null}function ke(e){if(g.isValid(e)){let t=g.timestamp(e),n=g.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 h.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 Ae(e){let t=m.timestamp(e),n=e.slice(10);return{id:e,type:`ulid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:n}}function je(e){let t=f.timestamp(e),n=f.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 Me(e){return{id:e,type:`cuid`,note:`This ID type contains no decodable metadata.`}}function Ne(e){return{id:e,type:`nanoid`,note:`This ID type contains no decodable metadata.`}}const Pe=s.text({name:`id`}).pipe(s.withDescription(`The ID to inspect`)),Fe=l.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(l.withDescription(`ID type (auto-detected if omitted)`),l.optional),Ie=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),Le=c.make(`inspect`,{id:Pe,type:Fe,json:Ie},({id:e,type:t,json:n})=>r.gen(function*(){let i=yield*D,a=De(e,o.isSome(t)?o.getOrThrow(t):void 0);if(!a){yield*r.fail(new T(`UNKNOWN_ID_TYPE`,`Could not identify ID type for: "${e}"`,`Use --type to specify the ID type`));return}yield*i.writeInspect(a,{json:n})})).pipe(c.withDescription(`Decode and inspect an ID`));var W=class extends _.Tag(`StdinService`)(){};const Re=W.of({readLines(){return r.async(e=>{let t=[];process.stdin.on(`data`,e=>{t.push(e)}),process.stdin.on(`end`,()=>{let n=Buffer.concat(t).toString(`utf-8`).split(`
3
- `).map(e=>e.trim()).filter(e=>e.length>0);e(r.succeed(n))}),process.stdin.on(`error`,t=>{e(r.fail(new T(`STDIN_ERROR`,t.message)))}),process.stdin.resume()})}}),ze=s.text({name:`id`}).pipe(s.withDescription(`The ID to validate`),s.optional),Be=l.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(l.withDescription(`Expected ID type (auto-detected if omitted)`),l.optional),Ve=l.boolean(`stdin`).pipe(l.withDescription(`Read IDs from stdin (one per line)`),l.withDefault(!1)),He=l.boolean(`json`).pipe(l.withDescription(`Output validation results as JSON`),l.withDefault(!1)),Ue=l.boolean(`quiet`).pipe(l.withDescription(`No output, exit code only`),l.withDefault(!1)),We=c.make(`validate`,{id:ze,type:Be,stdin:Ve,json:He,quiet:Ue},({id:e,type:t,stdin:n,json:i,quiet:a})=>r.gen(function*(){let s=yield*D,c=yield*W,l=o.isSome(t)?o.getOrThrow(t):void 0,u;if(n){if(u=yield*c.readLines(),u.length===0){yield*r.fail(new T(`NO_INPUT`,`No IDs provided on stdin`));return}}else if(o.isSome(e))u=[o.getOrThrow(e)];else{yield*r.fail(new T(`NO_INPUT`,`No ID provided`,`Pass an ID as argument or use --stdin`));return}let d=u.map(e=>l?xe(e,l):U(e));yield*s.writeValidation(d,{json:i,quiet:a}),d.some(e=>!e.valid)&&(yield*r.fail(new ne(`One or more IDs are invalid`)))})).pipe(c.withDescription(`Check if an ID is valid`)),Ge=c.make(`uniku`).pipe(c.withDescription(`Generate and validate unique identifiers`),c.withSubcommands([pe,We,Le,me,he,ge,_e,ve])),Ke=e=>c.run(Ge,{name:`uniku`,version:e});var G=class extends _.Tag(`UpdateCheckService`)(){};const K=`@uniku/cli`,q=C(x(),`uniku-update-check.json`);function J(e){let t=e.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);return t?{major:Number(t[1]),minor:Number(t[2]),patch:Number(t[3]),prerelease:t[4]??null}:null}function Y(e,t){let n=J(e),r=J(t);return!n||!r?!1:n.major===r.major?n.minor===r.minor?n.patch===r.patch?n.prerelease===null&&r.prerelease!==null?!0:(n.prerelease!==null&&r.prerelease,!1):n.patch>r.patch:n.minor>r.minor:n.major>r.major}function qe(){return!!process.env.NO_UPDATE_NOTIFIER||!!process.env.CI||!!process.env.CONTINUOUS_INTEGRATION||process.env.NODE_ENV===`test`||!process.stderr.isTTY}function X(e){if(process.env.NO_COLOR){let t=e.isStandaloneBinary?`Download at https://github.com/jkomyno/uniku/releases`:`Run \`npm install -g ${K}\` to update`;return[``,` Update available: ${e.currentVersion} → ${e.latestVersion}`,` ${t}`,` Set NO_UPDATE_NOTIFIER=1 to disable`,``].join(`
4
- `)}let t=`\x1B[2m`,n=`\x1B[36m`,r=`\x1B[0m`,i=e.isStandaloneBinary?`Download at ${n}https://github.com/jkomyno/uniku/releases${r}`:`Run ${n}\`npm install -g ${K}\`${r} to update`;return[``,` ${t}Update available:${r} ${t}${e.currentVersion}${r} ${t}→${r} ${e.latestVersion}${r}`,` ${i}`,` ${t}Set NO_UPDATE_NOTIFIER=1 to disable${r}`,``].join(`
5
- `)}function Je(){try{if(!v(q))return null;let e=te(q,`utf-8`);return JSON.parse(e)}catch{return null}}function Ye(e){try{ee(S(q),{recursive:!0});let t=`${q}.tmp`;b(t,JSON.stringify(e)),y(t,q)}catch{}}function Xe(e){return r.tryPromise({try:t=>fetch(`https://registry.npmjs.org/%40uniku%2Fcli/latest`,{headers:{Accept:`application/json`,"User-Agent":`${K}/${e}`},signal:AbortSignal.any([t,AbortSignal.timeout(5e3)])}).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();if(!t.version)throw Error(`Missing version field`);return t.version}),catch:()=>Error(`fetch failed`)}).pipe(r.catchAll(()=>r.succeed(null)))}function Z(){try{return typeof __STANDALONE_BINARY__<`u`&&__STANDALONE_BINARY__===!0}catch{return!1}}const Ze=G.of({check(e){return r.gen(function*(){if(qe())return o.none();let t=Je(),n=Date.now();if(t&&n-t.checkedAt<864e5)return Y(t.latestVersion,e)?o.some({currentVersion:e,latestVersion:t.latestVersion,isStandaloneBinary:Z()}):o.none();let r=yield*Xe(e);return r===null?o.none():(Ye({latestVersion:r,checkedAt:n}),Y(r,e)?o.some({currentVersion:e,latestVersion:r,isStandaloneBinary:Z()}):o.none())}).pipe(r.catchAll(()=>r.succeed(o.none())))},notify(e){return r.sync(()=>{process.stderr.write(X(e))})}});var Q=`0.0.12`;const Qe=Ke(Q);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 $e=a.mergeAll(a.succeed(D,fe),a.succeed(W,Re),a.succeed(G,Ze)),et=a.mergeAll($e,e.layer);r.gen(function*(){let e=yield*G,t=$(process.argv),a=yield*r.fork(e.check(Q));yield*r.suspend(()=>Qe(t)).pipe(r.catchAll(e=>r.sync(()=>{e instanceof T?(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)})));let s=yield*i.join(a).pipe(r.timeout(n.seconds(5)),r.catchAll(()=>r.succeed(o.none())));o.isSome(s)&&!t.includes(`--json`)&&(yield*e.notify(s.value))}).pipe(r.provide(et),t.runMain);export{$ as preprocessArgs};
1
+ #!/usr/bin/env node
2
+ import{BunContext as e,BunRuntime as t}from"@effect/platform-bun";import*as n from"effect/Duration";import*as r from"effect/Effect";import*as i from"effect/Fiber";import*as a from"effect/Layer";import*as o from"effect/Option";import{Args as s,Command as c,Options as l}from"@effect/cli";import{cuid2 as u}from"uniku/cuid2";import{UniqueIdError as d}from"uniku/errors";import{ksuid as f}from"uniku/ksuid";import{nanoid as p}from"uniku/nanoid";import{ulid as m}from"uniku/ulid";import{uuidv4 as h}from"uniku/uuid/v4";import{uuidv7 as g}from"uniku/uuid/v7";import*as _ from"effect/Context";import*as v from"@effect/cli/ValidationError";import{mkdirSync as ee,readFileSync as te,renameSync as ne,writeFileSync as y}from"node:fs";import{tmpdir as b,userInfo as x}from"node:os";import{dirname as S,join as C}from"node:path";import*as w from"effect/Config";const re={hex:`0123456789abcdef`,numeric:`0123456789`,alpha:`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`};var T=class extends Error{constructor(e,t,n,r=1){super(t),this.code=e,this.hint=n,this.exitCode=r,this.name=`CliError`}},ie=class extends T{constructor(e){super(`VALIDATION_FAILED`,e,void 0,2),this.name=`ValidationFailedError`}};function E(e){return new T(e.code,e.message)}function ae(e){let t={error:e.message,code:e.code};return e.hint&&(t.hint=e.hint),t}function oe(e){return r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++)t.push(u({length:e.length}));return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function se(e){return r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=e.timestamp==null?void 0:{secs:e.timestamp};t.push(f(n))}return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function ce(e){if(e)return re[e]??e}function le(e){return r.try({try:()=>{let t=ce(e.alphabet),n=[];for(let r=0;r<e.count;r++)n.push(p({size:e.size,alphabet:t}));return n},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function ue(e){return e.monotonic&&e.timestamp!=null?r.fail(new T(`INVALID_OPTIONS`,`--monotonic and --timestamp are mutually exclusive`,`Use --monotonic for monotonically increasing ULIDs, or --timestamp to specify a fixed timestamp`)):r.try({try:()=>{let t=[];for(let n=0;n<e.count;n++){let n=m(e.timestamp==null?void 0:{msecs:e.timestamp});e.lowercase&&(n=n.toLowerCase()),t.push(n)}return t},catch:e=>e instanceof d?E(e):new T(`GENERATE_FAILED`,String(e))})}function de(e){return r.try({try:()=>{let t=e.version===7?g:h,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 d?E(e):new T(`GENERATE_FAILED`,String(e))})}var D=class extends _.Tag(`OutputService`)(){};function fe(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 pe(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(`
3
+ `)}function me(e,t){if(t.json)return JSON.stringify(ae(e));let n=`Error: ${e.message}`;return e.hint&&(n+=`\n ${e.hint}`),n}const he=D.of({writeIds(e,t){return r.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 r.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(`${fe(t)}\n`)})},writeInspect(e,t){return r.sync(()=>{t.json?process.stdout.write(`${JSON.stringify(e)}\n`):process.stdout.write(`${pe(e)}\n`)})},writeError(e,t){return r.sync(()=>{process.stderr.write(`${me(e,t)}\n`)})}}),O=l.integer(`count`).pipe(l.withAlias(`n`),l.withDescription(`Number of IDs to generate`),l.withDefault(1)),k=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),A=l.choiceWithValue(`uuid-version`,[[`4`,4],[`7`,7]]).pipe(l.withAlias(`v`),l.withDescription(`UUID version: 4, 7`),l.withDefault(4)),j=l.boolean(`lowercase`).pipe(l.withDescription(`Output in lowercase`),l.withDefault(!1)),M=c.make(`uuid`,{count:O,json:k,version:A,lowercase:j},({count:e,json:t,version:n,lowercase:i})=>r.gen(function*(){let r=yield*D,a=yield*de({count:e,version:n,lowercase:i});yield*r.writeIds(a,{json:t})})).pipe(c.withDescription(`Generate UUIDs (v4 or v7)`)),N=l.boolean(`monotonic`).pipe(l.withDescription(`Generate monotonically increasing ULIDs`),l.withDefault(!1)),P=l.text(`timestamp`).pipe(l.withDescription(`Unix timestamp in milliseconds (or "now")`),l.optional),F=c.make(`ulid`,{count:O,json:k,monotonic:N,timestamp:P,lowercase:j},({count:e,json:t,monotonic:n,timestamp:i,lowercase:a})=>r.gen(function*(){let r=yield*D,s=yield*ue({count:e,monotonic:n,timestamp:o.isSome(i)?yield*we(o.getOrThrow(i)):void 0,lowercase:a});yield*r.writeIds(s,{json:t})})).pipe(c.withDescription(`Generate ULIDs`)),I=l.integer(`size`).pipe(l.withAlias(`s`),l.withDescription(`Length of ID (1-256)`),l.withDefault(21)),L=l.text(`alphabet`).pipe(l.withAlias(`a`),l.withDescription(`Custom alphabet or preset: hex, numeric, alpha`),l.optional),R=c.make(`nanoid`,{count:O,json:k,size:I,alphabet:L},({count:e,json:t,size:n,alphabet:i})=>r.gen(function*(){let r=yield*D,a=yield*le({count:e,size:n,alphabet:o.isSome(i)?o.getOrThrow(i):void 0});yield*r.writeIds(a,{json:t})})).pipe(c.withDescription(`Generate Nanoids`)),ge=l.integer(`length`).pipe(l.withAlias(`l`),l.withDescription(`Length of ID (2-32)`),l.withDefault(24)),z=c.make(`cuid`,{count:O,json:k,length:ge},({count:e,json:t,length:n})=>r.gen(function*(){let r=yield*D,i=yield*oe({count:e,length:n});yield*r.writeIds(i,{json:t})})).pipe(c.withDescription(`Generate CUIDs (v2)`)),_e=l.text(`timestamp`).pipe(l.withDescription(`Unix timestamp in seconds (or "now")`),l.optional),B=c.make(`ksuid`,{count:O,json:k,timestamp:_e},({count:e,json:t,timestamp:n})=>r.gen(function*(){let r=yield*D,i=yield*se({count:e,timestamp:o.isSome(n)?yield*Te(o.getOrThrow(n)):void 0});yield*r.writeIds(i,{json:t})})).pipe(c.withDescription(`Generate KSUIDs`)),ve=c.make(`generate`).pipe(c.withDescription(`Generate new IDs`),c.withSubcommands([M,F,R,z,B])),ye=M,be=F,xe=R,Se=z,Ce=B,we=e=>V(e,()=>Date.now(),`Provide a Unix timestamp in milliseconds or "now"`),Te=e=>V(e,()=>Math.floor(Date.now()/1e3),`Provide a Unix timestamp in seconds or "now"`);function V(e,t,n){if(e===`now`)return r.sync(t);let i=Number(e);return!Number.isFinite(i)||i<0?r.fail(new T(`INVALID_TIMESTAMP`,`Invalid timestamp: "${e}"`,n)):r.succeed(i)}function Ee(e,t){switch(t){case`uuid`:return De(e);case`ulid`:return Oe(e);case`ksuid`:return ke(e);case`cuid`:return Ae(e);case`nanoid`:return je(e)}}function H(e){return g.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:h.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:m.isValid(e)?{id:e,valid:!0,type:`ulid`}:f.isValid(e)?{id:e,valid:!0,type:`ksuid`}:u.isValid(e)?{id:e,valid:!0,type:`cuid`}:p.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,error:`malformed identifier`}}function De(e){return g.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:h.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:{id:e,valid:!1,type:`uuid`,error:`invalid UUID format`}}function Oe(e){return m.isValid(e)?{id:e,valid:!0,type:`ulid`}:{id:e,valid:!1,type:`ulid`,error:`invalid ULID format`}}function ke(e){return f.isValid(e)?{id:e,valid:!0,type:`ksuid`}:{id:e,valid:!1,type:`ksuid`,error:`invalid KSUID format`}}function Ae(e){return u.isValid(e)?{id:e,valid:!0,type:`cuid`}:{id:e,valid:!1,type:`cuid`,error:`invalid CUID format`}}function je(e){return p.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,type:`nanoid`,error:`invalid Nanoid format`}}function Me(e,t){let n=t??Ne(e);if(!n)return null;switch(n){case`uuid`:return Pe(e);case`ulid`:return Fe(e);case`ksuid`:return Ie(e);case`cuid`:return Le(e);case`nanoid`:return Re(e)}}function Ne(e){let t=H(e);return t.valid?t.type??null:null}function Pe(e){if(g.isValid(e)){let t=g.timestamp(e),n=g.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 h.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 Fe(e){let t=m.timestamp(e),n=e.slice(10);return{id:e,type:`ulid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:n}}function Ie(e){let t=f.timestamp(e),n=f.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 Le(e){return{id:e,type:`cuid`,note:`This ID type contains no decodable metadata.`}}function Re(e){return{id:e,type:`nanoid`,note:`This ID type contains no decodable metadata.`}}const ze=s.text({name:`id`}).pipe(s.withDescription(`The ID to inspect`)),Be=l.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(l.withDescription(`ID type (auto-detected if omitted)`),l.optional),Ve=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),He=c.make(`inspect`,{id:ze,type:Be,json:Ve},({id:e,type:t,json:n})=>r.gen(function*(){let i=yield*D,a=Me(e,o.isSome(t)?o.getOrThrow(t):void 0);if(!a){yield*r.fail(new T(`UNKNOWN_ID_TYPE`,`Could not identify ID type for: "${e}"`,`Use --type to specify the ID type`));return}yield*i.writeInspect(a,{json:n})})).pipe(c.withDescription(`Decode and inspect an ID`));var U=class extends _.Tag(`StdinService`)(){};const Ue=U.of({readLines(){return r.async(e=>{let t=[];process.stdin.on(`data`,e=>{t.push(e)}),process.stdin.on(`end`,()=>{let n=Buffer.concat(t).toString(`utf-8`).split(`
4
+ `).map(e=>e.trim()).filter(e=>e.length>0);e(r.succeed(n))}),process.stdin.on(`error`,t=>{e(r.fail(new T(`STDIN_ERROR`,t.message)))}),process.stdin.resume()})}}),We=s.text({name:`id`}).pipe(s.withDescription(`The ID to validate`),s.optional),Ge=l.choice(`type`,[`uuid`,`ulid`,`nanoid`,`cuid`,`ksuid`]).pipe(l.withDescription(`Expected ID type (auto-detected if omitted)`),l.optional),Ke=l.boolean(`stdin`).pipe(l.withDescription(`Read IDs from stdin (one per line)`),l.withDefault(!1)),qe=l.boolean(`json`).pipe(l.withDescription(`Output validation results as JSON`),l.withDefault(!1)),Je=l.boolean(`quiet`).pipe(l.withDescription(`No output, exit code only`),l.withDefault(!1)),Ye=c.make(`validate`,{id:We,type:Ge,stdin:Ke,json:qe,quiet:Je},({id:e,type:t,stdin:n,json:i,quiet:a})=>r.gen(function*(){let s=yield*D,c=yield*U,l=o.isSome(t)?o.getOrThrow(t):void 0,u;if(n){if(u=yield*c.readLines(),u.length===0){yield*r.fail(new T(`NO_INPUT`,`No IDs provided on stdin`));return}}else if(o.isSome(e))u=[o.getOrThrow(e)];else{yield*r.fail(new T(`NO_INPUT`,`No ID provided`,`Pass an ID as argument or use --stdin`));return}let d=u.map(e=>l?Ee(e,l):H(e));yield*s.writeValidation(d,{json:i,quiet:a}),d.some(e=>!e.valid)&&(yield*r.fail(new ie(`One or more IDs are invalid`)))})).pipe(c.withDescription(`Check if an ID is valid`)),Xe=c.make(`uniku`).pipe(c.withDescription(`Generate and validate unique identifiers`),c.withSubcommands([ve,Ye,He,ye,be,xe,Se,Ce])),Ze=e=>c.run(Xe,{name:`uniku`,version:e});function Qe(e){return e.includes(`--json`)}function $e(e,t){return e instanceof T?r.gen(function*(){yield*(yield*D).writeError(e,{json:Qe(t)}),process.exitCode=e.exitCode}):v.isValidationError(e)?r.sync(()=>{process.exitCode=1}):r.sync(()=>{process.stderr.write(`Error: ${et(e)}\n`),process.exitCode=1})}function et(e){return e instanceof Error?e.message:String(e)}var W=class extends _.Tag(`UpdateCheckService`)(){};const G=`@uniku/cli`;function tt(){let e=process.getuid;if(typeof e==`function`)return`uid-${e()}`;try{let e=x().username.replace(/[^0-9A-Za-z._-]/g,`_`);return e?`user-${e}`:null}catch{return null}}function nt(){let e=tt(),t=e?`uniku-update-check-${e}.json`:`uniku-update-check.json`;return C(b(),t)}const rt=nt();function K(e){let t=e.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/);return t?{major:Number(t[1]),minor:Number(t[2]),patch:Number(t[3]),prerelease:t[4]??null}:null}function q(e,t){let n=K(e),r=K(t);return!n||!r?!1:n.major===r.major?n.minor===r.minor?n.patch===r.patch?n.prerelease===null&&r.prerelease!==null?!0:(n.prerelease!==null&&r.prerelease,!1):n.patch>r.patch:n.minor>r.minor:n.major>r.major}function J(e){return w.option(w.string(e)).pipe(r.catchAll(()=>r.succeed(o.none())))}function Y(e){return o.isSome(e)&&e.value.length>0}const it=r.all({noUpdateNotifier:J(`NO_UPDATE_NOTIFIER`),ci:J(`CI`),continuousIntegration:J(`CONTINUOUS_INTEGRATION`),nodeEnv:J(`NODE_ENV`)});function at(e=process.stderr.isTTY){return it.pipe(r.map(t=>Y(t.noUpdateNotifier)||Y(t.ci)||Y(t.continuousIntegration)||o.isSome(t.nodeEnv)&&t.nodeEnv.value===`test`||!e))}function ot(e,t){if(t){let t=e.isStandaloneBinary?`Download at https://github.com/jkomyno/uniku/releases`:`Run \`npm install -g ${G}\` to update`;return[``,` Update available: ${e.currentVersion} → ${e.latestVersion}`,` ${t}`,` Set NO_UPDATE_NOTIFIER=1 to disable`,``].join(`
5
+ `)}let n=`\x1B[2m`,r=`\x1B[36m`,i=`\x1B[0m`,a=e.isStandaloneBinary?`Download at ${r}https://github.com/jkomyno/uniku/releases${i}`:`Run ${r}\`npm install -g ${G}\`${i} to update`;return[``,` ${n}Update available:${i} ${n}${e.currentVersion}${i} ${n}→${i} ${e.latestVersion}${i}`,` ${a}`,` ${n}Set NO_UPDATE_NOTIFIER=1 to disable${i}`,``].join(`
6
+ `)}function st(e){return J(`NO_COLOR`).pipe(r.map(t=>ot(e,Y(t))))}function X(e,t){return o.isSome(t)&&!e.includes(`--json`)}function ct(e){try{let t=te(e,`utf-8`),n=JSON.parse(t);if(typeof n!=`object`||!n)return null;let r=n;return typeof r.checkedAt!=`number`||!Number.isFinite(r.checkedAt)||r.latestVersion!==void 0&&typeof r.latestVersion!=`string`?null:r.latestVersion===void 0?{checkedAt:r.checkedAt}:{latestVersion:r.latestVersion,checkedAt:r.checkedAt}}catch{return null}}function Z(e,t){try{ee(S(t),{recursive:!0});let n=`${t}.tmp`;y(n,JSON.stringify(e)),ne(n,t)}catch{}}function lt(e){return r.tryPromise({try:t=>fetch(`https://registry.npmjs.org/%40uniku%2Fcli/latest`,{headers:{Accept:`application/json`,"User-Agent":`${G}/${e}`},signal:AbortSignal.any([t,AbortSignal.timeout(5e3)])}).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();if(!t.version)throw Error(`Missing version field`);return t.version}),catch:()=>Error(`fetch failed`)}).pipe(r.catchAll(()=>r.succeed(null)))}function ut(){try{return typeof __STANDALONE_BINARY__<`u`&&__STANDALONE_BINARY__===!0}catch{return!1}}function dt(e={}){let t=e.cacheFile??rt,n=e.fetchLatestVersion??lt,i=e.now??Date.now,a=e.isStandaloneBinary??ut,s=e.isStderrTTY??(()=>process.stderr.isTTY),c=e.writeStderr??(e=>process.stderr.write(e));return W.of({check(e){return r.gen(function*(){if(yield*at(s()))return o.none();let r=ct(t),c=i();if(r&&c-r.checkedAt<864e5)return r.latestVersion&&q(r.latestVersion,e)?o.some({currentVersion:e,latestVersion:r.latestVersion,isStandaloneBinary:a()}):o.none();let l=yield*n(e);return l===null?(Z({checkedAt:c},t),o.none()):(Z({latestVersion:l,checkedAt:c},t),q(l,e)?o.some({currentVersion:e,latestVersion:l,isStandaloneBinary:a()}):o.none())}).pipe(r.catchAll(()=>r.succeed(o.none())))},notify(e){return r.gen(function*(){let t=yield*st(e);yield*r.sync(()=>{c(t)})})}})}const ft=dt();var Q=`0.0.13`;const pt=Ze(Q);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 mt=a.mergeAll(a.succeed(D,he),a.succeed(U,Ue),a.succeed(W,ft)),ht=a.mergeAll(mt,e.layer);r.gen(function*(){let e=yield*W,t=$(process.argv),a=yield*r.fork(e.check(Q));yield*r.suspend(()=>pt(t)).pipe(r.catchAll(e=>$e(e,t)));let s=yield*i.join(a).pipe(r.timeout(n.millis(250)),r.catchAll(()=>r.succeed(o.none())));X(t,s)&&(yield*e.notify(s.value))}).pipe(r.provide(ht),t.runMain);export{$ as preprocessArgs};
6
7
  //# sourceMappingURL=bin.mjs.map
package/build/bin.mjs.map CHANGED
@@ -1 +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[]","version","updateCmd","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","../src/services/UpdateCheckService.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 { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport * as Context from 'effect/Context'\nimport * as Effect from 'effect/Effect'\nimport * as Option from 'effect/Option'\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface UpdateInfo {\n readonly currentVersion: string\n readonly latestVersion: string\n readonly isStandaloneBinary: boolean\n}\n\ninterface UpdateCache {\n readonly latestVersion: string\n readonly checkedAt: number\n}\n\n// ── Service tag ──────────────────────────────────────────────────────\n\nexport class UpdateCheckService extends Context.Tag('UpdateCheckService')<\n UpdateCheckService,\n {\n /** Check for available updates. Returns Some(info) if update available, None otherwise. */\n readonly check: (currentVersion: string) => Effect.Effect<Option.Option<UpdateInfo>>\n /** Print the update notification to stderr. */\n readonly notify: (info: UpdateInfo) => Effect.Effect<void>\n }\n>() {}\n\n// ── Constants ────────────────────────────────────────────────────────\n\nconst PACKAGE_NAME = '@uniku/cli'\nconst REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`\nconst CACHE_FILE = join(tmpdir(), 'uniku-update-check.json')\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\nconst FETCH_TIMEOUT_MS = 5_000\n\n// ── Version comparison ───────────────────────────────────────────────\n\n/**\n * Parse a semver version string into its components.\n * Returns null if the string is not a valid semver.\n */\nexport function parseSemver(version: string) {\n const match = version.match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-(.+))?$/)\n if (!match) return null\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n prerelease: match[4] ?? null,\n }\n}\n\n/**\n * Returns true if `latest` is newer than `current`.\n *\n * Handles pre-release correctly:\n * - 1.0.0 > 1.0.0-beta.1 (stable is newer than pre-release of same version)\n * - 1.0.0-beta.1 > 0.9.0 (pre-release of higher version is newer)\n */\nexport function isNewerVersion(latest: string, current: string): boolean {\n const l = parseSemver(latest)\n const c = parseSemver(current)\n if (!l || !c) return false\n\n if (l.major !== c.major) return l.major > c.major\n if (l.minor !== c.minor) return l.minor > c.minor\n if (l.patch !== c.patch) return l.patch > c.patch\n\n // Same major.minor.patch — stable (no prerelease) beats pre-release\n if (l.prerelease === null && c.prerelease !== null) return true\n if (l.prerelease !== null && c.prerelease === null) return false\n\n return false\n}\n\n// ── Skip conditions ──────────────────────────────────────────────────\n\nexport function shouldSkipUpdateCheck(): boolean {\n return (\n !!process.env.NO_UPDATE_NOTIFIER ||\n !!process.env.CI ||\n !!process.env.CONTINUOUS_INTEGRATION ||\n process.env.NODE_ENV === 'test' ||\n !process.stderr.isTTY\n )\n}\n\n// ── Notification formatting ──────────────────────────────────────────\n\nexport function formatNotification(info: UpdateInfo): string {\n const noColor = !!process.env.NO_COLOR\n\n if (noColor) {\n const updateCmd = info.isStandaloneBinary\n ? `Download at https://github.com/jkomyno/uniku/releases`\n : `Run \\`npm install -g ${PACKAGE_NAME}\\` to update`\n return [\n '',\n ` Update available: ${info.currentVersion} → ${info.latestVersion}`,\n ` ${updateCmd}`,\n ` Set NO_UPDATE_NOTIFIER=1 to disable`,\n '',\n ].join('\\n')\n }\n\n const dim = '\\x1b[2m'\n const cyan = '\\x1b[36m'\n const boldCyan = '\\x1b[1;36m'\n const reset = '\\x1b[0m'\n\n const updateCmd = info.isStandaloneBinary\n ? `Download at ${cyan}https://github.com/jkomyno/uniku/releases${reset}`\n : `Run ${cyan}\\`npm install -g ${PACKAGE_NAME}\\`${reset} to update`\n\n return [\n '',\n ` ${dim}Update available:${reset} ${dim}${info.currentVersion}${reset} ${dim}→${reset} ${boldCyan}${info.latestVersion}${reset}`,\n ` ${updateCmd}`,\n ` ${dim}Set NO_UPDATE_NOTIFIER=1 to disable${reset}`,\n '',\n ].join('\\n')\n}\n\n// ── Cache helpers (plain Node.js — maximally resilient) ──────────────\n\nfunction readCache(): UpdateCache | null {\n try {\n if (!existsSync(CACHE_FILE)) return null\n const content = readFileSync(CACHE_FILE, 'utf-8')\n return JSON.parse(content) as UpdateCache\n } catch {\n return null\n }\n}\n\nfunction writeCache(cache: UpdateCache): void {\n try {\n const dir = dirname(CACHE_FILE)\n mkdirSync(dir, { recursive: true })\n const tmpPath = `${CACHE_FILE}.tmp`\n writeFileSync(tmpPath, JSON.stringify(cache))\n renameSync(tmpPath, CACHE_FILE)\n } catch {\n // Silently ignore write errors\n }\n}\n\n// ── Registry fetch ───────────────────────────────────────────────────\n\nfunction fetchLatestVersion(currentVersion: string): Effect.Effect<string | null> {\n return Effect.tryPromise({\n try: (signal) =>\n fetch(REGISTRY_URL, {\n headers: {\n Accept: 'application/json',\n 'User-Agent': `${PACKAGE_NAME}/${currentVersion}`,\n },\n signal: AbortSignal.any([signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]),\n }).then(async (res) => {\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const data = (await res.json()) as { version?: string }\n if (!data.version) throw new Error('Missing version field')\n return data.version\n }),\n catch: () => new Error('fetch failed'),\n }).pipe(Effect.catchAll(() => Effect.succeed(null)))\n}\n\n// ── Standalone binary detection ──────────────────────────────────────\n\ndeclare const __STANDALONE_BINARY__: boolean | undefined\n\nfunction isStandaloneBinary(): boolean {\n try {\n return typeof __STANDALONE_BINARY__ !== 'undefined' && __STANDALONE_BINARY__ === true\n } catch {\n return false\n }\n}\n\n// ── Live implementation ──────────────────────────────────────────────\n\nexport const UpdateCheckServiceLive = UpdateCheckService.of({\n check(currentVersion) {\n return Effect.gen(function* () {\n if (shouldSkipUpdateCheck()) {\n return Option.none()\n }\n\n const cached = readCache()\n const now = Date.now()\n\n // Cache is fresh — use cached result\n if (cached && now - cached.checkedAt < CACHE_TTL_MS) {\n if (isNewerVersion(cached.latestVersion, currentVersion)) {\n return Option.some<UpdateInfo>({\n currentVersion,\n latestVersion: cached.latestVersion,\n isStandaloneBinary: isStandaloneBinary(),\n })\n }\n return Option.none()\n }\n\n // Cache is stale or missing — fetch from registry\n const latestVersion = yield* fetchLatestVersion(currentVersion)\n\n if (latestVersion === null) {\n return Option.none()\n }\n\n writeCache({ latestVersion, checkedAt: now })\n\n if (isNewerVersion(latestVersion, currentVersion)) {\n return Option.some<UpdateInfo>({\n currentVersion,\n latestVersion,\n isStandaloneBinary: isStandaloneBinary(),\n })\n }\n\n return Option.none()\n }).pipe(Effect.catchAll(() => Effect.succeed(Option.none())))\n },\n\n notify(info) {\n return Effect.sync(() => {\n process.stderr.write(formatNotification(info))\n })\n },\n})\n","","import { BunContext, BunRuntime } from '@effect/platform-bun'\nimport * as Duration from 'effect/Duration'\nimport * as Effect from 'effect/Effect'\nimport * as Fiber from 'effect/Fiber'\nimport * as Layer from 'effect/Layer'\nimport * as Option from 'effect/Option'\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 { UpdateCheckService, UpdateCheckServiceLive } from '@/src/services/UpdateCheckService'\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 Layer.succeed(UpdateCheckService, UpdateCheckServiceLive),\n)\n\nconst MainLayer = Layer.mergeAll(ServicesLayer, BunContext.layer)\n\n// ── Run ─────────────────────────────────────────────────────────────\n\nconst program = Effect.gen(function* () {\n const updateCheck = yield* UpdateCheckService\n const args = preprocessArgs(process.argv)\n\n // Fork update check as a background fiber\n const fiber = yield* Effect.fork(updateCheck.check(pkg.version))\n\n // Run the main CLI command\n yield* Effect.suspend(() => cli(args)).pipe(\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 process.stderr.write(`Error: ${String(err)}\\n`)\n process.exitCode = 1\n }\n }),\n ),\n )\n\n // After main command, join fiber with timeout\n const result = yield* Fiber.join(fiber).pipe(\n Effect.timeout(Duration.seconds(5)),\n Effect.catchAll(() => Effect.succeed(Option.none())),\n )\n\n // Show notification unless --json is active\n if (Option.isSome(result) && !args.includes('--json')) {\n yield* updateCheck.notify(result.value)\n }\n})\n\nprogram.pipe(Effect.provide(MainLayer), BunRuntime.runMain)\n"],"mappings":"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"}
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[]","version","updateCmd","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","../src/runtime/cli-failure.ts","../src/services/UpdateCheckService.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\nexport function 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\nexport function 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\nexport function formatError(error: CliError, options: OutputOptions): string {\n if (options.json) {\n return JSON.stringify(errorToJson(error))\n }\n\n let msg = `Error: ${error.message}`\n if (error.hint) {\n msg += `\\n ${error.hint}`\n }\n return msg\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 process.stderr.write(`${formatError(error, options)}\\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('uuid-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.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)\n ? yield* parseTimestampMs(Option.getOrThrow(timestampOpt))\n : 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)\n ? yield* parseTimestampSecs(Option.getOrThrow(timestampOpt))\n : 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\nconst parseTimestampMs = (input: string): Effect.Effect<number, CliError> =>\n parseTimestamp(input, () => Date.now(), 'Provide a Unix timestamp in milliseconds or \"now\"')\n\nconst parseTimestampSecs = (input: string): Effect.Effect<number, CliError> =>\n parseTimestamp(input, () => Math.floor(Date.now() / 1000), 'Provide a Unix timestamp in seconds or \"now\"')\n\nfunction parseTimestamp(input: string, now: () => number, hint: string): Effect.Effect<number, CliError> {\n if (input === 'now') return Effect.sync(now)\n const n = Number(input)\n if (!Number.isFinite(n) || n < 0) {\n return Effect.fail(new CliError('INVALID_TIMESTAMP', `Invalid timestamp: \"${input}\"`, hint))\n }\n return Effect.succeed(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 * as ValidationError from '@effect/cli/ValidationError'\nimport * as Effect from 'effect/Effect'\nimport { CliError } from '@/src/domain/errors'\nimport { OutputService } from '@/src/services/OutputService'\n\nconst EXIT_CODE_FAILURE = 1\n\nfunction usesJsonOutput(args: readonly string[]): boolean {\n return args.includes('--json')\n}\n\nexport function handleCliFailure(error: unknown, args: readonly string[]): Effect.Effect<void, never, OutputService> {\n if (error instanceof CliError) {\n return Effect.gen(function* () {\n const output = yield* OutputService\n yield* output.writeError(error, { json: usesJsonOutput(args) })\n process.exitCode = error.exitCode\n })\n }\n\n if (ValidationError.isValidationError(error)) {\n return Effect.sync(() => {\n process.exitCode = EXIT_CODE_FAILURE\n })\n }\n\n return Effect.sync(() => {\n process.stderr.write(`Error: ${formatUnknownError(error)}\\n`)\n process.exitCode = EXIT_CODE_FAILURE\n })\n}\n\nfunction formatUnknownError(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { tmpdir, userInfo } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport * as Config from 'effect/Config'\nimport * as Context from 'effect/Context'\nimport * as Effect from 'effect/Effect'\nimport * as Option from 'effect/Option'\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface UpdateInfo {\n readonly currentVersion: string\n readonly latestVersion: string\n readonly isStandaloneBinary: boolean\n}\n\ninterface UpdateCache {\n readonly latestVersion?: string\n readonly checkedAt: number\n}\n\ninterface UpdateCheckServiceOptions {\n readonly cacheFile?: string\n readonly fetchLatestVersion?: (currentVersion: string) => Effect.Effect<string | null>\n readonly isStandaloneBinary?: () => boolean\n readonly isStderrTTY?: () => boolean\n readonly now?: () => number\n readonly writeStderr?: (message: string) => void\n}\n\n// ── Service tag ──────────────────────────────────────────────────────\n\nexport class UpdateCheckService extends Context.Tag('UpdateCheckService')<\n UpdateCheckService,\n {\n /** Check for available updates. Returns Some(info) if update available, None otherwise. */\n readonly check: (currentVersion: string) => Effect.Effect<Option.Option<UpdateInfo>>\n /** Print the update notification to stderr. */\n readonly notify: (info: UpdateInfo) => Effect.Effect<void>\n }\n>() {}\n\n// ── Constants ────────────────────────────────────────────────────────\n\nconst PACKAGE_NAME = '@uniku/cli'\nconst REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`\nexport const CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\nconst FETCH_TIMEOUT_MS = 5_000\n\nfunction cacheUserSegment(): string | null {\n const getuid = (process as { getuid?: () => number }).getuid\n if (typeof getuid === 'function') {\n return `uid-${getuid()}`\n }\n\n try {\n const segment = userInfo().username.replace(/[^0-9A-Za-z._-]/g, '_')\n return segment ? `user-${segment}` : null\n } catch {\n return null\n }\n}\n\nfunction defaultCacheFile(): string {\n const userSegment = cacheUserSegment()\n const filename = userSegment ? `uniku-update-check-${userSegment}.json` : 'uniku-update-check.json'\n return join(tmpdir(), filename)\n}\n\nexport const DEFAULT_CACHE_FILE = defaultCacheFile()\n\n// ── Version comparison ───────────────────────────────────────────────\n\n/**\n * Parse a semver version string into its components.\n * Returns null if the string is not a valid semver.\n */\nexport function parseSemver(version: string) {\n const match = version.match(/^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?$/)\n if (!match) return null\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n prerelease: match[4] ?? null,\n }\n}\n\n/**\n * Returns true if `latest` is newer than `current`.\n *\n * Handles pre-release correctly:\n * - 1.0.0 > 1.0.0-beta.1 (stable is newer than pre-release of same version)\n * - 1.0.0-beta.1 > 0.9.0 (pre-release of higher version is newer)\n */\nexport function isNewerVersion(latest: string, current: string): boolean {\n const l = parseSemver(latest)\n const c = parseSemver(current)\n if (!l || !c) return false\n\n if (l.major !== c.major) return l.major > c.major\n if (l.minor !== c.minor) return l.minor > c.minor\n if (l.patch !== c.patch) return l.patch > c.patch\n\n // Same major.minor.patch — stable (no prerelease) beats pre-release\n if (l.prerelease === null && c.prerelease !== null) return true\n if (l.prerelease !== null && c.prerelease === null) return false\n\n return false\n}\n\n// ── Skip conditions ──────────────────────────────────────────────────\n\nfunction optionalConfigString(name: string): Effect.Effect<Option.Option<string>> {\n return Config.option(Config.string(name)).pipe(Effect.catchAll(() => Effect.succeed(Option.none())))\n}\n\nfunction isTruthyConfig(value: Option.Option<string>): boolean {\n return Option.isSome(value) && value.value.length > 0\n}\n\nconst updateCheckConfig = Effect.all({\n noUpdateNotifier: optionalConfigString('NO_UPDATE_NOTIFIER'),\n ci: optionalConfigString('CI'),\n continuousIntegration: optionalConfigString('CONTINUOUS_INTEGRATION'),\n nodeEnv: optionalConfigString('NODE_ENV'),\n})\n\nexport function shouldSkipUpdateCheck(isStderrTTY = process.stderr.isTTY): Effect.Effect<boolean> {\n return updateCheckConfig.pipe(\n Effect.map(\n (config) =>\n isTruthyConfig(config.noUpdateNotifier) ||\n isTruthyConfig(config.ci) ||\n isTruthyConfig(config.continuousIntegration) ||\n (Option.isSome(config.nodeEnv) && config.nodeEnv.value === 'test') ||\n !isStderrTTY,\n ),\n )\n}\n\n// ── Notification formatting ──────────────────────────────────────────\n\nfunction formatNotificationWithColor(info: UpdateInfo, noColor: boolean): string {\n if (noColor) {\n const updateCmd = info.isStandaloneBinary\n ? `Download at https://github.com/jkomyno/uniku/releases`\n : `Run \\`npm install -g ${PACKAGE_NAME}\\` to update`\n return [\n '',\n ` Update available: ${info.currentVersion} → ${info.latestVersion}`,\n ` ${updateCmd}`,\n ` Set NO_UPDATE_NOTIFIER=1 to disable`,\n '',\n ].join('\\n')\n }\n\n const dim = '\\x1b[2m'\n const cyan = '\\x1b[36m'\n const boldCyan = '\\x1b[1;36m'\n const reset = '\\x1b[0m'\n\n const updateCmd = info.isStandaloneBinary\n ? `Download at ${cyan}https://github.com/jkomyno/uniku/releases${reset}`\n : `Run ${cyan}\\`npm install -g ${PACKAGE_NAME}\\`${reset} to update`\n\n return [\n '',\n ` ${dim}Update available:${reset} ${dim}${info.currentVersion}${reset} ${dim}→${reset} ${boldCyan}${info.latestVersion}${reset}`,\n ` ${updateCmd}`,\n ` ${dim}Set NO_UPDATE_NOTIFIER=1 to disable${reset}`,\n '',\n ].join('\\n')\n}\n\nexport function formatNotification(info: UpdateInfo): Effect.Effect<string> {\n return optionalConfigString('NO_COLOR').pipe(\n Effect.map((noColor) => formatNotificationWithColor(info, isTruthyConfig(noColor))),\n )\n}\n\nexport function shouldNotifyUpdate(\n args: readonly string[],\n result: Option.Option<UpdateInfo>,\n): result is Option.Some<UpdateInfo> {\n return Option.isSome(result) && !args.includes('--json')\n}\n\n// ── Cache helpers (plain Node.js — maximally resilient) ──────────────\n\nfunction readCache(cacheFile: string): UpdateCache | null {\n try {\n const content = readFileSync(cacheFile, 'utf-8')\n const parsed = JSON.parse(content) as unknown\n\n if (typeof parsed !== 'object' || parsed === null) return null\n const cache = parsed as { checkedAt?: unknown; latestVersion?: unknown }\n if (typeof cache.checkedAt !== 'number' || !Number.isFinite(cache.checkedAt)) return null\n if (cache.latestVersion !== undefined && typeof cache.latestVersion !== 'string') return null\n\n return cache.latestVersion === undefined\n ? { checkedAt: cache.checkedAt }\n : { latestVersion: cache.latestVersion, checkedAt: cache.checkedAt }\n } catch {\n return null\n }\n}\n\nfunction writeCache(cache: UpdateCache, cacheFile: string): void {\n try {\n const dir = dirname(cacheFile)\n mkdirSync(dir, { recursive: true })\n const tmpPath = `${cacheFile}.tmp`\n writeFileSync(tmpPath, JSON.stringify(cache))\n renameSync(tmpPath, cacheFile)\n } catch {\n // Silently ignore write errors\n }\n}\n\n// ── Registry fetch ───────────────────────────────────────────────────\n\nfunction fetchLatestVersion(currentVersion: string): Effect.Effect<string | null> {\n return Effect.tryPromise({\n try: (signal) =>\n fetch(REGISTRY_URL, {\n headers: {\n Accept: 'application/json',\n 'User-Agent': `${PACKAGE_NAME}/${currentVersion}`,\n },\n signal: AbortSignal.any([signal, AbortSignal.timeout(FETCH_TIMEOUT_MS)]),\n }).then(async (res) => {\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const data = (await res.json()) as { version?: string }\n if (!data.version) throw new Error('Missing version field')\n return data.version\n }),\n catch: () => new Error('fetch failed'),\n }).pipe(Effect.catchAll(() => Effect.succeed(null)))\n}\n\n// ── Standalone binary detection ──────────────────────────────────────\n\ndeclare const __STANDALONE_BINARY__: boolean | undefined\n\nfunction isStandaloneBinary(): boolean {\n try {\n return typeof __STANDALONE_BINARY__ !== 'undefined' && __STANDALONE_BINARY__ === true\n } catch {\n return false\n }\n}\n\n// ── Live implementation ──────────────────────────────────────────────\n\nexport function makeUpdateCheckService(options: UpdateCheckServiceOptions = {}) {\n const cacheFile = options.cacheFile ?? DEFAULT_CACHE_FILE\n const fetchVersion = options.fetchLatestVersion ?? fetchLatestVersion\n const getNow = options.now ?? Date.now\n const detectStandaloneBinary = options.isStandaloneBinary ?? isStandaloneBinary\n const isStderrTTY = options.isStderrTTY ?? (() => process.stderr.isTTY)\n const writeStderr = options.writeStderr ?? ((message: string) => process.stderr.write(message))\n\n return UpdateCheckService.of({\n check(currentVersion) {\n return Effect.gen(function* () {\n if (yield* shouldSkipUpdateCheck(isStderrTTY())) {\n return Option.none()\n }\n\n const cached = readCache(cacheFile)\n const now = getNow()\n\n // Cache is fresh — use cached result\n if (cached && now - cached.checkedAt < CACHE_TTL_MS) {\n if (cached.latestVersion && isNewerVersion(cached.latestVersion, currentVersion)) {\n return Option.some<UpdateInfo>({\n currentVersion,\n latestVersion: cached.latestVersion,\n isStandaloneBinary: detectStandaloneBinary(),\n })\n }\n return Option.none()\n }\n\n // Cache is stale or missing — fetch from registry\n const latestVersion = yield* fetchVersion(currentVersion)\n\n if (latestVersion === null) {\n writeCache({ checkedAt: now }, cacheFile)\n return Option.none()\n }\n\n writeCache({ latestVersion, checkedAt: now }, cacheFile)\n\n if (isNewerVersion(latestVersion, currentVersion)) {\n return Option.some<UpdateInfo>({\n currentVersion,\n latestVersion,\n isStandaloneBinary: detectStandaloneBinary(),\n })\n }\n\n return Option.none()\n }).pipe(Effect.catchAll(() => Effect.succeed(Option.none())))\n },\n\n notify(info) {\n return Effect.gen(function* () {\n const message = yield* formatNotification(info)\n yield* Effect.sync(() => {\n writeStderr(message)\n })\n })\n },\n })\n}\n\nexport const UpdateCheckServiceLive = makeUpdateCheckService()\n","","#!/usr/bin/env node\n\nimport { BunContext, BunRuntime } from '@effect/platform-bun'\nimport * as Duration from 'effect/Duration'\nimport * as Effect from 'effect/Effect'\nimport * as Fiber from 'effect/Fiber'\nimport * as Layer from 'effect/Layer'\nimport * as Option from 'effect/Option'\nimport { makeCliRunner } from '@/src/commands'\nimport { handleCliFailure } from '@/src/runtime/cli-failure'\nimport { OutputService, OutputServiceLive } from '@/src/services/OutputService'\nimport { StdinService, StdinServiceLive } from '@/src/services/StdinService'\nimport { shouldNotifyUpdate, UpdateCheckService, UpdateCheckServiceLive } from '@/src/services/UpdateCheckService'\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 Layer.succeed(UpdateCheckService, UpdateCheckServiceLive),\n)\n\nconst MainLayer = Layer.mergeAll(ServicesLayer, BunContext.layer)\n\n// ── Run ─────────────────────────────────────────────────────────────\n\nconst program = Effect.gen(function* () {\n const updateCheck = yield* UpdateCheckService\n const args = preprocessArgs(process.argv)\n\n // Fork update check as a background fiber\n const fiber = yield* Effect.fork(updateCheck.check(pkg.version))\n\n // Run the main CLI command\n yield* Effect.suspend(() => cli(args)).pipe(Effect.catchAll((err) => handleCliFailure(err, args)))\n\n // After main command, join fiber with timeout\n const result = yield* Fiber.join(fiber).pipe(\n Effect.timeout(Duration.millis(250)),\n Effect.catchAll(() => Effect.succeed(Option.none())),\n )\n\n // Show notification unless --json is active\n if (shouldNotifyUpdate(args, result)) {\n yield* updateCheck.notify(result.value)\n }\n})\n\nprogram.pipe(Effect.provide(MainLayer), BunRuntime.runMain)\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@uniku/cli",
4
- "version": "0.0.12",
4
+ "version": "0.0.13",
5
5
  "description": "CLI tool for generating and validating unique identifiers",
6
6
  "author": {
7
7
  "name": "Alberto Schiabel",
@@ -18,6 +18,9 @@
18
18
  "bin": {
19
19
  "uniku": "./build/bin.mjs"
20
20
  },
21
+ "engines": {
22
+ "node": ">=20.19.0"
23
+ },
21
24
  "publishConfig": {
22
25
  "registry": "https://registry.npmjs.org/",
23
26
  "access": "public"
@@ -31,7 +34,7 @@
31
34
  "@effect/cli": "0.73.2",
32
35
  "@effect/platform": "0.94.3",
33
36
  "@effect/platform-bun": "0.87.1",
34
- "uniku": "0.0.12"
37
+ "uniku": "0.0.13"
35
38
  },
36
39
  "devDependencies": {
37
40
  "@types/bun": "^1.3.8",
@@ -45,6 +48,7 @@
45
48
  "install:binary": "bun scripts/install-binary.ts",
46
49
  "typecheck": "tsc --noEmit",
47
50
  "test": "vitest run",
51
+ "test:unit": "vitest run",
48
52
  "test:watch": "vitest"
49
53
  }
50
54
  }