zod-args-parser 2.0.0-beta.1 → 2.0.0-beta.2

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 (474) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +230 -289
  3. package/lib/esm/autocomplete-scripts/bash-autocomplete-script.js +74 -2
  4. package/lib/esm/autocomplete-scripts/bash-autocomplete-script.js.map +7 -1
  5. package/lib/esm/autocomplete-scripts/powershell-autocomplete-script.js +90 -2
  6. package/lib/esm/autocomplete-scripts/powershell-autocomplete-script.js.map +7 -1
  7. package/lib/esm/autocomplete-scripts/zsh-autocomplete-script.js +39 -13
  8. package/lib/esm/autocomplete-scripts/zsh-autocomplete-script.js.map +7 -1
  9. package/lib/esm/cli-error/cli-error.js +38 -0
  10. package/lib/esm/cli-error/cli-error.js.map +7 -0
  11. package/lib/esm/cli-error/error-cause.js +12 -0
  12. package/lib/esm/cli-error/error-cause.js.map +7 -0
  13. package/lib/esm/cli-error/error-code/definition-error-code.js +23 -0
  14. package/lib/esm/cli-error/error-code/definition-error-code.js.map +7 -0
  15. package/lib/esm/cli-error/error-code/internal-error-code.js +10 -0
  16. package/lib/esm/cli-error/error-code/internal-error-code.js.map +7 -0
  17. package/lib/esm/cli-error/error-code/parse-error-code.js +18 -0
  18. package/lib/esm/cli-error/error-code/parse-error-code.js.map +7 -0
  19. package/lib/esm/cli-error/error-code/validation-error-code.js +17 -0
  20. package/lib/esm/cli-error/error-code/validation-error-code.js.map +7 -0
  21. package/lib/esm/cli-error/error-message/definition-error-message.js +70 -0
  22. package/lib/esm/cli-error/error-message/definition-error-message.js.map +7 -0
  23. package/lib/esm/cli-error/error-message/internal-error-message.js +16 -0
  24. package/lib/esm/cli-error/error-message/internal-error-message.js.map +7 -0
  25. package/lib/esm/cli-error/error-message/parse-error-message.js +40 -0
  26. package/lib/esm/cli-error/error-message/parse-error-message.js.map +7 -0
  27. package/lib/esm/cli-error/error-message/validation-error-message.js +60 -0
  28. package/lib/esm/cli-error/error-message/validation-error-message.js.map +7 -0
  29. package/lib/esm/coerce/coerce-methods.js +197 -2
  30. package/lib/esm/coerce/coerce-methods.js.map +7 -1
  31. package/lib/esm/coerce/string-to-array.js +17 -2
  32. package/lib/esm/coerce/string-to-array.js.map +7 -1
  33. package/lib/esm/coerce/string-to-primitive.js +73 -2
  34. package/lib/esm/coerce/string-to-primitive.js.map +7 -1
  35. package/lib/esm/coerce/string-to-set.js +17 -2
  36. package/lib/esm/coerce/string-to-set.js.map +7 -1
  37. package/lib/esm/definitions/define-arguments.js +10 -2
  38. package/lib/esm/definitions/define-arguments.js.map +7 -1
  39. package/lib/esm/definitions/define-cli.js +89 -2
  40. package/lib/esm/definitions/define-cli.js.map +7 -1
  41. package/lib/esm/definitions/define-options.js +10 -2
  42. package/lib/esm/definitions/define-options.js.map +7 -1
  43. package/lib/esm/definitions/define-subcommand.js +56 -2
  44. package/lib/esm/definitions/define-subcommand.js.map +7 -1
  45. package/lib/esm/definitions/validate-cli-definition.js +360 -2
  46. package/lib/esm/definitions/validate-cli-definition.js.map +7 -1
  47. package/lib/esm/help-message/format-arguments.js +48 -2
  48. package/lib/esm/help-message/format-arguments.js.map +7 -1
  49. package/lib/esm/help-message/format-options.js +50 -2
  50. package/lib/esm/help-message/format-options.js.map +7 -1
  51. package/lib/esm/help-message/format-subcommands.js +37 -2
  52. package/lib/esm/help-message/format-subcommands.js.map +7 -1
  53. package/lib/esm/help-message/generate-for-cli.js +71 -2
  54. package/lib/esm/help-message/generate-for-cli.js.map +7 -1
  55. package/lib/esm/help-message/generate-for-subcommand.js +23 -2
  56. package/lib/esm/help-message/generate-for-subcommand.js.map +7 -1
  57. package/lib/esm/help-message/print-help.js +14 -2
  58. package/lib/esm/help-message/print-help.js.map +7 -1
  59. package/lib/esm/help-message/set-defaults.js +29 -2
  60. package/lib/esm/help-message/set-defaults.js.map +7 -1
  61. package/lib/esm/help-message/styles.js +154 -2
  62. package/lib/esm/help-message/styles.js.map +7 -1
  63. package/lib/esm/help-message/terminal-markdown.js +121 -2
  64. package/lib/esm/help-message/terminal-markdown.js.map +7 -1
  65. package/lib/esm/index.js +52 -2
  66. package/lib/esm/index.js.map +7 -1
  67. package/lib/esm/markdown/generate-markdown.js +153 -2
  68. package/lib/esm/markdown/generate-markdown.js.map +7 -1
  69. package/lib/esm/metadata/arguments-metadata.js +26 -2
  70. package/lib/esm/metadata/arguments-metadata.js.map +7 -1
  71. package/lib/esm/metadata/cli-metadata.js +24 -2
  72. package/lib/esm/metadata/cli-metadata.js.map +7 -1
  73. package/lib/esm/metadata/options-metadata.js +35 -2
  74. package/lib/esm/metadata/options-metadata.js.map +7 -1
  75. package/lib/esm/metadata/subcommands-metadata.js +32 -2
  76. package/lib/esm/metadata/subcommands-metadata.js.map +7 -1
  77. package/lib/esm/parse/context/cli-context-builder.js +283 -2
  78. package/lib/esm/parse/context/cli-context-builder.js.map +7 -1
  79. package/lib/esm/parse/context/object-context-builder.js +62 -2
  80. package/lib/esm/parse/context/object-context-builder.js.map +7 -1
  81. package/lib/esm/parse/parser-utilities.js +108 -2
  82. package/lib/esm/parse/parser-utilities.js.map +7 -1
  83. package/lib/esm/parse/safe-parse.js +57 -2
  84. package/lib/esm/parse/safe-parse.js.map +7 -1
  85. package/lib/esm/parse/validation/validate-context.js +17 -2
  86. package/lib/esm/parse/validation/validate-context.js.map +7 -1
  87. package/lib/esm/parse/validation/validators/arguments.js +67 -2
  88. package/lib/esm/parse/validation/validators/arguments.js.map +7 -1
  89. package/lib/esm/parse/validation/validators/conflict.js +38 -2
  90. package/lib/esm/parse/validation/validators/conflict.js.map +7 -1
  91. package/lib/esm/parse/validation/validators/exclusive.js +39 -2
  92. package/lib/esm/parse/validation/validators/exclusive.js.map +7 -1
  93. package/lib/esm/parse/validation/validators/explicitly-passed.js +18 -2
  94. package/lib/esm/parse/validation/validators/explicitly-passed.js.map +7 -1
  95. package/lib/esm/parse/validation/validators/options.js +67 -2
  96. package/lib/esm/parse/validation/validators/options.js.map +7 -1
  97. package/lib/esm/parse/validation/validators/requires.js +43 -2
  98. package/lib/esm/parse/validation/validators/requires.js.map +7 -1
  99. package/lib/esm/utilities/parse-argv.js +61 -0
  100. package/lib/esm/utilities/parse-argv.js.map +7 -0
  101. package/lib/esm/utilities/schema-utilities.js +57 -0
  102. package/lib/esm/utilities/schema-utilities.js.map +7 -0
  103. package/lib/esm/utilities/utilities.js +122 -0
  104. package/lib/esm/utilities/utilities.js.map +7 -0
  105. package/lib/iife/index.js +1 -1
  106. package/lib/iife/index.js.map +1 -1
  107. package/lib/mjs/autocomplete-scripts/bash-autocomplete-script.mjs +74 -2
  108. package/lib/mjs/autocomplete-scripts/bash-autocomplete-script.mjs.map +7 -1
  109. package/lib/mjs/autocomplete-scripts/powershell-autocomplete-script.mjs +90 -2
  110. package/lib/mjs/autocomplete-scripts/powershell-autocomplete-script.mjs.map +7 -1
  111. package/lib/mjs/autocomplete-scripts/zsh-autocomplete-script.mjs +39 -13
  112. package/lib/mjs/autocomplete-scripts/zsh-autocomplete-script.mjs.map +7 -1
  113. package/lib/mjs/cli-error/cli-error.mjs +38 -0
  114. package/lib/mjs/cli-error/cli-error.mjs.map +7 -0
  115. package/lib/mjs/cli-error/error-cause.mjs +12 -0
  116. package/lib/mjs/cli-error/error-cause.mjs.map +7 -0
  117. package/lib/mjs/cli-error/error-code/definition-error-code.mjs +23 -0
  118. package/lib/mjs/cli-error/error-code/definition-error-code.mjs.map +7 -0
  119. package/lib/mjs/cli-error/error-code/internal-error-code.mjs +10 -0
  120. package/lib/mjs/cli-error/error-code/internal-error-code.mjs.map +7 -0
  121. package/lib/mjs/cli-error/error-code/parse-error-code.mjs +18 -0
  122. package/lib/mjs/cli-error/error-code/parse-error-code.mjs.map +7 -0
  123. package/lib/mjs/cli-error/error-code/validation-error-code.mjs +17 -0
  124. package/lib/mjs/cli-error/error-code/validation-error-code.mjs.map +7 -0
  125. package/lib/mjs/cli-error/error-message/definition-error-message.mjs +70 -0
  126. package/lib/mjs/cli-error/error-message/definition-error-message.mjs.map +7 -0
  127. package/lib/mjs/cli-error/error-message/internal-error-message.mjs +16 -0
  128. package/lib/mjs/cli-error/error-message/internal-error-message.mjs.map +7 -0
  129. package/lib/mjs/cli-error/error-message/parse-error-message.mjs +40 -0
  130. package/lib/mjs/cli-error/error-message/parse-error-message.mjs.map +7 -0
  131. package/lib/mjs/cli-error/error-message/validation-error-message.mjs +60 -0
  132. package/lib/mjs/cli-error/error-message/validation-error-message.mjs.map +7 -0
  133. package/lib/mjs/coerce/coerce-methods.mjs +197 -2
  134. package/lib/mjs/coerce/coerce-methods.mjs.map +7 -1
  135. package/lib/mjs/coerce/string-to-array.mjs +17 -2
  136. package/lib/mjs/coerce/string-to-array.mjs.map +7 -1
  137. package/lib/mjs/coerce/string-to-primitive.mjs +73 -2
  138. package/lib/mjs/coerce/string-to-primitive.mjs.map +7 -1
  139. package/lib/mjs/coerce/string-to-set.mjs +17 -2
  140. package/lib/mjs/coerce/string-to-set.mjs.map +7 -1
  141. package/lib/mjs/definitions/define-arguments.mjs +10 -2
  142. package/lib/mjs/definitions/define-arguments.mjs.map +7 -1
  143. package/lib/mjs/definitions/define-cli.mjs +89 -2
  144. package/lib/mjs/definitions/define-cli.mjs.map +7 -1
  145. package/lib/mjs/definitions/define-options.mjs +10 -2
  146. package/lib/mjs/definitions/define-options.mjs.map +7 -1
  147. package/lib/mjs/definitions/define-subcommand.mjs +56 -2
  148. package/lib/mjs/definitions/define-subcommand.mjs.map +7 -1
  149. package/lib/mjs/definitions/validate-cli-definition.mjs +360 -2
  150. package/lib/mjs/definitions/validate-cli-definition.mjs.map +7 -1
  151. package/lib/mjs/help-message/format-arguments.mjs +48 -2
  152. package/lib/mjs/help-message/format-arguments.mjs.map +7 -1
  153. package/lib/mjs/help-message/format-options.mjs +50 -2
  154. package/lib/mjs/help-message/format-options.mjs.map +7 -1
  155. package/lib/mjs/help-message/format-subcommands.mjs +37 -2
  156. package/lib/mjs/help-message/format-subcommands.mjs.map +7 -1
  157. package/lib/mjs/help-message/generate-for-cli.mjs +71 -2
  158. package/lib/mjs/help-message/generate-for-cli.mjs.map +7 -1
  159. package/lib/mjs/help-message/generate-for-subcommand.mjs +23 -2
  160. package/lib/mjs/help-message/generate-for-subcommand.mjs.map +7 -1
  161. package/lib/mjs/help-message/print-help.mjs +14 -2
  162. package/lib/mjs/help-message/print-help.mjs.map +7 -1
  163. package/lib/mjs/help-message/set-defaults.mjs +29 -2
  164. package/lib/mjs/help-message/set-defaults.mjs.map +7 -1
  165. package/lib/mjs/help-message/styles.mjs +154 -2
  166. package/lib/mjs/help-message/styles.mjs.map +7 -1
  167. package/lib/mjs/help-message/terminal-markdown.mjs +121 -2
  168. package/lib/mjs/help-message/terminal-markdown.mjs.map +7 -1
  169. package/lib/mjs/index.mjs +52 -2
  170. package/lib/mjs/index.mjs.map +7 -1
  171. package/lib/mjs/markdown/generate-markdown.mjs +153 -2
  172. package/lib/mjs/markdown/generate-markdown.mjs.map +7 -1
  173. package/lib/mjs/metadata/arguments-metadata.mjs +26 -2
  174. package/lib/mjs/metadata/arguments-metadata.mjs.map +7 -1
  175. package/lib/mjs/metadata/cli-metadata.mjs +24 -2
  176. package/lib/mjs/metadata/cli-metadata.mjs.map +7 -1
  177. package/lib/mjs/metadata/options-metadata.mjs +35 -2
  178. package/lib/mjs/metadata/options-metadata.mjs.map +7 -1
  179. package/lib/mjs/metadata/subcommands-metadata.mjs +32 -2
  180. package/lib/mjs/metadata/subcommands-metadata.mjs.map +7 -1
  181. package/lib/mjs/parse/context/cli-context-builder.mjs +283 -2
  182. package/lib/mjs/parse/context/cli-context-builder.mjs.map +7 -1
  183. package/lib/mjs/parse/context/object-context-builder.mjs +62 -2
  184. package/lib/mjs/parse/context/object-context-builder.mjs.map +7 -1
  185. package/lib/mjs/parse/parser-utilities.mjs +108 -2
  186. package/lib/mjs/parse/parser-utilities.mjs.map +7 -1
  187. package/lib/mjs/parse/safe-parse.mjs +57 -2
  188. package/lib/mjs/parse/safe-parse.mjs.map +7 -1
  189. package/lib/mjs/parse/validation/validate-context.mjs +17 -2
  190. package/lib/mjs/parse/validation/validate-context.mjs.map +7 -1
  191. package/lib/mjs/parse/validation/validators/arguments.mjs +67 -2
  192. package/lib/mjs/parse/validation/validators/arguments.mjs.map +7 -1
  193. package/lib/mjs/parse/validation/validators/conflict.mjs +38 -2
  194. package/lib/mjs/parse/validation/validators/conflict.mjs.map +7 -1
  195. package/lib/mjs/parse/validation/validators/exclusive.mjs +39 -2
  196. package/lib/mjs/parse/validation/validators/exclusive.mjs.map +7 -1
  197. package/lib/mjs/parse/validation/validators/explicitly-passed.mjs +18 -2
  198. package/lib/mjs/parse/validation/validators/explicitly-passed.mjs.map +7 -1
  199. package/lib/mjs/parse/validation/validators/options.mjs +67 -2
  200. package/lib/mjs/parse/validation/validators/options.mjs.map +7 -1
  201. package/lib/mjs/parse/validation/validators/requires.mjs +43 -2
  202. package/lib/mjs/parse/validation/validators/requires.mjs.map +7 -1
  203. package/lib/mjs/utilities/parse-argv.mjs +61 -0
  204. package/lib/mjs/utilities/parse-argv.mjs.map +7 -0
  205. package/lib/mjs/utilities/schema-utilities.mjs +57 -0
  206. package/lib/mjs/utilities/schema-utilities.mjs.map +7 -0
  207. package/lib/mjs/utilities/utilities.mjs +122 -0
  208. package/lib/mjs/utilities/utilities.mjs.map +7 -0
  209. package/lib/{typescript → types}/autocomplete-scripts/bash-autocomplete-script.d.ts.map +1 -1
  210. package/lib/types/autocomplete-scripts/powershell-autocomplete-script.d.ts +15 -0
  211. package/lib/{typescript → types}/autocomplete-scripts/powershell-autocomplete-script.d.ts.map +1 -1
  212. package/lib/types/autocomplete-scripts/zsh-autocomplete-script.d.ts +4 -0
  213. package/lib/{typescript → types}/autocomplete-scripts/zsh-autocomplete-script.d.ts.map +1 -1
  214. package/lib/types/cli-error/cli-error.d.ts +152 -0
  215. package/lib/types/cli-error/cli-error.d.ts.map +1 -0
  216. package/lib/types/cli-error/error-cause.d.ts +5 -0
  217. package/lib/types/cli-error/error-cause.d.ts.map +1 -0
  218. package/lib/types/cli-error/error-code/definition-error-code.d.ts +5 -0
  219. package/lib/types/cli-error/error-code/definition-error-code.d.ts.map +1 -0
  220. package/lib/types/cli-error/error-code/internal-error-code.d.ts +5 -0
  221. package/lib/types/cli-error/error-code/internal-error-code.d.ts.map +1 -0
  222. package/lib/types/cli-error/error-code/parse-error-code.d.ts +5 -0
  223. package/lib/types/cli-error/error-code/parse-error-code.d.ts.map +1 -0
  224. package/lib/types/cli-error/error-code/validation-error-code.d.ts +5 -0
  225. package/lib/types/cli-error/error-code/validation-error-code.d.ts.map +1 -0
  226. package/lib/types/cli-error/error-message/definition-error-message.d.ts +3 -0
  227. package/lib/types/cli-error/error-message/definition-error-message.d.ts.map +1 -0
  228. package/lib/types/cli-error/error-message/internal-error-message.d.ts +3 -0
  229. package/lib/types/cli-error/error-message/internal-error-message.d.ts.map +1 -0
  230. package/lib/types/cli-error/error-message/parse-error-message.d.ts +3 -0
  231. package/lib/types/cli-error/error-message/parse-error-message.d.ts.map +1 -0
  232. package/lib/types/cli-error/error-message/validation-error-message.d.ts +3 -0
  233. package/lib/types/cli-error/error-message/validation-error-message.d.ts.map +1 -0
  234. package/lib/types/coerce/coerce-methods.d.ts +122 -0
  235. package/lib/types/coerce/coerce-methods.d.ts.map +1 -0
  236. package/lib/{typescript → types}/coerce/string-to-array.d.ts +2 -2
  237. package/lib/types/coerce/string-to-array.d.ts.map +1 -0
  238. package/lib/types/coerce/string-to-primitive.d.ts +21 -0
  239. package/lib/types/coerce/string-to-primitive.d.ts.map +1 -0
  240. package/lib/{typescript → types}/coerce/string-to-set.d.ts +2 -2
  241. package/lib/{typescript → types}/coerce/string-to-set.d.ts.map +1 -1
  242. package/lib/{typescript → types}/definitions/define-cli.d.ts +2 -6
  243. package/lib/types/definitions/define-cli.d.ts.map +1 -0
  244. package/lib/{typescript → types}/definitions/define-subcommand.d.ts +2 -4
  245. package/lib/types/definitions/define-subcommand.d.ts.map +1 -0
  246. package/lib/{typescript → types}/definitions/validate-cli-definition.d.ts +1 -1
  247. package/lib/types/definitions/validate-cli-definition.d.ts.map +1 -0
  248. package/lib/{typescript → types}/help-message/terminal-markdown.d.ts.map +1 -1
  249. package/lib/{typescript → types}/index.d.ts +7 -0
  250. package/lib/{typescript → types}/index.d.ts.map +1 -1
  251. package/lib/{typescript → types}/metadata/arguments-metadata.d.ts.map +1 -1
  252. package/lib/{typescript → types}/metadata/options-metadata.d.ts.map +1 -1
  253. package/lib/{typescript → types}/parse/context/cli-context-builder.d.ts +1 -1
  254. package/lib/{typescript → types}/parse/context/cli-context-builder.d.ts.map +1 -1
  255. package/lib/{typescript → types}/parse/context/object-context-builder.d.ts +1 -1
  256. package/lib/types/parse/context/object-context-builder.d.ts.map +1 -0
  257. package/lib/{typescript → types}/parse/parser-utilities.d.ts +9 -0
  258. package/lib/{typescript → types}/parse/parser-utilities.d.ts.map +1 -1
  259. package/lib/{typescript → types}/parse/safe-parse.d.ts.map +1 -1
  260. package/lib/{typescript → types}/parse/validation/validate-context.d.ts +1 -1
  261. package/lib/{typescript → types}/parse/validation/validate-context.d.ts.map +1 -1
  262. package/lib/{typescript → types}/parse/validation/validators/arguments.d.ts +1 -1
  263. package/lib/{typescript → types}/parse/validation/validators/arguments.d.ts.map +1 -1
  264. package/lib/{typescript → types}/parse/validation/validators/conflict.d.ts +3 -3
  265. package/lib/{typescript → types}/parse/validation/validators/conflict.d.ts.map +1 -1
  266. package/lib/{typescript → types}/parse/validation/validators/exclusive.d.ts +3 -3
  267. package/lib/{typescript → types}/parse/validation/validators/exclusive.d.ts.map +1 -1
  268. package/lib/{typescript → types}/parse/validation/validators/options.d.ts +1 -1
  269. package/lib/{typescript → types}/parse/validation/validators/options.d.ts.map +1 -1
  270. package/lib/{typescript → types}/parse/validation/validators/requires.d.ts +3 -3
  271. package/lib/{typescript → types}/parse/validation/validators/requires.d.ts.map +1 -1
  272. package/lib/{typescript → types}/types/definitions-types.d.ts +35 -4
  273. package/lib/types/types/definitions-types.d.ts.map +1 -0
  274. package/lib/types/types/error-types.d.ts +275 -0
  275. package/lib/types/types/error-types.d.ts.map +1 -0
  276. package/lib/types/types/types.d.ts +146 -0
  277. package/lib/types/types/types.d.ts.map +1 -0
  278. package/lib/{typescript → types}/types/utilities-types.d.ts +0 -2
  279. package/lib/{typescript → types}/types/utilities-types.d.ts.map +1 -1
  280. package/lib/types/utilities/parse-argv.d.ts +3 -0
  281. package/lib/types/utilities/parse-argv.d.ts.map +1 -0
  282. package/lib/types/utilities/schema-utilities.d.ts +15 -0
  283. package/lib/types/utilities/schema-utilities.d.ts.map +1 -0
  284. package/lib/{typescript → types/utilities}/utilities.d.ts +12 -15
  285. package/lib/types/utilities/utilities.d.ts.map +1 -0
  286. package/package.json +7 -7
  287. package/src/autocomplete-scripts/bash-autocomplete-script.ts +14 -12
  288. package/src/autocomplete-scripts/powershell-autocomplete-script.ts +67 -33
  289. package/src/autocomplete-scripts/zsh-autocomplete-script.ts +39 -31
  290. package/src/cli-error/cli-error.ts +44 -0
  291. package/src/cli-error/error-cause.ts +10 -0
  292. package/src/cli-error/error-code/definition-error-code.ts +21 -0
  293. package/src/cli-error/error-code/internal-error-code.ts +8 -0
  294. package/src/cli-error/error-code/parse-error-code.ts +16 -0
  295. package/src/cli-error/error-code/validation-error-code.ts +15 -0
  296. package/src/cli-error/error-message/definition-error-message.ts +144 -0
  297. package/src/cli-error/error-message/internal-error-message.ts +19 -0
  298. package/src/cli-error/error-message/parse-error-message.ts +76 -0
  299. package/src/cli-error/error-message/validation-error-message.ts +104 -0
  300. package/src/coerce/coerce-methods.ts +194 -39
  301. package/src/coerce/string-to-array.ts +2 -2
  302. package/src/coerce/string-to-primitive.ts +72 -13
  303. package/src/coerce/string-to-set.ts +2 -2
  304. package/src/definitions/define-arguments.ts +1 -1
  305. package/src/definitions/define-cli.ts +65 -30
  306. package/src/definitions/define-options.ts +1 -1
  307. package/src/definitions/define-subcommand.ts +47 -17
  308. package/src/definitions/validate-cli-definition.ts +287 -172
  309. package/src/help-message/format-arguments.ts +1 -1
  310. package/src/help-message/format-options.ts +1 -1
  311. package/src/help-message/format-subcommands.ts +1 -1
  312. package/src/help-message/generate-for-cli.ts +1 -1
  313. package/src/help-message/terminal-markdown.ts +3 -4
  314. package/src/index.ts +16 -0
  315. package/src/markdown/generate-markdown.ts +5 -4
  316. package/src/metadata/arguments-metadata.ts +2 -1
  317. package/src/metadata/options-metadata.ts +2 -1
  318. package/src/parse/context/cli-context-builder.ts +166 -39
  319. package/src/parse/context/object-context-builder.ts +37 -11
  320. package/src/parse/parser-utilities.ts +24 -10
  321. package/src/parse/safe-parse.ts +3 -6
  322. package/src/parse/validation/validate-context.ts +1 -1
  323. package/src/parse/validation/validators/arguments.ts +42 -14
  324. package/src/parse/validation/validators/conflict.ts +11 -20
  325. package/src/parse/validation/validators/exclusive.ts +16 -25
  326. package/src/parse/validation/validators/options.ts +40 -12
  327. package/src/parse/validation/validators/requires.ts +11 -20
  328. package/src/types/definitions-types.ts +36 -8
  329. package/src/types/error-types.ts +326 -0
  330. package/src/types/types.ts +100 -7
  331. package/src/types/utilities-types.ts +0 -10
  332. package/src/utilities/parse-argv.ts +79 -0
  333. package/src/utilities/schema-utilities.ts +72 -0
  334. package/src/{utilities.ts → utilities/utilities.ts} +25 -138
  335. package/lib/cjs/autocomplete-scripts/bash-autocomplete-script.cjs +0 -2
  336. package/lib/cjs/autocomplete-scripts/bash-autocomplete-script.cjs.map +0 -1
  337. package/lib/cjs/autocomplete-scripts/powershell-autocomplete-script.cjs +0 -2
  338. package/lib/cjs/autocomplete-scripts/powershell-autocomplete-script.cjs.map +0 -1
  339. package/lib/cjs/autocomplete-scripts/zsh-autocomplete-script.cjs +0 -42
  340. package/lib/cjs/autocomplete-scripts/zsh-autocomplete-script.cjs.map +0 -1
  341. package/lib/cjs/coerce/coerce-methods.cjs +0 -2
  342. package/lib/cjs/coerce/coerce-methods.cjs.map +0 -1
  343. package/lib/cjs/coerce/string-to-array.cjs +0 -2
  344. package/lib/cjs/coerce/string-to-array.cjs.map +0 -1
  345. package/lib/cjs/coerce/string-to-primitive.cjs +0 -2
  346. package/lib/cjs/coerce/string-to-primitive.cjs.map +0 -1
  347. package/lib/cjs/coerce/string-to-set.cjs +0 -2
  348. package/lib/cjs/coerce/string-to-set.cjs.map +0 -1
  349. package/lib/cjs/definitions/define-arguments.cjs +0 -2
  350. package/lib/cjs/definitions/define-arguments.cjs.map +0 -1
  351. package/lib/cjs/definitions/define-cli.cjs +0 -2
  352. package/lib/cjs/definitions/define-cli.cjs.map +0 -1
  353. package/lib/cjs/definitions/define-options.cjs +0 -2
  354. package/lib/cjs/definitions/define-options.cjs.map +0 -1
  355. package/lib/cjs/definitions/define-subcommand.cjs +0 -2
  356. package/lib/cjs/definitions/define-subcommand.cjs.map +0 -1
  357. package/lib/cjs/definitions/validate-cli-definition.cjs +0 -2
  358. package/lib/cjs/definitions/validate-cli-definition.cjs.map +0 -1
  359. package/lib/cjs/help-message/format-arguments.cjs +0 -2
  360. package/lib/cjs/help-message/format-arguments.cjs.map +0 -1
  361. package/lib/cjs/help-message/format-options.cjs +0 -2
  362. package/lib/cjs/help-message/format-options.cjs.map +0 -1
  363. package/lib/cjs/help-message/format-subcommands.cjs +0 -2
  364. package/lib/cjs/help-message/format-subcommands.cjs.map +0 -1
  365. package/lib/cjs/help-message/generate-for-cli.cjs +0 -2
  366. package/lib/cjs/help-message/generate-for-cli.cjs.map +0 -1
  367. package/lib/cjs/help-message/generate-for-subcommand.cjs +0 -2
  368. package/lib/cjs/help-message/generate-for-subcommand.cjs.map +0 -1
  369. package/lib/cjs/help-message/print-help.cjs +0 -2
  370. package/lib/cjs/help-message/print-help.cjs.map +0 -1
  371. package/lib/cjs/help-message/set-defaults.cjs +0 -2
  372. package/lib/cjs/help-message/set-defaults.cjs.map +0 -1
  373. package/lib/cjs/help-message/styles.cjs +0 -2
  374. package/lib/cjs/help-message/styles.cjs.map +0 -1
  375. package/lib/cjs/help-message/terminal-markdown.cjs +0 -2
  376. package/lib/cjs/help-message/terminal-markdown.cjs.map +0 -1
  377. package/lib/cjs/index.cjs +0 -2
  378. package/lib/cjs/index.cjs.map +0 -1
  379. package/lib/cjs/markdown/generate-markdown.cjs +0 -2
  380. package/lib/cjs/markdown/generate-markdown.cjs.map +0 -1
  381. package/lib/cjs/metadata/arguments-metadata.cjs +0 -2
  382. package/lib/cjs/metadata/arguments-metadata.cjs.map +0 -1
  383. package/lib/cjs/metadata/cli-metadata.cjs +0 -2
  384. package/lib/cjs/metadata/cli-metadata.cjs.map +0 -1
  385. package/lib/cjs/metadata/options-metadata.cjs +0 -2
  386. package/lib/cjs/metadata/options-metadata.cjs.map +0 -1
  387. package/lib/cjs/metadata/subcommands-metadata.cjs +0 -2
  388. package/lib/cjs/metadata/subcommands-metadata.cjs.map +0 -1
  389. package/lib/cjs/parse/context/cli-context-builder.cjs +0 -2
  390. package/lib/cjs/parse/context/cli-context-builder.cjs.map +0 -1
  391. package/lib/cjs/parse/context/object-context-builder.cjs +0 -2
  392. package/lib/cjs/parse/context/object-context-builder.cjs.map +0 -1
  393. package/lib/cjs/parse/parser-utilities.cjs +0 -2
  394. package/lib/cjs/parse/parser-utilities.cjs.map +0 -1
  395. package/lib/cjs/parse/safe-parse.cjs +0 -2
  396. package/lib/cjs/parse/safe-parse.cjs.map +0 -1
  397. package/lib/cjs/parse/validation/validate-context.cjs +0 -2
  398. package/lib/cjs/parse/validation/validate-context.cjs.map +0 -1
  399. package/lib/cjs/parse/validation/validators/arguments.cjs +0 -2
  400. package/lib/cjs/parse/validation/validators/arguments.cjs.map +0 -1
  401. package/lib/cjs/parse/validation/validators/conflict.cjs +0 -2
  402. package/lib/cjs/parse/validation/validators/conflict.cjs.map +0 -1
  403. package/lib/cjs/parse/validation/validators/exclusive.cjs +0 -2
  404. package/lib/cjs/parse/validation/validators/exclusive.cjs.map +0 -1
  405. package/lib/cjs/parse/validation/validators/explicitly-passed.cjs +0 -2
  406. package/lib/cjs/parse/validation/validators/explicitly-passed.cjs.map +0 -1
  407. package/lib/cjs/parse/validation/validators/options.cjs +0 -2
  408. package/lib/cjs/parse/validation/validators/options.cjs.map +0 -1
  409. package/lib/cjs/parse/validation/validators/requires.cjs +0 -2
  410. package/lib/cjs/parse/validation/validators/requires.cjs.map +0 -1
  411. package/lib/cjs/utilities.cjs +0 -2
  412. package/lib/cjs/utilities.cjs.map +0 -1
  413. package/lib/esm/utilities.js +0 -2
  414. package/lib/esm/utilities.js.map +0 -1
  415. package/lib/mjs/utilities.mjs +0 -2
  416. package/lib/mjs/utilities.mjs.map +0 -1
  417. package/lib/typescript/autocomplete-scripts/powershell-autocomplete-script.d.ts +0 -14
  418. package/lib/typescript/autocomplete-scripts/zsh-autocomplete-script.d.ts +0 -11
  419. package/lib/typescript/coerce/coerce-methods.d.ts +0 -20
  420. package/lib/typescript/coerce/coerce-methods.d.ts.map +0 -1
  421. package/lib/typescript/coerce/string-to-array.d.ts.map +0 -1
  422. package/lib/typescript/coerce/string-to-primitive.d.ts +0 -5
  423. package/lib/typescript/coerce/string-to-primitive.d.ts.map +0 -1
  424. package/lib/typescript/definitions/define-cli.d.ts.map +0 -1
  425. package/lib/typescript/definitions/define-subcommand.d.ts.map +0 -1
  426. package/lib/typescript/definitions/validate-cli-definition.d.ts.map +0 -1
  427. package/lib/typescript/parse/context/object-context-builder.d.ts.map +0 -1
  428. package/lib/typescript/types/definitions-types.d.ts.map +0 -1
  429. package/lib/typescript/types/types.d.ts +0 -61
  430. package/lib/typescript/types/types.d.ts.map +0 -1
  431. package/lib/typescript/utilities.d.ts.map +0 -1
  432. /package/lib/{typescript → types}/autocomplete-scripts/bash-autocomplete-script.d.ts +0 -0
  433. /package/lib/{typescript → types}/definitions/define-arguments.d.ts +0 -0
  434. /package/lib/{typescript → types}/definitions/define-arguments.d.ts.map +0 -0
  435. /package/lib/{typescript → types}/definitions/define-options.d.ts +0 -0
  436. /package/lib/{typescript → types}/definitions/define-options.d.ts.map +0 -0
  437. /package/lib/{typescript → types}/help-message/format-arguments.d.ts +0 -0
  438. /package/lib/{typescript → types}/help-message/format-arguments.d.ts.map +0 -0
  439. /package/lib/{typescript → types}/help-message/format-options.d.ts +0 -0
  440. /package/lib/{typescript → types}/help-message/format-options.d.ts.map +0 -0
  441. /package/lib/{typescript → types}/help-message/format-subcommands.d.ts +0 -0
  442. /package/lib/{typescript → types}/help-message/format-subcommands.d.ts.map +0 -0
  443. /package/lib/{typescript → types}/help-message/generate-for-cli.d.ts +0 -0
  444. /package/lib/{typescript → types}/help-message/generate-for-cli.d.ts.map +0 -0
  445. /package/lib/{typescript → types}/help-message/generate-for-subcommand.d.ts +0 -0
  446. /package/lib/{typescript → types}/help-message/generate-for-subcommand.d.ts.map +0 -0
  447. /package/lib/{typescript → types}/help-message/print-help.d.ts +0 -0
  448. /package/lib/{typescript → types}/help-message/print-help.d.ts.map +0 -0
  449. /package/lib/{typescript → types}/help-message/set-defaults.d.ts +0 -0
  450. /package/lib/{typescript → types}/help-message/set-defaults.d.ts.map +0 -0
  451. /package/lib/{typescript → types}/help-message/styles.d.ts +0 -0
  452. /package/lib/{typescript → types}/help-message/styles.d.ts.map +0 -0
  453. /package/lib/{typescript → types}/help-message/terminal-markdown.d.ts +0 -0
  454. /package/lib/{typescript → types}/markdown/generate-markdown.d.ts +0 -0
  455. /package/lib/{typescript → types}/markdown/generate-markdown.d.ts.map +0 -0
  456. /package/lib/{typescript → types}/metadata/arguments-metadata.d.ts +0 -0
  457. /package/lib/{typescript → types}/metadata/cli-metadata.d.ts +0 -0
  458. /package/lib/{typescript → types}/metadata/cli-metadata.d.ts.map +0 -0
  459. /package/lib/{typescript → types}/metadata/options-metadata.d.ts +0 -0
  460. /package/lib/{typescript → types}/metadata/subcommands-metadata.d.ts +0 -0
  461. /package/lib/{typescript → types}/metadata/subcommands-metadata.d.ts.map +0 -0
  462. /package/lib/{typescript → types}/parse/safe-parse.d.ts +0 -0
  463. /package/lib/{typescript → types}/parse/validation/validators/explicitly-passed.d.ts +0 -0
  464. /package/lib/{typescript → types}/parse/validation/validators/explicitly-passed.d.ts.map +0 -0
  465. /package/lib/{typescript → types}/types/context-types.d.ts +0 -0
  466. /package/lib/{typescript → types}/types/context-types.d.ts.map +0 -0
  467. /package/lib/{typescript → types}/types/help-message-types.d.ts +0 -0
  468. /package/lib/{typescript → types}/types/help-message-types.d.ts.map +0 -0
  469. /package/lib/{typescript → types}/types/io-types.d.ts +0 -0
  470. /package/lib/{typescript → types}/types/io-types.d.ts.map +0 -0
  471. /package/lib/{typescript → types}/types/metadata-types.d.ts +0 -0
  472. /package/lib/{typescript → types}/types/metadata-types.d.ts.map +0 -0
  473. /package/lib/{typescript → types}/types/schema-types.d.ts +0 -0
  474. /package/lib/{typescript → types}/types/schema-types.d.ts.map +0 -0
