zod-commander 0.0.2 → 0.0.3

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.d.ts CHANGED
@@ -4,15 +4,49 @@ type BeforeFirstUnderscore<S> = S extends `${infer T}_${infer _}` ? T : S;
4
4
  type ReplaceKeyTypes<Type extends z.ZodRawShape> = {
5
5
  [Key in keyof Type as BeforeFirstUnderscore<Key>]: Type[Key];
6
6
  };
7
- export type ZodCommandAction<A extends z.ZodRawShape, O extends z.ZodRawShape> = (args: z.infer<z.ZodObject<A>>, opts: z.infer<z.ZodObject<ReplaceKeyTypes<O>>>) => Promise<void> | void;
7
+ type Prettify<T> = {
8
+ [K in keyof T]: T[K];
9
+ } & {};
10
+ /**
11
+ * The action function signature for a Zod-powered command.
12
+ * @template A - ZodRawShape for arguments
13
+ * @template O - ZodRawShape for options
14
+ * @param args - Parsed and validated arguments
15
+ * @param opts - Parsed and validated options (with key normalization)
16
+ * @returns A Promise or void
17
+ */
18
+ export type ZodCommandAction<A extends z.ZodRawShape, O extends z.ZodRawShape> = ZodCommandProps<A, O>['action'];
8
19
  type ZodCommandProps<A extends z.ZodRawShape, O extends z.ZodRawShape> = {
9
20
  name: string;
10
21
  description?: string;
11
22
  args?: A;
12
23
  opts?: O;
13
- action: ZodCommandAction<A, O>;
24
+ action: (args: Prettify<z.infer<z.ZodObject<A>>>, opts: Prettify<z.infer<z.ZodObject<ReplaceKeyTypes<O>>>>) => Promise<void> | void;
14
25
  };
26
+ /**
27
+ * Creates a Commander.js Argument from a Zod schema.
28
+ * Handles optionality, default values, and enum choices.
29
+ * @param key - The argument name
30
+ * @param zod - The Zod schema for the argument
31
+ * @returns A Commander Argument instance
32
+ */
15
33
  export declare const zodArgument: (key: string, zod: z.ZodTypeAny) => Argument;
34
+ /**
35
+ * Creates a Commander.js Option from a Zod schema.
36
+ * Handles optionality, default values, enum choices, and boolean flags.
37
+ * Supports short flags via description prefix (e.g., 's;...').
38
+ * @param key - The option name (can include underscores for grouping)
39
+ * @param zod - The Zod schema for the option
40
+ * @returns A Commander Option instance
41
+ */
16
42
  export declare const zodOption: (key: string, zod: z.ZodTypeAny) => Option;
43
+ /**
44
+ * Defines a Commander.js Command using Zod schemas for arguments and options.
45
+ * Automatically wires up parsing, validation, and help configuration.
46
+ * @template A - ZodRawShape for arguments
47
+ * @template O - ZodRawShape for options
48
+ * @param props - Command properties (name, description, args, opts, action)
49
+ * @returns A Commander Command instance
50
+ */
17
51
  export declare const zodCommand: <A extends z.ZodRawShape, O extends z.ZodRawShape>({ name, description, args, opts, action, }: ZodCommandProps<A, O>) => Command;
18
52
  export {};
package/dist/index.js CHANGED
@@ -5,8 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.zodCommand = exports.zodOption = exports.zodArgument = void 0;
7
7
  const commander_1 = require("commander");
