zod-args-parser 1.1.0 → 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.
Files changed (206) hide show
  1. package/README.md +597 -91
  2. package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js +1 -1
  3. package/lib/commonjs/autocomplete-scripts/bash-autocomplete-script.js.map +1 -1
  4. package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js +1 -1
  5. package/lib/commonjs/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -1
  6. package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js +1 -1
  7. package/lib/commonjs/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -1
  8. package/lib/commonjs/help-message/format-arguments.js +1 -0
  9. package/lib/commonjs/help-message/format-arguments.js.map +1 -0
  10. package/lib/commonjs/help-message/format-cli.js +1 -0
  11. package/lib/commonjs/help-message/format-cli.js.map +1 -0
  12. package/lib/commonjs/help-message/format-options.js +1 -0
  13. package/lib/commonjs/help-message/format-options.js.map +1 -0
  14. package/lib/commonjs/help-message/format-subcommands.js +1 -0
  15. package/lib/commonjs/help-message/format-subcommands.js.map +1 -0
  16. package/lib/commonjs/help-message/styles.js +1 -0
  17. package/lib/commonjs/help-message/styles.js.map +1 -0
  18. package/lib/commonjs/index.js +1 -1
  19. package/lib/commonjs/index.js.map +1 -1
  20. package/lib/commonjs/markdown/generate-markdown.js.map +1 -1
  21. package/lib/commonjs/metadata/get-arguments-metadata.js +1 -1
  22. package/lib/commonjs/metadata/get-arguments-metadata.js.map +1 -1
  23. package/lib/commonjs/metadata/get-cli-metadata.js +1 -1
  24. package/lib/commonjs/metadata/get-cli-metadata.js.map +1 -1
  25. package/lib/commonjs/metadata/get-options-metadata.js +1 -1
  26. package/lib/commonjs/metadata/get-options-metadata.js.map +1 -1
  27. package/lib/commonjs/metadata/get-subcommands-metadata.js.map +1 -1
  28. package/lib/commonjs/parser/parse/parse.js +1 -0
  29. package/lib/commonjs/parser/parse/parse.js.map +1 -0
  30. package/lib/commonjs/parser/parse/parser-helpers.js +1 -0
  31. package/lib/commonjs/parser/parse/parser-helpers.js.map +1 -0
  32. package/lib/commonjs/parser/safe-parse.js +1 -1
  33. package/lib/commonjs/parser/safe-parse.js.map +1 -1
  34. package/lib/commonjs/parser/unsafe-parse.js +1 -0
  35. package/lib/commonjs/parser/unsafe-parse.js.map +1 -0
  36. package/lib/commonjs/parser/validate/validate-type.js +1 -0
  37. package/lib/commonjs/parser/validate/validate-type.js.map +1 -0
  38. package/lib/commonjs/parser/validate/validate.js +1 -0
  39. package/lib/commonjs/parser/validate/validate.js.map +1 -0
  40. package/lib/commonjs/utils.js +1 -1
  41. package/lib/commonjs/utils.js.map +1 -1
  42. package/lib/commonjs/zod-utils.js +1 -0
  43. package/lib/commonjs/zod-utils.js.map +1 -0
  44. package/lib/module/autocomplete-scripts/bash-autocomplete-script.js +1 -1
  45. package/lib/module/autocomplete-scripts/bash-autocomplete-script.js.map +1 -1
  46. package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js +1 -1
  47. package/lib/module/autocomplete-scripts/powershell-autocomplete-script.js.map +1 -1
  48. package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js +1 -1
  49. package/lib/module/autocomplete-scripts/zsh-autocomplete-script.js.map +1 -1
  50. package/lib/module/help-message/format-arguments.js +1 -0
  51. package/lib/module/help-message/format-arguments.js.map +1 -0
  52. package/lib/module/help-message/format-cli.js +1 -0
  53. package/lib/module/help-message/format-cli.js.map +1 -0
  54. package/lib/module/help-message/format-options.js +1 -0
  55. package/lib/module/help-message/format-options.js.map +1 -0
  56. package/lib/module/help-message/{print-subcommands.js → format-subcommands.js} +1 -1
  57. package/lib/module/help-message/format-subcommands.js.map +1 -0
  58. package/lib/module/help-message/styles.js +1 -0
  59. package/lib/module/help-message/styles.js.map +1 -0
  60. package/lib/module/index.js +1 -1
  61. package/lib/module/index.js.map +1 -1
  62. package/lib/module/markdown/generate-markdown.js.map +1 -1
  63. package/lib/module/metadata/get-arguments-metadata.js +1 -1
  64. package/lib/module/metadata/get-arguments-metadata.js.map +1 -1
  65. package/lib/module/metadata/get-cli-metadata.js +1 -1
  66. package/lib/module/metadata/get-cli-metadata.js.map +1 -1
  67. package/lib/module/metadata/get-options-metadata.js +1 -1
  68. package/lib/module/metadata/get-options-metadata.js.map +1 -1
  69. package/lib/module/metadata/get-subcommands-metadata.js.map +1 -1
  70. package/lib/module/parser/parse/parse.js +1 -0
  71. package/lib/module/parser/parse/parse.js.map +1 -0
  72. package/lib/module/parser/parse/parser-helpers.js +1 -0
  73. package/lib/module/parser/parse/parser-helpers.js.map +1 -0
  74. package/lib/module/parser/safe-parse.js +1 -1
  75. package/lib/module/parser/safe-parse.js.map +1 -1
  76. package/lib/module/parser/unsafe-parse.js +1 -0
  77. package/lib/module/parser/unsafe-parse.js.map +1 -0
  78. package/lib/module/parser/validate/validate-type.js +1 -0
  79. package/lib/module/parser/validate/validate-type.js.map +1 -0
  80. package/lib/module/parser/validate/validate.js +1 -0
  81. package/lib/module/parser/validate/validate.js.map +1 -0
  82. package/lib/module/utils.js +1 -1
  83. package/lib/module/utils.js.map +1 -1
  84. package/lib/module/zod-utils.js +1 -0
  85. package/lib/module/zod-utils.js.map +1 -0
  86. package/lib/typescript/help-message/format-arguments.d.ts +4 -0
  87. package/lib/typescript/help-message/format-arguments.d.ts.map +1 -0
  88. package/lib/typescript/help-message/format-cli.d.ts +6 -0
  89. package/lib/typescript/help-message/format-cli.d.ts.map +1 -0
  90. package/lib/typescript/help-message/format-options.d.ts +4 -0
  91. package/lib/typescript/help-message/format-options.d.ts.map +1 -0
  92. package/lib/typescript/help-message/format-subcommands.d.ts +4 -0
  93. package/lib/typescript/help-message/format-subcommands.d.ts.map +1 -0
  94. package/lib/typescript/help-message/styles.d.ts +108 -0
  95. package/lib/typescript/help-message/styles.d.ts.map +1 -0
  96. package/lib/typescript/index.d.ts +18 -29
  97. package/lib/typescript/index.d.ts.map +1 -1
  98. package/lib/typescript/markdown/generate-markdown.d.ts.map +1 -1
  99. package/lib/typescript/metadata/get-arguments-metadata.d.ts +2 -1
  100. package/lib/typescript/metadata/get-arguments-metadata.d.ts.map +1 -1
  101. package/lib/typescript/metadata/get-cli-metadata.d.ts +3 -2
  102. package/lib/typescript/metadata/get-cli-metadata.d.ts.map +1 -1
  103. package/lib/typescript/metadata/get-options-metadata.d.ts +2 -1
  104. package/lib/typescript/metadata/get-options-metadata.d.ts.map +1 -1
  105. package/lib/typescript/metadata/get-subcommands-metadata.d.ts +2 -1
  106. package/lib/typescript/metadata/get-subcommands-metadata.d.ts.map +1 -1
  107. package/lib/typescript/metadata/metadata-types.d.ts +80 -0
  108. package/lib/typescript/metadata/metadata-types.d.ts.map +1 -0
  109. package/lib/typescript/parser/parse/parse-types.d.ts +85 -0
  110. package/lib/typescript/parser/parse/parse-types.d.ts.map +1 -0
  111. package/lib/typescript/parser/parse/parse.d.ts +4 -0
  112. package/lib/typescript/parser/parse/parse.d.ts.map +1 -0
  113. package/lib/typescript/parser/parse/parser-helpers.d.ts +40 -0
  114. package/lib/typescript/parser/parse/parser-helpers.d.ts.map +1 -0
  115. package/lib/typescript/parser/safe-parse.d.ts +1 -0
  116. package/lib/typescript/parser/safe-parse.d.ts.map +1 -1
  117. package/lib/typescript/parser/unsafe-parse.d.ts +4 -0
  118. package/lib/typescript/parser/unsafe-parse.d.ts.map +1 -0
  119. package/lib/typescript/parser/validate/validate-type.d.ts +22 -0
  120. package/lib/typescript/parser/validate/validate-type.d.ts.map +1 -0
  121. package/lib/typescript/parser/validate/validate.d.ts +11 -0
  122. package/lib/typescript/parser/validate/validate.d.ts.map +1 -0
  123. package/lib/typescript/types.d.ts +66 -181
  124. package/lib/typescript/types.d.ts.map +1 -1
  125. package/lib/typescript/utils.d.ts +20 -19
  126. package/lib/typescript/utils.d.ts.map +1 -1
  127. package/lib/typescript/zod-utils.d.ts +27 -0
  128. package/lib/typescript/zod-utils.d.ts.map +1 -0
  129. package/package.json +7 -6
  130. package/src/autocomplete-scripts/bash-autocomplete-script.ts +1 -1
  131. package/src/autocomplete-scripts/powershell-autocomplete-script.ts +1 -1
  132. package/src/autocomplete-scripts/zsh-autocomplete-script.ts +1 -1
  133. package/src/help-message/format-arguments.ts +38 -0
  134. package/src/help-message/{print-help-message.ts → format-cli.ts} +43 -48
  135. package/src/help-message/{print-options.ts → format-options.ts} +16 -14
  136. package/src/help-message/format-subcommands.ts +37 -0
  137. package/src/help-message/styles.ts +120 -0
  138. package/src/index.ts +50 -44
  139. package/src/markdown/generate-markdown.ts +2 -1
  140. package/src/metadata/get-arguments-metadata.ts +3 -2
  141. package/src/metadata/get-cli-metadata.ts +4 -4
  142. package/src/metadata/get-options-metadata.ts +4 -3
  143. package/src/metadata/get-subcommands-metadata.ts +2 -1
  144. package/src/metadata/metadata-types.ts +114 -0
  145. package/src/parser/parse/parse-types.ts +89 -0
  146. package/src/parser/parse/parse.ts +227 -0
  147. package/src/parser/parse/parser-helpers.ts +167 -0
  148. package/src/parser/safe-parse.ts +60 -8
  149. package/src/parser/unsafe-parse.ts +98 -0
  150. package/src/parser/validate/validate-type.ts +21 -0
  151. package/src/parser/validate/validate.ts +66 -0
  152. package/src/types.ts +90 -231
  153. package/src/utils.ts +33 -65
  154. package/src/{zodUtils.ts → zod-utils.ts} +65 -17
  155. package/lib/commonjs/help-message/colors.js +0 -1
  156. package/lib/commonjs/help-message/colors.js.map +0 -1
  157. package/lib/commonjs/help-message/print-arguments.js +0 -1
  158. package/lib/commonjs/help-message/print-arguments.js.map +0 -1
  159. package/lib/commonjs/help-message/print-help-message.js +0 -1
  160. package/lib/commonjs/help-message/print-help-message.js.map +0 -1
  161. package/lib/commonjs/help-message/print-options.js +0 -1
  162. package/lib/commonjs/help-message/print-options.js.map +0 -1
  163. package/lib/commonjs/help-message/print-subcommands.js +0 -1
  164. package/lib/commonjs/help-message/print-subcommands.js.map +0 -1
  165. package/lib/commonjs/help-message/utils.js +0 -1
  166. package/lib/commonjs/help-message/utils.js.map +0 -1
  167. package/lib/commonjs/parser/parse.js +0 -1
  168. package/lib/commonjs/parser/parse.js.map +0 -1
  169. package/lib/commonjs/zodUtils.js +0 -1
  170. package/lib/commonjs/zodUtils.js.map +0 -1
  171. package/lib/module/help-message/colors.js +0 -1
  172. package/lib/module/help-message/colors.js.map +0 -1
  173. package/lib/module/help-message/print-arguments.js +0 -1
  174. package/lib/module/help-message/print-arguments.js.map +0 -1
  175. package/lib/module/help-message/print-help-message.js +0 -1
  176. package/lib/module/help-message/print-help-message.js.map +0 -1
  177. package/lib/module/help-message/print-options.js +0 -1
  178. package/lib/module/help-message/print-options.js.map +0 -1
  179. package/lib/module/help-message/print-subcommands.js.map +0 -1
  180. package/lib/module/help-message/utils.js +0 -1
  181. package/lib/module/help-message/utils.js.map +0 -1
  182. package/lib/module/parser/parse.js +0 -1
  183. package/lib/module/parser/parse.js.map +0 -1
  184. package/lib/module/zodUtils.js +0 -1
  185. package/lib/module/zodUtils.js.map +0 -1
  186. package/lib/typescript/help-message/colors.d.ts +0 -17
  187. package/lib/typescript/help-message/colors.d.ts.map +0 -1
  188. package/lib/typescript/help-message/print-arguments.d.ts +0 -4
  189. package/lib/typescript/help-message/print-arguments.d.ts.map +0 -1
  190. package/lib/typescript/help-message/print-help-message.d.ts +0 -4
  191. package/lib/typescript/help-message/print-help-message.d.ts.map +0 -1
  192. package/lib/typescript/help-message/print-options.d.ts +0 -4
  193. package/lib/typescript/help-message/print-options.d.ts.map +0 -1
  194. package/lib/typescript/help-message/print-subcommands.d.ts +0 -4
  195. package/lib/typescript/help-message/print-subcommands.d.ts.map +0 -1
  196. package/lib/typescript/help-message/utils.d.ts +0 -13
  197. package/lib/typescript/help-message/utils.d.ts.map +0 -1
  198. package/lib/typescript/parser/parse.d.ts +0 -3
  199. package/lib/typescript/parser/parse.d.ts.map +0 -1
  200. package/lib/typescript/zodUtils.d.ts +0 -14
  201. package/lib/typescript/zodUtils.d.ts.map +0 -1
  202. package/src/help-message/colors.ts +0 -24
  203. package/src/help-message/print-arguments.ts +0 -35
  204. package/src/help-message/print-subcommands.ts +0 -28
  205. package/src/help-message/utils.ts +0 -31
  206. package/src/parser/parse.ts +0 -272
