zod-args-parser 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +12 -1
  2. package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js +42 -0
  3. package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js.map +1 -0
  4. package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js +31 -0
  5. package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -0
  6. package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js +41 -0
  7. package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -0
  8. package/lib/commonjs/help-message/colors.js +1 -0
  9. package/lib/commonjs/help-message/colors.js.map +1 -0
  10. package/lib/commonjs/help-message/print-arguments.js +1 -0
  11. package/lib/commonjs/help-message/print-arguments.js.map +1 -0
  12. package/lib/commonjs/help-message/print-help-message.js +1 -0
  13. package/lib/commonjs/help-message/print-help-message.js.map +1 -0
  14. package/lib/commonjs/help-message/print-options.js +1 -0
  15. package/lib/commonjs/help-message/print-options.js.map +1 -0
  16. package/lib/commonjs/help-message/print-subcommands.js +1 -0
  17. package/lib/commonjs/help-message/print-subcommands.js.map +1 -0
  18. package/lib/commonjs/help-message/utils.js +1 -0
  19. package/lib/commonjs/help-message/utils.js.map +1 -0
  20. package/lib/commonjs/index.js +1 -1
  21. package/lib/commonjs/index.js.map +1 -1
  22. package/lib/commonjs/markdown/generate-markdown.js +1 -0
  23. package/lib/commonjs/markdown/generate-markdown.js.map +1 -0
  24. package/lib/commonjs/metadata/get-arguments-metadata.js +1 -0
  25. package/lib/commonjs/metadata/get-arguments-metadata.js.map +1 -0
  26. package/lib/commonjs/metadata/get-cli-metadata.js +1 -0
  27. package/lib/commonjs/metadata/get-cli-metadata.js.map +1 -0
  28. package/lib/commonjs/metadata/get-options-metadata.js +1 -0
  29. package/lib/commonjs/metadata/get-options-metadata.js.map +1 -0
  30. package/lib/commonjs/metadata/get-subcommands-metadata.js +1 -0
  31. package/lib/commonjs/metadata/get-subcommands-metadata.js.map +1 -0
  32. package/lib/commonjs/parser/parse.js +1 -0
  33. package/lib/commonjs/parser/parse.js.map +1 -0
  34. package/lib/commonjs/parser/safe-parse.js +1 -0
  35. package/lib/commonjs/parser/safe-parse.js.map +1 -0
  36. package/lib/commonjs/utils.js +1 -1
  37. package/lib/commonjs/utils.js.map +1 -1
  38. package/lib/module/autocomplete-scripts/bash-autocomplete-script.js +42 -0
  39. package/lib/module/autocomplete-scripts/bash-autocomplete-script.js.map +1 -0
  40. package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js +31 -0
  41. package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -0
  42. package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js +41 -0
  43. package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -0
  44. package/lib/module/help-message/colors.js +1 -0
  45. package/lib/module/help-message/colors.js.map +1 -0
  46. package/lib/module/help-message/print-arguments.js +1 -0
  47. package/lib/module/help-message/print-arguments.js.map +1 -0
  48. package/lib/module/help-message/print-help-message.js +1 -0
  49. package/lib/module/help-message/print-help-message.js.map +1 -0
  50. package/lib/module/help-message/print-options.js +1 -0
  51. package/lib/module/help-message/print-options.js.map +1 -0
  52. package/lib/module/help-message/print-subcommands.js +1 -0
  53. package/lib/module/help-message/print-subcommands.js.map +1 -0
  54. package/lib/module/help-message/utils.js +1 -0
  55. package/lib/module/help-message/utils.js.map +1 -0
  56. package/lib/module/index.js +1 -1
  57. package/lib/module/index.js.map +1 -1
  58. package/lib/module/markdown/generate-markdown.js +1 -0
  59. package/lib/module/markdown/generate-markdown.js.map +1 -0
  60. package/lib/module/metadata/get-arguments-metadata.js +1 -0
  61. package/lib/module/metadata/get-arguments-metadata.js.map +1 -0
  62. package/lib/module/metadata/get-cli-metadata.js +1 -0
  63. package/lib/module/metadata/get-cli-metadata.js.map +1 -0
  64. package/lib/module/metadata/get-options-metadata.js +1 -0
  65. package/lib/module/metadata/get-options-metadata.js.map +1 -0
  66. package/lib/module/metadata/get-subcommands-metadata.js +1 -0
  67. package/lib/module/metadata/get-subcommands-metadata.js.map +1 -0
  68. package/lib/module/parser/parse.js +1 -0
  69. package/lib/module/parser/parse.js.map +1 -0
  70. package/lib/module/parser/safe-parse.js +1 -0
  71. package/lib/module/parser/safe-parse.js.map +1 -0
  72. package/lib/module/utils.js +1 -1
  73. package/lib/module/utils.js.map +1 -1
  74. package/lib/typescript/autocomplete-scripts/bash-autocomplete-script.d.ts +11 -0
  75. package/lib/typescript/autocomplete-scripts/bash-autocomplete-script.d.ts.map +1 -0
  76. package/lib/typescript/autocomplete-scripts/powershell-autocomplete-script.d.ts +14 -0
  77. package/lib/typescript/autocomplete-scripts/powershell-autocomplete-script.d.ts.map +1 -0
  78. package/lib/typescript/autocomplete-scripts/zsh-autocomplete-script.d.ts +11 -0
  79. package/lib/typescript/autocomplete-scripts/zsh-autocomplete-script.d.ts.map +1 -0
  80. package/lib/typescript/help-message/colors.d.ts +17 -0
  81. package/lib/typescript/help-message/colors.d.ts.map +1 -0
  82. package/lib/typescript/help-message/print-arguments.d.ts +4 -0
  83. package/lib/typescript/help-message/print-arguments.d.ts.map +1 -0
  84. package/lib/typescript/help-message/print-help-message.d.ts +4 -0
  85. package/lib/typescript/help-message/print-help-message.d.ts.map +1 -0
  86. package/lib/typescript/help-message/print-options.d.ts +4 -0
  87. package/lib/typescript/help-message/print-options.d.ts.map +1 -0
  88. package/lib/typescript/help-message/print-subcommands.d.ts +4 -0
  89. package/lib/typescript/help-message/print-subcommands.d.ts.map +1 -0
  90. package/lib/typescript/help-message/utils.d.ts +13 -0
  91. package/lib/typescript/help-message/utils.d.ts.map +1 -0
  92. package/lib/typescript/index.d.ts +11 -4
  93. package/lib/typescript/index.d.ts.map +1 -1
  94. package/lib/typescript/markdown/generate-markdown.d.ts +3 -0
  95. package/lib/typescript/markdown/generate-markdown.d.ts.map +1 -0
  96. package/lib/typescript/metadata/get-arguments-metadata.d.ts +3 -0
  97. package/lib/typescript/metadata/get-arguments-metadata.d.ts.map +1 -0
  98. package/lib/typescript/metadata/get-cli-metadata.d.ts +3 -0
  99. package/lib/typescript/metadata/get-cli-metadata.d.ts.map +1 -0
  100. package/lib/typescript/metadata/get-options-metadata.d.ts +3 -0
  101. package/lib/typescript/metadata/get-options-metadata.d.ts.map +1 -0
  102. package/lib/typescript/metadata/get-subcommands-metadata.d.ts +3 -0
  103. package/lib/typescript/metadata/get-subcommands-metadata.d.ts.map +1 -0
  104. package/lib/typescript/parser/parse.d.ts +3 -0
  105. package/lib/typescript/parser/parse.d.ts.map +1 -0
  106. package/lib/typescript/parser/safe-parse.d.ts +3 -0
  107. package/lib/typescript/parser/safe-parse.d.ts.map +1 -0
  108. package/lib/typescript/types.d.ts +80 -0
  109. package/lib/typescript/types.d.ts.map +1 -1
  110. package/lib/typescript/utils.d.ts +0 -12
  111. package/lib/typescript/utils.d.ts.map +1 -1
  112. package/package.json +22 -22
  113. package/src/autocomplete-scripts/bash-autocomplete-script.ts +81 -0
  114. package/src/autocomplete-scripts/powershell-autocomplete-script.ts +78 -0
  115. package/src/autocomplete-scripts/zsh-autocomplete-script.ts +69 -0
  116. package/src/help-message/colors.ts +24 -0
  117. package/src/help-message/print-arguments.ts +35 -0
  118. package/src/help-message/print-help-message.ts +126 -0
  119. package/src/help-message/print-options.ts +40 -0
  120. package/src/help-message/print-subcommands.ts +28 -0
  121. package/src/help-message/utils.ts +31 -0
  122. package/src/index.ts +13 -10
  123. package/src/markdown/generate-markdown.ts +172 -0
  124. package/src/metadata/get-arguments-metadata.ts +23 -0
  125. package/src/metadata/get-cli-metadata.ts +23 -0
  126. package/src/metadata/get-options-metadata.ts +30 -0
  127. package/src/metadata/get-subcommands-metadata.ts +29 -0
  128. package/src/{parser.ts → parser/parse.ts} +4 -54
  129. package/src/parser/safe-parse.ts +45 -0
  130. package/src/types.ts +116 -0
  131. package/src/utils.ts +0 -32
  132. package/lib/commonjs/autocomplete.js +0 -107
  133. package/lib/commonjs/autocomplete.js.map +0 -1
  134. package/lib/commonjs/help.js +0 -1
  135. package/lib/commonjs/help.js.map +0 -1
  136. package/lib/commonjs/parser.js +0 -1
  137. package/lib/commonjs/parser.js.map +0 -1
  138. package/lib/module/autocomplete.js +0 -107
  139. package/lib/module/autocomplete.js.map +0 -1
  140. package/lib/module/help.js +0 -1
  141. package/lib/module/help.js.map +0 -1
  142. package/lib/module/parser.js +0 -1
  143. package/lib/module/parser.js.map +0 -1
  144. package/lib/typescript/autocomplete.d.ts +0 -32
  145. package/lib/typescript/autocomplete.d.ts.map +0 -1
  146. package/lib/typescript/help.d.ts +0 -9
  147. package/lib/typescript/help.d.ts.map +0 -1
  148. package/lib/typescript/parser.d.ts +0 -4
  149. package/lib/typescript/parser.d.ts.map +0 -1
  150. package/src/autocomplete.ts +0 -217
  151. package/src/help.ts +0 -341