package/src/index.ts CHANGED
@@ -20,8 +20,24 @@ export { defineSubcommand } from "./definitions/define-subcommand.ts";
20
20
 
21
21
  export { coerce } from "./coerce/coerce-methods.ts";
22
22
 
23
+ export { CliError } from "./cli-error/cli-error.ts";
24
+ export { ErrorCause } from "./cli-error/error-cause.ts";
25
+ export { DefinitionErrorCode } from "./cli-error/error-code/definition-error-code.ts";
26
+ export { InternalErrorCode } from "./cli-error/error-code/internal-error-code.ts";
27
+ export { ParseErrorCode } from "./cli-error/error-code/parse-error-code.ts";
28
+ export { ValidationErrorCode } from "./cli-error/error-code/validation-error-code.ts";
29
+
23
30
  export type * from "./types/context-types.ts";
24
31
  export type * from "./types/definitions-types.ts";
32
+ export type {
33
+ CliErrorI,
34
+ CliErrorOptionUnion,
35
+ DefinitionErrorI,
36
+ ErrorCauseI,
37
+ InternalErrorI,
38
+ ParseErrorI,
39
+ ValidationErrorI,
40
+ } from "./types/error-types.ts";
25
41
  export type * from "./types/help-message-types.ts";
26
42
  export type * from "./types/io-types.ts";
