@villedemontreal/caporal 3.1.7

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 (425) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/src/__tests__/issue-163.spec.d.ts +2 -0
  4. package/dist/src/__tests__/issue-163.spec.d.ts.map +1 -0
  5. package/dist/src/__tests__/issue-163.spec.js +17 -0
  6. package/dist/src/__tests__/issue-163.spec.js.map +1 -0
  7. package/dist/src/argument/__tests__/argument.spec.d.ts +2 -0
  8. package/dist/src/argument/__tests__/argument.spec.d.ts.map +1 -0
  9. package/dist/src/argument/__tests__/argument.spec.js +85 -0
  10. package/dist/src/argument/__tests__/argument.spec.js.map +1 -0
  11. package/dist/src/argument/find.d.ts +8 -0
  12. package/dist/src/argument/find.d.ts.map +1 -0
  13. package/dist/src/argument/find.js +11 -0
  14. package/dist/src/argument/find.js.map +1 -0
  15. package/dist/src/argument/index.d.ts +13 -0
  16. package/dist/src/argument/index.d.ts.map +1 -0
  17. package/dist/src/argument/index.js +27 -0
  18. package/dist/src/argument/index.js.map +1 -0
  19. package/dist/src/argument/synopsis.d.ts +19 -0
  20. package/dist/src/argument/synopsis.d.ts.map +1 -0
  21. package/dist/src/argument/synopsis.js +39 -0
  22. package/dist/src/argument/synopsis.js.map +1 -0
  23. package/dist/src/argument/validate.d.ts +43 -0
  24. package/dist/src/argument/validate.d.ts.map +1 -0
  25. package/dist/src/argument/validate.js +127 -0
  26. package/dist/src/argument/validate.js.map +1 -0
  27. package/dist/src/autocomplete/__fixtures__/prog-autocomplete.d.ts +3 -0
  28. package/dist/src/autocomplete/__fixtures__/prog-autocomplete.d.ts.map +1 -0
  29. package/dist/src/autocomplete/__fixtures__/prog-autocomplete.js +24 -0
  30. package/dist/src/autocomplete/__fixtures__/prog-autocomplete.js.map +1 -0
  31. package/dist/src/autocomplete/__tests__/autocomplete.spec.d.ts +2 -0
  32. package/dist/src/autocomplete/__tests__/autocomplete.spec.d.ts.map +1 -0
  33. package/dist/src/autocomplete/__tests__/autocomplete.spec.js +119 -0
  34. package/dist/src/autocomplete/__tests__/autocomplete.spec.js.map +1 -0
  35. package/dist/src/autocomplete/index.d.ts +20 -0
  36. package/dist/src/autocomplete/index.d.ts.map +1 -0
  37. package/dist/src/autocomplete/index.js +172 -0
  38. package/dist/src/autocomplete/index.js.map +1 -0
  39. package/dist/src/autocomplete/types.d.ts +26 -0
  40. package/dist/src/autocomplete/types.d.ts.map +1 -0
  41. package/dist/src/autocomplete/types.js +3 -0
  42. package/dist/src/autocomplete/types.js.map +1 -0
  43. package/dist/src/command/__fixtures__/example-cmd.d.ts +8 -0
  44. package/dist/src/command/__fixtures__/example-cmd.d.ts.map +1 -0
  45. package/dist/src/command/__fixtures__/example-cmd.js +10 -0
  46. package/dist/src/command/__fixtures__/example-cmd.js.map +1 -0
  47. package/dist/src/command/__tests__/command.spec.d.ts +2 -0
  48. package/dist/src/command/__tests__/command.spec.d.ts.map +1 -0
  49. package/dist/src/command/__tests__/command.spec.js +510 -0
  50. package/dist/src/command/__tests__/command.spec.js.map +1 -0
  51. package/dist/src/command/__tests__/find.spec.d.ts +2 -0
  52. package/dist/src/command/__tests__/find.spec.d.ts.map +1 -0
  53. package/dist/src/command/__tests__/find.spec.js +31 -0
  54. package/dist/src/command/__tests__/find.spec.js.map +1 -0
  55. package/dist/src/command/__tests__/import.spec.d.ts +2 -0
  56. package/dist/src/command/__tests__/import.spec.d.ts.map +1 -0
  57. package/dist/src/command/__tests__/import.spec.js +17 -0
  58. package/dist/src/command/__tests__/import.spec.js.map +1 -0
  59. package/dist/src/command/__tests__/scan.spec.d.ts +2 -0
  60. package/dist/src/command/__tests__/scan.spec.d.ts.map +1 -0
  61. package/dist/src/command/__tests__/scan.spec.js +20 -0
  62. package/dist/src/command/__tests__/scan.spec.js.map +1 -0
  63. package/dist/src/command/find.d.ts +8 -0
  64. package/dist/src/command/find.d.ts.map +1 -0
  65. package/dist/src/command/find.js +47 -0
  66. package/dist/src/command/find.js.map +1 -0
  67. package/dist/src/command/import.d.ts +7 -0
  68. package/dist/src/command/import.d.ts.map +1 -0
  69. package/dist/src/command/import.js +47 -0
  70. package/dist/src/command/import.js.map +1 -0
  71. package/dist/src/command/index.d.ts +211 -0
  72. package/dist/src/command/index.d.ts.map +1 -0
  73. package/dist/src/command/index.js +374 -0
  74. package/dist/src/command/index.js.map +1 -0
  75. package/dist/src/command/scan.d.ts +4 -0
  76. package/dist/src/command/scan.d.ts.map +1 -0
  77. package/dist/src/command/scan.js +31 -0
  78. package/dist/src/command/scan.js.map +1 -0
  79. package/dist/src/command/validate-call.d.ts +8 -0
  80. package/dist/src/command/validate-call.d.ts.map +1 -0
  81. package/dist/src/command/validate-call.js +13 -0
  82. package/dist/src/command/validate-call.js.map +1 -0
  83. package/dist/src/config/index.d.ts +7 -0
  84. package/dist/src/config/index.d.ts.map +1 -0
  85. package/dist/src/config/index.js +24 -0
  86. package/dist/src/config/index.js.map +1 -0
  87. package/dist/src/error/__tests__/fatal.spec.d.ts +2 -0
  88. package/dist/src/error/__tests__/fatal.spec.d.ts.map +1 -0
  89. package/dist/src/error/__tests__/fatal.spec.js +34 -0
  90. package/dist/src/error/__tests__/fatal.spec.js.map +1 -0
  91. package/dist/src/error/action.d.ts +9 -0
  92. package/dist/src/error/action.d.ts.map +1 -0
  93. package/dist/src/error/action.js +16 -0
  94. package/dist/src/error/action.js.map +1 -0
  95. package/dist/src/error/base.d.ts +11 -0
  96. package/dist/src/error/base.d.ts.map +1 -0
  97. package/dist/src/error/base.js +18 -0
  98. package/dist/src/error/base.js.map +1 -0
  99. package/dist/src/error/fatal.d.ts +10 -0
  100. package/dist/src/error/fatal.d.ts.map +1 -0
  101. package/dist/src/error/fatal.js +27 -0
  102. package/dist/src/error/fatal.js.map +1 -0
  103. package/dist/src/error/index.d.ts +18 -0
  104. package/dist/src/error/index.d.ts.map +1 -0
  105. package/dist/src/error/index.js +34 -0
  106. package/dist/src/error/index.js.map +1 -0
  107. package/dist/src/error/invalid-validator.d.ts +10 -0
  108. package/dist/src/error/invalid-validator.d.ts.map +1 -0
  109. package/dist/src/error/invalid-validator.js +15 -0
  110. package/dist/src/error/invalid-validator.js.map +1 -0
  111. package/dist/src/error/missing-argument.d.ts +11 -0
  112. package/dist/src/error/missing-argument.d.ts.map +1 -0
  113. package/dist/src/error/missing-argument.js +20 -0
  114. package/dist/src/error/missing-argument.js.map +1 -0
  115. package/dist/src/error/missing-flag.d.ts +11 -0
  116. package/dist/src/error/missing-flag.d.ts.map +1 -0
  117. package/dist/src/error/missing-flag.js +20 -0
  118. package/dist/src/error/missing-flag.js.map +1 -0
  119. package/dist/src/error/multi-validation.d.ts +10 -0
  120. package/dist/src/error/multi-validation.d.ts.map +1 -0
  121. package/dist/src/error/multi-validation.js +26 -0
  122. package/dist/src/error/multi-validation.js.map +1 -0
  123. package/dist/src/error/no-action.d.ts +10 -0
  124. package/dist/src/error/no-action.d.ts.map +1 -0
  125. package/dist/src/error/no-action.js +22 -0
  126. package/dist/src/error/no-action.js.map +1 -0
  127. package/dist/src/error/option-synopsis-syntax.d.ts +9 -0
  128. package/dist/src/error/option-synopsis-syntax.d.ts.map +1 -0
  129. package/dist/src/error/option-synopsis-syntax.js +15 -0
  130. package/dist/src/error/option-synopsis-syntax.js.map +1 -0
  131. package/dist/src/error/too-many-arguments.d.ts +11 -0
  132. package/dist/src/error/too-many-arguments.d.ts.map +1 -0
  133. package/dist/src/error/too-many-arguments.js +25 -0
  134. package/dist/src/error/too-many-arguments.js.map +1 -0
  135. package/dist/src/error/unknown-command.d.ts +13 -0
  136. package/dist/src/error/unknown-command.d.ts.map +1 -0
  137. package/dist/src/error/unknown-command.js +44 -0
  138. package/dist/src/error/unknown-command.js.map +1 -0
  139. package/dist/src/error/unknown-option.d.ts +13 -0
  140. package/dist/src/error/unknown-option.d.ts.map +1 -0
  141. package/dist/src/error/unknown-option.js +40 -0
  142. package/dist/src/error/unknown-option.js.map +1 -0
  143. package/dist/src/error/validation.d.ts +17 -0
  144. package/dist/src/error/validation.d.ts.map +1 -0
  145. package/dist/src/error/validation.js +49 -0
  146. package/dist/src/error/validation.js.map +1 -0
  147. package/dist/src/help/__tests__/help.spec.d.ts +2 -0
  148. package/dist/src/help/__tests__/help.spec.d.ts.map +1 -0
  149. package/dist/src/help/__tests__/help.spec.js +130 -0
  150. package/dist/src/help/__tests__/help.spec.js.map +1 -0
  151. package/dist/src/help/__tests__/utils.spec.d.ts +2 -0
  152. package/dist/src/help/__tests__/utils.spec.d.ts.map +1 -0
  153. package/dist/src/help/__tests__/utils.spec.js +16 -0
  154. package/dist/src/help/__tests__/utils.spec.js.map +1 -0
  155. package/dist/src/help/index.d.ts +47 -0
  156. package/dist/src/help/index.d.ts.map +1 -0
  157. package/dist/src/help/index.js +131 -0
  158. package/dist/src/help/index.js.map +1 -0
  159. package/dist/src/help/templates/command.d.ts +7 -0
  160. package/dist/src/help/templates/command.d.ts.map +1 -0
  161. package/dist/src/help/templates/command.js +23 -0
  162. package/dist/src/help/templates/command.js.map +1 -0
  163. package/dist/src/help/templates/custom.d.ts +7 -0
  164. package/dist/src/help/templates/custom.d.ts.map +1 -0
  165. package/dist/src/help/templates/custom.js +24 -0
  166. package/dist/src/help/templates/custom.js.map +1 -0
  167. package/dist/src/help/templates/header.d.ts +7 -0
  168. package/dist/src/help/templates/header.d.ts.map +1 -0
  169. package/dist/src/help/templates/header.js +16 -0
  170. package/dist/src/help/templates/header.js.map +1 -0
  171. package/dist/src/help/templates/index.d.ts +10 -0
  172. package/dist/src/help/templates/index.d.ts.map +1 -0
  173. package/dist/src/help/templates/index.js +26 -0
  174. package/dist/src/help/templates/index.js.map +1 -0
  175. package/dist/src/help/templates/program.d.ts +7 -0
  176. package/dist/src/help/templates/program.d.ts.map +1 -0
  177. package/dist/src/help/templates/program.js +18 -0
  178. package/dist/src/help/templates/program.js.map +1 -0
  179. package/dist/src/help/templates/usage.d.ts +7 -0
  180. package/dist/src/help/templates/usage.d.ts.map +1 -0
  181. package/dist/src/help/templates/usage.js +19 -0
  182. package/dist/src/help/templates/usage.js.map +1 -0
  183. package/dist/src/help/types.d.ts +53 -0
  184. package/dist/src/help/types.d.ts.map +1 -0
  185. package/dist/src/help/types.js +3 -0
  186. package/dist/src/help/types.js.map +1 -0
  187. package/dist/src/help/utils.d.ts +9 -0
  188. package/dist/src/help/utils.d.ts.map +1 -0
  189. package/dist/src/help/utils.js +92 -0
  190. package/dist/src/help/utils.js.map +1 -0
  191. package/dist/src/index.d.ts +90 -0
  192. package/dist/src/index.d.ts.map +1 -0
  193. package/dist/src/index.js +111 -0
  194. package/dist/src/index.js.map +1 -0
  195. package/dist/src/logger/__tests__/logger.spec.d.ts +2 -0
  196. package/dist/src/logger/__tests__/logger.spec.d.ts.map +1 -0
  197. package/dist/src/logger/__tests__/logger.spec.js +56 -0
  198. package/dist/src/logger/__tests__/logger.spec.js.map +1 -0
  199. package/dist/src/logger/index.d.ts +6 -0
  200. package/dist/src/logger/index.d.ts.map +1 -0
  201. package/dist/src/logger/index.js +128 -0
  202. package/dist/src/logger/index.js.map +1 -0
  203. package/dist/src/option/__tests__/global.spec.d.ts +2 -0
  204. package/dist/src/option/__tests__/global.spec.d.ts.map +1 -0
  205. package/dist/src/option/__tests__/global.spec.js +121 -0
  206. package/dist/src/option/__tests__/global.spec.js.map +1 -0
  207. package/dist/src/option/__tests__/option.spec.d.ts +2 -0
  208. package/dist/src/option/__tests__/option.spec.d.ts.map +1 -0
  209. package/dist/src/option/__tests__/option.spec.js +111 -0
  210. package/dist/src/option/__tests__/option.spec.js.map +1 -0
  211. package/dist/src/option/find.d.ts +14 -0
  212. package/dist/src/option/find.d.ts.map +1 -0
  213. package/dist/src/option/find.js +17 -0
  214. package/dist/src/option/find.js.map +1 -0
  215. package/dist/src/option/index.d.ts +65 -0
  216. package/dist/src/option/index.d.ts.map +1 -0
  217. package/dist/src/option/index.js +230 -0
  218. package/dist/src/option/index.js.map +1 -0
  219. package/dist/src/option/mapping.d.ts +7 -0
  220. package/dist/src/option/mapping.d.ts.map +1 -0
  221. package/dist/src/option/mapping.js +21 -0
  222. package/dist/src/option/mapping.js.map +1 -0
  223. package/dist/src/option/utils.d.ts +35 -0
  224. package/dist/src/option/utils.d.ts.map +1 -0
  225. package/dist/src/option/utils.js +139 -0
  226. package/dist/src/option/utils.js.map +1 -0
  227. package/dist/src/option/validate.d.ts +15 -0
  228. package/dist/src/option/validate.d.ts.map +1 -0
  229. package/dist/src/option/validate.js +63 -0
  230. package/dist/src/option/validate.js.map +1 -0
  231. package/dist/src/parser/__tests__/parser.spec.d.ts +2 -0
  232. package/dist/src/parser/__tests__/parser.spec.d.ts.map +1 -0
  233. package/dist/src/parser/__tests__/parser.spec.js +343 -0
  234. package/dist/src/parser/__tests__/parser.spec.js.map +1 -0
  235. package/dist/src/parser/index.d.ts +17 -0
  236. package/dist/src/parser/index.d.ts.map +1 -0
  237. package/dist/src/parser/index.js +299 -0
  238. package/dist/src/parser/index.js.map +1 -0
  239. package/dist/src/program/__tests__/program.spec.d.ts +2 -0
  240. package/dist/src/program/__tests__/program.spec.d.ts.map +1 -0
  241. package/dist/src/program/__tests__/program.spec.js +261 -0
  242. package/dist/src/program/__tests__/program.spec.js.map +1 -0
  243. package/dist/src/program/index.d.ts +349 -0
  244. package/dist/src/program/index.d.ts.map +1 -0
  245. package/dist/src/program/index.js +584 -0
  246. package/dist/src/program/index.js.map +1 -0
  247. package/dist/src/types.d.ts +396 -0
  248. package/dist/src/types.d.ts.map +1 -0
  249. package/dist/src/types.js +51 -0
  250. package/dist/src/types.js.map +1 -0
  251. package/dist/src/utils/__tests__/fs.spec.d.ts +2 -0
  252. package/dist/src/utils/__tests__/fs.spec.d.ts.map +1 -0
  253. package/dist/src/utils/__tests__/fs.spec.js +14 -0
  254. package/dist/src/utils/__tests__/fs.spec.js.map +1 -0
  255. package/dist/src/utils/__tests__/levenshtein.spec.d.ts +2 -0
  256. package/dist/src/utils/__tests__/levenshtein.spec.d.ts.map +1 -0
  257. package/dist/src/utils/__tests__/levenshtein.spec.js +18 -0
  258. package/dist/src/utils/__tests__/levenshtein.spec.js.map +1 -0
  259. package/dist/src/utils/__tests__/suggest.spec.d.ts +2 -0
  260. package/dist/src/utils/__tests__/suggest.spec.d.ts.map +1 -0
  261. package/dist/src/utils/__tests__/suggest.spec.js +31 -0
  262. package/dist/src/utils/__tests__/suggest.spec.js.map +1 -0
  263. package/dist/src/utils/colorize.d.ts +2 -0
  264. package/dist/src/utils/colorize.d.ts.map +1 -0
  265. package/dist/src/utils/colorize.js +27 -0
  266. package/dist/src/utils/colorize.js.map +1 -0
  267. package/dist/src/utils/fs.d.ts +2 -0
  268. package/dist/src/utils/fs.d.ts.map +1 -0
  269. package/dist/src/utils/fs.js +19 -0
  270. package/dist/src/utils/fs.js.map +1 -0
  271. package/dist/src/utils/levenshtein.d.ts +6 -0
  272. package/dist/src/utils/levenshtein.d.ts.map +1 -0
  273. package/dist/src/utils/levenshtein.js +32 -0
  274. package/dist/src/utils/levenshtein.js.map +1 -0
  275. package/dist/src/utils/suggest.d.ts +15 -0
  276. package/dist/src/utils/suggest.d.ts.map +1 -0
  277. package/dist/src/utils/suggest.js +49 -0
  278. package/dist/src/utils/suggest.js.map +1 -0
  279. package/dist/src/utils/version.d.ts +2 -0
  280. package/dist/src/utils/version.d.ts.map +1 -0
  281. package/dist/src/utils/version.js +21 -0
  282. package/dist/src/utils/version.js.map +1 -0
  283. package/dist/src/utils/web/autocomplete.d.ts +12 -0
  284. package/dist/src/utils/web/autocomplete.d.ts.map +1 -0
  285. package/dist/src/utils/web/autocomplete.js +12 -0
  286. package/dist/src/utils/web/autocomplete.js.map +1 -0
  287. package/dist/src/utils/web/process.d.ts +15 -0
  288. package/dist/src/utils/web/process.d.ts.map +1 -0
  289. package/dist/src/utils/web/process.js +29 -0
  290. package/dist/src/utils/web/process.js.map +1 -0
  291. package/dist/src/validator/__tests__/array.spec.d.ts +2 -0
  292. package/dist/src/validator/__tests__/array.spec.d.ts.map +1 -0
  293. package/dist/src/validator/__tests__/array.spec.js +34 -0
  294. package/dist/src/validator/__tests__/array.spec.js.map +1 -0
  295. package/dist/src/validator/__tests__/caporal.spec.d.ts +2 -0
  296. package/dist/src/validator/__tests__/caporal.spec.d.ts.map +1 -0
  297. package/dist/src/validator/__tests__/caporal.spec.js +86 -0
  298. package/dist/src/validator/__tests__/caporal.spec.js.map +1 -0
  299. package/dist/src/validator/__tests__/function.spec.d.ts +2 -0
  300. package/dist/src/validator/__tests__/function.spec.d.ts.map +1 -0
  301. package/dist/src/validator/__tests__/function.spec.js +42 -0
  302. package/dist/src/validator/__tests__/function.spec.js.map +1 -0
  303. package/dist/src/validator/__tests__/regexp.spec.d.ts +2 -0
  304. package/dist/src/validator/__tests__/regexp.spec.d.ts.map +1 -0
  305. package/dist/src/validator/__tests__/regexp.spec.js +34 -0
  306. package/dist/src/validator/__tests__/regexp.spec.js.map +1 -0
  307. package/dist/src/validator/__tests__/utils.spec.d.ts +2 -0
  308. package/dist/src/validator/__tests__/utils.spec.d.ts.map +1 -0
  309. package/dist/src/validator/__tests__/utils.spec.js +66 -0
  310. package/dist/src/validator/__tests__/utils.spec.js.map +1 -0
  311. package/dist/src/validator/__tests__/validate.spec.d.ts +2 -0
  312. package/dist/src/validator/__tests__/validate.spec.d.ts.map +1 -0
  313. package/dist/src/validator/__tests__/validate.spec.js +25 -0
  314. package/dist/src/validator/__tests__/validate.spec.js.map +1 -0
  315. package/dist/src/validator/array.d.ts +14 -0
  316. package/dist/src/validator/array.d.ts.map +1 -0
  317. package/dist/src/validator/array.js +29 -0
  318. package/dist/src/validator/array.js.map +1 -0
  319. package/dist/src/validator/caporal.d.ts +25 -0
  320. package/dist/src/validator/caporal.d.ts.map +1 -0
  321. package/dist/src/validator/caporal.js +89 -0
  322. package/dist/src/validator/caporal.js.map +1 -0
  323. package/dist/src/validator/function.d.ts +7 -0
  324. package/dist/src/validator/function.d.ts.map +1 -0
  325. package/dist/src/validator/function.js +27 -0
  326. package/dist/src/validator/function.js.map +1 -0
  327. package/dist/src/validator/regexp.d.ts +14 -0
  328. package/dist/src/validator/regexp.d.ts.map +1 -0
  329. package/dist/src/validator/regexp.js +31 -0
  330. package/dist/src/validator/regexp.js.map +1 -0
  331. package/dist/src/validator/utils.d.ts +14 -0
  332. package/dist/src/validator/utils.d.ts.map +1 -0
  333. package/dist/src/validator/utils.js +81 -0
  334. package/dist/src/validator/utils.js.map +1 -0
  335. package/dist/src/validator/validate.d.ts +7 -0
  336. package/dist/src/validator/validate.d.ts.map +1 -0
  337. package/dist/src/validator/validate.js +29 -0
  338. package/dist/src/validator/validate.js.map +1 -0
  339. package/dist/tsconfig.tsbuildinfo +1 -0
  340. package/package.json +75 -0
  341. package/src/__tests__/issue-163.spec.ts +18 -0
  342. package/src/argument/__tests__/argument.spec.ts +84 -0
  343. package/src/argument/find.ts +11 -0
  344. package/src/argument/index.ts +35 -0
  345. package/src/argument/synopsis.ts +41 -0
  346. package/src/argument/validate.ts +176 -0
  347. package/src/autocomplete/__fixtures__/prog-autocomplete.ts +24 -0
  348. package/src/autocomplete/__tests__/autocomplete.spec.ts +129 -0
  349. package/src/autocomplete/index.ts +225 -0
  350. package/src/autocomplete/types.ts +29 -0
  351. package/src/command/__fixtures__/example-cmd.ts +14 -0
  352. package/src/command/__tests__/command.spec.ts +621 -0
  353. package/src/command/__tests__/find.spec.ts +32 -0
  354. package/src/command/__tests__/import.spec.ts +14 -0
  355. package/src/command/__tests__/scan.spec.ts +16 -0
  356. package/src/command/find.ts +57 -0
  357. package/src/command/import.ts +13 -0
  358. package/src/command/index.ts +458 -0
  359. package/src/command/scan.ts +30 -0
  360. package/src/command/validate-call.ts +19 -0
  361. package/src/config/index.ts +26 -0
  362. package/src/error/__tests__/fatal.spec.ts +38 -0
  363. package/src/error/action.ts +13 -0
  364. package/src/error/base.ts +20 -0
  365. package/src/error/fatal.ts +25 -0
  366. package/src/error/index.ts +17 -0
  367. package/src/error/invalid-validator.ts +12 -0
  368. package/src/error/missing-argument.ts +16 -0
  369. package/src/error/missing-flag.ts +16 -0
  370. package/src/error/multi-validation.ts +22 -0
  371. package/src/error/no-action.ts +19 -0
  372. package/src/error/option-synopsis-syntax.ts +12 -0
  373. package/src/error/too-many-arguments.ts +28 -0
  374. package/src/error/unknown-command.ts +41 -0
  375. package/src/error/unknown-option.ts +40 -0
  376. package/src/error/validation.ts +80 -0
  377. package/src/help/__tests__/__snapshots__/help.spec.ts.snap +334 -0
  378. package/src/help/__tests__/help.spec.ts +144 -0
  379. package/src/help/__tests__/utils.spec.ts +14 -0
  380. package/src/help/index.ts +107 -0
  381. package/src/help/templates/command.ts +27 -0
  382. package/src/help/templates/custom.ts +25 -0
  383. package/src/help/templates/header.ts +19 -0
  384. package/src/help/templates/index.ts +9 -0
  385. package/src/help/templates/program.ts +21 -0
  386. package/src/help/templates/usage.ts +24 -0
  387. package/src/help/types.ts +57 -0
  388. package/src/help/utils.ts +109 -0
  389. package/src/index.ts +93 -0
  390. package/src/logger/__tests__/logger.spec.ts +65 -0
  391. package/src/logger/index.ts +97 -0
  392. package/src/option/__tests__/global.spec.ts +141 -0
  393. package/src/option/__tests__/option.spec.ts +115 -0
  394. package/src/option/find.ts +17 -0
  395. package/src/option/index.ts +280 -0
  396. package/src/option/mapping.ts +17 -0
  397. package/src/option/utils.ts +141 -0
  398. package/src/option/validate.ts +80 -0
  399. package/src/parser/__tests__/parser.spec.ts +371 -0
  400. package/src/parser/index.ts +383 -0
  401. package/src/program/__tests__/program.spec.ts +316 -0
  402. package/src/program/index.ts +676 -0
  403. package/src/types.ts +432 -0
  404. package/src/utils/__tests__/fs.spec.ts +14 -0
  405. package/src/utils/__tests__/levenshtein.spec.ts +16 -0
  406. package/src/utils/__tests__/suggest.spec.ts +30 -0
  407. package/src/utils/colorize.ts +21 -0
  408. package/src/utils/fs.ts +13 -0
  409. package/src/utils/levenshtein.ts +28 -0
  410. package/src/utils/suggest.ts +52 -0
  411. package/src/utils/version.ts +14 -0
  412. package/src/utils/web/autocomplete.ts +19 -0
  413. package/src/utils/web/process.ts +24 -0
  414. package/src/validator/__tests__/array.spec.ts +41 -0
  415. package/src/validator/__tests__/caporal.spec.ts +132 -0
  416. package/src/validator/__tests__/function.spec.ts +52 -0
  417. package/src/validator/__tests__/regexp.spec.ts +38 -0
  418. package/src/validator/__tests__/utils.spec.ts +67 -0
  419. package/src/validator/__tests__/validate.spec.ts +24 -0
  420. package/src/validator/array.ts +31 -0
  421. package/src/validator/caporal.ts +104 -0
  422. package/src/validator/function.ts +31 -0
  423. package/src/validator/regexp.ts +34 -0
  424. package/src/validator/utils.ts +84 -0
  425. package/src/validator/validate.ts +38 -0