8
- const kebabCase_1 = __importDefault(require("lodash/kebabCase"));
9
- const utis_1 = __importDefault(require("./utis"));
8
+ const utils_1 = __importDefault(require("./utils"));
10
9
  const zodParser = (zod, opt) => (value) => {
11
10
  const result = zod.safeParse(value);
12
11
  if (result.success)
@@ -16,38 +15,67 @@ const zodParser = (zod, opt) => (value) => {
16
15
  throw new commander_1.InvalidOptionArgumentError(msg);
17
16
  throw new commander_1.InvalidArgumentError(msg);
18
17
  };
18
+ /**
19
+ * Creates a Commander.js Argument from a Zod schema.
20
+ * Handles optionality, default values, and enum choices.
21
+ * @param key - The argument name
22
+ * @param zod - The Zod schema for the argument
23
+ * @returns A Commander Argument instance
24
+ */
19
25
  const zodArgument = (key, zod) => {
20
26
  const flag = zod.isOptional() ? `[${key}]` : `<${key}>`;
21
- const arg = new commander_1.Argument(flag, zod.description).argParser(zodParser(zod));
22
- if (utis_1.default.zodDefault(zod))
23
- arg.default(zod.parse(utis_1.default.zodDefault(zod)));
24
- const choices = utis_1.default.zodEnumVals(zod);
27
+ const arg = new commander_1.Argument(flag, zod.description);
28
+ const def = utils_1.default.zodDefault(zod);
29
+ if (def !== undefined)
30
+ arg.default(zod.parse(def));
31
+ const choices = utils_1.default.zodEnumVals(zod);
25
32
  if (choices)
26
33
  arg.choices(choices);
27
- return arg;
34
+ // parsing must be done at the end to override default parsers
35
+ return arg.argParser(zodParser(zod));
28
36
  };
29
37
  exports.zodArgument = zodArgument;
38
+ /**
39
+ * Creates a Commander.js Option from a Zod schema.
40
+ * Handles optionality, default values, enum choices, and boolean flags.
41
+ * Supports short flags via description prefix (e.g., 's;...').
42
+ * @param key - The option name (can include underscores for grouping)
43
+ * @param zod - The Zod schema for the option
44
+ * @returns A Commander Option instance
45
+ */
30
46
  const zodOption = (key, zod) => {
31
47
  const abbr = zod.description?.match(/^(\w);/)?.[1];
32
48
  const description = abbr ? zod.description.slice(2) : zod.description;
33
49
  const arg = key.includes('_') ? key.split('_').slice(1).join('-') : key;
34
50
  if (key.includes('_'))
35
51
  [key] = key.split('_');
36
- key = (0, kebabCase_1.default)(key);
37
- const isBoolean = utis_1.default.zodIsBoolean(zod);
38
- const flag = `--${key}${isBoolean ? '' : zod.isOptional() ? ` [${arg}]` : ` <${arg}>`}`;
52
+ const isBoolean = utils_1.default.zodIsBoolean(zod);
53
+ const flag = `--${key}${isBoolean ? '' : ` <${arg}>`}`;
39
54
  const flags = abbr ? `-${abbr}, ${flag}` : flag;
40
- const opt = new commander_1.Option(flags, description).argParser(zodParser(zod, 'opt'));
41
- if (utis_1.default.zodDefault(zod))
42
- opt.default(zod.parse(utis_1.default.zodDefault(zod)));
55
+ const opt = new commander_1.Option(flags, description);
56
+ // required for boolean flags
43
57
  if (isBoolean)
44
58
  opt.optional = true;
45
- const choices = utis_1.default.zodEnumVals(zod);
59
+ else if (!zod.isOptional())
60
+ opt.makeOptionMandatory();
61
+ const def = utils_1.default.zodDefault(zod);
62
+ if (def !== undefined)
63
+ opt.default(zod.parse(def));
64
+ const choices = utils_1.default.zodEnumVals(zod);
46
65
  if (choices)
47
66
  opt.choices(choices);
48
- return opt;
67
+ // parsing must be done at the end to override default parsers
68
+ return opt.argParser(zodParser(zod, 'opt'));
49
69
  };
50
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
+ */
51
79
  const zodCommand = ({ name, description, args, opts, action, }) => {
52
80
  const command = new commander_1.Command(name);
53
81
  if (description)
@@ -61,7 +89,6 @@ const zodCommand = ({ name, description, args, opts, action, }) => {
61
89
  const resultOpts = all[Object.keys(args ?? {}).length];
62
90
  await action(resultArgs, resultOpts);
63
91
  });
64
- command.configureHelp({ showGlobalOptions: true });
65
92
  return command;
66
93
  };
67
94
  exports.zodCommand = zodCommand;
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  declare const utils: {
3
3
  zodCore: <T>(zod: z.ZodTypeAny, fn: (zod: z.ZodTypeAny) => T) => T;
4
- zodEnumVals: (zod: z.ZodTypeAny) => any;
4
+ zodEnumVals: (zod: z.ZodTypeAny) => string[] | null;
5
5
  zodIsBoolean: (zod: z.ZodTypeAny) => boolean;
6
6
  zodDefault: <Output, Def extends z.ZodTypeDef, Input>(zod: z.ZodType<Output, Def, Input>) => Input | undefined;
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-commander",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
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,16 +16,15 @@
16
16
  ],
17
17
  "devDependencies": {
18
18
  "@biomejs/biome": "^2.0.6",
19
- "@types/lodash": "^4.17.20",
19
+ "@jest/globals": "^30.0.4",
20
+ "@types/node": "^22.16.3",
20
21
  "commander": "^14.0.0",
21
22
  "husky": "^9.1.7",
22
- "lint-staged": "^16.1.2",
23
+ "jest": "^30.0.4",
24
+ "ts-jest": "^29.4.0",
23
25
  "typescript": "^5.8.3",
24
26
  "zod": "^3.25.0"
25
27
  },
26
- "dependencies": {
27
- "lodash": "^4.17.21"
28
- },
29
28
  "main": "dist/index.js",
30
29
  "types": "dist/index.d.ts",
31
30
  "exports": {
@@ -38,10 +37,8 @@
38
37
  "files": [
39
38
  "dist/"
40
39
  ],
41
- "lint-staged": {
42
- "*.ts": [
43
- "tsc --noEmit && biome ci --threads=4"
44
- ]
40
+ "imports": {
41
+ "#/*": "./src/*"
45
42
  },
46
43
  "publishConfig": {
47
44
  "access": "public"
@@ -51,10 +48,11 @@
51
48
  "zod": ">=3.20.0 <4"
52
49
  },
53
50
  "scripts": {
54
- "build": "tsc",
51
+ "build": "tsc --project tsconfig.build.json",
55
52
  "lint": "biome check .",
56
53
  "lint:fix": "biome check --fix --formatter-enabled=false .",
57
54
  "format": "biome format --write .",
58
- "ci": "biome ci --threads=4"
55
+ "ci": "biome ci --threads=4",
56
+ "test": "jest"
59
57
  }
60
58
  }
File without changes