zod-args-parser 1.0.16 → 1.2.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 +598 -92
- package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js +1 -1
- package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js.map +1 -1
- package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js +1 -1
- package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -1
- package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js +1 -1
- package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -1
- package/lib/commonjs/help-message/format-arguments.js +1 -0
- package/lib/commonjs/help-message/format-arguments.js.map +1 -0
- package/lib/commonjs/help-message/format-cli.js +1 -0
- package/lib/commonjs/help-message/format-cli.js.map +1 -0
- package/lib/commonjs/help-message/format-options.js +1 -0
- package/lib/commonjs/help-message/format-options.js.map +1 -0
- package/lib/commonjs/help-message/format-subcommands.js +1 -0
- package/lib/commonjs/help-message/format-subcommands.js.map +1 -0
- package/lib/commonjs/help-message/styles.js +1 -0
- package/lib/commonjs/help-message/styles.js.map +1 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/markdown/generate-markdown.js.map +1 -1
- package/lib/commonjs/metadata/get-arguments-metadata.js +1 -1
- package/lib/commonjs/metadata/get-arguments-metadata.js.map +1 -1
- package/lib/commonjs/metadata/get-cli-metadata.js +1 -1
- package/lib/commonjs/metadata/get-cli-metadata.js.map +1 -1
- package/lib/commonjs/metadata/get-options-metadata.js +1 -1
- package/lib/commonjs/metadata/get-options-metadata.js.map +1 -1
- package/lib/commonjs/metadata/get-subcommands-metadata.js.map +1 -1
- package/lib/commonjs/parser/parse/parse.js +1 -0
- package/lib/commonjs/parser/parse/parse.js.map +1 -0
- package/lib/commonjs/parser/parse/parser-helpers.js +1 -0
- package/lib/commonjs/parser/parse/parser-helpers.js.map +1 -0
- package/lib/commonjs/parser/safe-parse.js +1 -1
- package/lib/commonjs/parser/safe-parse.js.map +1 -1
- package/lib/commonjs/parser/unsafe-parse.js +1 -0
- package/lib/commonjs/parser/unsafe-parse.js.map +1 -0
- package/lib/commonjs/parser/validate/validate-type.js +1 -0
- package/lib/commonjs/parser/validate/validate-type.js.map +1 -0
- package/lib/commonjs/parser/validate/validate.js +1 -0
- package/lib/commonjs/parser/validate/validate.js.map +1 -0
- package/lib/commonjs/utils.js +1 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/zod-utils.js +1 -0
- package/lib/commonjs/zod-utils.js.map +1 -0
- package/lib/module/autocomplete-scripts/bash-autocomplete-script.js +1 -1
- package/lib/module/autocomplete-scripts/bash-autocomplete-script.js.map +1 -1
- package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js +1 -1
- package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -1
- package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js +1 -1
- package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -1
- package/lib/module/help-message/format-arguments.js +1 -0
- package/lib/module/help-message/format-arguments.js.map +1 -0
- package/lib/module/help-message/format-cli.js +1 -0
- package/lib/module/help-message/format-cli.js.map +1 -0
- package/lib/module/help-message/format-options.js +1 -0
- package/lib/module/help-message/format-options.js.map +1 -0
- package/lib/module/help-message/{print-subcommands.js → format-subcommands.js} +1 -1
- package/lib/module/help-message/format-subcommands.js.map +1 -0
- package/lib/module/help-message/styles.js +1 -0
- package/lib/module/help-message/styles.js.map +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/markdown/generate-markdown.js.map +1 -1
- package/lib/module/metadata/get-arguments-metadata.js +1 -1
- package/lib/module/metadata/get-arguments-metadata.js.map +1 -1
- package/lib/module/metadata/get-cli-metadata.js +1 -1
- package/lib/module/metadata/get-cli-metadata.js.map +1 -1
- package/lib/module/metadata/get-options-metadata.js +1 -1
- package/lib/module/metadata/get-options-metadata.js.map +1 -1
- package/lib/module/metadata/get-subcommands-metadata.js.map +1 -1
- package/lib/module/parser/parse/parse.js +1 -0
- package/lib/module/parser/parse/parse.js.map +1 -0
- package/lib/module/parser/parse/parser-helpers.js +1 -0
- package/lib/module/parser/parse/parser-helpers.js.map +1 -0
- package/lib/module/parser/safe-parse.js +1 -1
- package/lib/module/parser/safe-parse.js.map +1 -1
- package/lib/module/parser/unsafe-parse.js +1 -0
- package/lib/module/parser/unsafe-parse.js.map +1 -0
- package/lib/module/parser/validate/validate-type.js +1 -0
- package/lib/module/parser/validate/validate-type.js.map +1 -0
- package/lib/module/parser/validate/validate.js +1 -0
- package/lib/module/parser/validate/validate.js.map +1 -0
- package/lib/module/utils.js +1 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/module/zod-utils.js +1 -0
- package/lib/module/zod-utils.js.map +1 -0
- package/lib/typescript/help-message/format-arguments.d.ts +4 -0
- package/lib/typescript/help-message/format-arguments.d.ts.map +1 -0
- package/lib/typescript/help-message/format-cli.d.ts +6 -0
- package/lib/typescript/help-message/format-cli.d.ts.map +1 -0
- package/lib/typescript/help-message/format-options.d.ts +4 -0
- package/lib/typescript/help-message/format-options.d.ts.map +1 -0
- package/lib/typescript/help-message/format-subcommands.d.ts +4 -0
- package/lib/typescript/help-message/format-subcommands.d.ts.map +1 -0
- package/lib/typescript/help-message/styles.d.ts +108 -0
- package/lib/typescript/help-message/styles.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +18 -29
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/markdown/generate-markdown.d.ts.map +1 -1
- package/lib/typescript/metadata/get-arguments-metadata.d.ts +2 -1
- package/lib/typescript/metadata/get-arguments-metadata.d.ts.map +1 -1
- package/lib/typescript/metadata/get-cli-metadata.d.ts +3 -2
- package/lib/typescript/metadata/get-cli-metadata.d.ts.map +1 -1
- package/lib/typescript/metadata/get-options-metadata.d.ts +2 -1
- package/lib/typescript/metadata/get-options-metadata.d.ts.map +1 -1
- package/lib/typescript/metadata/get-subcommands-metadata.d.ts +2 -1
- package/lib/typescript/metadata/get-subcommands-metadata.d.ts.map +1 -1
- package/lib/typescript/metadata/metadata-types.d.ts +80 -0
- package/lib/typescript/metadata/metadata-types.d.ts.map +1 -0
- package/lib/typescript/parser/parse/parse-types.d.ts +85 -0
- package/lib/typescript/parser/parse/parse-types.d.ts.map +1 -0
- package/lib/typescript/parser/parse/parse.d.ts +4 -0
- package/lib/typescript/parser/parse/parse.d.ts.map +1 -0
- package/lib/typescript/parser/parse/parser-helpers.d.ts +40 -0
- package/lib/typescript/parser/parse/parser-helpers.d.ts.map +1 -0
- package/lib/typescript/parser/safe-parse.d.ts +1 -0
- package/lib/typescript/parser/safe-parse.d.ts.map +1 -1
- package/lib/typescript/parser/unsafe-parse.d.ts +4 -0
- package/lib/typescript/parser/unsafe-parse.d.ts.map +1 -0
- package/lib/typescript/parser/validate/validate-type.d.ts +22 -0
- package/lib/typescript/parser/validate/validate-type.d.ts.map +1 -0
- package/lib/typescript/parser/validate/validate.d.ts +11 -0
- package/lib/typescript/parser/validate/validate.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +76 -186
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils.d.ts +20 -23
- package/lib/typescript/utils.d.ts.map +1 -1
- package/lib/typescript/zod-utils.d.ts +27 -0
- package/lib/typescript/zod-utils.d.ts.map +1 -0
- package/package.json +20 -19
- package/src/autocomplete-scripts/bash-autocomplete-script.ts +1 -1
- package/src/autocomplete-scripts/powershell-autocomplete-script.ts +1 -1
- package/src/autocomplete-scripts/zsh-autocomplete-script.ts +1 -1
- package/src/help-message/format-arguments.ts +38 -0
- package/src/help-message/{print-help-message.ts → format-cli.ts} +43 -48
- package/src/help-message/{print-options.ts → format-options.ts} +16 -14
- package/src/help-message/format-subcommands.ts +37 -0
- package/src/help-message/styles.ts +120 -0
- package/src/index.ts +50 -44
- package/src/markdown/generate-markdown.ts +2 -1
- package/src/metadata/get-arguments-metadata.ts +6 -5
- package/src/metadata/get-cli-metadata.ts +4 -4
- package/src/metadata/get-options-metadata.ts +7 -5
- package/src/metadata/get-subcommands-metadata.ts +2 -1
- package/src/metadata/metadata-types.ts +114 -0
- package/src/parser/parse/parse-types.ts +89 -0
- package/src/parser/parse/parse.ts +227 -0
- package/src/parser/parse/parser-helpers.ts +167 -0
- package/src/parser/safe-parse.ts +60 -8
- package/src/parser/unsafe-parse.ts +98 -0
- package/src/parser/validate/validate-type.ts +21 -0
- package/src/parser/validate/validate.ts +66 -0
- package/src/types.ts +99 -233
- package/src/utils.ts +31 -96
- package/src/zod-utils.ts +199 -0
- package/lib/commonjs/help-message/colors.js +0 -1
- package/lib/commonjs/help-message/colors.js.map +0 -1
- package/lib/commonjs/help-message/print-arguments.js +0 -1
- package/lib/commonjs/help-message/print-arguments.js.map +0 -1
- package/lib/commonjs/help-message/print-help-message.js +0 -1
- package/lib/commonjs/help-message/print-help-message.js.map +0 -1
- package/lib/commonjs/help-message/print-options.js +0 -1
- package/lib/commonjs/help-message/print-options.js.map +0 -1
- package/lib/commonjs/help-message/print-subcommands.js +0 -1
- package/lib/commonjs/help-message/print-subcommands.js.map +0 -1
- package/lib/commonjs/help-message/utils.js +0 -1
- package/lib/commonjs/help-message/utils.js.map +0 -1
- package/lib/commonjs/parser/parse.js +0 -1
- package/lib/commonjs/parser/parse.js.map +0 -1
- package/lib/module/help-message/colors.js +0 -1
- package/lib/module/help-message/colors.js.map +0 -1
- package/lib/module/help-message/print-arguments.js +0 -1
- package/lib/module/help-message/print-arguments.js.map +0 -1
- package/lib/module/help-message/print-help-message.js +0 -1
- package/lib/module/help-message/print-help-message.js.map +0 -1
- package/lib/module/help-message/print-options.js +0 -1
- package/lib/module/help-message/print-options.js.map +0 -1
- package/lib/module/help-message/print-subcommands.js.map +0 -1
- package/lib/module/help-message/utils.js +0 -1
- package/lib/module/help-message/utils.js.map +0 -1
- package/lib/module/parser/parse.js +0 -1
- package/lib/module/parser/parse.js.map +0 -1
- package/lib/typescript/help-message/colors.d.ts +0 -17
- package/lib/typescript/help-message/colors.d.ts.map +0 -1
- package/lib/typescript/help-message/print-arguments.d.ts +0 -4
- package/lib/typescript/help-message/print-arguments.d.ts.map +0 -1
- package/lib/typescript/help-message/print-help-message.d.ts +0 -4
- package/lib/typescript/help-message/print-help-message.d.ts.map +0 -1
- package/lib/typescript/help-message/print-options.d.ts +0 -4
- package/lib/typescript/help-message/print-options.d.ts.map +0 -1
- package/lib/typescript/help-message/print-subcommands.d.ts +0 -4
- package/lib/typescript/help-message/print-subcommands.d.ts.map +0 -1
- package/lib/typescript/help-message/utils.d.ts +0 -13
- package/lib/typescript/help-message/utils.d.ts.map +0 -1
- package/lib/typescript/parser/parse.d.ts +0 -3
- package/lib/typescript/parser/parse.d.ts.map +0 -1
- package/src/help-message/colors.ts +0 -24
- package/src/help-message/print-arguments.ts +0 -35
- package/src/help-message/print-subcommands.ts +0 -28
- package/src/help-message/utils.ts +0 -31
- package/src/parser/parse.ts +0 -270
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as help from "../help-message/format-cli.js";
|
|
2
|
+
import { findSubcommand } from "./parse/parser-helpers.js";
|
|
3
|
+
import { validate } from "./validate/validate.js";
|
|
4
|
+
import { parse } from "./parse/parse.js";
|
|
5
|
+
|
|
6
|
+
import type { Cli, NoSubcommand, HelpMsgStyle, Subcommand, UnsafeParseResult } from "../types.js";
|
|
7
|
+
|
|
8
|
+
export function unsafeParse<T extends Subcommand[], U extends Cli>(
|
|
9
|
+
argv: string[],
|
|
10
|
+
...params: [U, ...T]
|
|
11
|
+
): UnsafeParseResult<[...T, NoSubcommand & U]> {
|
|
12
|
+
const cliOptions = ("cliName" in params[0] ? params[0] : {}) as U;
|
|
13
|
+
const subcommandArr = params as unknown as T;
|
|
14
|
+
|
|
15
|
+
// Parse
|
|
16
|
+
const parsedData = parse(argv, ...params);
|
|
17
|
+
|
|
18
|
+
const subcommandObj = findSubcommand(parsedData.subcommand, subcommandArr);
|
|
19
|
+
if (!subcommandObj) {
|
|
20
|
+
throw new Error(`Subcommand "${parsedData.subcommand}" does not exist`, { cause: "zod-args-parser" });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Fire preValidation hook
|
|
24
|
+
if (subcommandObj.preValidation) {
|
|
25
|
+
subcommandObj.preValidation(parsedData);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Validate
|
|
29
|
+
const validateResult = validate(parsedData);
|
|
30
|
+
|
|
31
|
+
Object.assign(validateResult, {
|
|
32
|
+
printCliHelp(style?: Partial<HelpMsgStyle>) {
|
|
33
|
+
help.printCliHelp(params, style);
|
|
34
|
+
},
|
|
35
|
+
printSubcommandHelp(subCmdName: string, style?: Partial<HelpMsgStyle>) {
|
|
36
|
+
const subcommandObj = findSubcommand(subCmdName, subcommandArr);
|
|
37
|
+
if (!subcommandObj) {
|
|
38
|
+
console.error(`Cannot print help for subcommand "${subCmdName}" as it does not exist`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
help.printSubcommandHelp(subcommandObj, style, cliOptions.cliName);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Fire action
|
|
47
|
+
if (subcommandObj.action) {
|
|
48
|
+
subcommandObj.action(validateResult);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return validateResult as UnsafeParseResult<[...T, NoSubcommand & U]>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function unsafeParseAsync<T extends Subcommand[], U extends Cli>(
|
|
55
|
+
argv: string[],
|
|
56
|
+
...params: [U, ...T]
|
|
57
|
+
): Promise<UnsafeParseResult<[...T, NoSubcommand & U]>> {
|
|
58
|
+
const cliOptions = ("cliName" in params[0] ? params[0] : {}) as U;
|
|
59
|
+
const subcommandArr = params as unknown as T;
|
|
60
|
+
|
|
61
|
+
// Parse
|
|
62
|
+
const parsedData = parse(argv, ...params);
|
|
63
|
+
|
|
64
|
+
const subcommandObj = findSubcommand(parsedData.subcommand, subcommandArr);
|
|
65
|
+
if (!subcommandObj) {
|
|
66
|
+
throw new Error(`Subcommand "${parsedData.subcommand}" does not exist`, { cause: "zod-args-parser" });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fire preValidation hook
|
|
70
|
+
if (subcommandObj.preValidation) {
|
|
71
|
+
await subcommandObj.preValidation(parsedData);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Validate
|
|
75
|
+
const validateResult = validate(parsedData);
|
|
76
|
+
|
|
77
|
+
Object.assign(validateResult, {
|
|
78
|
+
printCliHelp(style?: Partial<HelpMsgStyle>) {
|
|
79
|
+
help.printCliHelp(params, style);
|
|
80
|
+
},
|
|
81
|
+
printSubcommandHelp(subCmdName: string, style?: Partial<HelpMsgStyle>) {
|
|
82
|
+
const subcommandObj = findSubcommand(subCmdName, subcommandArr);
|
|
83
|
+
if (!subcommandObj) {
|
|
84
|
+
console.error(`Cannot print help for subcommand "${subCmdName}" as it does not exist`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
help.printSubcommandHelp(subcommandObj, style, cliOptions.cliName);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Fire action
|
|
93
|
+
if (subcommandObj.action) {
|
|
94
|
+
await subcommandObj.action(validateResult);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return validateResult as UnsafeParseResult<[...T, NoSubcommand & U]>;
|
|
98
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Argument, Option, Prettify, Schema, Subcommand, ToOptional, ZodInfer } from "../../types.js";
|
|
2
|
+
import type { ParseResult } from "../parse/parse-types.js";
|
|
3
|
+
|
|
4
|
+
type OptionsArr2RecordType<T extends Option[] | undefined> = T extends Option[]
|
|
5
|
+
? ToOptional<{ [K in T[number]["name"]]: ZodInfer<Extract<T[number], { name: K }>["type"]> }>
|
|
6
|
+
: object;
|
|
7
|
+
|
|
8
|
+
type ArgumentsArr2ArrType<T extends Argument[] | undefined> = T extends Argument[]
|
|
9
|
+
? { [K in keyof T]: T[K] extends { type: Schema } ? ZodInfer<T[K]["type"]> : never }
|
|
10
|
+
: never;
|
|
11
|
+
|
|
12
|
+
export type ValidateResult<S extends Partial<Subcommand>[]> = {
|
|
13
|
+
[K in keyof S]: Prettify<
|
|
14
|
+
{
|
|
15
|
+
subcommand: S[K]["name"] extends string ? S[K]["name"] : undefined;
|
|
16
|
+
arguments: ArgumentsArr2ArrType<S[K]["arguments"]>;
|
|
17
|
+
positional: S[K]["allowPositional"] extends true ? string[] : never;
|
|
18
|
+
ctx: ParseResult<S>;
|
|
19
|
+
} & OptionsArr2RecordType<S[K]["options"]>
|
|
20
|
+
>;
|
|
21
|
+
}[number];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { prettifyError } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
import { generateOrdinalSuffix, stringToBoolean } from "../../utils.js";
|
|
4
|
+
import { isBooleanSchema, safeParseSchema } from "../../zod-utils.js";
|
|
5
|
+
|
|
6
|
+
import type { ParseCtx } from "../parse/parse-types.js";
|
|
7
|
+
|
|
8
|
+
/** The return result object temporarily type. used inside the `parse` function */
|
|
9
|
+
type ResultsTempType = Record<string, unknown> & {
|
|
10
|
+
subcommand: string | undefined;
|
|
11
|
+
positional?: string[];
|
|
12
|
+
arguments?: unknown[];
|
|
13
|
+
ctx: ParseCtx;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function validate(parsedData: ParseCtx) {
|
|
17
|
+
const results: ResultsTempType = {
|
|
18
|
+
subcommand: parsedData.subcommand,
|
|
19
|
+
positional: parsedData.positional,
|
|
20
|
+
ctx: parsedData,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// validate options
|
|
24
|
+
for (const [optionName, { schema, rawValue, flag }] of Object.entries(parsedData.options)) {
|
|
25
|
+
let optionsValue: string | boolean | undefined = rawValue;
|
|
26
|
+
|
|
27
|
+
// infer boolean value if possible
|
|
28
|
+
if (flag && rawValue && isBooleanSchema(schema)) {
|
|
29
|
+
const booleanValue = stringToBoolean(rawValue);
|
|
30
|
+
if (typeof booleanValue === "boolean") {
|
|
31
|
+
const isNegated = flag.startsWith("--no");
|
|
32
|
+
optionsValue = isNegated ? !booleanValue : booleanValue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const res = safeParseSchema(schema, optionsValue);
|
|
37
|
+
if (!res.success) {
|
|
38
|
+
throw new Error(`Invalid value "${rawValue}" for "${flag}": ${prettifyError(res.error)}`, {
|
|
39
|
+
cause: "zod-args-parser",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
results[optionName] = res.data;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// validate arguments
|
|
47
|
+
if (parsedData.arguments) {
|
|
48
|
+
if (!results.arguments) results.arguments = [];
|
|
49
|
+
|
|
50
|
+
for (const { schema, rawValue } of parsedData.arguments) {
|
|
51
|
+
const argValue = rawValue && isBooleanSchema(schema) ? stringToBoolean(rawValue) : rawValue;
|
|
52
|
+
|
|
53
|
+
const res = safeParseSchema(schema, argValue);
|
|
54
|
+
if (!res.success) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`The ${generateOrdinalSuffix(results.arguments.length)} argument "${rawValue}" is invalid: ${prettifyError(res.error)}`,
|
|
57
|
+
{ cause: "zod-args-parser" },
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
results.arguments.push(res.data);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return results;
|
|
66
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,124 +1,17 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as Z3 from "zod/v3";
|
|
2
|
+
import type * as Z4 from "zod/v4/core";
|
|
3
|
+
import type { ParseResult } from "./parser/parse/parse-types.js";
|
|
4
|
+
import type { ValidateResult } from "./parser/validate/validate-type.js";
|
|
2
5
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
export type SchemaV3 = Z3.ZodTypeAny;
|
|
7
|
+
export type SchemaV4 = Z4.$ZodType;
|
|
8
|
+
export type Schema = SchemaV3 | SchemaV4;
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
readonly description: string;
|
|
9
|
-
|
|
10
|
-
/** - The placeholder of the option. Empty string if not provided */
|
|
11
|
-
readonly placeholder: string;
|
|
12
|
-
|
|
13
|
-
/** - The usage of the cli program. Empty string if not provided */
|
|
14
|
-
readonly usage: string;
|
|
15
|
-
|
|
16
|
-
/** - The example of the cli program. Empty string if not provided */
|
|
17
|
-
readonly example: string;
|
|
18
|
-
|
|
19
|
-
/** - Whether the cli program allows positional arguments. */
|
|
20
|
-
readonly allowPositional: boolean;
|
|
21
|
-
|
|
22
|
-
/** - The options of the cli program. Empty array if not provided */
|
|
23
|
-
readonly options: OptionMetadata[];
|
|
24
|
-
|
|
25
|
-
/** - The arguments of the cli program. Empty array if not provided */
|
|
26
|
-
readonly arguments: ArgumentMetadata[];
|
|
27
|
-
|
|
28
|
-
/** - The subcommands of the cli program. Empty array if not provided */
|
|
29
|
-
readonly subcommands: SubcommandMetadata[];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface SubcommandMetadata {
|
|
33
|
-
/** The subcommand name. */
|
|
34
|
-
readonly name: string;
|
|
35
|
-
|
|
36
|
-
/** - The aliases of the subcommand. Empty array if not provided */
|
|
37
|
-
readonly aliases: string[];
|
|
38
|
-
|
|
39
|
-
/** - The description of the subcommand. Empty string if not provided */
|
|
40
|
-
readonly description: string;
|
|
41
|
-
|
|
42
|
-
/** - The placeholder of the subcommand. Empty string if not provided */
|
|
43
|
-
readonly placeholder: string;
|
|
44
|
-
|
|
45
|
-
/** - The usage of the subcommand. Empty string if not provided */
|
|
46
|
-
readonly usage: string;
|
|
47
|
-
|
|
48
|
-
/** - The example of the subcommand. Empty string if not provided */
|
|
49
|
-
readonly example: string;
|
|
50
|
-
|
|
51
|
-
/** - Whether the subcommand allows positional arguments. */
|
|
52
|
-
readonly allowPositional: boolean;
|
|
53
|
-
|
|
54
|
-
/** - The options of the subcommand. Empty array if not provided */
|
|
55
|
-
readonly options: OptionMetadata[];
|
|
56
|
-
|
|
57
|
-
/** - The arguments of the subcommand. Empty array if not provided */
|
|
58
|
-
readonly arguments: ArgumentMetadata[];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface OptionMetadata {
|
|
62
|
-
/** The option name in camelCase. E.g. `optionName` */
|
|
63
|
-
readonly name: string;
|
|
64
|
-
|
|
65
|
-
/** The option name in kebab-case. E.g. `--option-name` */
|
|
66
|
-
readonly nameAsArg: string;
|
|
67
|
-
|
|
68
|
-
/** - The aliases of the option in camelCase. Empty array if not provided. E.g. `[aliasName, ...]` */
|
|
69
|
-
readonly aliases: string[];
|
|
70
|
-
|
|
71
|
-
/** - The aliases of the option in kebab-case. Empty array if not provided. E.g. `[--alias-name, ...]` */
|
|
72
|
-
readonly aliasesAsArgs: string[];
|
|
73
|
-
|
|
74
|
-
/** - The description of the option. Empty string if not provided */
|
|
75
|
-
readonly description: string;
|
|
76
|
-
|
|
77
|
-
/** - The placeholder of the option. Empty string if not provided */
|
|
78
|
-
readonly placeholder: string;
|
|
79
|
-
|
|
80
|
-
/** - The example of the option. Empty string if not provided */
|
|
81
|
-
readonly example: string;
|
|
82
|
-
|
|
83
|
-
/** - The default value of the option. */
|
|
84
|
-
readonly defaultValue: unknown;
|
|
85
|
-
|
|
86
|
-
/** - The default value of the option as string. */
|
|
87
|
-
readonly defaultValueAsString: string;
|
|
88
|
-
|
|
89
|
-
/** - Whether the option is optional. */
|
|
90
|
-
readonly optional: boolean;
|
|
91
|
-
|
|
92
|
-
/** - The zod type of the option. */
|
|
93
|
-
readonly type: z.ZodTypeAny;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface ArgumentMetadata {
|
|
97
|
-
/** The argument name. */
|
|
98
|
-
readonly name: string;
|
|
99
|
-
|
|
100
|
-
/** - The description of the argument. Empty string if not provided */
|
|
101
|
-
readonly description: string;
|
|
102
|
-
|
|
103
|
-
/** - The example of the argument. Empty string if not provided */
|
|
104
|
-
readonly example: string;
|
|
105
|
-
|
|
106
|
-
/** - The default value of the argument. */
|
|
107
|
-
readonly defaultValue: unknown;
|
|
108
|
-
|
|
109
|
-
/** - The default value of the argument as string. */
|
|
110
|
-
readonly defaultValueAsString: string;
|
|
111
|
-
|
|
112
|
-
/** - Whether the argument is optional. */
|
|
113
|
-
readonly optional: boolean;
|
|
114
|
-
|
|
115
|
-
/** - The zod type of the argument. */
|
|
116
|
-
readonly type: z.ZodTypeAny;
|
|
117
|
-
}
|
|
10
|
+
export type ZodInfer<T extends Schema> = T extends SchemaV4 ? Z4.infer<T> : T extends SchemaV3 ? Z3.infer<T> : never;
|
|
118
11
|
|
|
119
12
|
export type Subcommand = {
|
|
120
13
|
/**
|
|
121
|
-
* - The subcommand name
|
|
14
|
+
* - The subcommand name
|
|
122
15
|
* - Make sure to not duplicate commands and aliases.
|
|
123
16
|
*
|
|
124
17
|
* @example
|
|
@@ -182,11 +75,21 @@ export type Subcommand = {
|
|
|
182
75
|
* const helpCommand = createSubcommand({ name: "help", options: [...] });
|
|
183
76
|
* helpCommand.setAction(res => console.log(res));
|
|
184
77
|
*/
|
|
185
|
-
action?: (results?: any) =>
|
|
78
|
+
action?: (results?: any) => any;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* - The preValidation hook is executed before the action.
|
|
82
|
+
* - To get typescript types use `setPreValidationHook` instead of this.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* const helpCommand = createSubcommand({ name: "help", options: [...] });
|
|
86
|
+
* helpCommand.setPreValidationHook(ctx => console.log(ctx));
|
|
87
|
+
*/
|
|
88
|
+
preValidation?: (ctx?: any) => any;
|
|
186
89
|
};
|
|
187
90
|
|
|
188
91
|
export type Cli = Prettify<
|
|
189
|
-
Omit<Subcommand, "name"> & {
|
|
92
|
+
Omit<Subcommand, "name" | "aliases" | "placeholder"> & {
|
|
190
93
|
/** - The name of the CLI program. */
|
|
191
94
|
cliName: string;
|
|
192
95
|
}
|
|
@@ -194,22 +97,22 @@ export type Cli = Prettify<
|
|
|
194
97
|
|
|
195
98
|
export type Option = {
|
|
196
99
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
100
|
+
* The name of the option, use a valid **JavaScript** variable name.\
|
|
101
|
+
* **Supports:** `camelCase`, `PascalCase`, `snake_case`, and `SCREAMING_SNAKE_CASE`.\
|
|
102
|
+
* **Examples:**
|
|
103
|
+
*
|
|
104
|
+
* - `I` or `i` ➡️ `-i`
|
|
105
|
+
* - `InputDir`, `inputDir`, or `INPUT_DIR` ➡️ `--input-dir`
|
|
106
|
+
* - `Help`, `help`, or `HELP` ➡️ `--help`
|
|
199
107
|
*/
|
|
200
108
|
name: string;
|
|
201
109
|
|
|
202
110
|
/**
|
|
203
111
|
* - The will be used to validate the user input.
|
|
204
112
|
*
|
|
205
|
-
* @
|
|
206
|
-
* type: z.boolean().default(false);
|
|
207
|
-
* type: z.coerce.number(); // will be coerced to number by Zod
|
|
208
|
-
* type: z.preprocess(parseStringToArrFn, z.array(z.coerce.number())); // array of numbers
|
|
209
|
-
*
|
|
210
|
-
* @see https://zod.dev/?id=types
|
|
113
|
+
* @see https://zod.dev/api
|
|
211
114
|
*/
|
|
212
|
-
type:
|
|
115
|
+
type: Schema;
|
|
213
116
|
|
|
214
117
|
/**
|
|
215
118
|
* - The description of the option.
|
|
@@ -241,14 +144,9 @@ export type Argument = {
|
|
|
241
144
|
/**
|
|
242
145
|
* - The will be used to validate the user input.
|
|
243
146
|
*
|
|
244
|
-
* @
|
|
245
|
-
* type: z.boolean();
|
|
246
|
-
* type: z.coerce.number(); // will be coerced to number by Zod
|
|
247
|
-
* type: z.preprocess(ParseStringToArrFn, z.array(z.coerce.number())); // array of numbers
|
|
248
|
-
*
|
|
249
|
-
* @see https://zod.dev/?id=types
|
|
147
|
+
* @see https://zod.dev/api
|
|
250
148
|
*/
|
|
251
|
-
type:
|
|
149
|
+
type: Schema;
|
|
252
150
|
|
|
253
151
|
/**
|
|
254
152
|
* - The description of the argument.
|
|
@@ -265,52 +163,21 @@ export type Argument = {
|
|
|
265
163
|
|
|
266
164
|
export type ColorFnType = (...text: unknown[]) => string;
|
|
267
165
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
default?: ColorFnType;
|
|
284
|
-
optional?: ColorFnType;
|
|
285
|
-
exampleTitle?: ColorFnType;
|
|
286
|
-
example?: ColorFnType;
|
|
287
|
-
command?: ColorFnType;
|
|
288
|
-
option?: ColorFnType;
|
|
289
|
-
argument?: ColorFnType;
|
|
290
|
-
placeholder?: ColorFnType;
|
|
291
|
-
punctuation?: ColorFnType;
|
|
292
|
-
};
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
export type _Info = {
|
|
296
|
-
/**
|
|
297
|
-
* - The raw argument as it was passed in
|
|
298
|
-
* - For options that have a default value and are not passed in, the raw argument will be `undefined`
|
|
299
|
-
*/
|
|
300
|
-
rawArg?: string;
|
|
301
|
-
/**
|
|
302
|
-
* - The raw value of the argument as it was passed in
|
|
303
|
-
* - It will be empty string for `boolean` options. E.g. `--help` or `-h`
|
|
304
|
-
* - For options that have a default value and are not passed in, the raw value will be `undefined`
|
|
305
|
-
*/
|
|
306
|
-
rawValue?: string;
|
|
307
|
-
/**
|
|
308
|
-
* - The source value of the argument:
|
|
309
|
-
* - `cli`: The argument was passed in by the user
|
|
310
|
-
* - `default`: The argument was not passed in and has a default value
|
|
311
|
-
*/
|
|
312
|
-
source: "cli" | "default";
|
|
313
|
-
};
|
|
166
|
+
/** - The colors to use for the help message. */
|
|
167
|
+
export type HelpMsgStyle = Record<
|
|
168
|
+
| "title"
|
|
169
|
+
| "description"
|
|
170
|
+
| "default"
|
|
171
|
+
| "optional"
|
|
172
|
+
| "exampleTitle"
|
|
173
|
+
| "example"
|
|
174
|
+
| "command"
|
|
175
|
+
| "option"
|
|
176
|
+
| "argument"
|
|
177
|
+
| "placeholder"
|
|
178
|
+
| "punctuation",
|
|
179
|
+
ColorFnType
|
|
180
|
+
>;
|
|
314
181
|
|
|
315
182
|
/**
|
|
316
183
|
* - Infer the options type from a subcommand.
|
|
@@ -320,7 +187,7 @@ export type _Info = {
|
|
|
320
187
|
* type OptionsType = InferOptionsType<typeof subcommand>;
|
|
321
188
|
*/
|
|
322
189
|
export type InferOptionsType<T extends Partial<Subcommand>> = T["options"] extends infer U extends Option[]
|
|
323
|
-
? ToOptional<{ [K in U[number]["name"]]:
|
|
190
|
+
? ToOptional<{ [K in U[number]["name"]]: ZodInfer<Extract<U[number], { name: K }>["type"]> }>
|
|
324
191
|
: undefined;
|
|
325
192
|
|
|
326
193
|
/**
|
|
@@ -331,7 +198,7 @@ export type InferOptionsType<T extends Partial<Subcommand>> = T["options"] exten
|
|
|
331
198
|
* type ArgumentsType = InferArgumentsType<typeof subcommand>;
|
|
332
199
|
*/
|
|
333
200
|
export type InferArgumentsType<T extends Partial<Subcommand>> = T["arguments"] extends infer U extends Argument[]
|
|
334
|
-
? { [K in keyof U]: U[K] extends { type:
|
|
201
|
+
? { [K in keyof U]: U[K] extends { type: Schema } ? ZodInfer<U[K]["type"]> : never }
|
|
335
202
|
: undefined;
|
|
336
203
|
|
|
337
204
|
/** `{ some props } & { other props }` => `{ some props, other props }` */
|
|
@@ -341,68 +208,36 @@ export type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
|
341
208
|
export type LiteralUnion<T extends string> = T | (string & {});
|
|
342
209
|
|
|
343
210
|
/** Extract the undefined properties from an object */
|
|
344
|
-
type UndefinedProperties<T> = { [P in keyof T]-?: undefined extends T[P] ? P : never }[keyof T];
|
|
211
|
+
export type UndefinedProperties<T> = { [P in keyof T]-?: undefined extends T[P] ? P : never }[keyof T];
|
|
345
212
|
|
|
346
213
|
/** Make undefined properties optional? */
|
|
347
|
-
type ToOptional<T> = Prettify<
|
|
214
|
+
export type ToOptional<T> = Prettify<
|
|
348
215
|
Partial<Pick<T, UndefinedProperties<T>>> & Pick<T, Exclude<keyof T, UndefinedProperties<T>>>
|
|
349
216
|
>;
|
|
350
217
|
|
|
351
|
-
export type OptionsArr2RecordType<T extends Option[] | undefined> = T extends Option[]
|
|
352
|
-
? ToOptional<{ [K in T[number]["name"]]: z.infer<Extract<T[number], { name: K }>["type"]> }>
|
|
353
|
-
: object;
|
|
354
|
-
|
|
355
|
-
export type ArgumentsArr2ArrType<T extends Argument[] | undefined> = T extends Argument[]
|
|
356
|
-
? { arguments: { [K in keyof T]: T[K] extends { type: z.ZodTypeAny } ? z.infer<T[K]["type"]> : never } }
|
|
357
|
-
: object;
|
|
358
|
-
|
|
359
|
-
export type Positional<S extends Partial<Subcommand>> = S["allowPositional"] extends true
|
|
360
|
-
? { positional: string[] }
|
|
361
|
-
: object;
|
|
362
|
-
|
|
363
|
-
export type Info<T extends Option[] | undefined> = T extends Option[]
|
|
364
|
-
? {
|
|
365
|
-
_info: ToOptional<{
|
|
366
|
-
[K in T[number]["name"]]: Extract<T[number], { name: K }> extends infer U extends Option
|
|
367
|
-
? undefined extends z.infer<U["type"]>
|
|
368
|
-
? undefined | Prettify<_Info & U> // if optional add undefined
|
|
369
|
-
: Prettify<_Info & U>
|
|
370
|
-
: never;
|
|
371
|
-
}>;
|
|
372
|
-
}
|
|
373
|
-
: object;
|
|
374
|
-
|
|
375
218
|
export type NoSubcommand = { name: undefined };
|
|
376
219
|
|
|
377
|
-
export type ParseResult<S extends Partial<Subcommand>[]> = {
|
|
378
|
-
[K in keyof S]: Prettify<
|
|
379
|
-
{ subcommand: S[K]["name"] } & Positional<S[K]> &
|
|
380
|
-
Info<S[K]["options"]> &
|
|
381
|
-
OptionsArr2RecordType<S[K]["options"]> &
|
|
382
|
-
ArgumentsArr2ArrType<S[K]["arguments"]>
|
|
383
|
-
>;
|
|
384
|
-
}[number];
|
|
385
|
-
|
|
386
220
|
export type PrintMethods<N extends Subcommand["name"]> = {
|
|
387
|
-
printCliHelp: (
|
|
388
|
-
printSubcommandHelp: (subcommand: LiteralUnion<NonNullable<N>>,
|
|
221
|
+
printCliHelp: (style?: Partial<HelpMsgStyle>) => void;
|
|
222
|
+
printSubcommandHelp: (subcommand: LiteralUnion<NonNullable<N>>, style?: Partial<HelpMsgStyle>) => void;
|
|
389
223
|
};
|
|
390
224
|
|
|
391
|
-
export type
|
|
225
|
+
export type UnsafeParseResult<S extends Partial<Subcommand>[]> =
|
|
392
226
|
CheckDuplicatedSubcommands<S> extends infer E extends string
|
|
393
227
|
? E
|
|
394
|
-
: Prettify<
|
|
228
|
+
: Prettify<ValidateResult<S> & PrintMethods<NonNullable<S[number]["name"]>>>;
|
|
395
229
|
|
|
396
230
|
export type SafeParseResult<S extends Partial<Subcommand>[]> =
|
|
397
231
|
CheckDuplicatedSubcommands<S> extends infer E extends string
|
|
398
232
|
? E
|
|
399
233
|
: Prettify<
|
|
400
|
-
({ success: false; error: Error } | { success: true; data:
|
|
234
|
+
({ success: false; error: Error } | { success: true; data: ValidateResult<S> }) &
|
|
401
235
|
PrintMethods<NonNullable<S[number]["name"]>>
|
|
402
236
|
>;
|
|
403
237
|
|
|
404
|
-
export type
|
|
405
|
-
setAction: (actions: (res:
|
|
238
|
+
export type ActionsFn<T extends Subcommand | Cli> = {
|
|
239
|
+
setAction: (actions: (res: UnsafeParseResult<[T]>) => void) => void;
|
|
240
|
+
setPreValidationHook: (hookFn: (ctx: ParseResult<[T]>) => void) => void;
|
|
406
241
|
};
|
|
407
242
|
|
|
408
243
|
/** - Combine `name` and `aliases` to a `string[]` */
|
|
@@ -430,20 +265,51 @@ type IsDuplicatesInArr<Input extends any[]> = Input extends [infer Item, ...infe
|
|
|
430
265
|
/**
|
|
431
266
|
* - Check if there are duplicated options including aliases in `subcommand`
|
|
432
267
|
* - Return an error message if duplicated is found
|
|
433
|
-
* - Return `
|
|
268
|
+
* - Return `undefined` if not found
|
|
434
269
|
*/
|
|
435
270
|
export type CheckDuplicatedOptions<T extends { options?: Option[] }> = T["options"] extends infer O extends Option[]
|
|
436
|
-
? IsDuplicatesInArr<MapNameAndAliases2StrArr<O>> extends infer
|
|
437
|
-
? `>>> Error: Duplicated Options \`${
|
|
438
|
-
:
|
|
439
|
-
:
|
|
271
|
+
? IsDuplicatesInArr<MapNameAndAliases2StrArr<O>> extends infer Name extends string
|
|
272
|
+
? `>>> Error: Duplicated Options. Check the options with the name \`${Name}\` <<<`
|
|
273
|
+
: undefined
|
|
274
|
+
: undefined;
|
|
440
275
|
|
|
441
276
|
/**
|
|
442
277
|
* - Check for duplicated subcommands including aliases
|
|
443
278
|
* - Return an error message if duplicated is found
|
|
444
|
-
* - Return the `
|
|
279
|
+
* - Return the `undefined` if no error
|
|
280
|
+
*/
|
|
281
|
+
type CheckDuplicatedSubcommands<T extends Partial<Subcommand>[]> =
|
|
282
|
+
IsDuplicatesInArr<MapNameAndAliases2StrArr<T>> extends infer Name extends string
|
|
283
|
+
? `>>> Error: Duplicated Subcommand. Check the subcommands with the name \`${Name}\` <<<`
|
|
284
|
+
: undefined;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* - Check for duplicated arguments
|
|
288
|
+
* - Return an error message if duplicated is found
|
|
289
|
+
* - Return the `undefined` if no error
|
|
290
|
+
*/
|
|
291
|
+
export type CheckDuplicatedArguments<T extends { arguments?: Argument[] }> = T["arguments"] extends infer A extends
|
|
292
|
+
Argument[]
|
|
293
|
+
? IsDuplicatesInArr<MapNameAndAliases2StrArr<A>> extends infer Name extends string
|
|
294
|
+
? `>>> Error: Duplicated Arguments. Check the arguments with the name \`${Name}\` <<<`
|
|
295
|
+
: undefined
|
|
296
|
+
: undefined;
|
|
297
|
+
|
|
298
|
+
type OptionalUnion = Z3.ZodOptional<Z3.ZodAny> | Z4.$ZodOptional | Z3.ZodDefault<Z3.ZodAny> | Z4.$ZodDefault;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* - Insures that only the last argument is optional
|
|
302
|
+
* - Insures no optional arguments are allowed when `allowPositional` is enabled
|
|
445
303
|
*/
|
|
446
|
-
export type
|
|
447
|
-
|
|
448
|
-
?
|
|
304
|
+
export type CheckArgumentsOptional<T extends { allowPositional?: boolean; arguments?: readonly Argument[] }> =
|
|
305
|
+
T["arguments"] extends readonly [...infer Rest, infer Last]
|
|
306
|
+
? Last extends { type: OptionalUnion }
|
|
307
|
+
? T["allowPositional"] extends true
|
|
308
|
+
? `>>> Error: Cannot have optional arguments when \`allowPositional\` is enabled. The argument \`${Last extends { name: string } ? Last["name"] : ""}\` should not be optional <<<`
|
|
309
|
+
: T
|
|
310
|
+
: Extract<Rest[number], { type: OptionalUnion }> extends never
|
|
311
|
+
? T
|
|
312
|
+
: T["allowPositional"] extends true
|
|
313
|
+
? `>>> Error: Cannot have optional arguments when \`allowPositional\` is enabled. The argument \`${Rest[number] extends { name: string } ? Rest[number]["name"] : ""}\` should not be optional <<<`
|
|
314
|
+
: `>>> Error: Only the last argument may be optional. The argument \`${Rest[number] extends { name: string } ? Rest[number]["name"] : ""}\` should not be optional <<<`
|
|
449
315
|
: T;
|