@uniku/cli 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +25 -199
  2. package/build/bin.mjs +1 -1
  3. package/package.json +6 -2
package/README.md CHANGED
@@ -1,230 +1,56 @@
1
1
  # @uniku/cli
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@uniku/cli.svg)](https://www.npmjs.com/package/@uniku/cli)
4
+ [![Documentation](https://img.shields.io/badge/docs-CLI-5b5bd6.svg)](https://jkomyno.github.io/uniku/docs/cli/)
4
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
6
 
6
- Command-line tool for generating, validating, and inspecting unique identifiers.
7
+ Generate, validate, and inspect IDs from a terminal or shell pipeline. The CLI supports every format in `uniku`: UUID v4/v7, ULID, TypeID, CUID v2, Nanoid, KSUID, ObjectID, XID, and TSID.
7
8
 
8
- Supports UUID v4/v7, ULID, TypeID, CUID2, Nanoid, KSUID, MongoDB ObjectID, TSID, and XID.
9
+ [CLI documentation](https://jkomyno.github.io/uniku/docs/cli/) · [GitHub releases](https://github.com/jkomyno/uniku/releases) · [Library documentation](https://jkomyno.github.io/uniku/)
9
10
 
10
- ## Installation
11
+ ## Install
11
12
 
12
- ### Pre-built Binary (recommended)
13
+ Install the current standalone binary on macOS or Linux without requiring Node.js:
13
14
 
14
- Download and install a standalone binary — no Node.js required:
15
-
16
- ```bash
15
+ ```sh
17
16
  curl -fsSL https://raw.githubusercontent.com/jkomyno/uniku/main/install.sh | sh
18
17
  ```
19
18
 
20
- Supports macOS (Intel and Apple Silicon) and Linux (x64/amd64 and ARM64). 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.2.0 curl -fsSL https://raw.githubusercontent.com/jkomyno/uniku/main/install.sh | sh
28
- ```
29
-
30
- ### mise
31
-
32
- Install the `uniku-cli-v0.2.0` GitHub release binary with [mise](https://mise.jdx.dev):
33
-
34
- ```bash
35
- mise use -g github:jkomyno/uniku@uniku-cli-v0.2.0
36
- ```
37
-
38
- This uses the exact CLI release tag.
39
-
40
- ### npm
19
+ Or install the npm package:
41
20
 
42
- ```bash
43
- # pnpm (recommended)
44
- pnpm add -g @uniku/cli
45
-
46
- # npm
21
+ ```sh
47
22
  npm install -g @uniku/cli
48
-
49
- # bun
50
- bun add -g @uniku/cli
51
23
  ```
52
24
 
53
- ## Usage
54
-
55
- ### Generate IDs
56
-
57
- ```bash
58
- # UUID v4 (default)
59
- uniku uuid
60
- # => 550e8400-e29b-41d4-a716-446655440000
61
-
62
- # UUID v7 (time-ordered)
63
- uniku uuid --uuid-version 7
64
- # => 018e5e5c-7c8a-7000-8000-000000000000
65
-
66
- # Generate multiple IDs
67
- uniku uuid --count 5
68
-
69
- # ULID
70
- uniku ulid
71
- # => 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
72
-
73
- # TypeID
74
- uniku typeid --prefix user
75
- # => user_01h2xcejqtf2nbrexx3vqjhp41
76
-
77
- # Monotonically increasing ULIDs
78
- uniku ulid --monotonic --count 3
25
+ The [installation guide](https://jkomyno.github.io/uniku/docs/cli/#install) also covers pnpm, Bun, mise, custom install directories, and version pinning.
79
26
 
80
- # Nanoid (custom size and alphabet)
81
- uniku nanoid --size 12 --alphabet hex
27
+ ## Quick start
82
28
 
83
- # CUID2 (custom length)
84
- uniku cuid --length 16
29
+ ```sh
30
+ # Generate a time-ordered UUID v7
31
+ uniku uuid -v 7
85
32
 
86
- # KSUID
87
- uniku ksuid
33
+ # Generate five TypeIDs as JSON
34
+ uniku typeid --prefix user --count 5 --json
88
35
 
89
- # MongoDB ObjectID
90
- uniku objectid
91
- # => 66e1a8d3f1c2b3a4d5e6f7a8
92
-
93
- # ObjectID for a fixed Unix timestamp (s)
94
- uniku objectid --timestamp 1720000000
95
-
96
- # TSID (64-bit Snowflake-style, time-sorted)
97
- uniku tsid
98
- # => 0QXW2CK4XZM2A
99
-
100
- # TSID for a fixed Unix timestamp (ms) - note: milliseconds, unlike ObjectID/KSUID's seconds
101
- uniku tsid --timestamp 1720000000000
102
-
103
- # TSID for a fixed node ID
104
- uniku tsid --node 42 --node-bits 10
105
-
106
- # XID (time-sortable, lowercase base32hex)
107
- uniku xid
108
- # => 9m4e2mr0ui3e8a215n4g
109
-
110
- # XID for a fixed Unix timestamp (s)
111
- uniku xid --timestamp 1720000000
112
-
113
- # Output as JSON
114
- uniku uuid --count 3 --json
115
- ```
116
-
117
- All generate commands also work under `uniku generate <type>` (e.g., `uniku generate uuid`).
118
-
119
- ### Validate IDs
120
-
121
- ```bash
122
- # Validate a single ID (type auto-detected)
36
+ # Validate or inspect an existing ID
123
37
  uniku validate 018e5e5c-7c8a-7000-8000-000000000000
38
+ uniku inspect 018e5e5c-7c8a-7000-8000-000000000000
124
39
 
125
- # Validate with explicit type
126
- uniku validate --type ulid 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
127
-
128
- # Validate a TypeID
129
- uniku validate --type typeid user_01h2xcejqtf2nbrexx3vqjhp41
130
-
131
- # Batch validate from stdin
132
- echo -e "018e5e5c-7c8a-7000-8000-000000000000\ninvalid-id" | uniku validate --stdin
133
-
134
- # Quiet mode (exit code only: 0 = valid, 2 = invalid)
135
- uniku validate --quiet 018e5e5c-7c8a-7000-8000-000000000000
136
-
137
- # JSON output
138
- uniku validate --json 018e5e5c-7c8a-7000-8000-000000000000
40
+ # Discover every command and option
41
+ uniku --help
139
42
  ```
140
43
 
141
- ### Inspect IDs
142
-
143
- ```bash
144
- # Decode metadata from an ID (type auto-detected)
145
- uniku inspect 018e5e5c-7c8a-7000-8000-000000000000
44
+ Top-level generator commands also work under `uniku generate <type>`. Use `--json` when output feeds another program.
146
45
 
147
- # Inspect with explicit type
148
- uniku inspect --type ulid 01HW9T2W9W9YJ3JZ1H4P4M2T8Q
46
+ See the [complete command reference](https://jkomyno.github.io/uniku/docs/cli/) for generator-specific flags, stdin validation, exit codes, timestamp units, and structured output.
149
47
 
150
- # Inspect TypeID metadata
151
- uniku inspect user_01h2xcejqtf2nbrexx3vqjhp41
48
+ ## Platform support
152
49
 
153
- # JSON output
154
- uniku inspect --json 018e5e5c-7c8a-7000-8000-000000000000
155
- ```
50
+ The standalone binary supports macOS x64/arm64 and Linux x64/arm64. The npm package requires Node.js `>=20.19.0`.
156
51
 
157
- For time-ordered IDs (UUID v7, ULID, TypeID, KSUID, ObjectID, TSID, XID), inspect extracts the embedded timestamp. For random-only IDs (UUID v4, CUID2, Nanoid), it reports that no decodable metadata is available. Timestamp precision varies by generator: UUID v7, ULID, and TSID are millisecond-precision, while KSUID, ObjectID, and XID are second-precision.
158
-
159
- ## Commands Reference
160
-
161
- | Command | Description |
162
- |---------|-------------|
163
- | `uniku uuid` | Generate UUIDs (v4 or v7) |
164
- | `uniku ulid` | Generate ULIDs |
165
- | `uniku typeid` | Generate TypeIDs |
166
- | `uniku nanoid` | Generate Nanoids |
167
- | `uniku cuid` | Generate CUIDs (v2) |
168
- | `uniku ksuid` | Generate KSUIDs |
169
- | `uniku objectid` | Generate MongoDB ObjectIDs |
170
- | `uniku tsid` | Generate TSIDs (64-bit Snowflake-style, time-sorted) |
171
- | `uniku xid` | Generate XIDs |
172
- | `uniku validate <id>` | Check if an ID is valid |
173
- | `uniku inspect <id>` | Decode and inspect an ID |
174
-
175
- ### Common Options
176
-
177
- | Option | Alias | Description |
178
- |--------|-------|-------------|
179
- | `--count` | `-n` | Number of IDs to generate (default: 1) |
180
- | `--json` | | Output as JSON |
181
- | `--help` | | Show help |
182
- | `--version` | `-V` | Show version |
183
-
184
- ### Generator-Specific Options
185
-
186
- | Command | Option | Alias | Description |
187
- |---------|--------|-------|-------------|
188
- | `uuid` | `--uuid-version` | `-v` | UUID version: 4 or 7 (default: 4) |
189
- | `uuid` | `--lowercase` | | Output in lowercase |
190
- | `ulid` | `--monotonic` | | Generate monotonically increasing ULIDs |
191
- | `ulid` | `--timestamp` | | Unix timestamp in ms or "now" |
192
- | `ulid` | `--lowercase` | | Output in lowercase |
193
- | `typeid` | `--prefix` | `-p` | Type prefix, e.g. `user` for `user_...` |
194
- | `nanoid` | `--size` | `-s` | Length of ID, 1-256 (default: 21) |
195
- | `nanoid` | `--alphabet` | `-a` | Custom alphabet or preset: hex, numeric, alpha |
196
- | `cuid` | `--length` | `-l` | Length of ID, 2-32 (default: 24) |
197
- | `ksuid` | `--timestamp` | | Unix timestamp in seconds or "now" |
198
- | `objectid` | `--timestamp` | | Unix timestamp in seconds or "now" |
199
- | `tsid` | `--timestamp` | | Unix timestamp in milliseconds or "now" |
200
- | `tsid` | `--node` | | Node ID (0 to 2^node-bits - 1) |
201
- | `tsid` | `--node-bits` | | Number of bits allocated to the node ID, 0-20 (default: 10) |
202
- | `xid` | `--timestamp` | | Unix timestamp in seconds or "now" |
203
-
204
- ### Validate Options
205
-
206
- | Option | Description |
207
- |--------|-------------|
208
- | `--type` | Expected ID type: uuid, ulid, typeid, nanoid, cuid, ksuid, objectid, tsid, xid (auto-detected if omitted) |
209
- | `--stdin` | Read IDs from stdin (one per line) |
210
- | `--quiet` | No output, exit code only (0 = valid, 2 = invalid) |
211
- | `--json` | Output as JSON |
212
-
213
- ### Inspect Options
214
-
215
- | Option | Description |
216
- |--------|-------------|
217
- | `--type` | ID type: uuid, ulid, typeid, nanoid, cuid, ksuid, objectid, tsid, xid (auto-detected if omitted) |
218
- | `--json` | Output as JSON |
219
-
220
- ## Tech Stack
221
-
222
- - [Effect](https://effect.website/) — functional effect system for TypeScript
223
- - [@effect/cli](https://github.com/Effect-TS/effect/tree/main/packages/cli) — CLI framework built on Effect
224
- - [@effect/platform](https://github.com/Effect-TS/effect/tree/main/packages/platform) — platform abstraction layer
225
- - [Bun](https://bun.sh/) — JavaScript runtime
226
- - [uniku](https://github.com/jkomyno/uniku) — core ID generation library
52
+ The library and CLI publish independently and may have different version numbers.
227
53
 
228
54
  ## License
229
55
 
230
- MIT — see [LICENSE](https://github.com/jkomyno/uniku/blob/main/LICENSE)
56
+ MIT © [Alberto Schiabel](https://github.com/jkomyno)
package/build/bin.mjs CHANGED
@@ -3,5 +3,5 @@ import*as e from"@effect/platform-bun/BunRuntime";import*as t from"@effect/platf
3
3
  `)}function De(e){return e.hint?`Error: ${e.message}\n ${e.hint}`:`Error: ${e.message}`}const N=l.integer(`count`).pipe(l.withAlias(`n`),l.withDescription(`Number of IDs to generate`),l.withDefault(1)),P=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),Oe=l.choiceWithValue(`uuid-version`,[[`4`,4],[`7`,7]]).pipe(l.withAlias(`v`),l.withDescription(`UUID version: 4, 7`),l.withDefault(4)),F=l.boolean(`lowercase`).pipe(l.withDescription(`Output in lowercase`),l.withDefault(!1)),I=c.make(`uuid`,{count:N,json:P,version:Oe,lowercase:F},r.fn(`cli.generate.uuid`)(function*({count:e,json:t,version:n,lowercase:r}){let i=yield*A,a=yield*be({count:e,version:n,lowercase:r});yield*i.write(M(a),{json:t})})).pipe(c.withDescription(`Generate UUIDs (v4 or v7)`),c.withExamples([{command:`uniku uuid -n 5 --json`,description:`Generate 5 UUIDs as a JSON array (machine-readable)`},{command:`uniku uuid -v 7`,description:`Generate a time-sortable UUID v7`},{command:`uniku uuid`,description:`Generate one random UUID v4`}])),ke=l.string(`prefix`).pipe(l.withAlias(`p`),l.withDescription(`Type prefix, e.g. "user" for user_... (empty by default)`),l.withDefault(``)),L=c.make(`typeid`,{count:N,json:P,prefix:ke},r.fn(`cli.generate.typeid`)(function*({count:e,json:t,prefix:n}){let r=yield*A,i=yield*ve({count:e,prefix:n});yield*r.write(M(i),{json:t})})).pipe(c.withDescription(`Generate TypeIDs`),c.withExamples([{command:`uniku typeid --prefix user`,description:`Generate a TypeID such as user_...`},{command:`uniku typeid -p api_key -n 5 --json`,description:`Generate 5 api_key TypeIDs as JSON`},{command:`uniku typeid`,description:`Generate a canonical prefixless TypeID`}])),Ae=l.boolean(`monotonic`).pipe(l.withDescription(`Generate monotonically increasing ULIDs`),l.withDefault(!1)),je=l.string(`timestamp`).pipe(l.withDescription(`Unix timestamp in milliseconds (or "now")`),l.optional),R=c.make(`ulid`,{count:N,json:P,monotonic:Ae,timestamp:je,lowercase:F},r.fn(`cli.generate.ulid`)(function*({count:e,json:t,monotonic:n,timestamp:r,lowercase:i}){let a=yield*A,s=o.getOrUndefined(r),c=yield*ye({count:e,monotonic:n,timestamp:s===void 0?void 0:yield*K(s),lowercase:i});yield*a.write(M(c),{json:t})})).pipe(c.withDescription(`Generate ULIDs`),c.withExamples([{command:`uniku ulid -n 10 --monotonic --json`,description:`Generate 10 strictly ordered ULIDs as a JSON array`},{command:`uniku ulid --timestamp 1720000000000`,description:`Generate a ULID for a fixed Unix timestamp (ms)`}])),Me=l.integer(`size`).pipe(l.withAlias(`s`),l.withDescription(`Length of ID (1-256)`),l.withDefault(21)),Ne=l.string(`alphabet`).pipe(l.withAlias(`a`),l.withDescription(`Custom alphabet or preset: hex, numeric, alpha`),l.optional),z=c.make(`nanoid`,{count:N,json:P,size:Me,alphabet:Ne},r.fn(`cli.generate.nanoid`)(function*({count:e,json:t,size:n,alphabet:r}){let i=yield*A,a=yield*he({count:e,size:n,alphabet:o.getOrUndefined(r)});yield*i.write(M(a),{json:t})})).pipe(c.withDescription(`Generate Nanoids`),c.withExamples([{command:`uniku nanoid -n 5 --json`,description:`Generate 5 Nanoids as a JSON array`},{command:`uniku nanoid --size 10 --alphabet hex`,description:`Generate a 10-char ID from the hex preset`}])),Pe=l.integer(`length`).pipe(l.withAlias(`l`),l.withDescription(`Length of ID (2-32)`),l.withDefault(24)),B=c.make(`cuid`,{count:N,json:P,length:Pe},r.fn(`cli.generate.cuid`)(function*({count:e,json:t,length:n}){let r=yield*A,i=yield*fe({count:e,length:n});yield*r.write(M(i),{json:t})})).pipe(c.withDescription(`Generate CUIDs (v2)`),c.withExamples([{command:`uniku cuid -n 5 --json`,description:`Generate 5 CUIDs as a JSON array`},{command:`uniku cuid --length 10`,description:`Generate a 10-char CUID`}])),Fe=l.string(`timestamp`).pipe(l.withDescription(`Unix timestamp in seconds (or "now")`),l.optional),V=c.make(`ksuid`,{count:N,json:P,timestamp:Fe},r.fn(`cli.generate.ksuid`)(function*({count:e,json:t,timestamp:n}){let r=yield*A,i=o.getOrUndefined(n),a=yield*pe({count:e,timestamp:i===void 0?void 0:yield*q(i)});yield*r.write(M(a),{json:t})})).pipe(c.withDescription(`Generate KSUIDs`),c.withExamples([{command:`uniku ksuid -n 5 --json`,description:`Generate 5 KSUIDs as a JSON array`},{command:`uniku ksuid --timestamp 1720000000`,description:`Generate a KSUID for a fixed Unix timestamp (s)`}])),Ie=l.string(`timestamp`).pipe(l.withDescription(`Unix timestamp in seconds (or "now")`),l.optional),H=c.make(`objectid`,{count:N,json:P,timestamp:Ie},r.fn(`cli.generate.objectid`)(function*({count:e,json:t,timestamp:n}){let r=yield*A,i=o.getOrUndefined(n),a=yield*ge({count:e,timestamp:i===void 0?void 0:yield*q(i)});yield*r.write(M(a),{json:t})})).pipe(c.withDescription(`Generate MongoDB ObjectIDs`),c.withExamples([{command:`uniku objectid -n 5 --json`,description:`Generate 5 ObjectIDs as a JSON array`},{command:`uniku objectid --timestamp 1720000000`,description:`Generate an ObjectID for a fixed Unix timestamp (s)`}])),Le=l.string(`timestamp`).pipe(l.withDescription(`Unix timestamp in seconds (or "now")`),l.optional),U=c.make(`xid`,{count:N,json:P,timestamp:Le},r.fn(`cli.generate.xid`)(function*({count:e,json:t,timestamp:n}){let r=yield*A,i=o.getOrUndefined(n),a=yield*xe({count:e,timestamp:i===void 0?void 0:yield*q(i)});yield*r.write(M(a),{json:t})})).pipe(c.withDescription(`Generate XIDs`),c.withExamples([{command:`uniku xid -n 5 --json`,description:`Generate 5 XIDs as a JSON array`},{command:`uniku xid --timestamp 1720000000`,description:`Generate an XID for a fixed Unix timestamp (s)`}])),Re=l.string(`timestamp`).pipe(l.withDescription(`Unix timestamp in milliseconds (or "now")`),l.optional),ze=l.string(`node`).pipe(l.withDescription(`Node ID (0 to 2^node-bits - 1)`),l.optional),Be=l.string(`node-bits`).pipe(l.withDescription(`Number of bits allocated to the node ID (0-20, default 10)`),l.optional),W=c.make(`tsid`,{count:N,json:P,timestamp:Re,node:ze,nodeBits:Be},r.fn(`cli.generate.tsid`)(function*({count:e,json:t,timestamp:n,node:r,nodeBits:i}){let a=yield*A,s=o.getOrUndefined(n),c=s===void 0?void 0:yield*K(s),l=o.getOrUndefined(r),u=l===void 0?void 0:yield*Ze(l),d=o.getOrUndefined(i),f=yield*_e({count:e,timestamp:c,node:u,nodeBits:d===void 0?void 0:yield*Qe(d)});yield*a.write(M(f),{json:t})})).pipe(c.withDescription(`Generate TSIDs (64-bit Snowflake-style, time-sorted)`),c.withExamples([{command:`uniku tsid -n 5 --json`,description:`Generate 5 TSIDs as a JSON array`},{command:`uniku tsid --timestamp 1720000000000`,description:`Generate a TSID for a fixed Unix timestamp (ms)`},{command:`uniku tsid --node 42 --node-bits 10`,description:`Generate a TSID for a fixed node ID`}])),Ve=c.make(`generate`).pipe(c.withDescription(`Generate new IDs`),c.withSubcommands([I,R,L,z,B,V,H,U,W]),c.withExamples([{command:`uniku generate uuid -n 5 --json`,description:`Generate 5 UUIDs as a JSON array`},{command:`uniku generate typeid --prefix user`,description:`Generate one user TypeID`},{command:`uniku generate ulid`,description:"Generate one ULID (subcommands also work top-level: `uniku ulid`)"}])),He=I,Ue=R,We=L,Ge=z,Ke=B,qe=V,Je=H,Ye=U,Xe=W,G=r.fn(`cli.generate.parseTimestamp`)(function*(e,t,n){if(e===`now`)return t(yield*u.currentTimeMillis);let r=Number(e);return!Number.isFinite(r)||r<0?yield*new D({code:`INVALID_TIMESTAMP`,message:`Invalid timestamp: "${e}"`,hint:n}):r}),K=e=>G(e,e=>e,`Provide a Unix timestamp in milliseconds or "now"`),q=e=>G(e,e=>Math.floor(e/1e3),`Provide a Unix timestamp in seconds or "now"`),J=r.fn(`cli.generate.parseNonNegativeInt`)(function*(e,t,n,r){let i=Number(e);return!Number.isInteger(i)||i<0?yield*new D({code:t,message:`Invalid ${n}: "${e}"`,hint:r}):i}),Ze=e=>J(e,`INVALID_NODE`,`node`,`Provide a non-negative integer for --node`),Qe=e=>J(e,`INVALID_NODE_BITS`,`node-bits`,`Provide a non-negative integer (0-20) for --node-bits`);function $e(e,t){switch(t){case`uuid`:return tt(e);case`ulid`:return nt(e);case`typeid`:return rt(e);case`ksuid`:return it(e);case`objectid`:return at(e);case`cuid`:return st(e);case`nanoid`:return ct(e);case`tsid`:return lt(e);case`xid`:return ot(e)}}function et(e){return x.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:b.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:v.isValid(e)?{id:e,valid:!0,type:`typeid`,version:7}:y.isValid(e)?{id:e,valid:!0,type:`ulid`}:m.isValid(e)?{id:e,valid:!0,type:`ksuid`}:g.isValid(e)?{id:e,valid:!0,type:`objectid`}:lt(e).valid?{id:e,valid:!0,type:`tsid`}:S.isValid(e)?{id:e,valid:!0,type:`xid`}:f.isValid(e)?{id:e,valid:!0,type:`cuid`}:h.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,error:`malformed identifier`}}function tt(e){return x.isValid(e)?{id:e,valid:!0,type:`uuid`,version:7}:b.isValid(e)?{id:e,valid:!0,type:`uuid`,version:4}:{id:e,valid:!1,type:`uuid`,error:`invalid UUID format`}}function nt(e){return y.isValid(e)?{id:e,valid:!0,type:`ulid`}:{id:e,valid:!1,type:`ulid`,error:`invalid ULID format`}}function rt(e){return v.isValid(e)?{id:e,valid:!0,type:`typeid`,version:7}:{id:e,valid:!1,type:`typeid`,error:`invalid TypeID format`}}function it(e){return m.isValid(e)?{id:e,valid:!0,type:`ksuid`}:{id:e,valid:!1,type:`ksuid`,error:`invalid KSUID format`}}function at(e){return g.isValid(e)?{id:e,valid:!0,type:`objectid`}:{id:e,valid:!1,type:`objectid`,error:`invalid ObjectID format`}}function ot(e){return S.isValid(e)?{id:e,valid:!0,type:`xid`}:{id:e,valid:!1,type:`xid`,error:`invalid XID format`}}function st(e){return f.isValid(e)?{id:e,valid:!0,type:`cuid`}:{id:e,valid:!1,type:`cuid`,error:`invalid CUID format`}}function ct(e){return h.isValid(e)?{id:e,valid:!0,type:`nanoid`}:{id:e,valid:!1,type:`nanoid`,error:`invalid Nanoid format`}}function lt(e){try{return _.fromString(e),{id:e,valid:!0,type:`tsid`}}catch{return{id:e,valid:!1,type:`tsid`,error:`invalid TSID format`}}}function ut(e,t){let n=t??dt(e);if(!n)return null;switch(n){case`uuid`:return ft(e);case`ulid`:return pt(e);case`typeid`:return mt(e);case`ksuid`:return ht(e);case`objectid`:return gt(e);case`cuid`:return vt(e);case`nanoid`:return yt(e);case`tsid`:return bt(e);case`xid`:return _t(e)}}function dt(e){let t=et(e);return t.valid?t.type??null:null}function ft(e){if(x.isValid(e)){let t=x.timestamp(e),n=x.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 b.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 pt(e){let t=y.timestamp(e),n=e.slice(10);return{id:e,type:`ulid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:n}}function mt(e){if(!v.isValid(e))return{id:e,type:`typeid`,note:`Unrecognized TypeID format.`};let t=v.timestamp(e),n=v.toBytes(e),r=Buffer.from(n.slice(10)).toString(`hex`);return{id:e,type:`typeid`,version:7,prefix:v.prefix(e),suffix:v.suffix(e),timestamp:new Date(t).toISOString(),timestamp_ms:t,random:r}}function ht(e){let t=m.timestamp(e),n=m.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 gt(e){let t=g.timestamp(e),n=g.toBytes(e),r=Buffer.from(n.slice(4)).toString(`hex`);return{id:e,type:`objectid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:r}}function _t(e){let t=S.timestamp(e),n=S.toBytes(e);return{id:e,type:`xid`,timestamp:new Date(t).toISOString(),timestamp_ms:t,random:Buffer.from(n.slice(4)).toString(`hex`)}}function vt(e){return{id:e,type:`cuid`,note:`This ID type contains no decodable metadata.`}}function yt(e){return{id:e,type:`nanoid`,note:`This ID type contains no decodable metadata.`}}function bt(e){let t;try{t=_.fromString(e)}catch{return{id:e,type:`tsid`,note:`Unrecognized TSID format.`}}let n=_.timestamp(t),r=(t&4194303n).toString(16);return{id:e,type:`tsid`,timestamp:new Date(n).toISOString(),timestamp_ms:n,random:r}}function xt(e){let t=e.indexOf(`--`),n=(t===-1?e:e.slice(0,t)).map(e=>e===`-V`?`--version`:e);if(t===-1)return n;let r=e.slice(t+1);return Dt(n)?[...n,...r.map(Et)]:[...n,`--`,...r]}const St=`\0uniku-literal:`,Ct=new Set([`inspect`,`validate`]),wt=new Set([`--completions`,`--log-level`]);function Tt(e){return e.startsWith(St)?e.slice(15):e}function Et(e){return`${St}${e}`}function Dt(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`-`)){wt.has(n)&&(t+=1);continue}return Ct.has(n)}return!1}const Ot=s.string(`id`).pipe(s.withDescription(`The ID to inspect`)),kt=l.choice(`type`,w).pipe(l.withDescription(`ID type (auto-detected if omitted)`),l.optional),At=l.boolean(`json`).pipe(l.withDescription(`Output as JSON`),l.withDefault(!1)),jt=c.make(`inspect`,{id:Ot,type:kt,json:At},r.fn(`cli.inspect`)(function*({id:e,type:t,json:n}){let r=yield*A,i=o.getOrUndefined(t),a=Tt(e),s=ut(a,i);if(!s)return yield*new D({code:`UNKNOWN_ID_TYPE`,message:`Could not identify ID type for: "${a}"`,hint:`Use --type to specify the ID type`});yield*r.write(Ce(s),{json:n})})).pipe(c.withDescription(`Decode and inspect an ID`),c.withExamples([{command:`uniku inspect 01J9YR2V5TZB8Q4W6X0E1N7M3S --json`,description:`Decode an ID to structured JSON (type, version, timestamp)`},{command:`uniku inspect --type uuid 3F2504E0-4F89-41D3-9A0C-0305E82C3301`,description:`Skip auto-detection`},{command:`uniku inspect -- --tricky-id`,description:`Inspect an ID that starts with a dash`}]));var Mt=class e extends C.Service()(`uniku/cli/StdinService`){static layer=a.succeed(e,e.of({readLines:r.fn(`StdinService.readLines`)(()=>r.callback(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
4
  `).map(e=>e.trim()).filter(e=>e.length>0);e(r.succeed(n))}),process.stdin.on(`error`,t=>{e(r.fail(new D({code:`STDIN_ERROR`,message:t.message})))}),process.stdin.resume()}))}))};const Nt=s.string(`id`).pipe(s.withDescription(`The ID to validate`),s.optional),Pt=l.choice(`type`,w).pipe(l.withDescription(`Expected ID type (auto-detected if omitted)`),l.optional),Ft=l.boolean(`stdin`).pipe(l.withDescription(`Read IDs from stdin (one per line)`),l.withDefault(!1)),It=l.boolean(`json`).pipe(l.withDescription(`Output validation results as JSON`),l.withDefault(!1)),Lt=l.boolean(`quiet`).pipe(l.withDescription(`No output, exit code only`),l.withDefault(!1)),Rt=c.make(`validate`,{id:Nt,type:Pt,stdin:Ft,json:It,quiet:Lt},r.fn(`cli.validate`)(function*({id:e,type:t,stdin:n,json:r,quiet:i}){let a=yield*A,s=yield*Mt,c=o.getOrUndefined(t),l;if(n){if(l=yield*s.readLines(),l.length===0)return yield*new D({code:`NO_INPUT`,message:`No IDs provided on stdin`})}else if(o.isSome(e))l=[Tt(e.value)];else return yield*new D({code:`NO_INPUT`,message:`No ID provided`,hint:`Pass an ID as argument or use --stdin`});let u=l.map(e=>c?$e(e,c):et(e));if(i||(yield*a.write(Se(u),{json:r})),u.some(e=>!e.valid))return yield*new ue({message:`One or more IDs are invalid`})})).pipe(c.withDescription(`Check if an ID is valid`),c.withExamples([{command:`uniku validate 3F2504E0-4F89-41D3-9A0C-0305E82C3301 --json`,description:`Validate one ID, result as JSON`},{command:`cat ids.txt | uniku validate --stdin --json`,description:`Validate many IDs (one per line), results as a JSON array`},{command:`uniku validate --quiet 01J9YR2V5TZB8Q4W6X0E1N7M3S`,description:`Exit code only: 0 valid, 2 invalid`}])),zt=c.make(`uniku`).pipe(c.withDescription(`Generate and validate unique identifiers`),c.withExamples([{command:`uniku uuid -n 5 --json`,description:`Generate 5 UUIDs as a JSON array (machine-readable)`},{command:`uniku typeid --prefix user`,description:`Generate one user TypeID`},{command:`uniku ulid`,description:`Generate one ULID`},{command:`uniku inspect <id> --json`,description:`Decode an ID (type, version, timestamp) as JSON`},{command:`cat ids.txt | uniku validate --stdin --json`,description:`Validate IDs from stdin, one per line`}]),c.withSubcommands([Ve,Rt,jt,He,Ue,We,Ge,Ke,qe,Je,Ye,Xe])),Bt=e=>c.runWith(zt,{version:e});function Vt(e){return e.includes(`--json`)}const Ht=T.type().pipe(T.tag(`CliError`,e=>e.exitCode),T.tag(`ValidationFailedError`,e=>e.exitCode),T.tag(`ShowHelp`,e=>+(e.errors.length>0)),T.tag(`UnrecognizedOption`,`DuplicateOption`,`MissingOption`,`MissingArgument`,`InvalidValue`,`UnknownSubcommand`,`UserError`,()=>1),T.exhaustive),Ut=r.fn(`cli.handleCliFailure`)(function*(e,t){yield*T.value(e).pipe(T.tag(`CliError`,`ValidationFailedError`,e=>A.use(n=>n.writeError(we(e),{json:Vt(t)}))),T.tag(`ShowHelp`,()=>r.void),T.tag(`UnrecognizedOption`,`DuplicateOption`,`MissingOption`,`MissingArgument`,`InvalidValue`,`UnknownSubcommand`,`UserError`,e=>ee.error(`Error: ${e.message}`)),T.exhaustive),process.exitCode=Ht(e)});var Y=class e extends C.Service()(`uniku/cli/UpdateCheckService`){static layer=a.sync(e,()=>an())};const X=`@uniku/cli`;function Wt(){let e=process.getuid;if(typeof e==`function`)return`uid-${e()}`;try{let e=oe().username.replace(/[^0-9A-Za-z._-]/g,`_`);return e?`user-${e}`:null}catch{return null}}function Gt(){let e=Wt(),t=e?`uniku-update-check-${e}.json`:`uniku-update-check.json`;return ce(ae(),t)}const Kt=Gt();function qt(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 Jt(e,t){let n=qt(e),r=qt(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 Z(e){return E.option(E.string(e)).pipe(r.catch(()=>r.succeed(o.none())))}function Q(e){return o.isSome(e)&&e.value.length>0}const Yt=r.all({noUpdateNotifier:Z(`NO_UPDATE_NOTIFIER`),ci:Z(`CI`),continuousIntegration:Z(`CONTINUOUS_INTEGRATION`),nodeEnv:Z(`NODE_ENV`)});function Xt(e=process.stderr.isTTY){return Yt.pipe(r.map(t=>Q(t.noUpdateNotifier)||Q(t.ci)||Q(t.continuousIntegration)||o.isSome(t.nodeEnv)&&t.nodeEnv.value===`test`||!e))}function Zt(e,t){if(t){let t=e.isStandaloneBinary?`Download at https://github.com/jkomyno/uniku/releases`:`Run \`npm install -g ${X}\` to update`;return[``,` Update available: ${e.currentVersion} → ${e.latestVersion}`,` ${t}`,` Set NO_UPDATE_NOTIFIER=1 to disable`,``].join(`
5
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 ${X}\`${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 Qt(e){return Z(`NO_COLOR`).pipe(r.map(t=>Zt(e,Q(t))))}function $t(e,t){return o.isSome(t)&&!e.includes(`--json`)}function en(e){try{let t=ne(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 tn(e,t){try{te(se(t),{recursive:!0});let n=`${t}.tmp`;ie(n,JSON.stringify(e)),re(n,t)}catch{}}function nn(e){return r.tryPromise({try:t=>fetch(`https://registry.npmjs.org/%40uniku%2Fcli/latest`,{headers:{Accept:`application/json`,"User-Agent":`${X}/${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.catch(()=>r.succeed(null)))}function rn(){try{return typeof __STANDALONE_BINARY__<`u`&&__STANDALONE_BINARY__===!0}catch{return!1}}function an(e={}){let t=e.cacheFile??Kt,n=e.fetchLatestVersion??nn,i=e.now??Date.now,a=e.isStandaloneBinary??rn,s=e.isStderrTTY??(()=>process.stderr.isTTY),c=e.writeStderr??(e=>process.stderr.write(e));return Y.of({check:r.fn(`UpdateCheckService.check`)(function*(e){if(yield*Xt(s()))return o.none();let r=en(t),c=i();if(r&&c-r.checkedAt<864e5)return r.latestVersion&&Jt(r.latestVersion,e)?o.some({currentVersion:e,latestVersion:r.latestVersion,isStandaloneBinary:a()}):o.none();let l=yield*n(e);return l===null?(tn({checkedAt:c},t),o.none()):(tn({latestVersion:l,checkedAt:c},t),Jt(l,e)?o.some({currentVersion:e,latestVersion:l,isStandaloneBinary:a()}):o.none())},r.catch(()=>r.succeed(o.none()))),notify:r.fn(`UpdateCheckService.notify`)(function*(e){let t=yield*Qt(e);yield*r.sync(()=>{c(t)})})})}var $=`0.6.1`;const on=Bt($),sn=a.mergeAll(A.layer,Mt.layer,Y.layer,t.layer);r.gen(function*(){let e=yield*Y,t=xt(process.argv.slice(2)),a=yield*r.forkChild(e.check($),{startImmediately:!0});yield*on(t).pipe(r.catch(e=>Ut(e,t)));let s=yield*i.join(a).pipe(r.timeoutOption(n.millis(250)));yield*i.interrupt(a);let c=o.flatten(s);$t(t,c)&&(yield*e.notify(c.value))}).pipe(r.provide(sn),e.runMain);export{};
6
+ `)}function Qt(e){return Z(`NO_COLOR`).pipe(r.map(t=>Zt(e,Q(t))))}function $t(e,t){return o.isSome(t)&&!e.includes(`--json`)}function en(e){try{let t=ne(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 tn(e,t){try{te(se(t),{recursive:!0});let n=`${t}.tmp`;ie(n,JSON.stringify(e)),re(n,t)}catch{}}function nn(e){return r.tryPromise({try:t=>fetch(`https://registry.npmjs.org/%40uniku%2Fcli/latest`,{headers:{Accept:`application/json`,"User-Agent":`${X}/${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.catch(()=>r.succeed(null)))}function rn(){try{return typeof __STANDALONE_BINARY__<`u`&&__STANDALONE_BINARY__===!0}catch{return!1}}function an(e={}){let t=e.cacheFile??Kt,n=e.fetchLatestVersion??nn,i=e.now??Date.now,a=e.isStandaloneBinary??rn,s=e.isStderrTTY??(()=>process.stderr.isTTY),c=e.writeStderr??(e=>process.stderr.write(e));return Y.of({check:r.fn(`UpdateCheckService.check`)(function*(e){if(yield*Xt(s()))return o.none();let r=en(t),c=i();if(r&&c-r.checkedAt<864e5)return r.latestVersion&&Jt(r.latestVersion,e)?o.some({currentVersion:e,latestVersion:r.latestVersion,isStandaloneBinary:a()}):o.none();let l=yield*n(e);return l===null?(tn({checkedAt:c},t),o.none()):(tn({latestVersion:l,checkedAt:c},t),Jt(l,e)?o.some({currentVersion:e,latestVersion:l,isStandaloneBinary:a()}):o.none())},r.catch(()=>r.succeed(o.none()))),notify:r.fn(`UpdateCheckService.notify`)(function*(e){let t=yield*Qt(e);yield*r.sync(()=>{c(t)})})})}var $=`0.6.2`;const on=Bt($),sn=a.mergeAll(A.layer,Mt.layer,Y.layer,t.layer);r.gen(function*(){let e=yield*Y,t=xt(process.argv.slice(2)),a=yield*r.forkChild(e.check($),{startImmediately:!0});yield*on(t).pipe(r.catch(e=>Ut(e,t)));let s=yield*i.join(a).pipe(r.timeoutOption(n.millis(250)));yield*i.interrupt(a);let c=o.flatten(s);$t(t,c)&&(yield*e.notify(c.value))}).pipe(r.provide(sn),e.runMain);export{};
7
7
  //# sourceMappingURL=bin.mjs.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@uniku/cli",
4
- "version": "0.6.1",
4
+ "version": "0.6.2",
5
5
  "description": "CLI tool for generating and validating unique identifiers",
6
6
  "author": {
7
7
  "name": "Alberto Schiabel",
@@ -14,6 +14,10 @@
14
14
  "url": "git+https://github.com/jkomyno/uniku.git",
15
15
  "directory": "packages/cli"
16
16
  },
17
+ "homepage": "https://jkomyno.github.io/uniku/docs/cli/",
18
+ "bugs": {
19
+ "url": "https://github.com/jkomyno/uniku/issues"
20
+ },
17
21
  "type": "module",
18
22
  "bin": {
19
23
  "uniku": "./build/bin.mjs"
@@ -32,7 +36,7 @@
32
36
  "dependencies": {
33
37
  "@effect/platform-bun": "4.0.0-beta.93",
34
38
  "effect": "4.0.0-beta.93",
35
- "uniku": "0.4.1"
39
+ "uniku": "0.4.2"
36
40
  },
37
41
  "devDependencies": {
38
42
  "@effect/vitest": "4.0.0-beta.93",