zod-commander 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +85 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +54 -0
- package/dist/index.d.ts +9 -7
- package/dist/index.js +80 -93
- package/dist/index.js.map +1 -0
- package/package.json +18 -13
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -26
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var commander = require('commander');
|
|
4
|
+
var zod = require('zod');
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var zodCore = /* @__PURE__ */ __name((zod$1, fn) => {
|
|
9
|
+
const types = [zod.z.ZodDefault, zod.z.ZodNullable, zod.z.ZodOptional];
|
|
10
|
+
for (const type of types)
|
|
11
|
+
if (zod$1 instanceof type) return zodCore(zod$1._def.innerType, fn);
|
|
12
|
+
if (zod$1 instanceof zod.z.ZodEffects) return zodCore(zod$1._def.schema, fn);
|
|
13
|
+
return fn(zod$1);
|
|
14
|
+
}, "zodCore");
|
|
15
|
+
var zodEnumVals = /* @__PURE__ */ __name((zod$1) => zodCore(zod$1, (zod2) => zod2 instanceof zod.z.ZodEnum ? zod2._def.values : null), "zodEnumVals");
|
|
16
|
+
var zodIsBoolean = /* @__PURE__ */ __name((zod$1) => zodCore(zod$1, (zod2) => zod2 instanceof zod.z.ZodBoolean), "zodIsBoolean");
|
|
17
|
+
var zodDefault = /* @__PURE__ */ __name((zod$1) => zod$1 instanceof zod.z.ZodEffects ? zodDefault(zod$1._def.schema) : zod$1 instanceof zod.z.ZodDefault ? zod$1._def.defaultValue() : void 0, "zodDefault");
|
|
18
|
+
var utils = {
|
|
19
|
+
zodCore,
|
|
20
|
+
zodEnumVals,
|
|
21
|
+
zodIsBoolean,
|
|
22
|
+
zodDefault
|
|
23
|
+
};
|
|
24
|
+
var utils_default = utils;
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var zodParser = /* @__PURE__ */ __name((zod, opt) => (value) => {
|
|
28
|
+
const result = zod.safeParse(value);
|
|
29
|
+
if (result.success) return result.data;
|
|
30
|
+
const msg = result.error.issues[0].message;
|
|
31
|
+
if (opt) throw new commander.InvalidOptionArgumentError(msg);
|
|
32
|
+
throw new commander.InvalidArgumentError(msg);
|
|
33
|
+
}, "zodParser");
|
|
34
|
+
var zodArgument = /* @__PURE__ */ __name((key, zod) => {
|
|
35
|
+
const flag = zod.isOptional() ? `[${key}]` : `<${key}>`;
|
|
36
|
+
const arg = new commander.Argument(flag, zod.description);
|
|
37
|
+
const def = utils_default.zodDefault(zod);
|
|
38
|
+
if (def !== void 0) arg.default(zod.parse(def));
|
|
39
|
+
const choices = utils_default.zodEnumVals(zod);
|
|
40
|
+
if (choices) arg.choices(choices);
|
|
41
|
+
return arg.argParser(zodParser(zod));
|
|
42
|
+
}, "zodArgument");
|
|
43
|
+
var zodOption = /* @__PURE__ */ __name((key, zod) => {
|
|
44
|
+
const abbr = zod.description?.match(/^(\w);/)?.[1];
|
|
45
|
+
const description = abbr ? zod.description.slice(2) : zod.description;
|
|
46
|
+
const arg = key.includes("_") ? key.split("_").slice(1).join("-") : key;
|
|
47
|
+
if (key.includes("_")) [key] = key.split("_");
|
|
48
|
+
const isBoolean = utils_default.zodIsBoolean(zod);
|
|
49
|
+
const flag = `--${key}${isBoolean ? "" : ` <${arg}>`}`;
|
|
50
|
+
const flags = abbr ? `-${abbr}, ${flag}` : flag;
|
|
51
|
+
const opt = new commander.Option(flags, description);
|
|
52
|
+
if (isBoolean) opt.optional = true;
|
|
53
|
+
else if (!zod.isOptional()) opt.makeOptionMandatory();
|
|
54
|
+
const def = utils_default.zodDefault(zod);
|
|
55
|
+
if (def !== void 0) opt.default(zod.parse(def));
|
|
56
|
+
const choices = utils_default.zodEnumVals(zod);
|
|
57
|
+
if (choices) opt.choices(choices);
|
|
58
|
+
return opt.argParser(zodParser(zod, "opt"));
|
|
59
|
+
}, "zodOption");
|
|
60
|
+
var zodCommand = /* @__PURE__ */ __name(({
|
|
61
|
+
name,
|
|
62
|
+
description,
|
|
63
|
+
args,
|
|
64
|
+
opts,
|
|
65
|
+
action
|
|
66
|
+
}) => {
|
|
67
|
+
const command = new commander.Command(name);
|
|
68
|
+
if (description) command.description(description);
|
|
69
|
+
for (const key in args) command.addArgument(zodArgument(key, args[key]));
|
|
70
|
+
for (const key in opts) command.addOption(zodOption(key, opts[key]));
|
|
71
|
+
command.action(async (...all) => {
|
|
72
|
+
const resultArgs = Object.fromEntries(
|
|
73
|
+
Object.keys(args ?? {}).map((key, i) => [key, all[i]])
|
|
74
|
+
);
|
|
75
|
+
const resultOpts = all[Object.keys(args ?? {}).length];
|
|
76
|
+
await action(resultArgs, resultOpts);
|
|
77
|
+
});
|
|
78
|
+
return command;
|
|
79
|
+
}, "zodCommand");
|
|
80
|
+
|
|
81
|
+
exports.zodArgument = zodArgument;
|
|
82
|
+
exports.zodCommand = zodCommand;
|
|
83
|
+
exports.zodOption = zodOption;
|
|
84
|
+
//# sourceMappingURL=index.cjs.map
|
|
85
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["zod","z","InvalidOptionArgumentError","InvalidArgumentError","Argument","Option","Command"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod'\n\nconst zodCore = <T>(zod: z.ZodTypeAny, fn: (zod: z.ZodTypeAny) => T): T => {\n\tconst types = [z.ZodDefault, z.ZodNullable, z.ZodOptional]\n\tfor (const type of types)\n\t\tif (zod instanceof type) return zodCore(zod._def.innerType, fn)\n\tif (zod instanceof z.ZodEffects) return zodCore(zod._def.schema, fn)\n\treturn fn(zod)\n}\n\nconst zodEnumVals = (zod: z.ZodTypeAny): string[] | null =>\n\tzodCore(zod, (zod) => (zod instanceof z.ZodEnum ? zod._def.values : null))\n\nconst zodIsBoolean = (zod: z.ZodTypeAny): boolean =>\n\tzodCore(zod, (zod) => zod instanceof z.ZodBoolean)\n\nconst zodDefault = <Output, Def extends z.ZodTypeDef, Input>(\n\tzod: z.ZodType<Output, Def, Input>,\n): Input | undefined =>\n\tzod instanceof z.ZodEffects\n\t\t? zodDefault(zod._def.schema)\n\t\t: zod instanceof z.ZodDefault\n\t\t\t? zod._def.defaultValue()\n\t\t\t: undefined\n\nconst utils = {\n\tzodCore,\n\tzodEnumVals,\n\tzodIsBoolean,\n\tzodDefault,\n}\n\nexport default utils\n","import {\n\tArgument,\n\tCommand,\n\tInvalidArgumentError,\n\tInvalidOptionArgumentError,\n\tOption,\n} from 'commander'\nimport type { z } from 'zod'\nimport utils from './utils.js'\n\ntype BeforeFirstUnderscore<S> = S extends `${infer T}_${infer _}` ? T : S\n\ntype ReplaceKeyTypes<Type extends z.ZodRawShape> = {\n\t[Key in keyof Type as BeforeFirstUnderscore<Key>]: Type[Key]\n}\n\ntype Prettify<T> = {\n\t[K in keyof T]: T[K]\n} & {}\n\n/**\n * The action function signature for a Zod-powered command.\n * @template A - ZodRawShape for arguments\n * @template O - ZodRawShape for options\n * @param args - Parsed and validated arguments\n * @param opts - Parsed and validated options (with key normalization)\n * @returns A Promise or void\n */\nexport type ZodCommandAction<\n\tA extends z.ZodRawShape,\n\tO extends z.ZodRawShape,\n> = ZodCommandProps<A, O>['action']\n\ntype ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {\n\tname: string\n\tdescription?: string\n\targs?: A\n\topts?: O\n\taction: (\n\t\targs: Prettify<z.infer<z.ZodObject<A>>>,\n\t\topts: Prettify<z.infer<z.ZodObject<ReplaceKeyTypes<O>>>>,\n\t) => Promise<void> | void\n}\n\nconst zodParser = (zod: z.ZodTypeAny, opt?: 'opt') => (value: string) => {\n\tconst result = zod.safeParse(value)\n\tif (result.success) return result.data\n\tconst msg = result.error.issues[0].message\n\tif (opt) throw new InvalidOptionArgumentError(msg)\n\tthrow new InvalidArgumentError(msg)\n}\n\n/**\n * Creates a Commander.js Argument from a Zod schema.\n * Handles optionality, default values, and enum choices.\n * @param key - The argument name\n * @param zod - The Zod schema for the argument\n * @returns A Commander Argument instance\n */\nexport const zodArgument = (key: string, zod: z.ZodTypeAny): Argument => {\n\tconst flag = zod.isOptional() ? `[${key}]` : `<${key}>`\n\tconst arg = new Argument(flag, zod.description)\n\n\tconst def = utils.zodDefault(zod)\n\tif (def !== undefined) arg.default(zod.parse(def))\n\n\tconst choices = utils.zodEnumVals(zod)\n\tif (choices) arg.choices(choices)\n\n\t// parsing must be done at the end to override default parsers\n\treturn arg.argParser(zodParser(zod))\n}\n\n/**\n * Creates a Commander.js Option from a Zod schema.\n * Handles optionality, default values, enum choices, and boolean flags.\n * Supports short flags via description prefix (e.g., 's;...').\n * @param key - The option name (can include underscores for grouping)\n * @param zod - The Zod schema for the option\n * @returns A Commander Option instance\n */\nexport const zodOption = (key: string, zod: z.ZodTypeAny): Option => {\n\tconst abbr = zod.description?.match(/^(\\w);/)?.[1]\n\tconst description = abbr ? zod.description.slice(2) : zod.description\n\tconst arg = key.includes('_') ? key.split('_').slice(1).join('-') : key\n\tif (key.includes('_')) [key] = key.split('_')\n\tconst isBoolean = utils.zodIsBoolean(zod)\n\tconst flag = `--${key}${isBoolean ? '' : ` <${arg}>`}`\n\tconst flags = abbr ? `-${abbr}, ${flag}` : flag\n\tconst opt = new Option(flags, description)\n\n\t// required for boolean flags\n\tif (isBoolean) opt.optional = true\n\telse if (!zod.isOptional()) opt.makeOptionMandatory()\n\n\tconst def = utils.zodDefault(zod)\n\tif (def !== undefined) opt.default(zod.parse(def))\n\n\tconst choices = utils.zodEnumVals(zod)\n\tif (choices) opt.choices(choices)\n\n\t// parsing must be done at the end to override default parsers\n\treturn opt.argParser(zodParser(zod, 'opt'))\n}\n\n/**\n * Defines a Commander.js Command using Zod schemas for arguments and options.\n * Automatically wires up parsing, validation, and help configuration.\n * @template A - ZodRawShape for arguments\n * @template O - ZodRawShape for options\n * @param props - Command properties (name, description, args, opts, action)\n * @returns A Commander Command instance\n */\nexport const zodCommand = <A extends z.ZodRawShape, O extends z.ZodRawShape>({\n\tname,\n\tdescription,\n\targs,\n\topts,\n\taction,\n}: ZodCommandProps<A, O>): Command => {\n\tconst command = new Command(name)\n\tif (description) command.description(description)\n\tfor (const key in args) command.addArgument(zodArgument(key, args[key]))\n\tfor (const key in opts) command.addOption(zodOption(key, opts[key]))\n\tcommand.action(async (...all) => {\n\t\tconst resultArgs = Object.fromEntries(\n\t\t\tObject.keys(args ?? {}).map((key, i) => [key, all[i]]),\n\t\t) as z.infer<z.ZodObject<A>>\n\t\tconst resultOpts = all[Object.keys(args ?? {}).length] as z.infer<\n\t\t\tz.ZodObject<ReplaceKeyTypes<O>>\n\t\t>\n\t\tawait action(resultArgs, resultOpts)\n\t})\n\treturn command\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Argument, Option, Command } from 'commander';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
type BeforeFirstUnderscore<S> = S extends `${infer T}_${infer _}` ? T : S;
|
|
5
|
+
type ReplaceKeyTypes<Type extends z.ZodRawShape> = {
|
|
6
|
+
[Key in keyof Type as BeforeFirstUnderscore<Key>]: Type[Key];
|
|
7
|
+
};
|
|
8
|
+
type Prettify<T> = {
|
|
9
|
+
[K in keyof T]: T[K];
|
|
10
|
+
} & {};
|
|
11
|
+
/**
|
|
12
|
+
* The action function signature for a Zod-powered command.
|
|
13
|
+
* @template A - ZodRawShape for arguments
|
|
14
|
+
* @template O - ZodRawShape for options
|
|
15
|
+
* @param args - Parsed and validated arguments
|
|
16
|
+
* @param opts - Parsed and validated options (with key normalization)
|
|
17
|
+
* @returns A Promise or void
|
|
18
|
+
*/
|
|
19
|
+
type ZodCommandAction<A extends z.ZodRawShape, O extends z.ZodRawShape> = ZodCommandProps<A, O>['action'];
|
|
20
|
+
type ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {
|
|
21
|
+
name: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
args?: A;
|
|
24
|
+
opts?: O;
|
|
25
|
+
action: (args: Prettify<z.infer<z.ZodObject<A>>>, opts: Prettify<z.infer<z.ZodObject<ReplaceKeyTypes<O>>>>) => Promise<void> | void;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Creates a Commander.js Argument from a Zod schema.
|
|
29
|
+
* Handles optionality, default values, and enum choices.
|
|
30
|
+
* @param key - The argument name
|
|
31
|
+
* @param zod - The Zod schema for the argument
|
|
32
|
+
* @returns A Commander Argument instance
|
|
33
|
+
*/
|
|
34
|
+
declare const zodArgument: (key: string, zod: z.ZodTypeAny) => Argument;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a Commander.js Option from a Zod schema.
|
|
37
|
+
* Handles optionality, default values, enum choices, and boolean flags.
|
|
38
|
+
* Supports short flags via description prefix (e.g., 's;...').
|
|
39
|
+
* @param key - The option name (can include underscores for grouping)
|
|
40
|
+
* @param zod - The Zod schema for the option
|
|
41
|
+
* @returns A Commander Option instance
|
|
42
|
+
*/
|
|
43
|
+
declare const zodOption: (key: string, zod: z.ZodTypeAny) => Option;
|
|
44
|
+
/**
|
|
45
|
+
* Defines a Commander.js Command using Zod schemas for arguments and options.
|
|
46
|
+
* Automatically wires up parsing, validation, and help configuration.
|
|
47
|
+
* @template A - ZodRawShape for arguments
|
|
48
|
+
* @template O - ZodRawShape for options
|
|
49
|
+
* @param props - Command properties (name, description, args, opts, action)
|
|
50
|
+
* @returns A Commander Command instance
|
|
51
|
+
*/
|
|
52
|
+
declare const zodCommand: <A extends z.ZodRawShape, O extends z.ZodRawShape>({ name, description, args, opts, action, }: ZodCommandProps<A, O>) => Command;
|
|
53
|
+
|
|
54
|
+
export { type ZodCommandAction, zodArgument, zodCommand, zodOption };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Argument,
|
|
2
|
-
import
|
|
1
|
+
import { Argument, Option, Command } from 'commander';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
3
4
|
type BeforeFirstUnderscore<S> = S extends `${infer T}_${infer _}` ? T : S;
|
|
4
5
|
type ReplaceKeyTypes<Type extends z.ZodRawShape> = {
|
|
5
6
|
[Key in keyof Type as BeforeFirstUnderscore<Key>]: Type[Key];
|
|
@@ -15,7 +16,7 @@ type Prettify<T> = {
|
|
|
15
16
|
* @param opts - Parsed and validated options (with key normalization)
|
|
16
17
|
* @returns A Promise or void
|
|
17
18
|
*/
|
|
18
|
-
|
|
19
|
+
type ZodCommandAction<A extends z.ZodRawShape, O extends z.ZodRawShape> = ZodCommandProps<A, O>['action'];
|
|
19
20
|
type ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {
|
|
20
21
|
name: string;
|
|
21
22
|
description?: string;
|
|
@@ -30,7 +31,7 @@ type ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {
|
|
|
30
31
|
* @param zod - The Zod schema for the argument
|
|
31
32
|
* @returns A Commander Argument instance
|
|
32
33
|
*/
|
|
33
|
-
|
|
34
|
+
declare const zodArgument: (key: string, zod: z.ZodTypeAny) => Argument;
|
|
34
35
|
/**
|
|
35
36
|
* Creates a Commander.js Option from a Zod schema.
|
|
36
37
|
* Handles optionality, default values, enum choices, and boolean flags.
|
|
@@ -39,7 +40,7 @@ export declare const zodArgument: (key: string, zod: z.ZodTypeAny) => Argument;
|
|
|
39
40
|
* @param zod - The Zod schema for the option
|
|
40
41
|
* @returns A Commander Option instance
|
|
41
42
|
*/
|
|
42
|
-
|
|
43
|
+
declare const zodOption: (key: string, zod: z.ZodTypeAny) => Option;
|
|
43
44
|
/**
|
|
44
45
|
* Defines a Commander.js Command using Zod schemas for arguments and options.
|
|
45
46
|
* Automatically wires up parsing, validation, and help configuration.
|
|
@@ -48,5 +49,6 @@ export declare const zodOption: (key: string, zod: z.ZodTypeAny) => Option;
|
|
|
48
49
|
* @param props - Command properties (name, description, args, opts, action)
|
|
49
50
|
* @returns A Commander Command instance
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
declare const zodCommand: <A extends z.ZodRawShape, O extends z.ZodRawShape>({ name, description, args, opts, action, }: ZodCommandProps<A, O>) => Command;
|
|
53
|
+
|
|
54
|
+
export { type ZodCommandAction, zodArgument, zodCommand, zodOption };
|
package/dist/index.js
CHANGED
|
@@ -1,94 +1,81 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Argument, Option, Command, InvalidOptionArgumentError, InvalidArgumentError } from 'commander';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
var zodCore = /* @__PURE__ */ __name((zod, fn) => {
|
|
7
|
+
const types = [z.ZodDefault, z.ZodNullable, z.ZodOptional];
|
|
8
|
+
for (const type of types)
|
|
9
|
+
if (zod instanceof type) return zodCore(zod._def.innerType, fn);
|
|
10
|
+
if (zod instanceof z.ZodEffects) return zodCore(zod._def.schema, fn);
|
|
11
|
+
return fn(zod);
|
|
12
|
+
}, "zodCore");
|
|
13
|
+
var zodEnumVals = /* @__PURE__ */ __name((zod) => zodCore(zod, (zod2) => zod2 instanceof z.ZodEnum ? zod2._def.values : null), "zodEnumVals");
|
|
14
|
+
var zodIsBoolean = /* @__PURE__ */ __name((zod) => zodCore(zod, (zod2) => zod2 instanceof z.ZodBoolean), "zodIsBoolean");
|
|
15
|
+
var zodDefault = /* @__PURE__ */ __name((zod) => zod instanceof z.ZodEffects ? zodDefault(zod._def.schema) : zod instanceof z.ZodDefault ? zod._def.defaultValue() : void 0, "zodDefault");
|
|
16
|
+
var utils = {
|
|
17
|
+
zodCore,
|
|
18
|
+
zodEnumVals,
|
|
19
|
+
zodIsBoolean,
|
|
20
|
+
zodDefault
|
|
4
21
|
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*/
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (choices)
|
|
66
|
-
opt.choices(choices);
|
|
67
|
-
// parsing must be done at the end to override default parsers
|
|
68
|
-
return opt.argParser(zodParser(zod, 'opt'));
|
|
69
|
-
};
|
|
70
|
-
exports.zodOption = zodOption;
|
|
71
|
-
/**
|
|
72
|
-
* Defines a Commander.js Command using Zod schemas for arguments and options.
|
|
73
|
-
* Automatically wires up parsing, validation, and help configuration.
|
|
74
|
-
* @template A - ZodRawShape for arguments
|
|
75
|
-
* @template O - ZodRawShape for options
|
|
76
|
-
* @param props - Command properties (name, description, args, opts, action)
|
|
77
|
-
* @returns A Commander Command instance
|
|
78
|
-
*/
|
|
79
|
-
const zodCommand = ({ name, description, args, opts, action, }) => {
|
|
80
|
-
const command = new commander_1.Command(name);
|
|
81
|
-
if (description)
|
|
82
|
-
command.description(description);
|
|
83
|
-
for (const key in args)
|
|
84
|
-
command.addArgument((0, exports.zodArgument)(key, args[key]));
|
|
85
|
-
for (const key in opts)
|
|
86
|
-
command.addOption((0, exports.zodOption)(key, opts[key]));
|
|
87
|
-
command.action(async (...all) => {
|
|
88
|
-
const resultArgs = Object.fromEntries(Object.keys(args ?? {}).map((key, i) => [key, all[i]]));
|
|
89
|
-
const resultOpts = all[Object.keys(args ?? {}).length];
|
|
90
|
-
await action(resultArgs, resultOpts);
|
|
91
|
-
});
|
|
92
|
-
return command;
|
|
93
|
-
};
|
|
94
|
-
exports.zodCommand = zodCommand;
|
|
22
|
+
var utils_default = utils;
|
|
23
|
+
|
|
24
|
+
// src/index.ts
|
|
25
|
+
var zodParser = /* @__PURE__ */ __name((zod, opt) => (value) => {
|
|
26
|
+
const result = zod.safeParse(value);
|
|
27
|
+
if (result.success) return result.data;
|
|
28
|
+
const msg = result.error.issues[0].message;
|
|
29
|
+
if (opt) throw new InvalidOptionArgumentError(msg);
|
|
30
|
+
throw new InvalidArgumentError(msg);
|
|
31
|
+
}, "zodParser");
|
|
32
|
+
var zodArgument = /* @__PURE__ */ __name((key, zod) => {
|
|
33
|
+
const flag = zod.isOptional() ? `[${key}]` : `<${key}>`;
|
|
34
|
+
const arg = new Argument(flag, zod.description);
|
|
35
|
+
const def = utils_default.zodDefault(zod);
|
|
36
|
+
if (def !== void 0) arg.default(zod.parse(def));
|
|
37
|
+
const choices = utils_default.zodEnumVals(zod);
|
|
38
|
+
if (choices) arg.choices(choices);
|
|
39
|
+
return arg.argParser(zodParser(zod));
|
|
40
|
+
}, "zodArgument");
|
|
41
|
+
var zodOption = /* @__PURE__ */ __name((key, zod) => {
|
|
42
|
+
const abbr = zod.description?.match(/^(\w);/)?.[1];
|
|
43
|
+
const description = abbr ? zod.description.slice(2) : zod.description;
|
|
44
|
+
const arg = key.includes("_") ? key.split("_").slice(1).join("-") : key;
|
|
45
|
+
if (key.includes("_")) [key] = key.split("_");
|
|
46
|
+
const isBoolean = utils_default.zodIsBoolean(zod);
|
|
47
|
+
const flag = `--${key}${isBoolean ? "" : ` <${arg}>`}`;
|
|
48
|
+
const flags = abbr ? `-${abbr}, ${flag}` : flag;
|
|
49
|
+
const opt = new Option(flags, description);
|
|
50
|
+
if (isBoolean) opt.optional = true;
|
|
51
|
+
else if (!zod.isOptional()) opt.makeOptionMandatory();
|
|
52
|
+
const def = utils_default.zodDefault(zod);
|
|
53
|
+
if (def !== void 0) opt.default(zod.parse(def));
|
|
54
|
+
const choices = utils_default.zodEnumVals(zod);
|
|
55
|
+
if (choices) opt.choices(choices);
|
|
56
|
+
return opt.argParser(zodParser(zod, "opt"));
|
|
57
|
+
}, "zodOption");
|
|
58
|
+
var zodCommand = /* @__PURE__ */ __name(({
|
|
59
|
+
name,
|
|
60
|
+
description,
|
|
61
|
+
args,
|
|
62
|
+
opts,
|
|
63
|
+
action
|
|
64
|
+
}) => {
|
|
65
|
+
const command = new Command(name);
|
|
66
|
+
if (description) command.description(description);
|
|
67
|
+
for (const key in args) command.addArgument(zodArgument(key, args[key]));
|
|
68
|
+
for (const key in opts) command.addOption(zodOption(key, opts[key]));
|
|
69
|
+
command.action(async (...all) => {
|
|
70
|
+
const resultArgs = Object.fromEntries(
|
|
71
|
+
Object.keys(args ?? {}).map((key, i) => [key, all[i]])
|
|
72
|
+
);
|
|
73
|
+
const resultOpts = all[Object.keys(args ?? {}).length];
|
|
74
|
+
await action(resultArgs, resultOpts);
|
|
75
|
+
});
|
|
76
|
+
return command;
|
|
77
|
+
}, "zodCommand");
|
|
78
|
+
|
|
79
|
+
export { zodArgument, zodCommand, zodOption };
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/index.ts"],"names":["zod"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod'\n\nconst zodCore = <T>(zod: z.ZodTypeAny, fn: (zod: z.ZodTypeAny) => T): T => {\n\tconst types = [z.ZodDefault, z.ZodNullable, z.ZodOptional]\n\tfor (const type of types)\n\t\tif (zod instanceof type) return zodCore(zod._def.innerType, fn)\n\tif (zod instanceof z.ZodEffects) return zodCore(zod._def.schema, fn)\n\treturn fn(zod)\n}\n\nconst zodEnumVals = (zod: z.ZodTypeAny): string[] | null =>\n\tzodCore(zod, (zod) => (zod instanceof z.ZodEnum ? zod._def.values : null))\n\nconst zodIsBoolean = (zod: z.ZodTypeAny): boolean =>\n\tzodCore(zod, (zod) => zod instanceof z.ZodBoolean)\n\nconst zodDefault = <Output, Def extends z.ZodTypeDef, Input>(\n\tzod: z.ZodType<Output, Def, Input>,\n): Input | undefined =>\n\tzod instanceof z.ZodEffects\n\t\t? zodDefault(zod._def.schema)\n\t\t: zod instanceof z.ZodDefault\n\t\t\t? zod._def.defaultValue()\n\t\t\t: undefined\n\nconst utils = {\n\tzodCore,\n\tzodEnumVals,\n\tzodIsBoolean,\n\tzodDefault,\n}\n\nexport default utils\n","import {\n\tArgument,\n\tCommand,\n\tInvalidArgumentError,\n\tInvalidOptionArgumentError,\n\tOption,\n} from 'commander'\nimport type { z } from 'zod'\nimport utils from './utils.js'\n\ntype BeforeFirstUnderscore<S> = S extends `${infer T}_${infer _}` ? T : S\n\ntype ReplaceKeyTypes<Type extends z.ZodRawShape> = {\n\t[Key in keyof Type as BeforeFirstUnderscore<Key>]: Type[Key]\n}\n\ntype Prettify<T> = {\n\t[K in keyof T]: T[K]\n} & {}\n\n/**\n * The action function signature for a Zod-powered command.\n * @template A - ZodRawShape for arguments\n * @template O - ZodRawShape for options\n * @param args - Parsed and validated arguments\n * @param opts - Parsed and validated options (with key normalization)\n * @returns A Promise or void\n */\nexport type ZodCommandAction<\n\tA extends z.ZodRawShape,\n\tO extends z.ZodRawShape,\n> = ZodCommandProps<A, O>['action']\n\ntype ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {\n\tname: string\n\tdescription?: string\n\targs?: A\n\topts?: O\n\taction: (\n\t\targs: Prettify<z.infer<z.ZodObject<A>>>,\n\t\topts: Prettify<z.infer<z.ZodObject<ReplaceKeyTypes<O>>>>,\n\t) => Promise<void> | void\n}\n\nconst zodParser = (zod: z.ZodTypeAny, opt?: 'opt') => (value: string) => {\n\tconst result = zod.safeParse(value)\n\tif (result.success) return result.data\n\tconst msg = result.error.issues[0].message\n\tif (opt) throw new InvalidOptionArgumentError(msg)\n\tthrow new InvalidArgumentError(msg)\n}\n\n/**\n * Creates a Commander.js Argument from a Zod schema.\n * Handles optionality, default values, and enum choices.\n * @param key - The argument name\n * @param zod - The Zod schema for the argument\n * @returns A Commander Argument instance\n */\nexport const zodArgument = (key: string, zod: z.ZodTypeAny): Argument => {\n\tconst flag = zod.isOptional() ? `[${key}]` : `<${key}>`\n\tconst arg = new Argument(flag, zod.description)\n\n\tconst def = utils.zodDefault(zod)\n\tif (def !== undefined) arg.default(zod.parse(def))\n\n\tconst choices = utils.zodEnumVals(zod)\n\tif (choices) arg.choices(choices)\n\n\t// parsing must be done at the end to override default parsers\n\treturn arg.argParser(zodParser(zod))\n}\n\n/**\n * Creates a Commander.js Option from a Zod schema.\n * Handles optionality, default values, enum choices, and boolean flags.\n * Supports short flags via description prefix (e.g., 's;...').\n * @param key - The option name (can include underscores for grouping)\n * @param zod - The Zod schema for the option\n * @returns A Commander Option instance\n */\nexport const zodOption = (key: string, zod: z.ZodTypeAny): Option => {\n\tconst abbr = zod.description?.match(/^(\\w);/)?.[1]\n\tconst description = abbr ? zod.description.slice(2) : zod.description\n\tconst arg = key.includes('_') ? key.split('_').slice(1).join('-') : key\n\tif (key.includes('_')) [key] = key.split('_')\n\tconst isBoolean = utils.zodIsBoolean(zod)\n\tconst flag = `--${key}${isBoolean ? '' : ` <${arg}>`}`\n\tconst flags = abbr ? `-${abbr}, ${flag}` : flag\n\tconst opt = new Option(flags, description)\n\n\t// required for boolean flags\n\tif (isBoolean) opt.optional = true\n\telse if (!zod.isOptional()) opt.makeOptionMandatory()\n\n\tconst def = utils.zodDefault(zod)\n\tif (def !== undefined) opt.default(zod.parse(def))\n\n\tconst choices = utils.zodEnumVals(zod)\n\tif (choices) opt.choices(choices)\n\n\t// parsing must be done at the end to override default parsers\n\treturn opt.argParser(zodParser(zod, 'opt'))\n}\n\n/**\n * Defines a Commander.js Command using Zod schemas for arguments and options.\n * Automatically wires up parsing, validation, and help configuration.\n * @template A - ZodRawShape for arguments\n * @template O - ZodRawShape for options\n * @param props - Command properties (name, description, args, opts, action)\n * @returns A Commander Command instance\n */\nexport const zodCommand = <A extends z.ZodRawShape, O extends z.ZodRawShape>({\n\tname,\n\tdescription,\n\targs,\n\topts,\n\taction,\n}: ZodCommandProps<A, O>): Command => {\n\tconst command = new Command(name)\n\tif (description) command.description(description)\n\tfor (const key in args) command.addArgument(zodArgument(key, args[key]))\n\tfor (const key in opts) command.addOption(zodOption(key, opts[key]))\n\tcommand.action(async (...all) => {\n\t\tconst resultArgs = Object.fromEntries(\n\t\t\tObject.keys(args ?? {}).map((key, i) => [key, all[i]]),\n\t\t) as z.infer<z.ZodObject<A>>\n\t\tconst resultOpts = all[Object.keys(args ?? {}).length] as z.infer<\n\t\t\tz.ZodObject<ReplaceKeyTypes<O>>\n\t\t>\n\t\tawait action(resultArgs, resultOpts)\n\t})\n\treturn command\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod-commander",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A TypeScript utility for building type-safe CLI commands using commander and zod.",
|
|
5
5
|
"author": "Román Via-Dufresne Saus <roman910dev@gmail.com>(https://github.com/roman910dev)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,22 +16,23 @@
|
|
|
16
16
|
],
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@biomejs/biome": "^2.0.6",
|
|
19
|
-
"@jest/globals": "^30.0.4",
|
|
20
19
|
"@types/node": "^22.16.3",
|
|
21
20
|
"commander": "^14.0.0",
|
|
22
21
|
"husky": "^9.1.7",
|
|
23
|
-
"
|
|
24
|
-
"ts-jest": "^29.4.0",
|
|
22
|
+
"tsup": "^8.5.0",
|
|
25
23
|
"typescript": "^5.8.3",
|
|
24
|
+
"vitest": "^3.2.4",
|
|
26
25
|
"zod": "^3.25.0"
|
|
27
26
|
},
|
|
28
|
-
"main": "dist/index.
|
|
29
|
-
"
|
|
27
|
+
"main": "./dist/index.cjs",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
30
|
"exports": {
|
|
31
31
|
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
32
33
|
"import": "./dist/index.js",
|
|
33
|
-
"require": "./dist/index.
|
|
34
|
-
"
|
|
34
|
+
"require": "./dist/index.cjs",
|
|
35
|
+
"default": "./dist/index.js"
|
|
35
36
|
}
|
|
36
37
|
},
|
|
37
38
|
"files": [
|
|
@@ -47,12 +48,16 @@
|
|
|
47
48
|
"commander": ">=8 <15",
|
|
48
49
|
"zod": ">=3.20.0 <4"
|
|
49
50
|
},
|
|
51
|
+
"type": "module",
|
|
50
52
|
"scripts": {
|
|
51
|
-
"build": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"format": "biome format --write
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"check": "biome check .",
|
|
55
|
+
"fix": "biome check . --write",
|
|
56
|
+
"format": "biome format . --write",
|
|
57
|
+
"full-check": "pnpm ts && pnpm check",
|
|
58
|
+
"lint": "biome lint .",
|
|
55
59
|
"ci": "biome ci --threads=4",
|
|
56
|
-
"test": "
|
|
60
|
+
"test": "vitest",
|
|
61
|
+
"ts": "tsc --noEmit"
|
|
57
62
|
}
|
|
58
63
|
}
|
package/dist/utils.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
declare const utils: {
|
|
3
|
-
zodCore: <T>(zod: z.ZodTypeAny, fn: (zod: z.ZodTypeAny) => T) => T;
|
|
4
|
-
zodEnumVals: (zod: z.ZodTypeAny) => string[] | null;
|
|
5
|
-
zodIsBoolean: (zod: z.ZodTypeAny) => boolean;
|
|
6
|
-
zodDefault: <Output, Def extends z.ZodTypeDef, Input>(zod: z.ZodType<Output, Def, Input>) => Input | undefined;
|
|
7
|
-
};
|
|
8
|
-
export default utils;
|
package/dist/utils.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const zod_1 = require("zod");
|
|
4
|
-
const zodCore = (zod, fn) => {
|
|
5
|
-
const types = [zod_1.z.ZodDefault, zod_1.z.ZodNullable, zod_1.z.ZodOptional];
|
|
6
|
-
for (const type of types)
|
|
7
|
-
if (zod instanceof type)
|
|
8
|
-
return zodCore(zod._def.innerType, fn);
|
|
9
|
-
if (zod instanceof zod_1.z.ZodEffects)
|
|
10
|
-
return zodCore(zod._def.schema, fn);
|
|
11
|
-
return fn(zod);
|
|
12
|
-
};
|
|
13
|
-
const zodEnumVals = (zod) => zodCore(zod, (zod) => (zod instanceof zod_1.z.ZodEnum ? zod._def.values : null));
|
|
14
|
-
const zodIsBoolean = (zod) => zodCore(zod, (zod) => zod instanceof zod_1.z.ZodBoolean);
|
|
15
|
-
const zodDefault = (zod) => zod instanceof zod_1.z.ZodEffects
|
|
16
|
-
? zodDefault(zod._def.schema)
|
|
17
|
-
: zod instanceof zod_1.z.ZodDefault
|
|
18
|
-
? zod._def.defaultValue()
|
|
19
|
-
: undefined;
|
|
20
|
-
const utils = {
|
|
21
|
-
zodCore,
|
|
22
|
-
zodEnumVals,
|
|
23
|
-
zodIsBoolean,
|
|
24
|
-
zodDefault,
|
|
25
|
-
};
|
|
26
|
-
exports.default = utils;
|