@@ -0,0 +1,676 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * @module caporal/program
4
+ */
5
+ import { EventEmitter } from "events"
6
+ import fs from "fs"
7
+ import path from "path"
8
+ import kebabCase from "lodash/kebabCase"
9
+ import mapKeys from "lodash/mapKeys"
10
+ import { createCommand, HELP_CMD, PROG_CMD } from "../command"
11
+ import { Command } from "../command"
12
+ import { findCommand } from "../command/find"
13
+ import { scanCommands } from "../command/scan"
14
+ import { createConfigurator } from "../config"
15
+ import { fatalError, UnknownOrUnspecifiedCommandError } from "../error"
16
+ import { customizeHelp } from "../help"
17
+ import { CustomizedHelpOpts } from "../help/types"
18
+ import { getLogger, logger, setLogger } from "../logger"
19
+ import {
20
+ addGlobalOption,
21
+ createOption,
22
+ disableGlobalOption,
23
+ processGlobalOptions,
24
+ showHelp,
25
+ } from "../option"
26
+ import { parseArgv } from "../parser"
27
+ import {
28
+ Action,
29
+ Logger,
30
+ Configurator,
31
+ ParserResult,
32
+ ParserTypes,
33
+ ProgramConfig,
34
+ CreateArgumentOpts,
35
+ CreateOptionProgramOpts,
36
+ CommandConfig,
37
+ } from "../types"
38
+ import { CaporalValidator } from "../types"
39
+ import { detectVersion } from "../utils/version"
40
+
41
+ const LOG_LEVEL_ENV_VAR = "CAPORAL_LOG_LEVEL"
42
+ // const SUPPORTED_SHELL = ["bash", "zsh", "fish"]
43
+
44
+ /**
45
+ * Program class
46
+ *
47
+ * @noInheritDoc
48
+ */
49
+ export class Program extends EventEmitter {
50
+ private commands: Command[] = []
51
+ private _config: Configurator<ProgramConfig>
52
+ private _version?: string
53
+ private _name?: string
54
+ private _description?: string
55
+ private _programmaticMode = false
56
+ /**
57
+ * @internal
58
+ */
59
+ public defaultCommand?: Command
60
+ private _progCommand?: Command
61
+ private _bin: string
62
+ private _discoveryPath?: string
63
+ private _discoveredCommands?: Command[]
64
+
65
+ /**
66
+ * Number validator. Check that the value looks like a numeric one
67
+ * and cast the provided value to a javascript `Number`.
68
+ */
69
+ readonly NUMBER = CaporalValidator.NUMBER
70
+ /**
71
+ * String validator. Mainly used to make sure the value is a string,
72
+ * and prevent Caporal auto-casting of numerical values and boolean
73
+ * strings like `true` or `false`.
74
+ */
75
+ readonly STRING = CaporalValidator.STRING
76
+ /**
77
+ * Array validator. Convert any provided value to an array. If a string is provided,
78
+ * this validator will try to split it by commas.
79
+ */
80
+ readonly ARRAY = CaporalValidator.ARRAY
81
+ /**
82
+ * Boolean validator. Check that the value looks like a boolean.
83
+ * It accepts values like `true`, `false`, `yes`, `no`, `0`, and `1`
84
+ * and will auto-cast those values to `true` or `false`.
85
+ */
86
+ readonly BOOLEAN = CaporalValidator.BOOLEAN
87
+
88
+ /**
89
+ * Program constructor.
90
+ * - Detects the "bin" name from process argv
91
+ * - Detects the version from package.json
92
+ * - Set up the help command
93
+ * @ignore
94
+ */
95
+ constructor() {
96
+ super()
97
+ this._bin = path.basename(process.argv[1])
98
+ this._version = detectVersion()
99
+ this._config = createConfigurator({
100
+ strictArgsCount: true,
101
+ strictOptions: true,
102
+ autoCast: true,
103
+ logLevelEnvVar: LOG_LEVEL_ENV_VAR,
104
+ })
105
+ this.setupHelpCommand()
106
+ this.setupErrorHandlers()
107
+ }
108
+
109
+ /**
110
+ * @internal
111
+ */
112
+ private setupErrorHandlers(): void {
113
+ process.once("unhandledRejection", (err) => {
114
+ if (this._programmaticMode) {
115
+ throw err
116
+ } else {
117
+ this.emit("error", err)
118
+ }
119
+ })
120
+ this.on("error", fatalError)
121
+ }
122
+
123
+ /**
124
+ * The program-command is the command attached directly to the program,
125
+ * meaning there is no command-keyword used to trigger it.
126
+ * Mainly used for programs executing only one possible action.
127
+ *
128
+ * @internal
129
+ */
130
+ get progCommand(): Command {
131
+ if (this._progCommand === undefined) {
132
+ this._progCommand = createCommand(this, PROG_CMD, "")
133
+ }
134
+ return this._progCommand
135
+ }
136
+
137
+ /**
138
+ * Setup the help command
139
+ */
140
+ private setupHelpCommand(): Command {
141
+ return this.command(HELP_CMD, "Get help about a specific command")
142
+ .argument(
143
+ "[command]",
144
+ "Command name to get help for. If the command does not exist, global help will be displayed.",
145
+ )
146
+ .action(async (actionParams) => {
147
+ const { args } = actionParams
148
+ const command = args.command
149
+ ? await findCommand(this, [args.command as string])
150
+ : undefined
151
+ // eslint-disable-next-line no-console
152
+ showHelp({ ...actionParams, command })
153
+ return -1
154
+ })
155
+ .hide()
156
+ }
157
+
158
+ /**
159
+ * Customize program help. Can be called multiple times to add more paragraphs and/or sections.
160
+ *
161
+ * @param text Help contents
162
+ * @param options Display options
163
+ */
164
+ help(text: string, options: Partial<CustomizedHelpOpts> = {}): Program {
165
+ customizeHelp(this, text, options)
166
+ return this
167
+ }
168
+
169
+ /**
170
+ * Toggle strict mode.
171
+ * Shortcut to calling: `.configure({ strictArgsCount: strict, strictOptions: strict })`.
172
+ * By default, the program is strict, so if you want to disable strict checking,
173
+ * just call `.strict(false)`. This setting can be overridden at the command level.
174
+ *
175
+ * @param strict boolean enabled flag
176
+ */
177
+ strict(strict = true): Program {
178
+ return this.configure({
179
+ strictArgsCount: strict,
180
+ strictOptions: strict,
181
+ })
182
+ }
183
+
184
+ /**
185
+ * Configure some behavioral properties.
186
+ *
187
+ * @param props properties to set/update
188
+ */
189
+ configure(props: Partial<ProgramConfig>): Program {
190
+ this._config.set(props)
191
+ return this
192
+ }
193
+
194
+ /**
195
+ * Get a configuration property value. {@link ProgramConfig Possible keys}.
196
+ *
197
+ * @param key Property
198
+ * @internal
199
+ */
200
+ getConfigProperty<K extends keyof ProgramConfig>(key: K): ProgramConfig[K] {
201
+ return this._config.get(key)
202
+ }
203
+
204
+ /**
205
+ * Return a reformatted synopsis string
206
+ *
207
+ * @internal
208
+ */
209
+ async getSynopsis(): Promise<string> {
210
+ return (
211
+ this.getBin() +
212
+ " " +
213
+ ((await this.hasCommands()) ? "<command> " : "") +
214
+ "[ARGUMENTS...] [OPTIONS...]"
215
+ ).trim()
216
+ }
217
+
218
+ /**
219
+ * Return the discovery path, if set
220
+ *
221
+ * @internal
222
+ */
223
+ get discoveryPath(): string | undefined {
224
+ return this._discoveryPath
225
+ }
226
+
227
+ /**
228
+ * Return the program version
229
+ *
230
+ * @internal
231
+ */
232
+ getVersion(): string | undefined {
233
+ return this._version
234
+ }
235
+
236
+ /**
237
+ * Set the version fo your program.
238
+ * You won't likely use this method as Caporal tries to guess it from your package.json
239
+ */
240
+ version(ver: string): Program {
241
+ this._version = ver
242
+ return this
243
+ }
244
+
245
+ /**
246
+ * Set the program name. If not set, the filename minus the extension will be used.
247
+ */
248
+ name(name: string): Program {
249
+ this._name = name
250
+ return this
251
+ }
252
+
253
+ /**
254
+ * Return the program name.
255
+ *
256
+ * @internal
257
+ */
258
+ getName(): string | undefined {
259
+ return this._name
260
+ }
261
+
262
+ /**
263
+ * Return the program description.
264
+ *
265
+ * @internal
266
+ */
267
+ getDescription(): string | undefined {
268
+ return this._description
269
+ }
270
+
271
+ /**
272
+ * Set the program description displayed in help.
273
+ */
274
+ description(desc: string): Program {
275
+ this._description = desc
276
+ return this
277
+ }
278
+
279
+ /**
280
+ * Get the bin name (the name of your executable).
281
+ *
282
+ * @internal
283
+ */
284
+ getBin(): string {
285
+ return this._bin
286
+ }
287
+
288
+ /**
289
+ * Sets the executable name. By default, it's auto-detected from the filename of your program.
290
+ *
291
+ * @param name Executable name
292
+ * @example
293
+ * ```ts
294
+ * program.bin('myprog')
295
+ * ```
296
+ */
297
+ bin(name: string): Program {
298
+ this._bin = name
299
+ return this
300
+ }
301
+
302
+ /**
303
+ * Set a custom logger for your program.
304
+ * Your logger should implement the {@link Logger} interface.
305
+ */
306
+ logger(logger: Logger): Program {
307
+ setLogger(logger)
308
+ return this
309
+ }
310
+
311
+ /**
312
+ * Get the configured logger instance
313
+ */
314
+ getLogger(): Logger {
315
+ return getLogger()
316
+ }
317
+
318
+ /**
319
+ * Disable a global option. Will warn if the global option
320
+ * does not exist of has already been disabled.
321
+ *
322
+ * @param name Name, short, or long notation of the option to disable.
323
+ */
324
+ disableGlobalOption(name: string): Program {
325
+ const disabled = disableGlobalOption(name)
326
+ if (!disabled) {
327
+ logger.warn(
328
+ "Cannot disable global option %s. Either the global option does not exist or has already been disabled.",
329
+ )
330
+ }
331
+ return this
332
+ }
333
+
334
+ /**
335
+ * Returns the list of all commands registered
336
+ * - By default, Caporal creates one: the "help" command
337
+ * - When calling argument() or action() on the program instance,
338
+ * Caporal also create what is called the "program command", which
339
+ * is a command directly attach to the program, usually used
340
+ * in mono-command programs.
341
+ * @internal
342
+ */
343
+ getCommands(): Command[] {
344
+ return this.commands
345
+ }
346
+
347
+ /**
348
+ * Add a command to the program.
349
+ *
350
+ * @param name Command name
351
+ * @param description Command description
352
+ * @example
353
+ * ```ts
354
+ * program.command('order', 'Order some food')
355
+ * ```
356
+ */
357
+ command(
358
+ name: string,
359
+ description: string,
360
+ config: Partial<CommandConfig> = {},
361
+ ): Command {
362
+ const cmd = createCommand(this, name, description, config)
363
+ this.commands.push(cmd)
364
+ return cmd
365
+ }
366
+
367
+ /**
368
+ * Check if the program has user-defined commands.
369
+ *
370
+ * @internal
371
+ * @private
372
+ */
373
+ async hasCommands(): Promise<boolean> {
374
+ return (await this.getAllCommands()).length > 1
375
+ }
376
+
377
+ /**
378
+ * @internal
379
+ */
380
+ async getAllCommands(): Promise<Command[]> {
381
+ const discoveredCommands = await this.scanCommands()
382
+ return [...this.commands, ...discoveredCommands]
383
+ }
384
+
385
+ /**
386
+ * Return the log level override, if any is provided using
387
+ * the right environment variable.
388
+ *
389
+ * @internal
390
+ * @private
391
+ */
392
+ public getLogLevelOverride(): string | undefined {
393
+ return process.env[this.getConfigProperty("logLevelEnvVar")]
394
+ }
395
+
396
+ /**
397
+ * Enable or disable auto casting of arguments & options at the program level.
398
+ *
399
+ * @param enabled
400
+ */
401
+ cast(enabled: boolean): Program {
402
+ return this.configure({ autoCast: enabled })
403
+ }
404
+
405
+ /**
406
+ * Sets a *unique* action for the *entire* program.
407
+ *
408
+ * @param {Function} action - Action to run
409
+ */
410
+ action(action: Action): Program {
411
+ this.progCommand.action(action)
412
+ return this
413
+ }
414
+
415
+ /**
416
+ * Add an argument to the *unique* command of the program.
417
+ */
418
+ argument(
419
+ synopsis: string,
420
+ description: string,
421
+ options: CreateArgumentOpts = {},
422
+ ): Command {
423
+ return this.progCommand.argument(synopsis, description, options)
424
+ }
425
+
426
+ /**
427
+ * Add an option to the *unique* command of the program,
428
+ * or add a global option to the program when `options.global`
429
+ * is set to `true`.
430
+ *
431
+ * @param synopsis Option synopsis like '-f, --force', or '-f, --file \<file\>', or '--with-openssl [path]'
432
+ * @param description Option description
433
+ * @param options Additional parameters
434
+ */
435
+ option(
436
+ synopsis: string,
437
+ description: string,
438
+ options: CreateOptionProgramOpts = {},
439
+ ): Program {
440
+ if (options.global) {
441
+ const opt = createOption(synopsis, description, options)
442
+ addGlobalOption(opt, options.action)
443
+ } else {
444
+ this.progCommand.option(synopsis, description, options)
445
+ }
446
+ return this
447
+ }
448
+
449
+ /**
450
+ * Discover commands from a specified path.
451
+ *
452
+ * Commands must be organized into files (one command per file) in a file tree like:
453
+ *
454
+ * ```sh
455
+ * └── commands
456
+ * ├── config
457
+ * │ ├── set.ts
458
+ * │ └── unset.ts
459
+ * ├── create
460
+ * │ ├── job.ts
461
+ * │ └── service.ts
462
+ * ├── create.ts
463
+ * ├── describe.ts
464
+ * └── get.ts
465
+ * ```
466
+ *
467
+ * The code above shows a short example of `kubectl` commands and subcommands.
468
+ * In this case, Caporal will generate the following commands:
469
+ *
470
+ * - kubectl get [args...] [options...]
471
+ * - kubectl config set [args...] [options...]
472
+ * - kubectl config unset [args...] [options...]
473
+ * - kubectl create [args...] [options...]
474
+ * - kubectl create job [args...] [options...]
475
+ * - kubectl create service [args...] [options...]
476
+ * - kubectl describe [args...] [options...]
477
+ * - kubectl get [args...] [options...]
478
+ *
479
+ * Notice how the `config` command has a mandatory subcommand associated,
480
+ * hence cannot be called without a subcommand, contrary to the `create` command.
481
+ * This is why there is no `config.ts` in the tree.
482
+ *
483
+ * @param path
484
+ */
485
+ discover(dirPath: string): Program {
486
+ let stat
487
+ try {
488
+ stat = fs.statSync(dirPath)
489
+ // eslint-disable-next-line no-empty
490
+ } catch (e) {}
491
+ if (!stat || !stat.isDirectory()) {
492
+ throw new Error(
493
+ "Caporal setup error: parameter `dirPath` of discover() should be a directory",
494
+ )
495
+ }
496
+
497
+ this._discoveryPath = dirPath
498
+ return this
499
+ }
500
+
501
+ /**
502
+ * Do a full scan of the discovery path to get all existing commands
503
+ * This should only be used to generate the full list of command,
504
+ * as for help rendering
505
+ *
506
+ * @private
507
+ */
508
+ private async scanCommands(): Promise<Command[]> {
509
+ if (this._discoveryPath === undefined) {
510
+ return []
511
+ }
512
+ if (this._discoveredCommands) {
513
+ return this._discoveredCommands
514
+ }
515
+ this._discoveredCommands = await scanCommands(this, this._discoveryPath)
516
+ return this._discoveredCommands
517
+ }
518
+
519
+ /* istanbul ignore next */
520
+ /**
521
+ * Reset all commands
522
+ *
523
+ * @internal
524
+ */
525
+ public reset(): Program {
526
+ this.commands = []
527
+ this._progCommand = undefined
528
+ this.setupHelpCommand()
529
+ return this
530
+ }
531
+
532
+ /**
533
+ * Run the program by parsing command line arguments.
534
+ * Caporal will automatically detect command line arguments from `process.argv` values,
535
+ * but it can be overridden by providing the `argv` parameter. It returns a Promise
536
+ * of the value returned by the *Action* triggered.
537
+ *
538
+ * ::: warning Be careful
539
+ * This method returns a `Promise`. You'll usually ignore the returned promise and call run() like this:
540
+ *
541
+ * ```ts
542
+ * [...]
543
+ * program.action(...)
544
+ * program.run()
545
+ * ```
546
+ *
547
+ * If you do add some `.catch()` handler to it, Caporal won't display any potential errors
548
+ * that the promise could reject, and will let you the responsibility to do it.
549
+ * :::
550
+ *
551
+ * @param argv Command line arguments to parse, default to `process.argv.slice(2)`.
552
+ */
553
+ async run(argv?: string[]): Promise<unknown> {
554
+ if (!argv) {
555
+ // used on web playground
556
+ if (process.env.CAPORAL_CMD_LINE) {
557
+ argv = process.env.CAPORAL_CMD_LINE.split(" ").slice(1)
558
+ // defaut value for common usage
559
+ } else {
560
+ argv = process.argv.slice(2)
561
+ }
562
+ }
563
+
564
+ /*
565
+ Search for the command from args, then, if a default command exists,
566
+ take it, otherwise take the command attached to the program,
567
+ and lastly the help command/
568
+ */
569
+ const cmd = await this.findCommand(argv)
570
+
571
+ // parse command line args
572
+ const result = parseArgv(cmd?.getParserConfig(), argv)
573
+
574
+ /*
575
+ Run command with parsed args.
576
+ We are forced to catch a potential error to prevent the rejected
577
+ promise to propagate un in the stack.
578
+ */
579
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
580
+ return this._run(result, cmd) /*
581
+ .catch((e) => e) */
582
+ }
583
+
584
+ /**
585
+ * Try to find the executed command from argv
586
+ * If command cannot be found from argv, return the default command if any,
587
+ * then the program-command if any, or finally `undefined`.
588
+ * If argv is empty, and there is no defaultCommand or progCommand
589
+ * use the help command
590
+ *
591
+ * @param argv
592
+ */
593
+ private async findCommand(argv: string[]): ReturnType<typeof findCommand> {
594
+ const cmd = await findCommand(this, argv)
595
+ if (cmd) {
596
+ return cmd
597
+ }
598
+ /**
599
+ * If we've been asked for help (and only help) and there is no progCommand,
600
+ * so we should return undefined in order for the help command to display
601
+ * the global help.
602
+ * Fixes this particular use case: Fixes this particular use case:
603
+ * https://github.com/mattallty/Caporal.js/issues/196
604
+ */
605
+ if (argv.every((arg) => arg === "--help") && !this._progCommand) {
606
+ return undefined
607
+ }
608
+
609
+ return this.defaultCommand || this._progCommand
610
+ }
611
+
612
+ /**
613
+ * Run a command, providing parsed data
614
+ *
615
+ * @param result
616
+ * @param cmd
617
+ * @internal
618
+ */
619
+ private async _run(result: ParserResult, cmd?: Command): Promise<unknown> {
620
+ // Override logger level via ENV if needed
621
+ const loggerLevel = this.getLogLevelOverride()
622
+ if (loggerLevel && Object.keys(logger.levels).includes(loggerLevel)) {
623
+ logger.level = loggerLevel
624
+ }
625
+ // try to run the command
626
+ // try {
627
+ if (!cmd) {
628
+ // we may not have any associated command, but some global options may have been passed
629
+ // process them, if any
630
+ // Process any global options
631
+ const processedResult = { ...result, errors: [] as undefined[], args: {} }
632
+ const shouldStop = await processGlobalOptions(processedResult, this)
633
+ if (shouldStop) {
634
+ this.emit("run")
635
+ return -1
636
+ }
637
+ // todo: use case: "git unknown-command some args" will display "unknown command 'git'"
638
+ // but should display "unknown command 'git unknown-command'"
639
+ throw new UnknownOrUnspecifiedCommandError(this, result.rawArgv[0])
640
+ }
641
+ const ret = await cmd.run(result)
642
+ this.emit("run", ret)
643
+ return ret
644
+ }
645
+
646
+ /**
647
+ * Programmatic usage. Execute input command with given arguments & options
648
+ *
649
+ * Not ideal regarding type casting etc.
650
+ *
651
+ * @param args argv array
652
+ * @param options options object
653
+ * @param ddash double dash array
654
+ * @public
655
+ */
656
+ async exec(
657
+ args: string[],
658
+ options: Record<string, ParserTypes> = {},
659
+ ddash: string[] = [],
660
+ ): Promise<unknown> {
661
+ this._programmaticMode = true
662
+ const cmd = await this.findCommand(args)
663
+ options = mapKeys(options, (v, key) => kebabCase(key))
664
+ return this._run(
665
+ {
666
+ args,
667
+ options,
668
+ line: args.join(" "),
669
+ rawOptions: options,
670
+ rawArgv: args,
671
+ ddash,
672
+ },
673
+ cmd,
674
+ )
675
+ }
676
+ }