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.
Files changed (200) hide show
  1. package/README.md +598 -92
  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 +76 -186
  124. package/lib/typescript/types.d.ts.map +1 -1
  125. package/lib/typescript/utils.d.ts +20 -23
  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 +20 -19
  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 +6 -5
  141. package/src/metadata/get-cli-metadata.ts +4 -4
  142. package/src/metadata/get-options-metadata.ts +7 -5
  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 +99 -233
  153. package/src/utils.ts +31 -96
  154. package/src/zod-utils.ts +199 -0
  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/module/help-message/colors.js +0 -1
  170. package/lib/module/help-message/colors.js.map +0 -1
  171. package/lib/module/help-message/print-arguments.js +0 -1
  172. package/lib/module/help-message/print-arguments.js.map +0 -1
  173. package/lib/module/help-message/print-help-message.js +0 -1
  174. package/lib/module/help-message/print-help-message.js.map +0 -1
  175. package/lib/module/help-message/print-options.js +0 -1
  176. package/lib/module/help-message/print-options.js.map +0 -1
  177. package/lib/module/help-message/print-subcommands.js.map +0 -1
  178. package/lib/module/help-message/utils.js +0 -1
  179. package/lib/module/help-message/utils.js.map +0 -1
  180. package/lib/module/parser/parse.js +0 -1
  181. package/lib/module/parser/parse.js.map +0 -1
  182. package/lib/typescript/help-message/colors.d.ts +0 -17
  183. package/lib/typescript/help-message/colors.d.ts.map +0 -1
  184. package/lib/typescript/help-message/print-arguments.d.ts +0 -4
  185. package/lib/typescript/help-message/print-arguments.d.ts.map +0 -1
  186. package/lib/typescript/help-message/print-help-message.d.ts +0 -4
  187. package/lib/typescript/help-message/print-help-message.d.ts.map +0 -1
  188. package/lib/typescript/help-message/print-options.d.ts +0 -4
  189. package/lib/typescript/help-message/print-options.d.ts.map +0 -1
  190. package/lib/typescript/help-message/print-subcommands.d.ts +0 -4
  191. package/lib/typescript/help-message/print-subcommands.d.ts.map +0 -1
  192. package/lib/typescript/help-message/utils.d.ts +0 -13
  193. package/lib/typescript/help-message/utils.d.ts.map +0 -1
  194. package/lib/typescript/parser/parse.d.ts +0 -3
  195. package/lib/typescript/parser/parse.d.ts.map +0 -1
  196. package/src/help-message/colors.ts +0 -24
  197. package/src/help-message/print-arguments.ts +0 -35
  198. package/src/help-message/print-subcommands.ts +0 -28
  199. package/src/help-message/utils.ts +0 -31
  200. package/src/parser/parse.ts +0 -270
@@ -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,19 +1,20 @@
1
- import { getDefaultValueFromSchema } from "../utils.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[] = [];
7
8
 
8
9
  for (const arg of args) {
9
- const defaultValue = getDefaultValueFromSchema(arg.type);
10
+ const defaultValue = schemaDefaultValue(arg.type);
10
11
 
11
12
  outputMetadata.push({
12
13
  name: arg.name,
13
- description: arg.description ?? arg.type.description ?? "",
14
+ description: arg.description ?? schemaDescription(arg.type) ?? "",
14
15
  defaultValue,
15
16
  defaultValueAsString: JSON.stringify(defaultValue),
16
- optional: arg.type.isOptional(),
17
+ optional: isOptionalSchema(arg.type),
17
18
  example: arg.example ?? "",
18
19
  type: arg.type,
19
20
  });
@@ -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,6 +1,8 @@
1
- import { getDefaultValueFromSchema, transformOptionToArg } from "../utils.js";
1
+ import { transformOptionToArg } from "../parser/parse/parser-helpers.js";
2
+ import { isOptionalSchema, schemaDefaultValue, schemaDescription } from "../zod-utils.js";
2
3
 
3
- import type { Option, OptionMetadata } from "../types.js";
4
+ import type { Option } from "../types.js";
5
+ import type { OptionMetadata } from "./metadata-types.js";
4
6
 
5
7
  export function getOptionsMetadata(options: Option[]): OptionMetadata[] {
6
8
  const outputMetadata: OptionMetadata[] = [];
@@ -8,7 +10,7 @@ export function getOptionsMetadata(options: Option[]): OptionMetadata[] {
8
10
  if (!options || !options.length) return outputMetadata;
9
11
 
10
12
  for (const option of options) {
11
- const defaultValue = getDefaultValueFromSchema(option.type);
13
+ const defaultValue = schemaDefaultValue(option.type);
12
14
  const aliases = option.aliases ?? [];
13
15
 
14
16
  outputMetadata.push({
@@ -17,8 +19,8 @@ export function getOptionsMetadata(options: Option[]): OptionMetadata[] {
17
19
  aliases,
18
20
  aliasesAsArgs: aliases.map(transformOptionToArg),
19
21
  placeholder: option.placeholder ?? "",
20
- description: option.description ?? option.type.description ?? "",
21
- optional: option.type.isOptional(),
22
+ description: option.description ?? schemaDescription(option.type) ?? "",
23
+ optional: isOptionalSchema(option.type),
22
24
  example: option.example ?? "",
23
25
  defaultValue,
24
26
  defaultValueAsString: JSON.stringify(defaultValue),
@@ -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[] = [];