@@ -1,47 +1,39 @@
1
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";
2
+ import { concat, indent, ln } from "../utils.js";
3
+ import { formatHelpMsgArguments } from "./format-arguments.js";
4
+ import { formatHelpMsgOptions } from "./format-options.js";
5
+ import { formatHelpMsgCommands } from "./format-subcommands.js";
6
+ import { helpMsgStyles } from "./styles.js";
7
7
 
8
- import type { Cli, PrintHelpOpt, Subcommand } from "../types.js";
8
+ import type { Cli, HelpMsgStyle, Subcommand } from "../types.js";
9
9
 
10
- export function printCliHelp(params: [Cli, ...Subcommand[]], printConfig: PrintHelpOpt = {}) {
11
- printConfig.colors ??= true;
12
-
13
- const c = printConfig.colors ? printColors : noColors;
10
+ export function formatCliHelpMsg(params: readonly [Cli, ...Subcommand[]], style?: Partial<HelpMsgStyle>): string {
11
+ const c = helpMsgStyles.default;
12
+ if (style) Object.assign(c, style);
14
13
 
15
14
  const metadata = getCliMetadata(params);
16
15
 
17
- if (printConfig.customColors) {
18
- Object.assign(c, printConfig.customColors);
19
- }
16
+ const formatTitle = (title: string) => c.title(` ${title.toUpperCase()}`);
20
17
 
21
- /** Print a styled title */
22
- const printTitle = (title: string) => {
23
- print(c.title(` ${title.toUpperCase()} `));
24
- };
18
+ let msg = "";
25
19
 
26
- // Print CLI usage
20
+ // CLI usage
27
21
  const usage =
28
22
  metadata.usage ||
29
23
  concat(
30
24
  c.punctuation("$"),
31
- metadata.name,
25
+ c.description(metadata.name),
32
26
  metadata.subcommands.length ? c.command("[command]") : "",
33
27
  metadata.options.length ? c.option("[options]") : "",
34
28
  metadata.arguments.length || metadata.allowPositional ? c.argument("<arguments>") : "",
35
29
  );
36
- printTitle("Usage");
37
- println();
38
- println(indent(2), usage, ln(1));
30
+ msg += formatTitle("Usage") + ln(1);
31
+ msg += indent(2) + usage + ln(2);
39
32
 
40
- // Print CLI description
33
+ // CLI description
41
34
  if (metadata.description) {
42
- printTitle("Description");
43
- println();
44
- println(indent(2), c.description(metadata.description), ln(1));
35
+ msg += formatTitle("Description") + ln(1);
36
+ msg += indent(2) + c.description(metadata.description) + ln(2);
45
37
  }
46
38
 
47
39
  let longest = 0;
@@ -76,35 +68,34 @@ export function printCliHelp(params: [Cli, ...Subcommand[]], printConfig: PrintH
76
68
 
77
69
  // Prepare CLI arguments
78
70
  const argsMetadata = metadata.arguments;
79
-
80
71
  const longestArgTitle = argsMetadata.reduce((acc, arg) => (arg.name.length > acc ? arg.name.length : acc), 0);
81
-
82
72
  if (longestArgTitle > longest) {
83
73
  longest = longestArgTitle;
84
74
  }
85
75
 
86
- // Print CLI options
87
- printOptions(optionsMetadata, c, longest);
76
+ // CLI options
77
+ msg += formatHelpMsgOptions(optionsMetadata, c, longest);
88
78
 
89
- // Print CLI commands
90
- printSubcommands(subcommandsMetadata, c, longest);
79
+ // CLI commands
80
+ msg += formatHelpMsgCommands(subcommandsMetadata, c, longest);
91
81
 
92
- // Print CLI arguments
93
- printPreparedArguments(argsMetadata, c, longest);
82
+ // CLI arguments
83
+ msg += formatHelpMsgArguments(argsMetadata, c, longest);
94
84
 
95
- // Print CLI example
85
+ // CLI example
96
86
  if (metadata.example) {
97
- printTitle("Example");
98
- println();
87
+ msg += formatTitle("Example");
88
+ msg += ln(1);
99
89
  const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(3));
100
- println(indent(2), c.example(normalizeExample), ln(1));
90
+ msg += concat(indent(2), c.example(normalizeExample), ln(2));
101
91
  }
102
- }
103
92
 
104
- export function printSubcommandHelp(subcommand: Subcommand, printConfig: PrintHelpOpt = {}, cliName = "") {
105
- printConfig.colors ??= true;
93
+ return msg;
94
+ }
106
95
 
107
- const c = printConfig.colors ? printColors : noColors;
96
+ export function formatSubcommandHelpMsg(subcommand: Subcommand, printStyle?: Partial<HelpMsgStyle>, cliName = "") {
97
+ const c = helpMsgStyles.default;
98
+ if (printStyle) Object.assign(c, printStyle);
108
99
 
109
100
  const usage =
110
101
  subcommand.usage ||
@@ -116,11 +107,15 @@ export function printSubcommandHelp(subcommand: Subcommand, printConfig: PrintHe
116
107
  subcommand.arguments?.length || subcommand.allowPositional ? c.argument("<arguments>") : "",
117
108
  );
118
109
 
119
- const asCli: Cli = {
120
- cliName,
121
- usage,
122
- ...subcommand,
123
- };
110
+ const asCli: Cli = { cliName, usage, ...subcommand };
111
+
112
+ return formatCliHelpMsg([asCli], c);
113
+ }
114
+
115
+ export function printCliHelp(params: readonly [Cli, ...Subcommand[]], style?: Partial<HelpMsgStyle>) {
116
+ console.log(formatCliHelpMsg(params, style));
117
+ }
124
118
 
125
- printCliHelp([asCli], printConfig);
119
+ export function printSubcommandHelp(subcommand: Subcommand, style?: Partial<HelpMsgStyle>, cliName = "") {
120
+ console.log(formatSubcommandHelpMsg(subcommand, style, cliName));
126
121
  }
@@ -1,14 +1,12 @@
1
- import { indent, print, println } from "./utils.js";
1
+ import { concat, indent, ln } from "../utils.js";
2
2
 
3
- import type { PrintHelpColors } from "./colors.js";
4
- import type { OptionMetadata } from "../types.js";
3
+ import type { OptionMetadata } from "../metadata/metadata-types.js";
4
+ import type { HelpMsgStyle } from "../types.js";
5
5
 
6
- export function printOptions(optionsMetadata: OptionMetadata[], c: PrintHelpColors, longest: number) {
7
- if (!optionsMetadata.length) return;
6
+ export function formatHelpMsgOptions(optionsMetadata: OptionMetadata[], c: HelpMsgStyle, longest: number): string {
7
+ if (!optionsMetadata.length) return "";
8
8
 
9
- print(c.title(" OPTIONS "));
10
-
11
- println();
9
+ let msg = c.title(" OPTIONS") + ln(1);
12
10
 
13
11
  for (const metadata of optionsMetadata) {
14
12
  const names = metadata.aliasesAsArgs.concat([metadata.nameAsArg]);
@@ -21,20 +19,24 @@ export function printOptions(optionsMetadata: OptionMetadata[], c: PrintHelpColo
21
19
 
22
20
  const coloredNames = names.map(name => c.option(name)).join(c.punctuation(", "));
23
21
 
24
- println(
25
- indent(2),
26
- coloredNames,
22
+ msg += concat(
23
+ indent(2) + coloredNames,
27
24
  c.placeholder(metadata.placeholder),
28
25
  indent(spacing),
29
26
  c.description(normalizeDesc),
30
- defaultStr ? c.default(defaultStr) : metadata.optional ? c.optional("(optional)") : "",
27
+ (defaultStr ? c.default(defaultStr) : metadata.optional ? c.optional("(optional)") : "") + ln(1),
31
28
  );
32
29
 
33
30
  if (metadata.example) {
34
31
  const normalizeExample = metadata.example.replace(/\n/g, "\n" + indent(longest + 17));
35
- println(indent(longest + 6), c.punctuation("└") + c.exampleTitle("Example:"), c.example(normalizeExample));
32
+ msg += concat(
33
+ indent(longest + 6) + c.punctuation("└") + c.exampleTitle("Example:"),
34
+ c.example(normalizeExample) + ln(1),
35
+ );
36
36
  }
37
37
  }
38
38
 
39
- println();
39
+ msg += ln(1);
40
+
41
+ return msg;
40
42
  }
@@ -0,0 +1,37 @@
1
+ import { concat, indent, ln } from "../utils.js";
2
+
3
+ import type { SubcommandMetadata } from "../metadata/metadata-types.js";
4
+ import type { HelpMsgStyle } from "../types.js";
5
+
6
+ export function formatHelpMsgCommands(
7
+ subcommandsMetadata: SubcommandMetadata[],
8
+ c: HelpMsgStyle,
9
+ longest: number,
10
+ ): string {
11
+ if (!subcommandsMetadata.length) return "";
12
+
13
+ let msg = c.title(" COMMANDS") + ln(1);
14
+
15
+ for (const metadata of subcommandsMetadata) {
16
+ const names = metadata.aliases.concat([metadata.name]);
17
+ const placeholder =
18
+ metadata.placeholder || (metadata.options.length ? "[options]" : metadata.allowPositional ? "<args>" : " ");
19
+ const normalizeDesc = metadata.description.replace(/\n/g, "\n" + indent(longest + 7) + c.punctuation("└"));
20
+
21
+ const optLength = names.join(", ").length + placeholder.length;
22
+ const spacing = longest + 1 - optLength;
23
+
24
+ const coloredNames = names.map(name => c.command(name)).join(c.punctuation(", "));
25
+
26
+ msg += concat(
27
+ indent(2) + coloredNames,
28
+ c.placeholder(placeholder),
29
+ indent(spacing),
30
+ c.description(normalizeDesc) + ln(1),
31
+ );
32
+ }
33
+
34
+ msg += ln(1);
35
+
36
+ return msg;
37
+ }
@@ -0,0 +1,120 @@
1
+ import chalk from "chalk";
2
+ import type { HelpMsgStyle } from "../types.js";
3
+
4
+ export const helpMsgStyles = Object.freeze({
5
+ default: {
6
+ title: chalk.bold.blue,
7
+ description: chalk.white,
8
+ default: chalk.dim.italic,
9
+ optional: chalk.dim.italic,
10
+ exampleTitle: chalk.yellow,
11
+ example: chalk.dim,
12
+ command: chalk.yellow,
13
+ option: chalk.cyan,
14
+ argument: chalk.green,
15
+ placeholder: chalk.hex("#FF9800"),
16
+ punctuation: chalk.white.dim,
17
+ },
18
+ dracula: {
19
+ title: chalk.bold.hex("#BD93F9"),
20
+ description: chalk.hex("#F8F8F2"),
21
+ default: chalk.italic.hex("#6272A4"),
22
+ optional: chalk.italic.hex("#6272A4"),
23
+ exampleTitle: chalk.hex("#FFB86C"),
24
+ example: chalk.hex("#6272A4"),
25
+ command: chalk.hex("#50FA7B"),
26
+ option: chalk.hex("#8BE9FD"),
27
+ argument: chalk.hex("#FF79C6"),
28
+ placeholder: chalk.hex("#F1FA8C"),
29
+ punctuation: chalk.hex("#6272A4"),
30
+ },
31
+ solarizedDark: {
32
+ title: chalk.bold.hex("#268BD2"),
33
+ description: chalk.hex("#93A1A1"),
34
+ default: chalk.italic.hex("#586E75"),
35
+ optional: chalk.italic.hex("#586E75"),
36
+ exampleTitle: chalk.hex("#B58900"),
37
+ example: chalk.hex("#586E75"),
38
+ command: chalk.hex("#2AA198"),
39
+ option: chalk.hex("#268BD2"),
40
+ argument: chalk.hex("#859900"),
41
+ placeholder: chalk.hex("#CB4B16"),
42
+ punctuation: chalk.hex("#657B83"),
43
+ },
44
+ nord: {
45
+ title: chalk.bold.hex("#81A1C1"),
46
+ description: chalk.hex("#D8DEE9"),
47
+ default: chalk.italic.hex("#4C566A"),
48
+ optional: chalk.italic.hex("#4C566A"),
49
+ exampleTitle: chalk.hex("#EBCB8B"),
50
+ example: chalk.hex("#4C566A"),
51
+ command: chalk.hex("#A3BE8C"),
52
+ option: chalk.hex("#88C0D0"),
53
+ argument: chalk.hex("#BF616A"),
54
+ placeholder: chalk.hex("#D08770"),
55
+ punctuation: chalk.hex("#4C566A"),
56
+ },
57
+ html: {
58
+ title: (...str) => `<span style="color: #89dceb; font-weight: bold;">${escapeHTML(str.join(" "))}</span>`,
59
+ description: (...str) => `<span style="color: #cdd6e8;">${escapeHTML(str.join(" "))}</span>`,
60
+ default: (...str) => `<span style="color: #6c7086; font-style: italic;">${escapeHTML(str.join(" "))}</span>`,
61
+ optional: (...str) => `<span style="color: #6c7086; font-style: italic;">${escapeHTML(str.join(" "))}</span>`,
62
+ exampleTitle: (...str) => `<span style="color: #f9e2af;">${escapeHTML(str.join(" "))}</span>`,
63
+ example: (...str) => `<span style="color: #6c7086;">${escapeHTML(str.join(" "))}</span>`,
64
+ command: (...str) => `<span style="color: #f9e2af;">${escapeHTML(str.join(" "))}</span>`,
65
+ option: (...str) => `<span style="color: #17b85d;">${escapeHTML(str.join(" "))}</span>`,
66
+ argument: (...str) => `<span style="color: #00ff00;">${escapeHTML(str.join(" "))}</span>`,
67
+ placeholder: (...str) => `<span style="color: #db9518;">${escapeHTML(str.join(" "))}</span>`,
68
+ punctuation: (...str) => `<span style="color: #6c7086;">${escapeHTML(str.join(" "))}</span>`,
69
+ },
70
+ gruvboxDark: {
71
+ title: chalk.bold.hex("#FABD2F"),
72
+ description: chalk.hex("#EBDBB2"),
73
+ default: chalk.italic.hex("#928374"),
74
+ optional: chalk.italic.hex("#928374"),
75
+ exampleTitle: chalk.hex("#FE8019"),
76
+ example: chalk.hex("#928374"),
77
+ command: chalk.hex("#B8BB26"),
78
+ option: chalk.hex("#83A598"),
79
+ argument: chalk.hex("#D3869B"),
80
+ placeholder: chalk.hex("#FB4934"),
81
+ punctuation: chalk.hex("#928374"),
82
+ },
83
+ monokai: {
84
+ title: chalk.bold.hex("#AE81FF"),
85
+ description: chalk.hex("#F8F8F2"),
86
+ default: chalk.italic.hex("#75715E"),
87
+ optional: chalk.italic.hex("#75715E"),
88
+ exampleTitle: chalk.hex("#FD971F"),
89
+ example: chalk.hex("#75715E"),
90
+ command: chalk.hex("#A6E22E"),
91
+ option: chalk.hex("#66D9EF"),
92
+ argument: chalk.hex("#F92672"),
93
+ placeholder: chalk.hex("#E6DB74"),
94
+ punctuation: chalk.hex("#75715E"),
95
+ },
96
+ oneDark: {
97
+ title: chalk.bold.hex("#61AFEF"),
98
+ description: chalk.hex("#ABB2BF"),
99
+ default: chalk.italic.hex("#5C6370"),
100
+ optional: chalk.italic.hex("#5C6370"),
101
+ exampleTitle: chalk.hex("#E5C07B"),
102
+ example: chalk.hex("#5C6370"),
103
+ command: chalk.hex("#98C379"),
104
+ option: chalk.hex("#56B6C2"),
105
+ argument: chalk.hex("#E06C75"),
106
+ placeholder: chalk.hex("#C678DD"),
107
+ punctuation: chalk.hex("#5C6370"),
108
+ },
109
+ get noColors() {
110
+ return new Proxy(this.default, {
111
+ get() {
112
+ return (...str: string[]) => str.join(" ");
113
+ },
114
+ });
115
+ },
116
+ }) satisfies Record<string, HelpMsgStyle>;
117
+
118
+ function escapeHTML(str: string) {
119
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
120
+ }
package/src/index.ts CHANGED
@@ -1,63 +1,56 @@
1
1
  import type {
2
- ActionFn,
2
+ ActionsFn,
3
3
  Argument,
4
+ CheckArgumentsOptional,
5
+ CheckDuplicatedArguments,
4
6
  CheckDuplicatedOptions,
5
7
  Cli,
6
8
  Option,
7
9
  Prettify,
8
10
  Subcommand,
9
- UnSafeParseResult,
10
11
  } from "./types.js";
11
12
 
12
- /**
13
- * - Insures that there is no extra keys in `obj` compared to `shape`
14
- * - Also checks objects in arrays useful for the keys `options` and `arguments`
15
- */
16
- type Exact<Obj extends object, Shape extends object> = {
17
- [K in keyof Obj]: K extends keyof Shape
18
- ? Obj[K] extends infer ObjArr extends object[]
19
- ? Required<Shape>[K] extends infer ShapeArr extends object[]
20
- ? ExactObjArr<ObjArr, ShapeArr[number]>
21
- : Obj[K]
22
- : Obj[K]
23
- : never;
24
- };
25
-
26
- /** - Insures that there is no extra keys in `obj` compared to `shape` */
27
- type ExactKeys<T extends object, U extends object> = { [K in keyof T]: K extends keyof U ? T[K] : never };
28
-
29
- /** - Insures that there is no extra keys in the objects in an array compared to `shape` */
30
- type ExactObjArr<ObjArr extends object[], ShapeObj extends object> = {
31
- [K in keyof ObjArr]: ExactKeys<ObjArr[K], ShapeObj>;
32
- };
33
-
34
13
  /**
35
14
  * - Insures that there are no duplicated options
36
- * - Disallow extra keys
15
+ * - Insures that there are no duplicated arguments
16
+ * - Insures that only the last argument is optional
17
+ * - Insures no optional arguments are allowed when `allowPositional` is enabled
37
18
  */
38
- type CliInput<T extends Cli> = CheckDuplicatedOptions<T> extends T ? Exact<T, Cli> : CheckDuplicatedOptions<T>;
39
-
40
- export function createCli<const T extends Cli>(input: CliInput<T>) {
41
- const setAction = (action: (res: UnSafeParseResult<[T]>) => void) => {
19
+ type CheckCliSubcommandInput<T extends Cli | Subcommand> =
20
+ CheckDuplicatedOptions<T> extends infer Err extends string
21
+ ? Err
22
+ : CheckDuplicatedArguments<T> extends infer Err extends string
23
+ ? Err
24
+ : CheckArgumentsOptional<T> extends infer Err extends string
25
+ ? Err
26
+ : T;
27
+
28
+ export function createCli<const T extends Cli>(input: CheckCliSubcommandInput<T>) {
29
+ const setAction = (action: (res: any) => any) => {
30
+ if (typeof input === "string") return;
42
31
  input.action = action;
43
32
  };
44
33
 
45
- return Object.assign(input, { setAction }) as Prettify<CliInput<T> & ActionFn<T>>;
34
+ const setPreValidationHook = (hook: (ctx: any) => any) => {
35
+ if (typeof input === "string") return;
36
+ input.preValidation = hook;
37
+ };
38
+
39
+ return Object.assign(input, { setAction, setPreValidationHook }) as Prettify<typeof input & ActionsFn<T>>;
46
40
  }
47
41
 
48
- /**
49
- * - Insures that there are no duplicated options
50
- * - Disallow extra keys
51
- */
52
- type SubcommandInput<T extends Subcommand> =
53
- CheckDuplicatedOptions<T> extends T ? Exact<T, Subcommand> : CheckDuplicatedOptions<T>;
42
+ export function createSubcommand<const T extends Subcommand>(input: CheckCliSubcommandInput<T>) {
43
+ const setAction = (action: (res: any) => any) => {
44
+ if (typeof input === "string") return;
45
+ input.action = action as T["action"];
46
+ };
54
47
 
55
- export function createSubcommand<const T extends Subcommand>(input: SubcommandInput<T>) {
56
- const setAction = (action: (res: UnSafeParseResult<[T]>) => void) => {
57
- input.action = action;
48
+ const setPreValidationHook = (hook: (ctx: any) => any) => {
49
+ if (typeof input === "string") return;
50
+ input.preValidation = hook;
58
51
  };
59
52
 
60
- return Object.assign(input, { setAction }) as Prettify<SubcommandInput<T> & ActionFn<T>>;
53
+ return Object.assign(input, { setAction, setPreValidationHook }) as Prettify<typeof input & ActionsFn<T>>;
61
54
  }
62
55
 
63
56
  /** - Insures that there are no duplicated options */
@@ -68,14 +61,26 @@ export function createOptions<const T extends [Option, ...Option[]]>(options: Ch
68
61
  return options;
69
62
  }
70
63
 
71
- export function createArguments<const T extends [Argument, ...Argument[]]>(args: T) {
64
+ /** - Insures that only the last argument is optional */
65
+ type CheckArgumentsInput<T extends Argument[]> =
66
+ CheckArgumentsOptional<{ arguments: T }> extends infer Err extends string ? Err : T;
67
+
68
+ export function createArguments<const T extends [Argument, ...Argument[]]>(args: CheckArgumentsInput<T>) {
72
69
  return args;
73
70
  }
74
71
 
75
- export { printCliHelp, printSubcommandHelp } from "./help-message/print-help-message.js";
72
+ export {
73
+ formatCliHelpMsg,
74
+ printCliHelp,
75
+ formatSubcommandHelpMsg,
76
+ printSubcommandHelp,
77
+ } from "./help-message/format-cli.js";
78
+ export { helpMsgStyles } from "./help-message/styles.js";
79
+
80
+ export { unsafeParse as parse, unsafeParseAsync as parseAsync } from "./parser/unsafe-parse.js";
81
+ export { safeParse, safeParseAsync } from "./parser/safe-parse.js";
76
82
 
77
- export { parse } from "./parser/parse.js";
78
- export { safeParse } from "./parser/safe-parse.js";
83
+ export { isOptionalSchema, schemaDefaultValue, stringToArray, stringToSet } from "./zod-utils.js";
79
84
 
80
85
  export { generateBashAutocompleteScript } from "./autocomplete-scripts/bash-autocomplete-script.js";
81
86
  export { generatePowerShellAutocompleteScript } from "./autocomplete-scripts/powershell-autocomplete-script.js";
@@ -89,3 +94,4 @@ export { getSubcommandsMetadata } from "./metadata/get-subcommands-metadata.js";
89
94
  export { generateMarkdown } from "./markdown/generate-markdown.js";
90
95
 
91
96
  export type * from "./types.js";
97
+ export type * from "./metadata/metadata-types.js";
@@ -1,6 +1,7 @@
1
1
  import { getCliMetadata } from "../metadata/get-cli-metadata.js";
2
2
 
3
- import type { ArgumentMetadata, Cli, OptionMetadata, Subcommand, SubcommandMetadata } from "../types.js";
3
+ import type { ArgumentMetadata, OptionMetadata, SubcommandMetadata } from "../metadata/metadata-types.js";
4
+ import type { Cli, Subcommand } from "../types.js";
4
5
 
5
6
  export function generateMarkdown(...params: [Cli, ...Subcommand[]]): string {
6
7
  const metadata = getCliMetadata(params);
@@ -1,6 +1,7 @@
1
- import { isOptionalSchema, schemaDefaultValue, schemaDescription } from "../zodUtils.js";
1
+ import { isOptionalSchema, schemaDefaultValue, schemaDescription } from "../zod-utils.js";
2
2
 
3
- import type { Argument, ArgumentMetadata } from "../types.js";
3
+ import type { Argument } from "../types.js";
4
+ import type { ArgumentMetadata } from "./metadata-types.js";
4
5
 
5
6
  export function getArgumentsMetadata(args: Argument[]): ArgumentMetadata[] {
6
7
  const outputMetadata: ArgumentMetadata[] = [];
@@ -1,16 +1,16 @@
1
- import { getOptionsMetadata } from "./get-options-metadata.js";
2
1
  import { getArgumentsMetadata } from "./get-arguments-metadata.js";
2
+ import { getOptionsMetadata } from "./get-options-metadata.js";
3
3
  import { getSubcommandsMetadata } from "./get-subcommands-metadata.js";
4
4
 
5
- import type { Cli, CliMetadata, Subcommand } from "../types.js";
5
+ import type { Cli, Subcommand } from "../types.js";
6
+ import type { CliMetadata } from "./metadata-types.js";
6
7
 
7
- export function getCliMetadata(inputData: [Cli, ...Subcommand[]]): CliMetadata {
8
+ export function getCliMetadata(inputData: readonly [Cli, ...Subcommand[]]): CliMetadata {
8
9
  const [cli, ...subcommands] = inputData;
9
10
 
10
11
  const outputMetadata: CliMetadata = {
11
12
  name: cli.cliName,
12
13
  description: cli.description ?? "",
13
- placeholder: cli.placeholder ?? "",
14
14
  usage: cli.usage ?? "",
15
15
  example: cli.example ?? "",
16
16
  allowPositional: cli.allowPositional ?? false,
@@ -1,7 +1,8 @@
1
- import { transformOptionToArg } from "../utils.js";
2
- import { isOptionalSchema, schemaDefaultValue, schemaDescription } from "../zodUtils.js";
1
+ import { transformOptionToArg } from "../parser/parse/parser-helpers.js";
2
+ import { isOptionalSchema, schemaDefaultValue, schemaDescription } from "../zod-utils.js";
3
3
 
4
- import type { Option, OptionMetadata } from "../types.js";
4
+ import type { Option } from "../types.js";
5
+ import type { OptionMetadata } from "./metadata-types.js";
5
6
 
6
7
  export function getOptionsMetadata(options: Option[]): OptionMetadata[] {
7
8
  const outputMetadata: OptionMetadata[] = [];
@@ -1,7 +1,8 @@
1
1
  import { getArgumentsMetadata } from "./get-arguments-metadata.js";
2
2
  import { getOptionsMetadata } from "./get-options-metadata.js";
3
3
 
4
- import type { Subcommand, SubcommandMetadata } from "../types.js";
4
+ import type { Subcommand } from "../types.js";
5
+ import type { SubcommandMetadata } from "./metadata-types.js";
5
6
 
6
7
  export function getSubcommandsMetadata(subcommands: Subcommand[]): SubcommandMetadata[] {
7
8
  const outputMetadata: SubcommandMetadata[] = [];
@@ -0,0 +1,114 @@
1
+ import type { Schema } from "../types.js";
2
+
3
+ export interface CliMetadata {
4
+ /** The name of the cli program. */
5
+ readonly name: string;
6
+
7
+ /** - The description of the cli program. Empty string if not provided */
8
+ readonly description: string;
9
+
10
+ /** - The usage of the cli program. Empty string if not provided */
11
+ readonly usage: string;
12
+
13
+ /** - The example of the cli program. Empty string if not provided */
14
+ readonly example: string;
15
+
16
+ /** - Whether the cli program allows positional arguments. */
17
+ readonly allowPositional: boolean;
18
+
19
+ /** - The options of the cli program. Empty array if not provided */
20
+ readonly options: OptionMetadata[];
21
+
22
+ /** - The arguments of the cli program. Empty array if not provided */
23
+ readonly arguments: ArgumentMetadata[];
24
+
25
+ /** - The subcommands of the cli program. Empty array if not provided */
26
+ readonly subcommands: SubcommandMetadata[];
27
+ }
28
+
29
+ export interface SubcommandMetadata {
30
+ /** The subcommand name. */
31
+ readonly name: string;
32
+
33
+ /** - The aliases of the subcommand. Empty array if not provided */
34
+ readonly aliases: string[];
35
+
36
+ /** - The description of the subcommand. Empty string if not provided */
37
+ readonly description: string;
38
+
39
+ /** - The placeholder of the subcommand. Empty string if not provided */
40
+ readonly placeholder: string;
41
+
42
+ /** - The usage of the subcommand. Empty string if not provided */
43
+ readonly usage: string;
44
+
45
+ /** - The example of the subcommand. Empty string if not provided */
46
+ readonly example: string;
47
+
48
+ /** - Whether the subcommand allows positional arguments. */
49
+ readonly allowPositional: boolean;
50
+
51
+ /** - The options of the subcommand. Empty array if not provided */
52
+ readonly options: OptionMetadata[];
53
+
54
+ /** - The arguments of the subcommand. Empty array if not provided */
55
+ readonly arguments: ArgumentMetadata[];
56
+ }
57
+
58
+ export interface OptionMetadata {
59
+ /** The option name in camelCase. E.g. `optionName` */
60
+ readonly name: string;
61
+
62
+ /** The option name in kebab-case. E.g. `--option-name` */
63
+ readonly nameAsArg: string;
64
+
65
+ /** - The aliases of the option in camelCase. Empty array if not provided. E.g. `[aliasName, ...]` */
66
+ readonly aliases: string[];
67
+
68
+ /** - The aliases of the option in kebab-case. Empty array if not provided. E.g. `[--alias-name, ...]` */
69
+ readonly aliasesAsArgs: string[];
70
+
71
+ /** - The description of the option. Empty string if not provided */
72
+ readonly description: string;
73
+
74
+ /** - The placeholder of the option. Empty string if not provided */
75
+ readonly placeholder: string;
76
+
77
+ /** - The example of the option. Empty string if not provided */
78
+ readonly example: string;
79
+
80
+ /** - The default value of the option. */
81
+ readonly defaultValue: unknown;
82
+
83
+ /** - The default value of the option as string. */
84
+ readonly defaultValueAsString: string;
85
+
86
+ /** - Whether the option is optional. */
87
+ readonly optional: boolean;
88
+
89
+ /** - The zod type of the option. */
90
+ readonly type: Schema;
91
+ }
92
+
93
+ export interface ArgumentMetadata {
94
+ /** The argument name. */
95
+ readonly name: string;
96
+
97
+ /** - The description of the argument. Empty string if not provided */
98
+ readonly description: string;
99
+
100
+ /** - The example of the argument. Empty string if not provided */
101
+ readonly example: string;
102
+
103
+ /** - The default value of the argument. */
104
+ readonly defaultValue: unknown;
105
+
106
+ /** - The default value of the argument as string. */
107
+ readonly defaultValueAsString: string;
108
+
109
+ /** - Whether the argument is optional. */
110
+ readonly optional: boolean;
111
+
112
+ /** - The zod type of the argument. */
113
+ readonly type: Schema;
114
+ }