politty 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +297 -28
- package/dist/arg-registry-ClI2WGgH.d.cts +89 -0
- package/dist/arg-registry-ClI2WGgH.d.cts.map +1 -0
- package/dist/arg-registry-D4NsqcNZ.d.ts +89 -0
- package/dist/arg-registry-D4NsqcNZ.d.ts.map +1 -0
- package/dist/augment.cjs +0 -0
- package/dist/augment.d.cts +17 -0
- package/dist/augment.d.cts.map +1 -0
- package/dist/augment.d.ts +17 -0
- package/dist/augment.d.ts.map +1 -0
- package/dist/augment.js +1 -0
- package/dist/command-Bgd-yIwv.cjs +25 -0
- package/dist/command-Bgd-yIwv.cjs.map +1 -0
- package/dist/command-CvKyk4ag.js +20 -0
- package/dist/command-CvKyk4ag.js.map +1 -0
- package/dist/completion/index.cjs +595 -0
- package/dist/completion/index.cjs.map +1 -0
- package/dist/completion/index.d.cts +153 -0
- package/dist/completion/index.d.cts.map +1 -0
- package/dist/completion/index.d.ts +153 -0
- package/dist/completion/index.d.ts.map +1 -0
- package/dist/completion/index.js +588 -0
- package/dist/completion/index.js.map +1 -0
- package/dist/docs/index.cjs +1239 -0
- package/dist/docs/index.cjs.map +1 -0
- package/dist/docs/index.d.cts +500 -0
- package/dist/docs/index.d.cts.map +1 -0
- package/dist/docs/index.d.ts +500 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +1182 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/index.cjs +28 -0
- package/dist/index.d.cts +439 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +439 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/runner-C8rhhx6L.js +1372 -0
- package/dist/runner-C8rhhx6L.js.map +1 -0
- package/dist/runner-C_m6ve-j.js +4 -0
- package/dist/runner-CmjYWlam.cjs +1486 -0
- package/dist/runner-CmjYWlam.cjs.map +1 -0
- package/dist/runner-pmoTWUXY.cjs +4 -0
- package/dist/schema-extractor-B9D3Rf22.cjs +354 -0
- package/dist/schema-extractor-B9D3Rf22.cjs.map +1 -0
- package/dist/schema-extractor-D-Eo7I77.d.cts +303 -0
- package/dist/schema-extractor-D-Eo7I77.d.cts.map +1 -0
- package/dist/schema-extractor-Dk5Z0Iei.js +324 -0
- package/dist/schema-extractor-Dk5Z0Iei.js.map +1 -0
- package/dist/schema-extractor-kkajLb9E.d.ts +303 -0
- package/dist/schema-extractor-kkajLb9E.d.ts.map +1 -0
- package/dist/subcommand-router-BiSvDXHg.js +153 -0
- package/dist/subcommand-router-BiSvDXHg.js.map +1 -0
- package/dist/subcommand-router-Vf-0w9P4.cjs +189 -0
- package/dist/subcommand-router-Vf-0w9P4.cjs.map +1 -0
- package/package.json +108 -6
package/README.md
CHANGED
|
@@ -1,45 +1,314 @@
|
|
|
1
1
|
# politty
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**politty** is a lightweight, type-safe CLI framework for Node.js built on **Zod v4**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
From simple scripts to complex CLI tools with subcommands, validation, and auto-generated help, you can build them all with a developer-friendly API.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **Zod Native**: Use Zod schemas directly for argument definition and validation
|
|
10
|
+
- **Type Safety**: Full TypeScript support with automatic type inference for parsed arguments
|
|
11
|
+
- **Flexible Argument Definition**: Support for positional arguments, flags, aliases, arrays, and environment variable fallbacks
|
|
12
|
+
- **Subcommands**: Build Git-style nested subcommands (with lazy loading support)
|
|
13
|
+
- **Lifecycle Management**: Guaranteed `setup` → `run` → `cleanup` execution order
|
|
14
|
+
- **Signal Handling**: Proper SIGINT/SIGTERM handling with guaranteed cleanup execution
|
|
15
|
+
- **Auto Help Generation**: Automatically generate help text from definitions
|
|
16
|
+
- **Discriminated Union**: Support for mutually exclusive argument sets
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `politty`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
18
|
+
## Requirements
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
- Node.js >= 18
|
|
21
|
+
- Zod >= 4.2.1
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
## Installation
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
```bash
|
|
26
|
+
npm install politty zod
|
|
27
|
+
# or
|
|
28
|
+
pnpm add politty zod
|
|
29
|
+
# or
|
|
30
|
+
yarn add politty zod
|
|
31
|
+
```
|
|
21
32
|
|
|
22
|
-
|
|
33
|
+
## Quick Start
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
35
|
+
```typescript
|
|
36
|
+
import { z } from "zod";
|
|
37
|
+
import { defineCommand, runMain, arg } from "politty";
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
const command = defineCommand({
|
|
40
|
+
name: "greet",
|
|
41
|
+
description: "A CLI tool that displays greetings",
|
|
42
|
+
args: z.object({
|
|
43
|
+
name: arg(z.string(), {
|
|
44
|
+
positional: true,
|
|
45
|
+
description: "Name of the person to greet",
|
|
46
|
+
}),
|
|
47
|
+
greeting: arg(z.string().default("Hello"), {
|
|
48
|
+
alias: "g",
|
|
49
|
+
description: "Greeting phrase",
|
|
50
|
+
}),
|
|
51
|
+
loud: arg(z.boolean().default(false), {
|
|
52
|
+
alias: "l",
|
|
53
|
+
description: "Output in uppercase",
|
|
54
|
+
}),
|
|
55
|
+
}),
|
|
56
|
+
run: (args) => {
|
|
57
|
+
let message = `${args.greeting}, ${args.name}!`;
|
|
58
|
+
if (args.loud) {
|
|
59
|
+
message = message.toUpperCase();
|
|
60
|
+
}
|
|
61
|
+
console.log(message);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
30
64
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
65
|
+
runMain(command);
|
|
66
|
+
```
|
|
36
67
|
|
|
37
|
-
|
|
68
|
+
Example usage:
|
|
38
69
|
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
70
|
+
```bash
|
|
71
|
+
$ my-cli World
|
|
72
|
+
Hello, World!
|
|
42
73
|
|
|
43
|
-
|
|
74
|
+
$ my-cli World -g "Hi" -l
|
|
75
|
+
HI, WORLD!
|
|
44
76
|
|
|
45
|
-
|
|
77
|
+
$ my-cli --help
|
|
78
|
+
Usage: greet <name> [options]
|
|
79
|
+
|
|
80
|
+
A CLI tool that displays greetings
|
|
81
|
+
|
|
82
|
+
Arguments:
|
|
83
|
+
name Name of the person to greet
|
|
84
|
+
|
|
85
|
+
Options:
|
|
86
|
+
-g, --greeting <value> Greeting phrase (default: "Hello")
|
|
87
|
+
-l, --loud Output in uppercase
|
|
88
|
+
-h, --help Show help
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Basic Usage
|
|
92
|
+
|
|
93
|
+
### Defining Arguments
|
|
94
|
+
|
|
95
|
+
Use the `arg()` function to define argument metadata:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { z } from "zod";
|
|
99
|
+
import { arg, defineCommand } from "politty";
|
|
100
|
+
|
|
101
|
+
const command = defineCommand({
|
|
102
|
+
name: "example",
|
|
103
|
+
args: z.object({
|
|
104
|
+
// Positional argument (required)
|
|
105
|
+
input: arg(z.string(), {
|
|
106
|
+
positional: true,
|
|
107
|
+
description: "Input file",
|
|
108
|
+
}),
|
|
109
|
+
|
|
110
|
+
// Optional positional argument
|
|
111
|
+
output: arg(z.string().optional(), {
|
|
112
|
+
positional: true,
|
|
113
|
+
description: "Output file",
|
|
114
|
+
}),
|
|
115
|
+
|
|
116
|
+
// Flag (with alias)
|
|
117
|
+
verbose: arg(z.boolean().default(false), {
|
|
118
|
+
alias: "v",
|
|
119
|
+
description: "Verbose output",
|
|
120
|
+
}),
|
|
121
|
+
|
|
122
|
+
// Environment variable fallback
|
|
123
|
+
apiKey: arg(z.string().optional(), {
|
|
124
|
+
env: "API_KEY",
|
|
125
|
+
description: "API key",
|
|
126
|
+
}),
|
|
127
|
+
|
|
128
|
+
// Array argument (--file a.txt --file b.txt)
|
|
129
|
+
files: arg(z.array(z.string()).default([]), {
|
|
130
|
+
alias: "f",
|
|
131
|
+
description: "Files to process",
|
|
132
|
+
}),
|
|
133
|
+
}),
|
|
134
|
+
run: (args) => {
|
|
135
|
+
console.log(args);
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Subcommands
|
|
141
|
+
|
|
142
|
+
Define Git-style subcommands:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { z } from "zod";
|
|
146
|
+
import { arg, defineCommand, runMain } from "politty";
|
|
147
|
+
|
|
148
|
+
const initCommand = defineCommand({
|
|
149
|
+
name: "init",
|
|
150
|
+
description: "Initialize a project",
|
|
151
|
+
args: z.object({
|
|
152
|
+
template: arg(z.string().default("default"), {
|
|
153
|
+
alias: "t",
|
|
154
|
+
description: "Template name",
|
|
155
|
+
}),
|
|
156
|
+
}),
|
|
157
|
+
run: (args) => {
|
|
158
|
+
console.log(`Initializing with template: ${args.template}`);
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const buildCommand = defineCommand({
|
|
163
|
+
name: "build",
|
|
164
|
+
description: "Build the project",
|
|
165
|
+
args: z.object({
|
|
166
|
+
output: arg(z.string().default("dist"), {
|
|
167
|
+
alias: "o",
|
|
168
|
+
description: "Output directory",
|
|
169
|
+
}),
|
|
170
|
+
minify: arg(z.boolean().default(false), {
|
|
171
|
+
alias: "m",
|
|
172
|
+
description: "Minify output",
|
|
173
|
+
}),
|
|
174
|
+
}),
|
|
175
|
+
run: (args) => {
|
|
176
|
+
console.log(`Building to: ${args.output}`);
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const cli = defineCommand({
|
|
181
|
+
name: "my-cli",
|
|
182
|
+
description: "Example CLI with subcommands",
|
|
183
|
+
subCommands: {
|
|
184
|
+
init: initCommand,
|
|
185
|
+
build: buildCommand,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
runMain(cli, { version: "1.0.0" });
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Example usage:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
$ my-cli init -t react
|
|
196
|
+
$ my-cli build -o out -m
|
|
197
|
+
$ my-cli --help
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Lifecycle Hooks
|
|
201
|
+
|
|
202
|
+
Execute hooks in `setup` → `run` → `cleanup` order. The `cleanup` hook is always executed, even if an error occurs:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
const command = defineCommand({
|
|
206
|
+
name: "db-query",
|
|
207
|
+
description: "Execute database queries",
|
|
208
|
+
args: z.object({
|
|
209
|
+
database: arg(z.string(), {
|
|
210
|
+
alias: "d",
|
|
211
|
+
description: "Database connection string",
|
|
212
|
+
}),
|
|
213
|
+
query: arg(z.string(), {
|
|
214
|
+
alias: "q",
|
|
215
|
+
description: "SQL query",
|
|
216
|
+
}),
|
|
217
|
+
}),
|
|
218
|
+
setup: async ({ args }) => {
|
|
219
|
+
console.log("[setup] Connecting to database...");
|
|
220
|
+
// Establish DB connection
|
|
221
|
+
},
|
|
222
|
+
run: async (args) => {
|
|
223
|
+
console.log("[run] Executing query...");
|
|
224
|
+
// Execute query
|
|
225
|
+
return { rowCount: 42 };
|
|
226
|
+
},
|
|
227
|
+
cleanup: async ({ args, error }) => {
|
|
228
|
+
console.log("[cleanup] Closing connection...");
|
|
229
|
+
if (error) {
|
|
230
|
+
console.error(`Error occurred: ${error.message}`);
|
|
231
|
+
}
|
|
232
|
+
// Close connection
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## API
|
|
238
|
+
|
|
239
|
+
### `defineCommand(options)`
|
|
240
|
+
|
|
241
|
+
Define a command.
|
|
242
|
+
|
|
243
|
+
| Option | Type | Description |
|
|
244
|
+
| ------------- | ----------------------------- | ------------------- |
|
|
245
|
+
| `name` | `string` | Command name |
|
|
246
|
+
| `description` | `string?` | Command description |
|
|
247
|
+
| `args` | `ZodSchema` | Argument schema |
|
|
248
|
+
| `subCommands` | `Record<string, Command>?` | Subcommands |
|
|
249
|
+
| `setup` | `(context) => Promise<void>?` | Setup hook |
|
|
250
|
+
| `run` | `(args) => T?` | Run function |
|
|
251
|
+
| `cleanup` | `(context) => Promise<void>?` | Cleanup hook |
|
|
252
|
+
|
|
253
|
+
### `runMain(command, options?)`
|
|
254
|
+
|
|
255
|
+
CLI entry point. Handles signals and calls `process.exit()`.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
runMain(command, {
|
|
259
|
+
version: "1.0.0", // Displayed with --version flag
|
|
260
|
+
argv: process.argv, // Custom argv
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### `runCommand(command, argv, options?)`
|
|
265
|
+
|
|
266
|
+
Programmatic/testing entry point. Does not call `process.exit()` and returns a result object.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const result = await runCommand(command, ["arg1", "--flag"]);
|
|
270
|
+
if (result.success) {
|
|
271
|
+
console.log(result.result);
|
|
272
|
+
} else {
|
|
273
|
+
console.error(result.error);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `arg(schema, meta)`
|
|
278
|
+
|
|
279
|
+
Attach metadata to an argument.
|
|
280
|
+
|
|
281
|
+
| Metadata | Type | Description |
|
|
282
|
+
| ------------- | ---------- | ------------------------------------ |
|
|
283
|
+
| `positional` | `boolean?` | Treat as positional argument |
|
|
284
|
+
| `alias` | `string?` | Short alias (e.g., `-v`) |
|
|
285
|
+
| `description` | `string?` | Argument description |
|
|
286
|
+
| `placeholder` | `string?` | Placeholder shown in help |
|
|
287
|
+
| `env` | `string?` | Environment variable name (fallback) |
|
|
288
|
+
|
|
289
|
+
## Documentation
|
|
290
|
+
|
|
291
|
+
For detailed documentation, see the `docs/` directory:
|
|
292
|
+
|
|
293
|
+
- [Getting Started](./docs/getting-started.md) - Installation and creating your first command
|
|
294
|
+
- [Essentials](./docs/essentials.md) - Core concepts explained
|
|
295
|
+
- [Advanced Features](./docs/advanced-features.md) - Subcommands, Discriminated Union
|
|
296
|
+
- [Recipes](./docs/recipes.md) - Testing, configuration, error handling
|
|
297
|
+
- [API Reference](./docs/api-reference.md) - Detailed API reference
|
|
298
|
+
- [Doc Generation](./docs/doc-generation.md) - Automatic documentation generation
|
|
299
|
+
|
|
300
|
+
## Examples
|
|
301
|
+
|
|
302
|
+
The `playground/` directory contains many examples:
|
|
303
|
+
|
|
304
|
+
- `01-hello-world` - Minimal command configuration
|
|
305
|
+
- `02-greet` - Positional arguments and flags
|
|
306
|
+
- `03-array-args` - Array arguments
|
|
307
|
+
- `05-lifecycle-hooks` - Lifecycle hooks
|
|
308
|
+
- `10-subcommands` - Subcommands
|
|
309
|
+
- `12-discriminated-union` - Discriminated Union
|
|
310
|
+
- `21-lazy-subcommands` - Lazy loading
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
MIT
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/core/arg-registry.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base metadata shared by all argument types
|
|
7
|
+
*/
|
|
8
|
+
interface BaseArgMeta {
|
|
9
|
+
/** Argument description */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Treat as positional argument */
|
|
12
|
+
positional?: boolean;
|
|
13
|
+
/** Placeholder for help display */
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Environment variable name(s) to read value from.
|
|
17
|
+
* If an array is provided, earlier entries take priority.
|
|
18
|
+
* CLI arguments always take precedence over environment variables.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Single env var
|
|
23
|
+
* port: arg(z.coerce.number(), { env: "PORT" })
|
|
24
|
+
*
|
|
25
|
+
* // Multiple env vars (PORT takes priority over SERVER_PORT)
|
|
26
|
+
* port: arg(z.coerce.number(), { env: ["PORT", "SERVER_PORT"] })
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
env?: string | string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Metadata for regular arguments (non-builtin aliases)
|
|
33
|
+
*/
|
|
34
|
+
interface RegularArgMeta extends BaseArgMeta {
|
|
35
|
+
/** Short alias (e.g., 'v' for --verbose) */
|
|
36
|
+
alias?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Metadata for overriding built-in aliases (-h, -H)
|
|
40
|
+
*/
|
|
41
|
+
interface BuiltinOverrideArgMeta extends BaseArgMeta {
|
|
42
|
+
/** Built-in alias to override ('h' or 'H') */
|
|
43
|
+
alias: "h" | "H";
|
|
44
|
+
/** Must be true to override built-in aliases */
|
|
45
|
+
overrideBuiltinAlias: true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Metadata options for argument definition
|
|
49
|
+
*/
|
|
50
|
+
type ArgMeta = RegularArgMeta | BuiltinOverrideArgMeta;
|
|
51
|
+
/**
|
|
52
|
+
* Register metadata for a Zod schema
|
|
53
|
+
*
|
|
54
|
+
* @param schema - The Zod schema
|
|
55
|
+
* @param meta - Argument metadata
|
|
56
|
+
* @returns The same schema (for chaining)
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { z } from "zod";
|
|
61
|
+
* import { arg, defineCommand } from "politty";
|
|
62
|
+
*
|
|
63
|
+
* const cmd = defineCommand({
|
|
64
|
+
* args: z.object({
|
|
65
|
+
* name: arg(z.string(), { description: "User name", positional: true }),
|
|
66
|
+
* verbose: arg(z.boolean().default(false), { alias: "v" }),
|
|
67
|
+
* }),
|
|
68
|
+
* run: (args) => {
|
|
69
|
+
* console.log(args.name, args.verbose);
|
|
70
|
+
* },
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
/**
|
|
75
|
+
* Type helper to validate ArgMeta
|
|
76
|
+
* Forces a type error if alias is "h" or "H" without overrideBuiltinAlias: true
|
|
77
|
+
*/
|
|
78
|
+
type ValidateArgMeta<M> = M extends {
|
|
79
|
+
alias: "h" | "H";
|
|
80
|
+
} ? M extends {
|
|
81
|
+
overrideBuiltinAlias: true;
|
|
82
|
+
} ? M : { [K in keyof M]: M[K] } & {
|
|
83
|
+
__typeError: "Alias 'h' or 'H' requires overrideBuiltinAlias: true";
|
|
84
|
+
} : M;
|
|
85
|
+
declare function arg<T extends z.ZodType>(schema: T): T;
|
|
86
|
+
declare function arg<T extends z.ZodType, M extends ArgMeta>(schema: T, meta: ValidateArgMeta<M>): T;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { arg as n, ArgMeta as t };
|
|
89
|
+
//# sourceMappingURL=arg-registry-ClI2WGgH.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arg-registry-ClI2WGgH.d.cts","names":[],"sources":["../src/core/arg-registry.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AA2BiB,UA3BA,WAAA,CA2Be;EAQf;EAUL,WAAO,CAAA,EAAA,MAAA;EAmCd;EAAqB,UAAA,CAAA,EAAA,OAAA;EACtB;EACE,WAAA,CAAA,EAAA,MAAA;EAEc;;;;;AAMpB;;;;;AACA;;;;EAA6F,GAAA,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;;;;;UAhE5E,cAAA,SAAuB;;;;;;;UAQvB,sBAAA,SAA+B;;;;;;;;;KAUpC,OAAA,GAAU,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmClC,qBAAqB;;IACtB;;IACE,kBAEc,IAAI,EAAE;;IAItB;iBAEY,cAAc,CAAA,CAAE,iBAAiB,IAAI;iBACrC,cAAc,CAAA,CAAE,mBAAmB,iBAAiB,SAAS,gBAAgB,KAAK"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/core/arg-registry.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base metadata shared by all argument types
|
|
7
|
+
*/
|
|
8
|
+
interface BaseArgMeta {
|
|
9
|
+
/** Argument description */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Treat as positional argument */
|
|
12
|
+
positional?: boolean;
|
|
13
|
+
/** Placeholder for help display */
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Environment variable name(s) to read value from.
|
|
17
|
+
* If an array is provided, earlier entries take priority.
|
|
18
|
+
* CLI arguments always take precedence over environment variables.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Single env var
|
|
23
|
+
* port: arg(z.coerce.number(), { env: "PORT" })
|
|
24
|
+
*
|
|
25
|
+
* // Multiple env vars (PORT takes priority over SERVER_PORT)
|
|
26
|
+
* port: arg(z.coerce.number(), { env: ["PORT", "SERVER_PORT"] })
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
env?: string | string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Metadata for regular arguments (non-builtin aliases)
|
|
33
|
+
*/
|
|
34
|
+
interface RegularArgMeta extends BaseArgMeta {
|
|
35
|
+
/** Short alias (e.g., 'v' for --verbose) */
|
|
36
|
+
alias?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Metadata for overriding built-in aliases (-h, -H)
|
|
40
|
+
*/
|
|
41
|
+
interface BuiltinOverrideArgMeta extends BaseArgMeta {
|
|
42
|
+
/** Built-in alias to override ('h' or 'H') */
|
|
43
|
+
alias: "h" | "H";
|
|
44
|
+
/** Must be true to override built-in aliases */
|
|
45
|
+
overrideBuiltinAlias: true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Metadata options for argument definition
|
|
49
|
+
*/
|
|
50
|
+
type ArgMeta = RegularArgMeta | BuiltinOverrideArgMeta;
|
|
51
|
+
/**
|
|
52
|
+
* Register metadata for a Zod schema
|
|
53
|
+
*
|
|
54
|
+
* @param schema - The Zod schema
|
|
55
|
+
* @param meta - Argument metadata
|
|
56
|
+
* @returns The same schema (for chaining)
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { z } from "zod";
|
|
61
|
+
* import { arg, defineCommand } from "politty";
|
|
62
|
+
*
|
|
63
|
+
* const cmd = defineCommand({
|
|
64
|
+
* args: z.object({
|
|
65
|
+
* name: arg(z.string(), { description: "User name", positional: true }),
|
|
66
|
+
* verbose: arg(z.boolean().default(false), { alias: "v" }),
|
|
67
|
+
* }),
|
|
68
|
+
* run: (args) => {
|
|
69
|
+
* console.log(args.name, args.verbose);
|
|
70
|
+
* },
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
/**
|
|
75
|
+
* Type helper to validate ArgMeta
|
|
76
|
+
* Forces a type error if alias is "h" or "H" without overrideBuiltinAlias: true
|
|
77
|
+
*/
|
|
78
|
+
type ValidateArgMeta<M> = M extends {
|
|
79
|
+
alias: "h" | "H";
|
|
80
|
+
} ? M extends {
|
|
81
|
+
overrideBuiltinAlias: true;
|
|
82
|
+
} ? M : { [K in keyof M]: M[K] } & {
|
|
83
|
+
__typeError: "Alias 'h' or 'H' requires overrideBuiltinAlias: true";
|
|
84
|
+
} : M;
|
|
85
|
+
declare function arg<T extends z.ZodType>(schema: T): T;
|
|
86
|
+
declare function arg<T extends z.ZodType, M extends ArgMeta>(schema: T, meta: ValidateArgMeta<M>): T;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { arg as n, ArgMeta as t };
|
|
89
|
+
//# sourceMappingURL=arg-registry-D4NsqcNZ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arg-registry-D4NsqcNZ.d.ts","names":[],"sources":["../src/core/arg-registry.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AA2BiB,UA3BA,WAAA,CA2Be;EAQf;EAUL,WAAO,CAAA,EAAA,MAAA;EAmCd;EAAqB,UAAA,CAAA,EAAA,OAAA;EACtB;EACE,WAAA,CAAA,EAAA,MAAA;EAEc;;;;;AAMpB;;;;;AACA;;;;EAA6F,GAAA,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;;;;;UAhE5E,cAAA,SAAuB;;;;;;;UAQvB,sBAAA,SAA+B;;;;;;;;;KAUpC,OAAA,GAAU,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmClC,qBAAqB;;IACtB;;IACE,kBAEc,IAAI,EAAE;;IAItB;iBAEY,cAAc,CAAA,CAAE,iBAAiB,IAAI;iBACrC,cAAc,CAAA,CAAE,mBAAmB,iBAAiB,SAAS,gBAAgB,KAAK"}
|
package/dist/augment.cjs
ADDED
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { t as ArgMeta } from "./arg-registry-ClI2WGgH.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/augment.d.ts
|
|
4
|
+
|
|
5
|
+
declare module "zod" {
|
|
6
|
+
interface ZodTypeDef {
|
|
7
|
+
argMeta?: ArgMeta;
|
|
8
|
+
}
|
|
9
|
+
interface GlobalMeta {
|
|
10
|
+
description?: string;
|
|
11
|
+
positional?: boolean;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
alias?: string;
|
|
14
|
+
overrideBuiltinAlias?: boolean;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=augment.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augment.d.cts","names":[],"sources":["../src/augment.ts"],"sourcesContent":[],"mappings":";;;;;;cAkBc"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { t as ArgMeta } from "./arg-registry-D4NsqcNZ.js";
|
|
2
|
+
|
|
3
|
+
//#region src/augment.d.ts
|
|
4
|
+
|
|
5
|
+
declare module "zod" {
|
|
6
|
+
interface ZodTypeDef {
|
|
7
|
+
argMeta?: ArgMeta;
|
|
8
|
+
}
|
|
9
|
+
interface GlobalMeta {
|
|
10
|
+
description?: string;
|
|
11
|
+
positional?: boolean;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
alias?: string;
|
|
14
|
+
overrideBuiltinAlias?: boolean;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=augment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"augment.d.ts","names":[],"sources":["../src/augment.ts"],"sourcesContent":[],"mappings":";;;;;;cAkBc"}
|
package/dist/augment.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
let zod = require("zod");
|
|
2
|
+
|
|
3
|
+
//#region src/core/command.ts
|
|
4
|
+
function defineCommand(config) {
|
|
5
|
+
return {
|
|
6
|
+
name: config.name,
|
|
7
|
+
description: config.description,
|
|
8
|
+
args: config.args,
|
|
9
|
+
subCommands: config.subCommands,
|
|
10
|
+
setup: config.setup,
|
|
11
|
+
run: config.run,
|
|
12
|
+
cleanup: config.cleanup,
|
|
13
|
+
notes: config.notes,
|
|
14
|
+
examples: config.examples
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
Object.defineProperty(exports, 'defineCommand', {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () {
|
|
22
|
+
return defineCommand;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=command-Bgd-yIwv.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-Bgd-yIwv.cjs","names":[],"sources":["../src/core/command.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type {\n ArgsSchema,\n Command,\n Example,\n NonRunnableCommand,\n RunnableCommand,\n SubCommandsRecord,\n} from \"../types.js\";\n\n/**\n * Infer args type from schema, defaults to empty object if undefined\n */\ntype InferArgs<TArgsSchema> = TArgsSchema extends z.ZodType\n ? z.infer<TArgsSchema>\n : Record<string, never>;\n\n/**\n * Config for defining a command\n * @template TArgsSchema - The Zod schema type for arguments\n * @template TResult - The return type of run function (void if no run)\n */\ninterface DefineCommandConfig<TArgsSchema extends ArgsSchema | undefined, TResult> {\n name: string;\n description?: string;\n args?: TArgsSchema;\n subCommands?: SubCommandsRecord;\n setup?: (context: { args: InferArgs<TArgsSchema> }) => void | Promise<void>;\n run?: (args: InferArgs<TArgsSchema>) => TResult;\n cleanup?: (context: {\n args: InferArgs<TArgsSchema>;\n error?: Error | undefined;\n }) => void | Promise<void>;\n notes?: string;\n examples?: Example[];\n}\n\n/**\n * Config with run function (runnable command)\n */\ninterface RunnableConfig<\n TArgsSchema extends ArgsSchema | undefined,\n TResult,\n> extends DefineCommandConfig<TArgsSchema, TResult> {\n run: (args: InferArgs<TArgsSchema>) => TResult;\n}\n\n/**\n * Config without run function (non-runnable command)\n */\ninterface NonRunnableConfig<TArgsSchema extends ArgsSchema | undefined> extends Omit<\n DefineCommandConfig<TArgsSchema, void>,\n \"run\"\n> {\n run?: undefined;\n}\n\n/**\n * Define a CLI command with type-safe arguments\n *\n * @param config - Command configuration\n * @returns A defined command with preserved type information\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { arg, defineCommand } from \"politty\";\n *\n * const command = defineCommand({\n * name: \"greet\",\n * args: z.object({\n * name: arg(z.string(), { description: \"Name to greet\", positional: true }),\n * loud: arg(z.boolean().default(false), { alias: \"l\", description: \"Use uppercase\" }),\n * }),\n * run: (args) => {\n * const greeting = `Hello, ${args.name}!`;\n * console.log(args.loud ? greeting.toUpperCase() : greeting);\n * },\n * });\n *\n * // Type of command.argsSchema is preserved as z.ZodObject<...>\n * // Type of command.run is (args: { name: string; loud: boolean }) => void\n * ```\n *\n * @example\n * ```ts\n * // With discriminated union for subcommand-like behavior\n * const command = defineCommand({\n * name: \"resource\",\n * args: z.discriminatedUnion(\"action\", [\n * z.object({\n * action: z.literal(\"create\"),\n * name: arg(z.string(), { description: \"Resource name\" }),\n * }),\n * z.object({\n * action: z.literal(\"delete\"),\n * id: arg(z.coerce.number(), { description: \"Resource ID\" }),\n * }),\n * ]),\n * run: (args) => {\n * if (args.action === \"create\") {\n * console.log(`Creating ${args.name}`);\n * } else {\n * console.log(`Deleting ${args.id}`);\n * }\n * },\n * });\n * ```\n */\n// Overload 1: with run function - returns RunnableCommand with preserved schema type\nexport function defineCommand<\n TArgsSchema extends ArgsSchema | undefined = undefined,\n TResult = void,\n>(\n config: RunnableConfig<TArgsSchema, TResult>,\n): RunnableCommand<TArgsSchema, InferArgs<TArgsSchema>, TResult>;\n\n// Overload 2: without run function - returns NonRunnableCommand with preserved schema type\nexport function defineCommand<TArgsSchema extends ArgsSchema | undefined = undefined>(\n config: NonRunnableConfig<TArgsSchema>,\n): NonRunnableCommand<TArgsSchema, InferArgs<TArgsSchema>>;\n\n// Implementation\nexport function defineCommand<\n TArgsSchema extends ArgsSchema | undefined = undefined,\n TResult = void,\n>(\n config: RunnableConfig<TArgsSchema, TResult> | NonRunnableConfig<TArgsSchema>,\n): Command<TArgsSchema, InferArgs<TArgsSchema>, TResult> {\n return {\n name: config.name,\n description: config.description,\n args: config.args as TArgsSchema,\n subCommands: config.subCommands,\n setup: config.setup,\n run: config.run,\n cleanup: config.cleanup,\n notes: config.notes,\n examples: config.examples,\n } as Command<TArgsSchema, InferArgs<TArgsSchema>, TResult>;\n}\n"],"mappings":";;;AA2HA,SAAgB,cAId,QACuD;AACvD,QAAO;EACL,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,OAAO,OAAO;EACd,KAAK,OAAO;EACZ,SAAS,OAAO;EAChB,OAAO,OAAO;EACd,UAAU,OAAO;EAClB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/core/command.ts
|
|
4
|
+
function defineCommand(config) {
|
|
5
|
+
return {
|
|
6
|
+
name: config.name,
|
|
7
|
+
description: config.description,
|
|
8
|
+
args: config.args,
|
|
9
|
+
subCommands: config.subCommands,
|
|
10
|
+
setup: config.setup,
|
|
11
|
+
run: config.run,
|
|
12
|
+
cleanup: config.cleanup,
|
|
13
|
+
notes: config.notes,
|
|
14
|
+
examples: config.examples
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { defineCommand as t };
|
|
20
|
+
//# sourceMappingURL=command-CvKyk4ag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-CvKyk4ag.js","names":[],"sources":["../src/core/command.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type {\n ArgsSchema,\n Command,\n Example,\n NonRunnableCommand,\n RunnableCommand,\n SubCommandsRecord,\n} from \"../types.js\";\n\n/**\n * Infer args type from schema, defaults to empty object if undefined\n */\ntype InferArgs<TArgsSchema> = TArgsSchema extends z.ZodType\n ? z.infer<TArgsSchema>\n : Record<string, never>;\n\n/**\n * Config for defining a command\n * @template TArgsSchema - The Zod schema type for arguments\n * @template TResult - The return type of run function (void if no run)\n */\ninterface DefineCommandConfig<TArgsSchema extends ArgsSchema | undefined, TResult> {\n name: string;\n description?: string;\n args?: TArgsSchema;\n subCommands?: SubCommandsRecord;\n setup?: (context: { args: InferArgs<TArgsSchema> }) => void | Promise<void>;\n run?: (args: InferArgs<TArgsSchema>) => TResult;\n cleanup?: (context: {\n args: InferArgs<TArgsSchema>;\n error?: Error | undefined;\n }) => void | Promise<void>;\n notes?: string;\n examples?: Example[];\n}\n\n/**\n * Config with run function (runnable command)\n */\ninterface RunnableConfig<\n TArgsSchema extends ArgsSchema | undefined,\n TResult,\n> extends DefineCommandConfig<TArgsSchema, TResult> {\n run: (args: InferArgs<TArgsSchema>) => TResult;\n}\n\n/**\n * Config without run function (non-runnable command)\n */\ninterface NonRunnableConfig<TArgsSchema extends ArgsSchema | undefined> extends Omit<\n DefineCommandConfig<TArgsSchema, void>,\n \"run\"\n> {\n run?: undefined;\n}\n\n/**\n * Define a CLI command with type-safe arguments\n *\n * @param config - Command configuration\n * @returns A defined command with preserved type information\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { arg, defineCommand } from \"politty\";\n *\n * const command = defineCommand({\n * name: \"greet\",\n * args: z.object({\n * name: arg(z.string(), { description: \"Name to greet\", positional: true }),\n * loud: arg(z.boolean().default(false), { alias: \"l\", description: \"Use uppercase\" }),\n * }),\n * run: (args) => {\n * const greeting = `Hello, ${args.name}!`;\n * console.log(args.loud ? greeting.toUpperCase() : greeting);\n * },\n * });\n *\n * // Type of command.argsSchema is preserved as z.ZodObject<...>\n * // Type of command.run is (args: { name: string; loud: boolean }) => void\n * ```\n *\n * @example\n * ```ts\n * // With discriminated union for subcommand-like behavior\n * const command = defineCommand({\n * name: \"resource\",\n * args: z.discriminatedUnion(\"action\", [\n * z.object({\n * action: z.literal(\"create\"),\n * name: arg(z.string(), { description: \"Resource name\" }),\n * }),\n * z.object({\n * action: z.literal(\"delete\"),\n * id: arg(z.coerce.number(), { description: \"Resource ID\" }),\n * }),\n * ]),\n * run: (args) => {\n * if (args.action === \"create\") {\n * console.log(`Creating ${args.name}`);\n * } else {\n * console.log(`Deleting ${args.id}`);\n * }\n * },\n * });\n * ```\n */\n// Overload 1: with run function - returns RunnableCommand with preserved schema type\nexport function defineCommand<\n TArgsSchema extends ArgsSchema | undefined = undefined,\n TResult = void,\n>(\n config: RunnableConfig<TArgsSchema, TResult>,\n): RunnableCommand<TArgsSchema, InferArgs<TArgsSchema>, TResult>;\n\n// Overload 2: without run function - returns NonRunnableCommand with preserved schema type\nexport function defineCommand<TArgsSchema extends ArgsSchema | undefined = undefined>(\n config: NonRunnableConfig<TArgsSchema>,\n): NonRunnableCommand<TArgsSchema, InferArgs<TArgsSchema>>;\n\n// Implementation\nexport function defineCommand<\n TArgsSchema extends ArgsSchema | undefined = undefined,\n TResult = void,\n>(\n config: RunnableConfig<TArgsSchema, TResult> | NonRunnableConfig<TArgsSchema>,\n): Command<TArgsSchema, InferArgs<TArgsSchema>, TResult> {\n return {\n name: config.name,\n description: config.description,\n args: config.args as TArgsSchema,\n subCommands: config.subCommands,\n setup: config.setup,\n run: config.run,\n cleanup: config.cleanup,\n notes: config.notes,\n examples: config.examples,\n } as Command<TArgsSchema, InferArgs<TArgsSchema>, TResult>;\n}\n"],"mappings":";;;AA2HA,SAAgB,cAId,QACuD;AACvD,QAAO;EACL,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,OAAO,OAAO;EACd,KAAK,OAAO;EACZ,SAAS,OAAO;EAChB,OAAO,OAAO;EACd,UAAU,OAAO;EAClB"}
|