27
43
  export type * from "./types/metadata-types.ts";
@@ -1,5 +1,5 @@
1
1
  import { getCliMetadata } from "../metadata/cli-metadata.ts";
2
- import { escapeHtmlTags, stripAnsi } from "../utilities.ts";
2
+ import { escapeHtmlTags, stripAnsi } from "../utilities/utilities.ts";
3
3
 
4
4
  import type { Cli } from "../types/definitions-types.ts";
5
5
  import type { ArgumentMetadata, OptionMetadata, SubcommandMetadata } from "../types/metadata-types.ts";
@@ -72,7 +72,6 @@ function renderOptions(optionsMetadata: OptionMetadata[] = [], h: number) {
72
72
  if (metadata.hidden) continue;
73
73
 
74
74
  const aliases = [metadata.nameAsArg].concat(metadata.aliasesAsArgs).join(", ");
75
-
76
75
  const placeholder = metadata.placeholder && ` ${metadata.placeholder}`;
77
76
 
78
77
  outString += `${"#".repeat(h)} \`${aliases + placeholder}\``;
@@ -92,7 +91,8 @@ function renderOptions(optionsMetadata: OptionMetadata[] = [], h: number) {
92
91
  }
93
92
 
94
93
  if (metadata.defaultValue !== undefined) {
95
- outString += `\n**default:** \`${metadata.defaultValueAsString}\`\n`;
94
+ const nl = outString.endsWith("\n\n") ? "" : "\n";
95
+ outString += `${nl}**default:** \`${metadata.defaultValueAsString}\`\n`;
96
96
  }
97
97
 
98
98
  if (metadata.example) {
@@ -131,7 +131,8 @@ function renderArguments(argumentsMetadata: ArgumentMetadata[] = [], h: number)
131
131
  }
132
132
 
133
133
  if (metadata.defaultValue !== undefined) {
134
- outString += `\n**default:** \`${metadata.defaultValueAsString}\`\n`;
134
+ const nl = outString.endsWith("\n\n") ? "" : "\n";
135
+ outString += `${nl}**default:** \`${metadata.defaultValueAsString}\`\n`;
135
136
  }
136
137
 
137
138
  if (metadata.example) {
@@ -1,4 +1,5 @@
1
- import { defaultValueAndIsOptional, stringifyValue } from "../utilities.ts";
1
+ import { defaultValueAndIsOptional } from "../utilities/schema-utilities.ts";
2
+ import { stringifyValue } from "../utilities/utilities.ts";
2
3
 
3
4
  import type { Argument } from "../types/definitions-types.ts";
4
5
  import type { ArgumentMetadata } from "../types/metadata-types.ts";
@@ -1,5 +1,6 @@
1
1
  import { transformOptionToArgument } from "../parse/parser-utilities.ts";
2
- import { defaultValueAndIsOptional, stringifyValue } from "../utilities.ts";
2
+ import { defaultValueAndIsOptional } from "../utilities/schema-utilities.ts";
3
+ import { stringifyValue } from "../utilities/utilities.ts";
3
4
 
4
5
  import type { Option } from "../types/definitions-types.ts";
5
6
  import type { OptionMetadata } from "../types/metadata-types.ts";
@@ -1,10 +1,14 @@
1
+ import { CliError } from "../../cli-error/cli-error.ts";
2
+ import { ErrorCause } from "../../cli-error/error-cause.ts";
3
+ import { InternalErrorCode } from "../../cli-error/error-code/internal-error-code.ts";
4
+ import { ParseErrorCode } from "../../cli-error/error-code/parse-error-code.ts";
1
5
  import {
2
6
  decoupleFlags,
3
7
  findOption,
4
8
  findSubcommandDefinition,
5
9
  isFlagArgument,
6
10
  isOptionArgument,
7
- transformOptionToArgument,
11
+ splitAndGetKeys,
8
12
  } from "../parser-utilities.ts";
9
13
 
10
14
  import type { ContextWide } from "../../types/context-types.ts";
@@ -13,9 +17,10 @@ import type { Cli } from "../../types/definitions-types.ts";
13
17
  /**
14
18
  * Parse argv and create a cli context
15
19
  *
16
- * @throws {Error}
20
+ * @throws {CliError}
17
21
  */
18
22
  export function buildCliContext(argv: string[], cliDefinition: Cli) {
23
+ const cliName = cliDefinition.cliName;
19
24
  const subcommandArray = cliDefinition.subcommands ?? [];
20
25
  const allSubcommands = new Set<string>(subcommandArray.flatMap(c => [c.name, ...(c.aliases || [])]));
21
26
 
@@ -44,70 +49,136 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
44
49
 
45
50
  const argumentAndValue = argvItem.split("=").filter(Boolean); // E.g --option=value -> ["--option", "value"]
46
51
  const argumentWithEquals = argvItem.includes("="); // E.g --option=value
47
- const argument = argumentAndValue[0];
52
+ const [argument, keys] = splitAndGetKeys(argumentAndValue[0]); // E.g --option.foo.bar -> ["--option", ["foo", "bar"]]
53
+ const optionWithKeys = keys.length > 0; // E.g --option.foo.bar
48
54
  const argumentValue: string | undefined = argumentAndValue[1];
55
+ const isNegated = argument.startsWith("--no-");
49
56
 
50
57
  if (isOptionArgument(argument)) {
58
+ const commandDefinition = getCommandDefinition();
59
+ const commandKind = context.subcommand === undefined ? "command" : "subcommand";
60
+ const commandName = context.subcommand ?? cliName;
61
+
51
62
  if (isFlagArgument(argument) && argumentWithEquals) {
52
- throw new Error(`flag arguments cannot be assigned using "=": "${argvItem}"`);
63
+ throw new CliError({
64
+ cause: ErrorCause.Parse,
65
+ code: ParseErrorCode.FlagAssignedValue,
66
+ context: { commandKind, commandName, flag: argument, value: argumentValue },
67
+ });
53
68
  }
54
69
 
55
- const commandDefinition = getCommandDefinition();
56
70
  if (!commandDefinition) {
57
- throw new Error(`unknown subcommand: "${context.subcommand}"`);
71
+ if (context.subcommand === undefined) {
72
+ throw new CliError({
73
+ cause: ErrorCause.Internal,
74
+ code: InternalErrorCode.CannotFindCliDefinition,
75
+ context: { cliName },
76
+ });
77
+ }
78
+
79
+ throw new CliError({
80
+ cause: ErrorCause.Parse,
81
+ code: ParseErrorCode.UnknownSubcommand,
82
+ context: { commandName },
83
+ });
58
84
  }
59
85
 
60
86
  if (!commandDefinition.options) {
61
- if (!context.subcommand) {
62
- throw new Error(`options are not allowed here: "${argument}"`);
63
- }
64
-
65
- throw new Error(`subcommand "${context.subcommand}" does not accept options: "${argument}"`);
87
+ throw new CliError({
88
+ cause: ErrorCause.Parse,
89
+ code: ParseErrorCode.CommandWithoutOptions,
90
+ context: { commandKind, commandName, optionName: argument },
91
+ });
66
92
  }
67
93
 
68
94
  const nameOptionTuple = findOption(argument, commandDefinition.options);
69
95
  if (!nameOptionTuple) {
70
- throw new Error(`unknown option: "${argument}"`);
96
+ throw new CliError({
97
+ cause: ErrorCause.Parse,
98
+ code: ParseErrorCode.UnknownOption,
99
+ context: { commandKind, commandName, optionName: argument },
100
+ });
71
101
  }
72
102
 
73
103
  const [optionName, optionDefinition] = nameOptionTuple;
74
104
 
75
- if (context.options && optionName in context.options) {
76
- throw new Error(`duplicated option: "${argument}"`);
105
+ if (!optionWithKeys && context.options && optionName in context.options) {
106
+ throw new CliError({
107
+ cause: ErrorCause.Parse,
108
+ code: ParseErrorCode.DuplicateOptionProvided,
109
+ context: { commandKind, commandName, optionName },
110
+ });
77
111
  }
78
112
 
79
113
  if (!optionDefinition._preparedType) {
80
- throw new Error(`internal error: missing prepared type for option "${optionName}"`);
114
+ throw new CliError({
115
+ cause: ErrorCause.Internal,
116
+ code: InternalErrorCode.MissingPreparedTypes,
117
+ context: { commandKind, commandName, kind: "option", name: optionName },
118
+ });
81
119
  }
82
120
 
83
121
  const { schema, optional, defaultValue, coerceTo } = optionDefinition._preparedType;
84
122
 
85
123
  const nextArgument = argv[index + 1];
86
124
 
87
- let optionValue: string | boolean = argumentWithEquals ? argumentValue : nextArgument;
125
+ let optionValue: string | boolean | undefined = argumentWithEquals ? argumentValue : nextArgument;
126
+
127
+ const isBoolean = coerceTo === "boolean";
128
+
129
+ if (isNegated && !isBoolean) {
130
+ throw new CliError({
131
+ cause: ErrorCause.Parse,
132
+ code: ParseErrorCode.InvalidNegationForNonBooleanOption,
133
+ context: { commandKind, commandName, optionName },
134
+ });
135
+ }
88
136
 
89
137
  // infer value for boolean options
90
- if (coerceTo === "boolean") {
138
+ if (isBoolean) {
91
139
  if (!argumentWithEquals) {
92
140
  optionValue = "true";
93
141
  }
94
142
 
95
- const isNegated = argument.startsWith("--no-");
96
-
97
143
  if (isNegated && ["true", "false"].includes(optionValue.toLowerCase())) {
98
144
  optionValue = optionValue === "true" ? "false" : "true";
99
145
  }
100
146
  }
101
147
 
102
- if (optionValue === undefined) {
103
- throw new Error(`expected a value for "${argument}" but got nothing`);
148
+ if (optionValue === undefined || (!argumentWithEquals && isOptionArgument(optionValue))) {
149
+ throw new CliError({
150
+ cause: ErrorCause.Parse,
151
+ code: ParseErrorCode.OptionMissingValue,
152
+ context: { commandKind, commandName, optionName },
153
+ });
104
154
  }
105
155
 
106
- if (!argumentWithEquals && isOptionArgument(optionValue)) {
107
- throw new Error(`expected a value for "${argument}" but got an argument "${nextArgument}"`);
156
+ context.options ??= {};
157
+
158
+ // Handle options with keys for type `object`
159
+ // E.g. `--option.key.nested=value`
160
+ if (optionWithKeys) {
161
+ const previousObject = JSON.parse(context.options[optionName]?.stringValue || "{}") as Record<string, any>;
162
+
163
+ let current = previousObject;
164
+ for (let index = 0; index < keys.length; index++) {
165
+ const key = keys[index];
166
+
167
+ if (current[key] === undefined) {
168
+ current[key] = {};
169
+ }
170
+
171
+ if (index === keys.length - 1) {
172
+ current[key] = optionValue;
173
+ continue;
174
+ }
175
+
176
+ current = current[key] as Record<string, any>;
177
+ }
178
+
179
+ optionValue = JSON.stringify(previousObject);
108
180
  }
109
181
 
110
- context.options ??= {};
111
182
  context.options[optionName] = {
112
183
  schema,
113
184
  optional,
@@ -118,7 +189,7 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
118
189
  };
119
190
 
120
191
  // Skip to the next argument if it is the current option's value.
121
- if (!argumentWithEquals && coerceTo !== "boolean") {
192
+ if (!argumentWithEquals && !isBoolean) {
122
193
  index++;
123
194
  }
124
195
 
@@ -139,7 +210,16 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
139
210
  const [name, argumentDefinition] = argumentDefinitionEntries[currentArgumentCount];
140
211
 
141
212
  if (!argumentDefinition._preparedType) {
142
- throw new Error(`internal error: missing prepared type for argument "${currentArgumentCount}"`);
213
+ throw new CliError({
214
+ cause: ErrorCause.Internal,
215
+ code: InternalErrorCode.MissingPreparedTypes,
216
+ context: {
217
+ commandKind: context.subcommand ? "subcommand" : "command",
218
+ commandName: context.subcommand ?? cliName,
219
+ kind: "argument",
220
+ name,
221
+ },
222
+ });
143
223
  }
144
224
 
145
225
  const { schema, optional, defaultValue } = argumentDefinition._preparedType;
@@ -156,18 +236,32 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
156
236
  continue;
157
237
  }
158
238
 
159
- if (!context.subcommand) {
160
- throw new Error(`unexpected argument "${argvItem}": positionals arguments are not allowed here`);
161
- }
162
-
163
- throw new Error(
164
- `unexpected argument "${argvItem}": positionals arguments are not allowed for subcommand "${context.subcommand}"`,
165
- );
239
+ throw new CliError({
240
+ cause: ErrorCause.Parse,
241
+ code: ParseErrorCode.PositionalArgumentNotAllowed,
242
+ context: {
243
+ commandKind: context.subcommand ? "subcommand" : "command",
244
+ commandName: context.subcommand ?? cliName,
245
+ argumentName: argvItem,
246
+ },
247
+ });
166
248
  }
167
249
 
168
250
  const commandDefinition = getCommandDefinition();
169
251
  if (!commandDefinition) {
170
- throw new Error(`unknown subcommand: "${context.subcommand}"`);
252
+ if (context.subcommand === undefined) {
253
+ throw new CliError({
254
+ cause: ErrorCause.Internal,
255
+ code: InternalErrorCode.CannotFindCliDefinition,
256
+ context: { cliName },
257
+ });
258
+ }
259
+
260
+ throw new CliError({
261
+ cause: ErrorCause.Parse,
262
+ code: ParseErrorCode.UnknownSubcommand,
263
+ context: { commandName: context.subcommand ?? cliName },
264
+ });
171
265
  }
172
266
 
173
267
  // Options
@@ -179,7 +273,16 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
179
273
  if (name in context.options) continue;
180
274
 
181
275
  if (!optionDefinition._preparedType) {
182
- throw new Error(`internal error: missing prepared type for option "${name}"`);
276
+ throw new CliError({
277
+ cause: ErrorCause.Internal,
278
+ code: InternalErrorCode.MissingPreparedTypes,
279
+ context: {
280
+ commandKind: context.subcommand ? "subcommand" : "command",
281
+ commandName: context.subcommand ?? cliName,
282
+ kind: "option",
283
+ name,
284
+ },
285
+ });
183
286
  }
184
287
 
185
288
  const { schema, optional, defaultValue } = optionDefinition._preparedType;
@@ -195,8 +298,15 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
195
298
  continue;
196
299
  }
197
300
 
198
- // required option
199
- throw new Error(`missing required option: ${transformOptionToArgument(name)}`);
301
+ throw new CliError({
302
+ cause: ErrorCause.Parse,
303
+ code: ParseErrorCode.MissingRequiredOption,
304
+ context: {
305
+ commandKind: context.subcommand ? "subcommand" : "command",
306
+ commandName: context.subcommand ?? cliName,
307
+ optionName: name,
308
+ },
309
+ });
200
310
  }
201
311
  }
202
312
 
@@ -215,7 +325,16 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
215
325
  const [name, argumentDefinition] = argumentDefinitionEntries[index];
216
326
 
217
327
  if (!argumentDefinition._preparedType) {
218
- throw new Error(`internal error: missing prepared type for the argument "${name}"`);
328
+ throw new CliError({
329
+ cause: ErrorCause.Internal,
330
+ code: InternalErrorCode.MissingPreparedTypes,
331
+ context: {
332
+ commandKind: context.subcommand ? "subcommand" : "command",
333
+ commandName: context.subcommand ?? cliName,
334
+ kind: "argument",
335
+ name,
336
+ },
337
+ });
219
338
  }
220
339
 
221
340
  const { schema, optional, defaultValue } = argumentDefinition._preparedType;
@@ -232,7 +351,15 @@ export function buildCliContext(argv: string[], cliDefinition: Cli) {
232
351
  }
233
352
 
234
353
  // required argument
235
- throw new Error(`The argument "${name}" is required`);
354
+ throw new CliError({
355
+ cause: ErrorCause.Parse,
356
+ code: ParseErrorCode.MissingRequiredArgument,
357
+ context: {
358
+ commandKind: context.subcommand ? "subcommand" : "command",
359
+ commandName: context.subcommand ?? cliName,
360
+ argumentName: name,
361
+ },
362
+ });
236
363
  }
237
364
  }
238
365
  }
@@ -1,20 +1,21 @@
1
+ import { CliError } from "../../cli-error/cli-error.ts";
2
+ import { ErrorCause } from "../../cli-error/error-cause.ts";
3
+ import { InternalErrorCode } from "../../cli-error/error-code/internal-error-code.ts";
4
+ import { ParseErrorCode } from "../../cli-error/error-code/parse-error-code.ts";
5
+
1
6
  import type { ContextWide } from "../../types/context-types.ts";
2
7
  import type { Argument, Cli, Option, Subcommand } from "../../types/definitions-types.ts";
3
8
  import type { InputTypeWide } from "../../types/io-types.ts";
4
9
 
5
- /** @throws {Error} */
10
+ /** @throws {CliError} */
6
11
  export function buildObjectContext(inputValues: InputTypeWide, commandDefinition: Subcommand | Cli) {
7
12
  const context: ContextWide = {
8
13
  subcommand: "cliName" in commandDefinition ? undefined : commandDefinition.name,
9
14
  };
10
15
 
11
- if (commandDefinition.options) {
12
- buildForOptionsOrArguments(commandDefinition.options, context, inputValues.options, "options");
13
- }
16
+ buildForOptionsOrArguments(commandDefinition, context, inputValues.options, "options");
14
17
 
15
- if (commandDefinition.arguments) {
16
- buildForOptionsOrArguments(commandDefinition.arguments, context, inputValues.arguments, "arguments");
17
- }
18
+ buildForOptionsOrArguments(commandDefinition, context, inputValues.arguments, "arguments");
18
19
 
19
20
  if (commandDefinition.allowPositionals) {
20
21
  context.positionals ??= inputValues.positionals;
@@ -24,16 +25,27 @@ export function buildObjectContext(inputValues: InputTypeWide, commandDefinition
24
25
  }
25
26
 
26
27
  function buildForOptionsOrArguments(
27
- definitionRecord: Record<string, Option> | Record<string, Argument>,
28
+ commandDefinition: Subcommand | Cli,
28
29
  context: ContextWide,
29
30
  inputRecord: Record<string, unknown> | undefined,
30
31
  type: "options" | "arguments",
31
32
  ) {
32
- const definitionEntries = Object.entries(definitionRecord) as [string, Option][] | [string, Argument][];
33
+ if (!commandDefinition[type]) return;
34
+
35
+ const optionOrArgumentDefinitions = commandDefinition[type];
36
+ const kind = type.slice(0, -1) as "option" | "argument";
37
+ const commandKind = "cliName" in commandDefinition ? "command" : "subcommand";
38
+ const commandName = "cliName" in commandDefinition ? commandDefinition.cliName : commandDefinition.name;
39
+
40
+ const definitionEntries = Object.entries(optionOrArgumentDefinitions) as [string, Option][] | [string, Argument][];
33
41
 
34
42
  for (const [name, definition] of definitionEntries) {
35
43
  if (!definition._preparedType) {
36
- throw new Error(`internal error: missing prepared type for ${type.slice(0, -1)} "${name}"`);
44
+ throw new CliError({
45
+ cause: ErrorCause.Internal,
46
+ code: InternalErrorCode.MissingPreparedTypes,
47
+ context: { commandKind, commandName, kind, name },
48
+ });
37
49
  }
38
50
 
39
51
  const { schema, optional, defaultValue } = definition._preparedType;
@@ -53,7 +65,21 @@ function buildForOptionsOrArguments(
53
65
 
54
66
  // case the value is not passed
55
67
  if (!optional) {
56
- throw new Error(`the ${type.slice(0, -1)} "${name}" is required`);
68
+ if (kind === "option") {
69
+ throw new CliError({
70
+ cause: ErrorCause.Parse,
71
+ code: ParseErrorCode.MissingRequiredOption,
72
+ context: { commandKind, commandName, optionName: name },
73
+ });
74
+ }
75
+
76
+ if (kind === "argument") {
77
+ throw new CliError({
78
+ cause: ErrorCause.Parse,
79
+ code: ParseErrorCode.MissingRequiredArgument,
80
+ context: { commandKind, commandName, argumentName: name },
81
+ });
82
+ }
57
83
  }
58
84
 
59
85
  // case the value is optional
@@ -49,9 +49,7 @@ export function findOption(optionArgument: string, options: Record<string, Optio
49
49
  return true;
50
50
  }
51
51
 
52
- const isBool = option._preparedType && option._preparedType.coerceTo === "boolean";
53
-
54
- if (isNegated && isBool && validVariableNames.has(negateOption(optionName))) {
52
+ if (isNegated && validVariableNames.has(negateOption(optionName))) {
55
53
  return true;
56
54
  }
57
55
 
@@ -63,7 +61,7 @@ export function findOption(optionArgument: string, options: Record<string, Optio
63
61
  return true;
64
62
  }
65
63
 
66
- if (isNegated && isBool && option.aliases.map(alias => negateOption(alias)).some(a => validVariableNames.has(a))) {
64
+ if (isNegated && option.aliases.map(alias => negateOption(alias)).some(a => validVariableNames.has(a))) {
67
65
  return true;
68
66
  }
69
67
 
@@ -110,10 +108,6 @@ export function decoupleFlags(arguments_: string[]): string[] {
110
108
  * @param name - Should start with `'--'` or `'-'`
111
109
  */
112
110
  export function optionArgumentToVariableNames(name: string): Set<string> {
113
- if (!name.startsWith("-")) {
114
- throw new Error(`invalid option name: ${name}`);
115
- }
116
-
117
111
  name = name.startsWith("--") ? name.slice(2) : name.slice(1); // remove prefix
118
112
  name = name.toLowerCase(); // lowercase
119
113
 
@@ -141,9 +135,14 @@ export function isFlagArgument(name: string): boolean {
141
135
  return /^-[A-Za-z]$/.test(name);
142
136
  }
143
137
 
144
- /** - Check if an arg string is a long arg. E.g. `--input-dir` -> `true` */
138
+ /**
139
+ * - Check if an arg string is a long arg.
140
+ * - `--input-dir` -> `true`
141
+ * - `-h` -> `false`
142
+ * - `--db.https` -> `true`
143
+ */
145
144
  function isLongArgument(name: string): boolean {
146
- return /^--[A-Za-z-]+[A-Za-z0-9]$/.test(name);
145
+ return /^--.{2,}/.test(name);
147
146
  }
148
147
 
149
148
  /** - Check if an arg string is an options arg. E.g. `--input-dir` -> `true` , `-i` -> `true` */
@@ -185,3 +184,18 @@ export function transformOptionToArgument(name: string): string {
185
184
 
186
185
  return `--${name.toLowerCase()}`;
187
186
  }
187
+
188
+ /**
189
+ * Split an option with keys into name and a set of keys
190
+ *
191
+ * - `--foo` -> `[--foo, []]`
192
+ * - `--foo.bar` -> `[--foo, ["bar"]]`
193
+ * - `--foo.bar.baz` -> `[--foo, ["bar", "baz"]]`
194
+ * - `--foo.bar.` -> `[--foo, Set(1) ["bar"]]`
195
+ */
196
+ export function splitAndGetKeys(option: string): [string, string[]] {
197
+ const parts = option.split(".");
198
+ const optionName = parts[0];
199
+ const keys = parts.slice(1).filter(Boolean);
200
+ return [optionName, keys];
201
+ }
@@ -1,5 +1,5 @@
1
1
  import { validateCliDefinition } from "../definitions/validate-cli-definition.ts";
2
- import { parseArgv } from "../utilities.ts";
2
+ import { parseArgv } from "../utilities/parse-argv.ts";
3
3
  import { buildCliContext } from "./context/cli-context-builder.ts";
4
4
  import { findSubcommandDefinition } from "./parser-utilities.ts";
5
5
  import { validate } from "./validation/validate-context.ts";
@@ -16,7 +16,7 @@ export function safeParse(stringOrArgv: string | string[], cliDefinition: Cli):
16
16
  // Fire action (throw errors caused by the usage of the action hook)
17
17
  if (subcommandObject._onExecute) {
18
18
  for (const handler of subcommandObject._onExecute) {
19
- handler(validateResult);
19
+ void handler(validateResult);
20
20
  }
21
21
  }
22
22
 
@@ -31,10 +31,7 @@ export async function safeParseAsync(stringOrArgv: string | string[], cliDefinit
31
31
 
32
32
  // Fire action (throw errors caused by the usage of the action hook)
33
33
  if (subcommandObject._onExecute) {
34
- for (const handler of subcommandObject._onExecute) {
35
- // eslint-disable-next-line @typescript-eslint/await-thenable
36
- await handler(validateResult);
37
- }
34
+ await Promise.all(subcommandObject._onExecute.map(async handler => await handler(validateResult)));
38
35
  }
39
36
 
40
37
  return { error: undefined, value: validateResult };
@@ -5,7 +5,7 @@ import type { ContextWide } from "../../types/context-types.ts";
5
5
  import type { Cli, Subcommand } from "../../types/definitions-types.ts";
6
6
  import type { OutputTypeWide } from "../../types/io-types.ts";
7
7
 
8
- /** @throws {Error} */
8
+ /** @throws {CliError} */
9
9
  export function validate(context: ContextWide, commandDefinition: Subcommand | Cli) {
10
10
  const output: OutputTypeWide = {
11
11
  subcommand: context.subcommand,