@@ -0,0 +1,78 @@
1
+ import { transformOptionToArg } from "../utils.js";
2
+
3
+ import type { Cli, Subcommand } from "../types.js";
4
+
5
+ /**
6
+ * - Generates a PowerShell autocomplete script for your CLI.
7
+ * - The script assumes that your CLI is available as a `.ps1` file in the environment variable. For example:
8
+ * `cliName.ps1`.
9
+ * - This should return a path to your script: `(Get-Command <cliName>.ps1).Source`
10
+ * - The generated script should be added to your `profile.ps1` file:
11
+ *
12
+ * - Run: `notepad $profile`
13
+ * - Add the following line: `. "<generated script path>"`
14
+ * - Save and reopen powershell to take effect
15
+ */
16
+ export function generatePowerShellAutocompleteScript(...params: [Cli, ...Subcommand[]]): string {
17
+ const [cli, ...subcommands] = params;
18
+
19
+ type MappedCommands = Record<string, { options: string[]; aliases: string[] }>;
20
+
21
+ const mappedCommands = subcommands.reduce((acc: MappedCommands, subcommand) => {
22
+ acc[subcommand.name] = {
23
+ options: subcommand.options?.map(option => transformOptionToArg(option.name)) ?? [],
24
+ aliases: subcommand.aliases ?? [],
25
+ };
26
+ return acc;
27
+ }, {});
28
+
29
+ const subcommandsStr = Object.keys(mappedCommands)
30
+ .map(key => `'${key}'`)
31
+ .join(", ");
32
+ const cliOptionsStr = cli.options?.map(option => `'${transformOptionToArg(option.name)}'`).join(", ") || "";
33
+
34
+ let switchCase = "switch ($subcommand) {\n";
35
+ for (const [key, { options, aliases }] of Object.entries(mappedCommands)) {
36
+ const optionsStr = options.map(option => `'${option}'`).join(", ");
37
+ switchCase += ` '${key}' { @(${optionsStr}) }\n`;
38
+ aliases.forEach(a => (switchCase += ` '${a}' { @(${optionsStr}) }\n`));
39
+ }
40
+ switchCase += ` default { @(${cliOptionsStr}) }\n }`;
41
+
42
+ let functionInfo = "";
43
+ if (cli.description) {
44
+ functionInfo = `<#\n.DESCRIPTION\n${cli.description}\n${cli.example ? `\n.EXAMPLE\n${cli.example}` : ""}\n#>`;
45
+ }
46
+
47
+ return `# Auto-generated by zod-args-parser
48
+
49
+ ${functionInfo}
50
+ function ${cli.cliName} {
51
+ param(
52
+ [Parameter(Position = 0, Mandatory = $false)]
53
+ [string]$subcommand,
54
+ [Parameter(Position = 1, ValueFromRemainingArguments = $true)]
55
+ [string[]]$arguments
56
+ )
57
+ $scriptPath = (Get-Command '${cli.cliName}.ps1').Source
58
+ if ($scriptPath) {
59
+ $argumentList = @($subcommand) + ($arguments | Where-Object { $_ -notin '--', '--%' }) | Where-Object { $_ -ne '' }
60
+ & $scriptPath @argumentList
61
+ return
62
+ }
63
+ Write-Error "Could not find '${cli.cliName}.ps1' script"
64
+ }
65
+
66
+ Register-ArgumentCompleter -CommandName '${cli.cliName}' -ParameterName 'subcommand' -ScriptBlock {
67
+ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
68
+ $subcommands = @(${subcommandsStr}${subcommandsStr && cliOptionsStr ? ", " : ""}${cliOptionsStr})
69
+ $subcommands | Where-Object { $_ -like "$wordToComplete*" }
70
+ }
71
+
72
+ Register-ArgumentCompleter -CommandName '${cli.cliName}' -ParameterName 'arguments' -ScriptBlock {
73
+ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
74
+ $subcommand = $commandAst.CommandElements[1].Value
75
+ $arguments = ${switchCase}
76
+ $arguments | Where-Object { $_ -like "$wordToComplete*" }
77
+ }`;
78
+ }
@@ -0,0 +1,69 @@
1
+ import { transformOptionToArg } from "../utils.js";
2
+
3
+ import type { Cli, Option, Subcommand } from "../types.js";
4
+
5
+ /**
6
+ * - Generates a ZSH autocomplete script for your CLI.
7
+ * - The generated script should be added to your `~/.zshrc` or `~/.zsh_profile` file:
8
+ *
9
+ * - Run: `nano $HOME/.zshrc` or `nano $HOME/.zsh_profile`
10
+ * - Add the following line: `source <generated script path>`
11
+ * - Save and reopen zsh to take effect
12
+ */
13
+ export function generateZshAutocompleteScript(...params: [Cli, ...Subcommand[]]): string {
14
+ const [cli, ...subcommands] = params;
15
+
16
+ const genArguments = (options: Option[]) => {
17
+ return options
18
+ ?.map(option => `'${transformOptionToArg(option.name)}[${option.description ?? ""}]'`)
19
+ .join(" \\\n ");
20
+ };
21
+
22
+ const genSubCommand = (subcommand: Subcommand) => {
23
+ const options = subcommand.options;
24
+ if (!options || options.length === 0) return "";
25
+ return `${subcommand.name})
26
+ _arguments \\
27
+ ${genArguments(options)} \\
28
+ '*: :_files' \\
29
+ && ret=0
30
+ ;;`;
31
+ };
32
+
33
+ return `# Auto-generated by zod-args-parser
34
+
35
+ _${cli.cliName}_autocomplete() {
36
+ local ret=1
37
+
38
+ _arguments -C \\
39
+ '1: :_${cli.cliName}_commands' \\
40
+ '*:: :->subcmds' \\
41
+ && ret=0
42
+
43
+ case $state in
44
+ subcmds)
45
+ case "$words[1]" in
46
+ ${subcommands.map(genSubCommand).filter(Boolean).join("\n ")}
47
+ *)
48
+ _arguments \\
49
+ '*: :_files' \\
50
+ && ret=0
51
+ ;;
52
+ esac
53
+ ;;
54
+ esac
55
+
56
+ return $ret
57
+ }
58
+
59
+ _${cli.cliName}_commands() {
60
+ local -a commands=(
61
+ ${subcommands.map(subcommand => `"${subcommand.name}:${subcommand.description ?? ""}"`).join("\n ")}
62
+ )
63
+
64
+ _describe -t subcommands 'subcommand' commands
65
+ }
66
+
67
+ compdef _${cli.cliName}_autocomplete ${cli.cliName}
68
+ `;
69
+ }
@@ -0,0 +1,24 @@
1
+ import chalk from "chalk";
2
+ import type { PrintHelpOpt } from "../types.js";
3
+
4
+ export type PrintHelpColors = NonNullable<Required<PrintHelpOpt["customColors"]>>;
5
+
6
+ export const printColors: PrintHelpColors = {
7
+ title: chalk.bold.blue,
8
+ description: chalk.white,
9
+ default: chalk.dim.italic,
10
+ optional: chalk.dim.italic,
11
+ exampleTitle: chalk.yellow,
12
+ example: chalk.dim,
13
+ command: chalk.yellow,
14
+ option: chalk.cyan,
15
+ argument: chalk.green,
16
+ placeholder: chalk.hex("#FF9800"),
17
+ punctuation: chalk.white.dim,
18
+ };
19
+
20
+ export const noColors = new Proxy(printColors, {
21
+ get: () => {
22
+ return (...str: string[]) => str.join(" ");
23
+ },
24
+ });
@@ -0,0 +1,35 @@
1
+ import { indent, print, println } from "./utils.js";
2
+
3
+ import type { ArgumentMetadata } from "../types.js";
4
+ import type { PrintHelpColors } from "./colors.js";
5
+
6
+ export function printPreparedArguments(argsMetadata: ArgumentMetadata[], c: PrintHelpColors, longest: number) {
7
+ if (!argsMetadata.length) return;
8
+
9
+ print(c.title(" ARGUMENTS "));
10
+
11
+ println();
12
+
13
+ for (const metadata of argsMetadata) {
14
+ const defaultStr =
15
+ typeof metadata.defaultValue !== "undefined" ? `(default: ${metadata.defaultValueAsString})` : "";
16
+
17
+ const spacing = longest + 2 - metadata.name.length;
18
+ const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 6) + c.punctuation("└"));
19
+
20
+ println(
21
+ indent(2),
22
+ c.argument(metadata.name),
23
+ indent(spacing),
24
+ c.description(normalizeDesc),
25
+ defaultStr ? c.default(defaultStr) : c.optional(metadata.optional),
26
+ );
27
+
28
+ if (metadata.example) {
29
+ const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(longest + 16));
30
+ println(indent(longest + 5), c.punctuation("└") + c.exampleTitle("Example:"), c.example(normalizeExample));
31
+ }
32
+ }
33
+
34
+ println();
35
+ }
@@ -0,0 +1,126 @@
1
+ import { getCliMetadata } from "../metadata/get-cli-metadata.js";
2
+ import { noColors, printColors } from "./colors.js";
3
+ import { printPreparedArguments } from "./print-arguments.js";
4
+ import { printOptions } from "./print-options.js";
5
+ import { printSubcommands } from "./print-subcommands.js";
6
+ import { concat, indent, ln, print, println } from "./utils.js";
7
+
8
+ import type { Cli, PrintHelpOpt, Subcommand } from "../types.js";
9
+
10
+ export function printCliHelp(params: [Cli, ...Subcommand[]], printConfig: PrintHelpOpt = {}) {
11
+ printConfig.colors ??= true;
12
+
13
+ const c = printConfig.colors ? printColors : noColors;
14
+
15
+ const metadata = getCliMetadata(params);
16
+
17
+ if (printConfig.customColors) {
18
+ Object.assign(c, printConfig.customColors);
19
+ }
20
+
21
+ /** Print a styled title */
22
+ const printTitle = (title: string) => {
23
+ print(c.title(` ${title.toUpperCase()} `));
24
+ };
25
+
26
+ // Print CLI usage
27
+ const usage =
28
+ metadata.usage ||
29
+ concat(
30
+ c.punctuation("$"),
31
+ metadata.name,
32
+ metadata.subcommands.length ? c.command("[command]") : "",
33
+ metadata.options.length ? c.option("[options]") : "",
34
+ metadata.arguments.length || metadata.allowPositional ? c.argument("<arguments>") : "",
35
+ );
36
+ printTitle("Usage");
37
+ println();
38
+ println(indent(2), usage, ln(1));
39
+
40
+ // Print CLI description
41
+ if (metadata.description) {
42
+ printTitle("Description");
43
+ println();
44
+ println(indent(2), c.description(metadata.description), ln(1));
45
+ }
46
+
47
+ let longest = 0;
48
+
49
+ // Prepare CLI options
50
+ const optionsMetadata = metadata.options;
51
+
52
+ const longestOptionTitle = optionsMetadata.reduce((acc, metadata) => {
53
+ const names = metadata.aliasesAsArgs.concat([metadata.nameAsArg]).join(", ");
54
+ const optLength = names.length + metadata.placeholder.length;
55
+ return optLength > acc ? optLength : acc;
56
+ }, 0);
57
+
58
+ if (longestOptionTitle > longest) {
59
+ longest = longestOptionTitle;
60
+ }
61
+
62
+ // Prepare CLI commands
63
+ const subcommandsMetadata = metadata.subcommands;
64
+
65
+ const longestSubcommandTitle = subcommandsMetadata.reduce((acc, metadata) => {
66
+ const names = metadata.aliases.concat([metadata.name]).join(", ");
67
+ const placeholder =
68
+ metadata.placeholder || (metadata.options.length ? "[options]" : metadata.allowPositional ? "<args>" : " ");
69
+ const optLength = names.length + placeholder.length;
70
+ return optLength > acc ? optLength : acc;
71
+ }, 0);
72
+
73
+ if (longestSubcommandTitle > longest) {
74
+ longest = longestSubcommandTitle;
75
+ }
76
+
77
+ // Prepare CLI arguments
78
+ const argsMetadata = metadata.arguments;
79
+
80
+ const longestArgTitle = argsMetadata.reduce((acc, arg) => (arg.name.length > acc ? arg.name.length : acc), 0);
81
+
82
+ if (longestArgTitle > longest) {
83
+ longest = longestArgTitle;
84
+ }
85
+
86
+ // Print CLI options
87
+ printOptions(optionsMetadata, c, longest);
88
+
89
+ // Print CLI commands
90
+ printSubcommands(subcommandsMetadata, c, longest);
91
+
92
+ // Print CLI arguments
93
+ printPreparedArguments(argsMetadata, c, longest);
94
+
95
+ // Print CLI example
96
+ if (metadata.example) {
97
+ printTitle("Example");
98
+ println();
99
+ const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(3));
100
+ println(indent(2), c.example(normalizeExample), ln(1));
101
+ }
102
+ }
103
+
104
+ export function printSubcommandHelp(subcommand: Subcommand, printConfig: PrintHelpOpt = {}, cliName = "") {
105
+ printConfig.colors ??= true;
106
+
107
+ const c = printConfig.colors ? printColors : noColors;
108
+
109
+ const usage =
110
+ subcommand.usage ||
111
+ concat(
112
+ c.punctuation("$"),
113
+ cliName,
114
+ c.command(subcommand.name),
115
+ subcommand.options?.length ? c.option("[options]") : "",
116
+ subcommand.arguments?.length || subcommand.allowPositional ? c.argument("<arguments>") : "",
117
+ );
118
+
119
+ const asCli: Cli = {
120
+ cliName,
121
+ usage,
122
+ ...subcommand,
123
+ };
124
+
125
+ printCliHelp([asCli], printConfig);
126
+ }
@@ -0,0 +1,40 @@
1
+ import { indent, print, println } from "./utils.js";
2
+
3
+ import type { PrintHelpColors } from "./colors.js";
4
+ import type { OptionMetadata } from "../types.js";
5
+
6
+ export function printOptions(optionsMetadata: OptionMetadata[], c: PrintHelpColors, longest: number) {
7
+ if (!optionsMetadata.length) return;
8
+
9
+ print(c.title(" OPTIONS "));
10
+
11
+ println();
12
+
13
+ for (const metadata of optionsMetadata) {
14
+ const names = metadata.aliasesAsArgs.concat([metadata.nameAsArg]);
15
+ const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 7) + c.punctuation("└"));
16
+ const defaultStr =
17
+ typeof metadata.defaultValue !== "undefined" ? `(default: ${metadata.defaultValueAsString})` : "";
18
+
19
+ const optLength = names.join(", ").length + metadata.placeholder.length;
20
+ const spacing = longest + 1 - optLength;
21
+
22
+ const coloredNames = names.map(name => c.option(name)).join(c.punctuation(", "));
23
+
24
+ println(
25
+ indent(2),
26
+ coloredNames,
27
+ c.placeholder(metadata.placeholder),
28
+ indent(spacing),
29
+ c.description(normalizeDesc),
30
+ defaultStr ? c.default(defaultStr) : c.optional(metadata.optional),
31
+ );
32
+
33
+ if (metadata.example) {
34
+ const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(longest + 17));
35
+ println(indent(longest + 6), c.punctuation("└") + c.exampleTitle("Example:"), c.example(normalizeExample));
36
+ }
37
+ }
38
+
39
+ println();
40
+ }
@@ -0,0 +1,28 @@
1
+ import { indent, print, println } from "./utils.js";
2
+
3
+ import type { SubcommandMetadata } from "src/types.js";
4
+ import type { PrintHelpColors } from "./colors.js";
5
+
6
+ export function printSubcommands(subcommandsMetadata: SubcommandMetadata[], c: PrintHelpColors, longest: number) {
7
+ if (!subcommandsMetadata.length) return;
8
+
9
+ print(c.title(" COMMANDS "));
10
+
11
+ println();
12
+
13
+ for (const metadata of subcommandsMetadata) {
14
+ const names = metadata.aliases.concat([metadata.name]);
15
+ const placeholder =
16
+ metadata.placeholder || (metadata.options.length ? "[options]" : metadata.allowPositional ? "<args>" : " ");
17
+ const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 7) + c.punctuation("└"));
18
+
19
+ const optLength = names.join(", ").length + placeholder.length;
20
+ const spacing = longest + 1 - optLength;
21
+
22
+ const coloredNames = names.map(name => c.command(name)).join(c.punctuation(", "));
23
+
24
+ println(indent(2), coloredNames, c.placeholder(placeholder), indent(spacing), c.description(normalizeDesc));
25
+ }
26
+
27
+ println();
28
+ }
@@ -0,0 +1,31 @@
1
+ /** Print */
2
+ export function print(...messages: string[]) {
3
+ return process.stdout.write(messages.join(" "));
4
+ }
5
+
6
+ /** Print line */
7
+ export function println(...messages: string[]) {
8
+ messages = messages.filter(Boolean);
9
+ return console.log(...messages);
10
+ }
11
+
12
+ /** New line */
13
+ export function ln(count: number) {
14
+ return "\n".repeat(count);
15
+ }
16
+
17
+ /** Space */
18
+ export function indent(count: number) {
19
+ return " ".repeat(count);
20
+ }
21
+
22
+ /** Add indent before each new line */
23
+ export function addIndentLn(message: string, indent: string = "") {
24
+ return message.replace(/\n/g, `\n${indent}`);
25
+ }
26
+
27
+ /** Concat strings */
28
+ export function concat(...messages: string[]) {
29
+ messages = messages.filter(Boolean);
30
+ return messages.join(" ");
31
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { help } from "./help.js";
2
-
3
1
  import type {
4
2
  ActionFn,
5
3
  Argument,
@@ -74,15 +72,20 @@ export function createArguments<const T extends [Argument, ...Argument[]]>(args:
74
72
  return args;
75
73
  }
76
74
 
77
- const { printCliHelp, printSubcommandHelp } = help;
78
- export { printCliHelp, printSubcommandHelp };
75
+ export { printCliHelp, printSubcommandHelp } from "./help-message/print-help-message.js";
76
+
77
+ export { parse } from "./parser/parse.js";
78
+ export { safeParse } from "./parser/safe-parse.js";
79
+
80
+ export { generateBashAutocompleteScript } from "./autocomplete-scripts/bash-autocomplete-script.js";
81
+ export { generatePowerShellAutocompleteScript } from "./autocomplete-scripts/powershell-autocomplete-script.js";
82
+ export { generateZshAutocompleteScript } from "./autocomplete-scripts/zsh-autocomplete-script.js";
79
83
 
80
- export { parse, safeParse } from "./parser.js";
84
+ export { getArgumentsMetadata } from "./metadata/get-arguments-metadata.js";
85
+ export { getCliMetadata } from "./metadata/get-cli-metadata.js";
86
+ export { getOptionsMetadata } from "./metadata/get-options-metadata.js";
87
+ export { getSubcommandsMetadata } from "./metadata/get-subcommands-metadata.js";
81
88
 
82
- export {
83
- generateBashAutocompleteScript,
84
- generateZshAutocompleteScript,
85
- generatePowerShellAutocompleteScript,
86
- } from "./autocomplete.js";
89
+ export { generateMarkdown } from "./markdown/generate-markdown.js";
87
90
 
88
91
  export type * from "./types.js";
@@ -0,0 +1,172 @@
1
+ import { getCliMetadata } from "../metadata/get-cli-metadata.js";
2
+
3
+ import type { ArgumentMetadata, Cli, OptionMetadata, Subcommand, SubcommandMetadata } from "../types.js";
4
+
5
+ export function generateMarkdown(...params: [Cli, ...Subcommand[]]): string {
6
+ const metadata = getCliMetadata(params);
7
+
8
+ let md = "<!-- Auto-generated by zod-args-parser -->\n\n";
9
+
10
+ // Title
11
+ md += `# ${metadata.name}\n\n`;
12
+
13
+ // Description
14
+ if (metadata.description) {
15
+ md += `${metadata.description}\n`;
16
+ }
17
+
18
+ // Examples
19
+ if (metadata.example) {
20
+ md += renderExamples(metadata.example);
21
+ }
22
+
23
+ // Options
24
+ if (metadata.options.length) {
25
+ md += "\n## Options:\n\n";
26
+ md += renderOptions(metadata.options, 3);
27
+ }
28
+
29
+ // Arguments
30
+ if (metadata.arguments.length) {
31
+ md += "\n## Arguments:\n\n";
32
+ md += renderArguments(metadata.arguments, 3);
33
+ }
34
+
35
+ // Subcommands
36
+ if (metadata.subcommands.length) {
37
+ md += "\n## Subcommands:\n\n";
38
+ md += renderSubcommands(metadata.subcommands);
39
+ }
40
+
41
+ return md;
42
+ }
43
+
44
+ function renderExamples(examples: string, list = false) {
45
+ let outStr = "";
46
+
47
+ const lang = "bash";
48
+
49
+ const listIndent = " ".repeat(list ? 2 : 0);
50
+
51
+ outStr += "\n" + (list ? "- " : "");
52
+
53
+ outStr += "```" + lang + "\n";
54
+ outStr += listIndent + examples.replace(/\n/g, "\n" + listIndent);
55
+ outStr += "\n" + listIndent + "```\n";
56
+
57
+ return outStr;
58
+ }
59
+
60
+ function renderOptions(optionsMetadata: OptionMetadata[] = [], h: number) {
61
+ let outStr = "";
62
+
63
+ for (let i = 0; i < optionsMetadata.length; i++) {
64
+ const metadata = optionsMetadata[i];
65
+
66
+ const aliases = [metadata.nameAsArg].concat(metadata.aliasesAsArgs).join(", ");
67
+
68
+ const placeholder = metadata.placeholder && ` ${metadata.placeholder}`;
69
+
70
+ outStr += `${"#".repeat(h)} \`${aliases + placeholder}\``;
71
+
72
+ if (metadata.optional) {
73
+ outStr += " **[optional]**";
74
+ }
75
+
76
+ outStr += "\n\n";
77
+
78
+ if (metadata.description) {
79
+ outStr += `- ${metadata.description}\n`;
80
+ }
81
+
82
+ if (typeof metadata.defaultValue !== "undefined") {
83
+ outStr += `- **default:** \`${metadata.defaultValueAsString}\`\n`;
84
+ }
85
+
86
+ if (metadata.example) {
87
+ outStr += renderExamples(metadata.example, true);
88
+ }
89
+
90
+ if (i < optionsMetadata.length - 1) {
91
+ outStr += "\n";
92
+ }
93
+ }
94
+
95
+ return outStr;
96
+ }
97
+
98
+ function renderArguments(argsMetadata: ArgumentMetadata[] = [], h: number) {
99
+ let outStr = "";
100
+
101
+ for (let i = 0; i < argsMetadata.length; i++) {
102
+ const metadata = argsMetadata[i];
103
+
104
+ outStr += `${"#".repeat(h)} \`${metadata.name}\``;
105
+
106
+ if (metadata.optional) {
107
+ outStr += " **[optional]**";
108
+ }
109
+
110
+ outStr += "\n\n";
111
+
112
+ if (metadata.description) {
113
+ outStr += `- ${metadata.description}\n`;
114
+ }
115
+
116
+ if (typeof metadata.defaultValue !== "undefined") {
117
+ outStr += `- **default:** \`${metadata.defaultValueAsString}\`\n`;
118
+ }
119
+
120
+ if (metadata.example) {
121
+ outStr += renderExamples(metadata.example);
122
+ }
123
+
124
+ if (i < argsMetadata.length - 1) {
125
+ outStr += "\n";
126
+ }
127
+ }
128
+
129
+ return outStr;
130
+ }
131
+
132
+ function renderSubcommands(subcommandsMetadata: SubcommandMetadata[]) {
133
+ let outStr = "";
134
+
135
+ for (let i = 0; i < subcommandsMetadata.length; i++) {
136
+ const metadata = subcommandsMetadata[i];
137
+
138
+ const aliases = [metadata.name].concat(metadata.aliases).join(", ");
139
+
140
+ const placeholder = metadata.placeholder && ` ${escapeTags(metadata.placeholder)}`;
141
+
142
+ outStr += `### ${aliases + placeholder}\n\n`;
143
+
144
+ if (metadata.description) {
145
+ outStr += `${metadata.description}\n`;
146
+ }
147
+
148
+ if (metadata.example) {
149
+ outStr += renderExamples(metadata.example);
150
+ }
151
+
152
+ if (metadata.options.length) {
153
+ outStr += "\n#### Options:\n\n";
154
+ outStr += renderOptions(metadata.options, 4);
155
+ }
156
+
157
+ if (metadata.arguments.length) {
158
+ outStr += "\n#### Arguments:\n\n";
159
+ outStr += renderArguments(metadata.arguments, 4);
160
+ }
161
+
162
+ if (i < subcommandsMetadata.length - 1) {
163
+ outStr += "\n---\n\n";
164
+ }
165
+ }
166
+
167
+ return outStr;
168
+ }
169
+
170
+ function escapeTags(str: string) {
171
+ return str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
172
+ }
@@ -0,0 +1,23 @@
1
+ import { getDefaultValueFromSchema } from "../utils.js";
2
+
3
+ import type { Argument, ArgumentMetadata } from "../types.js";
4
+
5
+ export function getArgumentsMetadata(args: Argument[]): ArgumentMetadata[] {
6
+ const outputMetadata: ArgumentMetadata[] = [];
7
+
8
+ for (const arg of args) {
9
+ const defaultValue = getDefaultValueFromSchema(arg.type);
10
+
11
+ outputMetadata.push({
12
+ name: arg.name,
13
+ description: arg.description ?? arg.type.description ?? "",
14
+ defaultValue,
15
+ defaultValueAsString: JSON.stringify(defaultValue),
16
+ optional: arg.type.isOptional(),
17
+ example: arg.example ?? "",
18
+ type: arg.type,
19
+ });
20
+ }
21
+
22
+ return outputMetadata;
23
+ }
@@ -0,0 +1,23 @@
1
+ import { getOptionsMetadata } from "./get-options-metadata.js";
2
+ import { getArgumentsMetadata } from "./get-arguments-metadata.js";
3
+ import { getSubcommandsMetadata } from "./get-subcommands-metadata.js";
4
+
5
+ import type { Cli, CliMetadata, Subcommand } from "../types.js";
6
+
7
+ export function getCliMetadata(inputData: [Cli, ...Subcommand[]]): CliMetadata {
8
+ const [cli, ...subcommands] = inputData;
9
+
10
+ const outputMetadata: CliMetadata = {
11
+ name: cli.cliName,
12
+ description: cli.description ?? "",
13
+ placeholder: cli.placeholder ?? "",
14
+ usage: cli.usage ?? "",
15
+ example: cli.example ?? "",
16
+ allowPositional: cli.allowPositional ?? false,
17
+ options: cli.options ? getOptionsMetadata(cli.options) : [],
18
+ arguments: cli.arguments ? getArgumentsMetadata(cli.arguments) : [],
19
+ subcommands: subcommands ? getSubcommandsMetadata(subcommands) : [],
20
+ };
21
+
22
+ return outputMetadata;
23
+ }