@flowscripter/dynamic-cli-framework 1.7.3 → 1.7.5

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 (369) hide show
  1. package/cli-plugin.ts +1 -1
  2. package/dist/cli-plugin.d.ts +1 -1
  3. package/dist/cli-plugin.d.ts.map +1 -1
  4. package/dist/cli-plugin.js +25 -247
  5. package/dist/index.js +70 -105754
  6. package/dist/src/api/BaseCLIFeatureOptions.js +0 -0
  7. package/dist/src/api/CLI.js +0 -0
  8. package/dist/src/api/CLIConfig.js +0 -0
  9. package/dist/src/api/Context.js +0 -0
  10. package/dist/src/api/RunResult.js +73 -0
  11. package/dist/src/api/argument/Argument.js +0 -0
  12. package/dist/src/api/argument/ArgumentValueTypes.js +18 -0
  13. package/dist/src/api/argument/ComplexOption.js +1 -0
  14. package/dist/src/api/argument/GlobalCommandArgument.js +0 -0
  15. package/dist/src/api/argument/Option.js +0 -0
  16. package/dist/src/api/argument/Positional.js +0 -0
  17. package/dist/src/api/argument/SubCommandArgument.js +1 -0
  18. package/dist/src/api/command/Command.js +0 -0
  19. package/dist/src/api/command/GlobalCommand.js +0 -0
  20. package/dist/src/api/command/GlobalModifierCommand.js +0 -0
  21. package/dist/src/api/command/GroupCommand.js +0 -0
  22. package/dist/src/api/command/SubCommand.js +0 -0
  23. package/dist/src/api/command/UsageExample.js +0 -0
  24. package/dist/src/api/plugin/CLIPlugin.js +2 -0
  25. package/dist/src/api/plugin/CommandFactory.js +7 -0
  26. package/dist/src/api/plugin/ServiceProviderFactory.js +7 -0
  27. package/dist/src/api/plugin/createCLIPlugin.js +30 -0
  28. package/dist/src/api/service/ServiceProvider.js +0 -0
  29. package/dist/src/api/service/core/ArgumentPrompterService.js +1 -0
  30. package/dist/src/api/service/core/AsciiBannerGeneratorService.js +1 -0
  31. package/dist/src/api/service/core/CompletionService.js +8 -0
  32. package/dist/src/api/service/core/DataDumpGeneratorService.js +7 -0
  33. package/dist/src/api/service/core/ImagePrinterService.js +1 -0
  34. package/dist/src/api/service/core/KeyValueService.js +7 -0
  35. package/dist/src/api/service/core/PluginService.js +6 -0
  36. package/dist/src/api/service/core/PrettyPrinterService.js +1 -0
  37. package/dist/src/api/service/core/PrinterService.js +42 -0
  38. package/dist/src/api/service/core/PrompterService.js +10 -0
  39. package/dist/src/api/service/core/SecretService.js +0 -0
  40. package/dist/src/api/service/core/ShutdownService.js +1 -0
  41. package/dist/src/api/service/core/SyntaxHighlighterService.js +1 -0
  42. package/dist/src/api/service/core/Table.js +49 -0
  43. package/dist/src/api/service/core/TableGeneratorService.d.ts +1 -0
  44. package/dist/src/api/service/core/TableGeneratorService.d.ts.map +1 -1
  45. package/dist/src/api/service/core/TableGeneratorService.js +7 -0
  46. package/dist/src/api/service/core/TreePrinterService.js +1 -0
  47. package/dist/src/cli/BaseCLI.d.ts.map +1 -1
  48. package/dist/src/cli/BaseCLI.js +232 -0
  49. package/dist/src/cli/DefaultRuntimeCLI.js +20 -0
  50. package/dist/src/cli/DynamicPluginRuntimeCLI.js +50 -0
  51. package/dist/src/command/MultiCommandCliHelpCommand.js +238 -0
  52. package/dist/src/command/SingleCommandCliHelpCommand.js +104 -0
  53. package/dist/src/command/UsageCommand.js +16 -0
  54. package/dist/src/command/VersionCommand.js +13 -0
  55. package/dist/src/launcher.js +61 -0
  56. package/dist/src/runtime/DefaultContext.js +25 -0
  57. package/dist/src/runtime/argument/ArgumentTypeGuards.js +3 -0
  58. package/dist/src/runtime/command/CommandTypeGuards.js +12 -0
  59. package/dist/src/runtime/command/CommandValidator.js +371 -0
  60. package/dist/src/runtime/parser.js +105 -0
  61. package/dist/src/runtime/registry/CommandRegistry.js +0 -0
  62. package/dist/src/runtime/registry/DefaultCommandRegistry.js +190 -0
  63. package/dist/src/runtime/registry/DefaultServiceProviderRegistry.js +20 -0
  64. package/dist/src/runtime/registry/ServiceProviderRegistry.js +0 -0
  65. package/dist/src/runtime/runner.js +507 -0
  66. package/dist/src/runtime/scanner.js +244 -0
  67. package/dist/src/runtime/values/ValuePopulationResult.js +0 -0
  68. package/dist/src/runtime/values/argumentValueMerge.js +122 -0
  69. package/dist/src/runtime/values/argumentValueValidation.js +505 -0
  70. package/dist/src/runtime/values/globalCommandValuePopulation.js +67 -0
  71. package/dist/src/runtime/values/subCommandValuePopulation.js +549 -0
  72. package/dist/src/service/argumentPrompter/ArgumentPrompterServiceProvider.js +19 -0
  73. package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.js +197 -0
  74. package/dist/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.js +28 -0
  75. package/dist/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.js +233 -0
  76. package/dist/src/service/asciiBannerGenerator/standard.flf.json +3 -0
  77. package/dist/src/service/banner/BannerServiceProvider.js +60 -0
  78. package/dist/src/service/banner/command/NoBannerCommand.js +24 -0
  79. package/dist/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.js +51 -0
  80. package/dist/src/service/chiselAsciiBannerGenerator/chisel.flf.json +3 -0
  81. package/dist/src/service/completion/CompletionServiceProvider.d.ts +2 -1
  82. package/dist/src/service/completion/CompletionServiceProvider.d.ts.map +1 -1
  83. package/dist/src/service/completion/CompletionServiceProvider.js +159 -0
  84. package/dist/src/service/completion/DefaultCompletionService.js +279 -0
  85. package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts +15 -0
  86. package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts.map +1 -0
  87. package/dist/src/service/completion/command/CompletionCompleteSubCommand.js +37 -0
  88. package/dist/src/service/completion/command/CompletionGroupCommand.d.ts +14 -0
  89. package/dist/src/service/completion/command/CompletionGroupCommand.d.ts.map +1 -0
  90. package/dist/src/service/completion/command/CompletionGroupCommand.js +10 -0
  91. package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts +14 -0
  92. package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts.map +1 -0
  93. package/dist/src/service/completion/command/CompletionIntegrationSubCommand.js +67 -0
  94. package/dist/src/service/completion/shell/ShellHandler.js +0 -0
  95. package/dist/src/service/completion/shell/bash.js +39 -0
  96. package/dist/src/service/completion/shell/fish.js +35 -0
  97. package/dist/src/service/completion/shell/powershell.js +51 -0
  98. package/dist/src/service/completion/shell/zsh.js +42 -0
  99. package/dist/src/service/configuration/ConfigurationServiceProvider.js +482 -0
  100. package/dist/src/service/configuration/DefaultKeyValueService.js +80 -0
  101. package/dist/src/service/configuration/DefaultSecretService.js +60 -0
  102. package/dist/src/service/configuration/command/ConfigCommand.js +24 -0
  103. package/dist/src/service/configuration/command/DumpConfigCommand.js +18 -0
  104. package/dist/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.js +24 -0
  105. package/dist/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.js +59 -0
  106. package/dist/src/service/imagePrinter/DefaultImagePrinterService.js +10 -0
  107. package/dist/src/service/imagePrinter/ImagePrinterServiceProvider.js +20 -0
  108. package/dist/src/service/plugin/DefaultPluginService.js +21 -0
  109. package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts +1 -1
  110. package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts.map +1 -1
  111. package/dist/src/service/plugin/DefaultPluginServiceProvider.js +21 -0
  112. package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts +17 -0
  113. package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts.map +1 -0
  114. package/dist/src/service/plugin/command/PluginAddSubCommand.js +49 -0
  115. package/dist/src/service/plugin/command/PluginGroupCommand.d.ts +12 -0
  116. package/dist/src/service/plugin/command/PluginGroupCommand.d.ts.map +1 -0
  117. package/dist/src/service/plugin/command/PluginGroupCommand.js +21 -0
  118. package/dist/src/service/plugin/command/PluginListSubCommand.d.ts +12 -0
  119. package/dist/src/service/plugin/command/PluginListSubCommand.d.ts.map +1 -0
  120. package/dist/src/service/plugin/command/PluginListSubCommand.js +25 -0
  121. package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts +17 -0
  122. package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts.map +1 -0
  123. package/dist/src/service/plugin/command/PluginRemoveSubCommand.js +24 -0
  124. package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts +18 -0
  125. package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts.map +1 -0
  126. package/dist/src/service/plugin/command/PluginSearchSubCommand.js +34 -0
  127. package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts +12 -0
  128. package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts.map +1 -0
  129. package/dist/src/service/plugin/command/PluginUpgradeSubCommand.js +25 -0
  130. package/dist/src/service/plugin/command/getPluginId.d.ts +3 -0
  131. package/dist/src/service/plugin/command/getPluginId.d.ts.map +1 -0
  132. package/dist/src/service/plugin/command/getPluginId.js +3 -0
  133. package/dist/src/service/prettyPrinter/DefaultPrettyPrinterService.js +45 -0
  134. package/dist/src/service/prettyPrinter/PrettyPrinterServiceProvider.js +28 -0
  135. package/dist/src/service/printer/DefaultPrinterService.js +250 -0
  136. package/dist/src/service/printer/PrinterServiceProvider.js +43 -0
  137. package/dist/src/service/printer/command/DarkModeCommand.js +24 -0
  138. package/dist/src/service/printer/command/LogLevelCommand.js +41 -0
  139. package/dist/src/service/printer/command/NoColorCommand.js +24 -0
  140. package/dist/src/service/printer/command/NoHyperlinksCommand.js +21 -0
  141. package/dist/src/service/printer/terminal/Color.js +15 -0
  142. package/dist/src/service/printer/terminal/Progress.js +271 -0
  143. package/dist/src/service/printer/terminal/Spinner.js +83 -0
  144. package/dist/src/service/printer/terminal/Theme.js +26 -0
  145. package/dist/src/service/prompter/DefaultPrompterService.js +52 -0
  146. package/dist/src/service/prompter/PrompterServiceProvider.js +20 -0
  147. package/dist/src/service/prompter/command/NoPromptCommand.js +21 -0
  148. package/dist/src/service/prompter/prompt/PromptContext.js +22 -0
  149. package/dist/src/service/prompter/prompt/promptAcknowledge.js +19 -0
  150. package/dist/src/service/prompter/prompt/promptMultiSelect.js +74 -0
  151. package/dist/src/service/prompter/prompt/promptOpenUrl.js +70 -0
  152. package/dist/src/service/prompter/prompt/promptSingleSelect.js +73 -0
  153. package/dist/src/service/prompter/prompt/promptText.js +75 -0
  154. package/dist/src/service/prompter/prompt/promptToggle.js +21 -0
  155. package/dist/src/service/shutdown/DefaultShutdownService.js +16 -0
  156. package/dist/src/service/shutdown/ShutdownServiceProvider.js +60 -0
  157. package/dist/src/service/shutdown/ShutdownState.js +5 -0
  158. package/dist/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.js +54 -0
  159. package/dist/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.js +32 -0
  160. package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts +3 -1
  161. package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts.map +1 -1
  162. package/dist/src/service/tableGenerator/DefaultTableGeneratorService.js +344 -0
  163. package/dist/src/service/tableGenerator/TableGeneratorServiceProvider.js +26 -0
  164. package/dist/src/service/treePrinter/DefaultTreePrinterService.js +35 -0
  165. package/dist/src/service/treePrinter/TreePrinterServiceProvider.js +24 -0
  166. package/dist/src/terminal/Ansi.js +23 -0
  167. package/dist/src/terminal/ImageRenderer.d.ts.map +1 -1
  168. package/dist/src/terminal/ImageRenderer.js +166 -0
  169. package/dist/src/terminal/KeyReader.js +13 -0
  170. package/dist/src/terminal/PngDecoder.js +115 -0
  171. package/dist/src/terminal/Styler.js +0 -0
  172. package/dist/src/terminal/Terminal.js +0 -0
  173. package/dist/src/terminal/TtyKeyReader.js +87 -0
  174. package/dist/src/terminal/TtyStyler.js +55 -0
  175. package/dist/src/terminal/TtyTerminal.js +52 -0
  176. package/dist/src/terminal/supportsHyperlinks.js +95 -0
  177. package/dist/src/util/configHelper.js +61 -0
  178. package/dist/src/util/envVarHelper.js +216 -0
  179. package/dist/src/util/helpHelper.d.ts.map +1 -1
  180. package/dist/src/util/helpHelper.js +497 -0
  181. package/dist/src/util/logger.js +81 -0
  182. package/dist/src/util/runnerHelper.js +80 -0
  183. package/package.json +2 -2
  184. package/src/api/service/core/TableGeneratorService.ts +1 -0
  185. package/src/cli/BaseCLI.ts +4 -19
  186. package/src/service/completion/CompletionServiceProvider.ts +16 -3
  187. package/src/service/completion/command/CompletionCompleteSubCommand.ts +59 -0
  188. package/src/service/completion/command/CompletionGroupCommand.ts +21 -0
  189. package/src/{command/CompletionCommand.ts → service/completion/command/CompletionIntegrationSubCommand.ts} +12 -73
  190. package/src/service/completion/shell/bash.ts +1 -1
  191. package/src/service/completion/shell/fish.ts +1 -1
  192. package/src/service/completion/shell/powershell.ts +1 -1
  193. package/src/service/completion/shell/zsh.ts +1 -1
  194. package/src/service/plugin/DefaultPluginServiceProvider.ts +2 -2
  195. package/src/service/plugin/command/PluginAddSubCommand.ts +64 -0
  196. package/src/service/plugin/command/PluginGroupCommand.ts +27 -0
  197. package/src/service/plugin/command/PluginListSubCommand.ts +33 -0
  198. package/src/service/plugin/command/PluginRemoveSubCommand.ts +32 -0
  199. package/src/service/plugin/command/PluginSearchSubCommand.ts +42 -0
  200. package/src/service/plugin/command/PluginUpgradeSubCommand.ts +36 -0
  201. package/src/service/plugin/command/getPluginId.ts +5 -0
  202. package/src/service/tableGenerator/DefaultTableGeneratorService.ts +6 -1
  203. package/src/terminal/ImageRenderer.ts +7 -5
  204. package/src/util/helpHelper.ts +1 -2
  205. package/dist/src/command/CompletionCommand.d.ts +0 -32
  206. package/dist/src/command/CompletionCommand.d.ts.map +0 -1
  207. package/dist/src/command/PluginCommand.d.ts +0 -67
  208. package/dist/src/command/PluginCommand.d.ts.map +0 -1
  209. package/dist/tests/cli/BaseCLI.test.d.ts +0 -2
  210. package/dist/tests/cli/BaseCLI.test.d.ts.map +0 -1
  211. package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts +0 -2
  212. package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts.map +0 -1
  213. package/dist/tests/command/CompletionCommand.test.d.ts +0 -2
  214. package/dist/tests/command/CompletionCommand.test.d.ts.map +0 -1
  215. package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts +0 -2
  216. package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts.map +0 -1
  217. package/dist/tests/command/PluginCommand.test.d.ts +0 -2
  218. package/dist/tests/command/PluginCommand.test.d.ts.map +0 -1
  219. package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts +0 -2
  220. package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts.map +0 -1
  221. package/dist/tests/command/UsageCommand.test.d.ts +0 -2
  222. package/dist/tests/command/UsageCommand.test.d.ts.map +0 -1
  223. package/dist/tests/command/VersionCommand.test.d.ts +0 -2
  224. package/dist/tests/command/VersionCommand.test.d.ts.map +0 -1
  225. package/dist/tests/fixtures/CLIConfig.d.ts +0 -3
  226. package/dist/tests/fixtures/CLIConfig.d.ts.map +0 -1
  227. package/dist/tests/fixtures/Command.d.ts +0 -20
  228. package/dist/tests/fixtures/Command.d.ts.map +0 -1
  229. package/dist/tests/fixtures/CommandRegistry.d.ts +0 -4
  230. package/dist/tests/fixtures/CommandRegistry.d.ts.map +0 -1
  231. package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts +0 -10
  232. package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts.map +0 -1
  233. package/dist/tests/fixtures/Context.d.ts +0 -4
  234. package/dist/tests/fixtures/Context.d.ts.map +0 -1
  235. package/dist/tests/fixtures/ServiceProviderRegistry.d.ts +0 -4
  236. package/dist/tests/fixtures/ServiceProviderRegistry.d.ts.map +0 -1
  237. package/dist/tests/fixtures/StreamString.d.ts +0 -10
  238. package/dist/tests/fixtures/StreamString.d.ts.map +0 -1
  239. package/dist/tests/fixtures/prettierPluginFoo.d.ts +0 -4
  240. package/dist/tests/fixtures/prettierPluginFoo.d.ts.map +0 -1
  241. package/dist/tests/fixtures/util.d.ts +0 -8
  242. package/dist/tests/fixtures/util.d.ts.map +0 -1
  243. package/dist/tests/runtime/DefaultContext.test.d.ts +0 -2
  244. package/dist/tests/runtime/DefaultContext.test.d.ts.map +0 -1
  245. package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts +0 -2
  246. package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts.map +0 -1
  247. package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts +0 -2
  248. package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts.map +0 -1
  249. package/dist/tests/runtime/command/CommandValidator.test.d.ts +0 -2
  250. package/dist/tests/runtime/command/CommandValidator.test.d.ts.map +0 -1
  251. package/dist/tests/runtime/parser.test.d.ts +0 -2
  252. package/dist/tests/runtime/parser.test.d.ts.map +0 -1
  253. package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts +0 -2
  254. package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts.map +0 -1
  255. package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts +0 -2
  256. package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts.map +0 -1
  257. package/dist/tests/runtime/runner.test.d.ts +0 -2
  258. package/dist/tests/runtime/runner.test.d.ts.map +0 -1
  259. package/dist/tests/runtime/scanner.test.d.ts +0 -2
  260. package/dist/tests/runtime/scanner.test.d.ts.map +0 -1
  261. package/dist/tests/runtime/values/argumentValueMerge.test.d.ts +0 -2
  262. package/dist/tests/runtime/values/argumentValueMerge.test.d.ts.map +0 -1
  263. package/dist/tests/runtime/values/argumentValueValidation.test.d.ts +0 -2
  264. package/dist/tests/runtime/values/argumentValueValidation.test.d.ts.map +0 -1
  265. package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts +0 -2
  266. package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts.map +0 -1
  267. package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts +0 -2
  268. package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts.map +0 -1
  269. package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts +0 -2
  270. package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts.map +0 -1
  271. package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts +0 -2
  272. package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts.map +0 -1
  273. package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts +0 -2
  274. package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts.map +0 -1
  275. package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts +0 -2
  276. package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts.map +0 -1
  277. package/dist/tests/service/banner/BannerServiceProvider.test.d.ts +0 -2
  278. package/dist/tests/service/banner/BannerServiceProvider.test.d.ts.map +0 -1
  279. package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts +0 -2
  280. package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts.map +0 -1
  281. package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts +0 -2
  282. package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts.map +0 -1
  283. package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts +0 -2
  284. package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts.map +0 -1
  285. package/dist/tests/service/completion/DefaultCompletionService.test.d.ts +0 -2
  286. package/dist/tests/service/completion/DefaultCompletionService.test.d.ts.map +0 -1
  287. package/dist/tests/service/completion/shell/bash.test.d.ts +0 -2
  288. package/dist/tests/service/completion/shell/bash.test.d.ts.map +0 -1
  289. package/dist/tests/service/completion/shell/fish.test.d.ts +0 -2
  290. package/dist/tests/service/completion/shell/fish.test.d.ts.map +0 -1
  291. package/dist/tests/service/completion/shell/powershell.test.d.ts +0 -2
  292. package/dist/tests/service/completion/shell/powershell.test.d.ts.map +0 -1
  293. package/dist/tests/service/completion/shell/zsh.test.d.ts +0 -2
  294. package/dist/tests/service/completion/shell/zsh.test.d.ts.map +0 -1
  295. package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts +0 -2
  296. package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts.map +0 -1
  297. package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts +0 -2
  298. package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts.map +0 -1
  299. package/dist/tests/service/configuration/DefaultSecretService.test.d.ts +0 -2
  300. package/dist/tests/service/configuration/DefaultSecretService.test.d.ts.map +0 -1
  301. package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts +0 -2
  302. package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts.map +0 -1
  303. package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts +0 -2
  304. package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts.map +0 -1
  305. package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts +0 -2
  306. package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts.map +0 -1
  307. package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts +0 -2
  308. package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts.map +0 -1
  309. package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts +0 -2
  310. package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts.map +0 -1
  311. package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts +0 -2
  312. package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts.map +0 -1
  313. package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts +0 -2
  314. package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts.map +0 -1
  315. package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts +0 -2
  316. package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts.map +0 -1
  317. package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts +0 -2
  318. package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts.map +0 -1
  319. package/dist/tests/service/printer/DefaultPrinterService.test.d.ts +0 -2
  320. package/dist/tests/service/printer/DefaultPrinterService.test.d.ts.map +0 -1
  321. package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts +0 -2
  322. package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts.map +0 -1
  323. package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts +0 -2
  324. package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts.map +0 -1
  325. package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts +0 -2
  326. package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts.map +0 -1
  327. package/dist/tests/service/printer/command/NoColorCommand.test.d.ts +0 -2
  328. package/dist/tests/service/printer/command/NoColorCommand.test.d.ts.map +0 -1
  329. package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts +0 -2
  330. package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts.map +0 -1
  331. package/dist/tests/service/printer/terminal/Progress.test.d.ts +0 -2
  332. package/dist/tests/service/printer/terminal/Progress.test.d.ts.map +0 -1
  333. package/dist/tests/service/printer/terminal/Spinner.test.d.ts +0 -2
  334. package/dist/tests/service/printer/terminal/Spinner.test.d.ts.map +0 -1
  335. package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts +0 -2
  336. package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts.map +0 -1
  337. package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts +0 -2
  338. package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts.map +0 -1
  339. package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts +0 -2
  340. package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts.map +0 -1
  341. package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts +0 -2
  342. package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts.map +0 -1
  343. package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts +0 -2
  344. package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts.map +0 -1
  345. package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts +0 -2
  346. package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts.map +0 -1
  347. package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts +0 -2
  348. package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts.map +0 -1
  349. package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts +0 -2
  350. package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts.map +0 -1
  351. package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts +0 -2
  352. package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts.map +0 -1
  353. package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts +0 -2
  354. package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts.map +0 -1
  355. package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts +0 -2
  356. package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts.map +0 -1
  357. package/dist/tests/terminal/ImageRenderer.test.d.ts +0 -2
  358. package/dist/tests/terminal/ImageRenderer.test.d.ts.map +0 -1
  359. package/dist/tests/terminal/PngDecoder.test.d.ts +0 -2
  360. package/dist/tests/terminal/PngDecoder.test.d.ts.map +0 -1
  361. package/dist/tests/terminal/supportsHyperlinks.test.d.ts +0 -2
  362. package/dist/tests/terminal/supportsHyperlinks.test.d.ts.map +0 -1
  363. package/dist/tests/util/configHelper.test.d.ts +0 -2
  364. package/dist/tests/util/configHelper.test.d.ts.map +0 -1
  365. package/dist/tests/util/envVarHelper.test.d.ts +0 -2
  366. package/dist/tests/util/envVarHelper.test.d.ts.map +0 -1
  367. package/dist/tests/util/logger.test.d.ts +0 -2
  368. package/dist/tests/util/logger.test.d.ts.map +0 -1
  369. package/src/command/PluginCommand.ts +0 -197
@@ -0,0 +1,371 @@
1
+ import { isGroupCommand, isSubCommand } from "./CommandTypeGuards.js";
2
+ import { ArgumentValueTypeName, ComplexValueTypeName, } from "../../api/argument/ArgumentValueTypes.js";
3
+ import { isComplexOption } from "../argument/ArgumentTypeGuards.js";
4
+ import { getInvalidArgumentString, validateGlobalCommandArgumentValue, validateOptionValue, } from "../values/argumentValueValidation.js";
5
+ import getLogger from "../../util/logger.js";
6
+ import { getGlobalCommandArgumentConfigurationKey, getSubCommandArgumentConfigurationKey, } from "../../util/configHelper.js";
7
+ const logger = getLogger("commandValidation");
8
+ function validateValueType(type, value, argumentName, isDefaultValue, isRangeValue) {
9
+ switch (type) {
10
+ case ArgumentValueTypeName.BOOLEAN:
11
+ if (typeof value !== "boolean") {
12
+ throw new Error(`Specified ${isDefaultValue ? "default" : "allowable"} value: '${value}' for argument: '${argumentName}' should be a boolean`);
13
+ }
14
+ break;
15
+ case ArgumentValueTypeName.NUMBER:
16
+ if (typeof value !== "number" || !Number.isFinite(value)) {
17
+ throw new Error(`Specified ${isDefaultValue ? "default" : isRangeValue ? "range" : "allowable"} value: '${value}' for argument: '${argumentName}' should be a finite number`);
18
+ }
19
+ break;
20
+ case ArgumentValueTypeName.INTEGER:
21
+ if (typeof value !== "number" || !Number.isInteger(value)) {
22
+ throw new Error(`Specified ${isDefaultValue ? "default" : isRangeValue ? "range" : "allowable"} value: '${value}' for argument: '${argumentName}' should be an integer`);
23
+ }
24
+ break;
25
+ case ArgumentValueTypeName.STRING:
26
+ if (typeof value !== "string") {
27
+ throw new Error(`Specified ${isDefaultValue ? "default" : "allowable"} value: '${value}' for argument: '${argumentName}' should be a string`);
28
+ }
29
+ break;
30
+ }
31
+ }
32
+ function isAlphaNumeric(value) {
33
+ return value.match(/^[a-z0-9]$/i) !== null;
34
+ }
35
+ function isAlphaNumericOrDashOrUnderscore(value) {
36
+ return value.match(/^[a-z0-9\-_]+$/i) !== null;
37
+ }
38
+ function isUppercaseAlphaNumericOrUnderscore(value) {
39
+ return value.match(/^[A-Z0-9_]+$/) !== null;
40
+ }
41
+ function isNameLegal(name) {
42
+ return name.length > 0 && isAlphaNumericOrDashOrUnderscore(name) && name[0] !== "-";
43
+ }
44
+ function isConfigurationKeyLegal(configurationKey) {
45
+ return (configurationKey.length > 0 &&
46
+ isUppercaseAlphaNumericOrUnderscore(configurationKey) &&
47
+ !configurationKey[0].match(/[0-9]/));
48
+ }
49
+ function validateArgument(argument, name) {
50
+ if (argument.type !== ArgumentValueTypeName.NUMBER &&
51
+ argument.type !== ArgumentValueTypeName.INTEGER &&
52
+ argument.type !== ArgumentValueTypeName.STRING &&
53
+ argument.type !== ArgumentValueTypeName.BOOLEAN) {
54
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}'`);
55
+ }
56
+ if (argument.allowableValues) {
57
+ if (argument.type === ArgumentValueTypeName.BOOLEAN) {
58
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}' with allowable values specified`);
59
+ }
60
+ argument.allowableValues.forEach((value) => {
61
+ validateValueType(argument.type, value, name, false, false);
62
+ });
63
+ }
64
+ if (argument.isCaseInsensitive !== undefined) {
65
+ if (argument.type === ArgumentValueTypeName.BOOLEAN && argument.isCaseInsensitive === false) {
66
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}' must always be case insensitive`);
67
+ }
68
+ else if (argument.type !== ArgumentValueTypeName.STRING) {
69
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}' with case insensitive specified`);
70
+ }
71
+ }
72
+ if (argument.minValueInclusive !== undefined) {
73
+ if (argument.type !== ArgumentValueTypeName.NUMBER &&
74
+ argument.type !== ArgumentValueTypeName.INTEGER) {
75
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}' with min value specified`);
76
+ }
77
+ if (argument.allowableValues) {
78
+ throw new Error(`Illegal combination of allowable values and min value for argument: '${name}'`);
79
+ }
80
+ validateValueType(argument.type, argument.minValueInclusive, name, false, true);
81
+ }
82
+ if (argument.maxValueInclusive !== undefined) {
83
+ if (argument.type !== ArgumentValueTypeName.NUMBER &&
84
+ argument.type !== ArgumentValueTypeName.INTEGER) {
85
+ throw new Error(`Illegal type: '${argument.type}' for argument: '${name}' with max value specified`);
86
+ }
87
+ if (argument.allowableValues) {
88
+ throw new Error(`Illegal combination of allowable values and max value for argument: '${name}'`);
89
+ }
90
+ validateValueType(argument.type, argument.maxValueInclusive, name, false, true);
91
+ }
92
+ }
93
+ function validateSubCommandArgument(subCommandArgument) {
94
+ if (!isNameLegal(subCommandArgument.name)) {
95
+ throw new Error(`Illegal argument name: '${subCommandArgument.name}'`);
96
+ }
97
+ return validateArgument(subCommandArgument, subCommandArgument.name);
98
+ }
99
+ export default class CommandValidator {
100
+ #cliConfig;
101
+ #configurationKeys = [];
102
+ constructor(cliConfig) {
103
+ this.#cliConfig = cliConfig;
104
+ }
105
+ /**
106
+ * Validates the provided {@link Command}.
107
+ *
108
+ * @param command the {@link Command} to validate.
109
+ *
110
+ * @throws {Error} if the provided command does not pass validation.
111
+ */
112
+ validate(command) {
113
+ logger.debug("Validating command: %s", command.name);
114
+ if (isSubCommand(command)) {
115
+ this.#validateSubCommand(command);
116
+ }
117
+ else if (isGroupCommand(command)) {
118
+ this.#validateGroupCommand(command);
119
+ }
120
+ else {
121
+ this.#validateGlobalCommand(command);
122
+ }
123
+ }
124
+ /**
125
+ * Validates the provided {@link GlobalCommand} or by extension {@link GlobalModifierCommand}.
126
+ *
127
+ * @param globalCommand the {@link GlobalCommand} to validate.
128
+ *
129
+ * @throws {Error} if:
130
+ * * the {@link Command.name} does not consist only of alphanumeric non-whitespace ASCII characters or `_` and `-`
131
+ * characters.
132
+ * * the {@link Command.name} starts with `-`.
133
+ * * the {@link GlobalCommand.shortAlias} does not consist of a single alphanumeric non-whitespace ASCII character.
134
+ * * the {@link GlobalCommand.argument} is defined and it is not valid.
135
+ */
136
+ #validateGlobalCommand(globalCommand) {
137
+ if (!isNameLegal(globalCommand.name)) {
138
+ throw new Error(`Illegal global command name: '${globalCommand.name}'`);
139
+ }
140
+ if (globalCommand.shortAlias &&
141
+ (globalCommand.shortAlias.length !== 1 || !isAlphaNumeric(globalCommand.shortAlias))) {
142
+ throw new Error(`Illegal short alias: '${globalCommand.shortAlias}' for global command: '${globalCommand.name}'`);
143
+ }
144
+ if (globalCommand.argument) {
145
+ const { argument } = globalCommand;
146
+ validateArgument(argument, globalCommand.name);
147
+ if (argument.defaultValue) {
148
+ const invalidArguments = [];
149
+ validateGlobalCommandArgumentValue(globalCommand, argument.defaultValue, invalidArguments);
150
+ if (invalidArguments.length > 0) {
151
+ throw new Error(`Illegal default value for global command: '${globalCommand.name}' => ${invalidArguments
152
+ .map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
153
+ .join(", ")}`);
154
+ }
155
+ }
156
+ this.#validateGlobalCommandArgumentConfigurationKey(globalCommand, argument);
157
+ }
158
+ }
159
+ /**
160
+ * Validates the provided {@link GroupCommand}.
161
+ *
162
+ * @param groupCommand the {@link GroupCommand} to validate.
163
+ *
164
+ * @throws {Error} if:
165
+ * * the {@link Command.name} does not consist only of alphanumeric non-whitespace ASCII characters or `_` and `-`
166
+ * characters.
167
+ * * the {@link Command.name} starts with `-`.
168
+ * * {@link GroupCommand.memberSubCommands} is empty.
169
+ * * any of the member {@link SubCommand} instances are themselves not valid.
170
+ * * any of the member {@link SubCommand} instances define duplicate names.
171
+ * * any of the member {@link SubCommand} instances define a name which duplicates the group command name.
172
+ */
173
+ #validateGroupCommand(groupCommand) {
174
+ if (!isNameLegal(groupCommand.name)) {
175
+ throw new Error(`Illegal group command name: '${groupCommand.name}'`);
176
+ }
177
+ if (groupCommand.memberSubCommands.length === 0) {
178
+ throw new Error(`Group command: '${groupCommand.name}' has no member sub-commands`);
179
+ }
180
+ const subCommandNames = [];
181
+ groupCommand.memberSubCommands.forEach((subCommand) => {
182
+ if (subCommandNames.includes(subCommand.name)) {
183
+ throw new Error(`Group command: '${groupCommand.name}' contains member sub-commands with duplicate name: '${subCommand.name}'`);
184
+ }
185
+ if (subCommand.name === groupCommand.name) {
186
+ throw new Error(`Group command: '${groupCommand.name}' contains member sub-command with the same name`);
187
+ }
188
+ subCommandNames.push(subCommand.name);
189
+ this.#validateSubCommand(subCommand);
190
+ });
191
+ }
192
+ /**
193
+ * Validates the provided {@link SubCommand}.
194
+ *
195
+ * @param subCommand the {@link SubCommand} to validate.
196
+ *
197
+ * @throws {Error} if:
198
+ * the {@link Command.name} does not consist only of alphanumeric non-whitespace ASCII characters or `_` and `-`
199
+ characters.
200
+ * the {@link Command.name} starts with `-`.
201
+ * * any [[SubCommandArgument.name]] name does not consist only of alphanumeric non-whitespace ASCII characters
202
+ * or `_` and `-` characters or starts with `-`.
203
+ * * any entry in {@link SubCommand.options} is not valid.
204
+ * * any entry in {@link SubCommand.positionals} is not valid.
205
+ * * there are duplicate names in the {@link SubCommandArgument} instances defined by {@link SubCommand.options} and
206
+ * {@link SubCommand.positionals}.
207
+ * * there are duplicate property paths defined by {@link Argument.name} and {@link Option.shortAlias} entries in nested
208
+ * {@link ComplexOption} instances.
209
+ */
210
+ #validateSubCommand(subCommand) {
211
+ if (!isNameLegal(subCommand.name)) {
212
+ throw new Error(`Illegal sub-command name: '${subCommand.name}'`);
213
+ }
214
+ const argumentNames = [];
215
+ const optionAliases = [];
216
+ const allOptionPaths = [];
217
+ if (subCommand.options) {
218
+ subCommand.options.forEach((option) => {
219
+ if (argumentNames.includes(option.name)) {
220
+ throw new Error(`Sub-command: '${subCommand.name}' contains arguments with the same name: '${option.name}'`);
221
+ }
222
+ argumentNames.push(option.name);
223
+ const currentOptionPaths = [""];
224
+ if (option.shortAlias) {
225
+ if (argumentNames.includes(option.shortAlias)) {
226
+ throw new Error(`Sub-command: '${subCommand.name}' contains arguments with the same name and short alias: '${option.shortAlias}'`);
227
+ }
228
+ if (optionAliases.includes(option.shortAlias)) {
229
+ throw new Error(`Sub-command: '${subCommand.name}' contains arguments with the same short alias: '${option.shortAlias}'`);
230
+ }
231
+ optionAliases.push(option.shortAlias);
232
+ }
233
+ this.#validateOptionOrComplexOption(subCommand, option, currentOptionPaths, allOptionPaths, []);
234
+ });
235
+ }
236
+ if (subCommand.positionals) {
237
+ for (let i = 0; i < subCommand.positionals.length; i += 1) {
238
+ const positional = subCommand.positionals[i];
239
+ validateSubCommandArgument(positional);
240
+ if (argumentNames.includes(positional.name)) {
241
+ throw new Error(`Sub-command: '${subCommand.name}' contains arguments with the same name: '${positional.name}'`);
242
+ }
243
+ argumentNames.push(positional.name);
244
+ if (i < subCommand.positionals.length - 1 &&
245
+ (positional.isVarargOptional || positional.isVarargMultiple)) {
246
+ throw new Error(`Positional: '${positional.name}' for the command: '${subCommand.name}' is defined as a vararg but it is not the last positional argument`);
247
+ }
248
+ this.#validateSubCommandArgumentConfigurationKey(subCommand, [positional]);
249
+ }
250
+ }
251
+ }
252
+ #validateSubCommandArgumentConfigurationKey(command, argumentAncestry) {
253
+ const argument = argumentAncestry[argumentAncestry.length - 1];
254
+ if (command.enableConfiguration === true) {
255
+ if (argument.configurationKey !== undefined &&
256
+ !isConfigurationKeyLegal(argument.configurationKey)) {
257
+ throw new Error(`Illegal configuration key: '${argument.configurationKey}'`);
258
+ }
259
+ const configurationKey = getSubCommandArgumentConfigurationKey(this.#cliConfig, command, argumentAncestry);
260
+ if (configurationKey !== undefined) {
261
+ if (this.#configurationKeys.includes(configurationKey)) {
262
+ throw new Error(`Command: '${command.name}' contains arguments with the same configuration key: '${configurationKey}'`);
263
+ }
264
+ this.#configurationKeys.push(configurationKey);
265
+ }
266
+ }
267
+ else if (argument.configurationKey !== undefined) {
268
+ throw new Error(`Command: '${command.name}' enableConfiguration is false, but an argument defines a configurationKey: '${argument.configurationKey}'`);
269
+ }
270
+ }
271
+ #validateGlobalCommandArgumentConfigurationKey(command, globalCommandArgument) {
272
+ if (command.enableConfiguration === true) {
273
+ if (globalCommandArgument.configurationKey !== undefined &&
274
+ !isConfigurationKeyLegal(globalCommandArgument.configurationKey)) {
275
+ throw new Error(`Illegal configuration key: '${globalCommandArgument.configurationKey}'`);
276
+ }
277
+ const configurationKey = getGlobalCommandArgumentConfigurationKey(this.#cliConfig, command, globalCommandArgument);
278
+ if (configurationKey !== undefined) {
279
+ if (this.#configurationKeys.includes(configurationKey)) {
280
+ throw new Error(`Command: '${command.name}' contains arguments with the same configuration key: '${configurationKey}'`);
281
+ }
282
+ this.#configurationKeys.push(configurationKey);
283
+ }
284
+ }
285
+ else if (globalCommandArgument.configurationKey !== undefined) {
286
+ throw new Error(`Command: '${command.name}' enableConfiguration is false, but an argument defines a configurationKey: '${globalCommandArgument.configurationKey}'`);
287
+ }
288
+ }
289
+ #validateOptionOrComplexOption(subCommand, option, currentOptionPaths, allOptionPaths, argumentAncestry) {
290
+ if (option.shortAlias &&
291
+ (option.shortAlias.length !== 1 || !isAlphaNumeric(option.shortAlias))) {
292
+ throw new Error(`Illegal short alias: '${option.shortAlias}' for option: '${option.name}'`);
293
+ }
294
+ if (isComplexOption(option)) {
295
+ this.#validateComplexOption(subCommand, option, currentOptionPaths, allOptionPaths, [
296
+ ...argumentAncestry,
297
+ option,
298
+ ]);
299
+ }
300
+ else {
301
+ this.#validateOption(option, currentOptionPaths, allOptionPaths);
302
+ this.#validateSubCommandArgumentConfigurationKey(subCommand, [...argumentAncestry, option]);
303
+ }
304
+ }
305
+ #validateOption(option, currentOptionPaths, allOptionPaths) {
306
+ validateSubCommandArgument(option);
307
+ if (Array.isArray(option.defaultValue) && !option.isArray) {
308
+ throw new Error(`Illegal array default value: '${option.defaultValue.join(",")}' for non-array option: '${option.name}'`);
309
+ }
310
+ if (option.defaultValue) {
311
+ const invalidArguments = [];
312
+ validateOptionValue(option, option.defaultValue, invalidArguments);
313
+ if (invalidArguments.length > 0) {
314
+ throw new Error(`Illegal default value for option: '${option.name}' => ${invalidArguments
315
+ .map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
316
+ .join(", ")}`);
317
+ }
318
+ }
319
+ currentOptionPaths.forEach((currentOptionPath) => {
320
+ const leafPath = `${currentOptionPath}.${option.name}`;
321
+ if (allOptionPaths.includes(leafPath)) {
322
+ throw new Error(`Duplicate nested option path: '${leafPath}' discovered for option: '${option.name}'`);
323
+ }
324
+ allOptionPaths.push(leafPath);
325
+ });
326
+ if (option.shortAlias) {
327
+ currentOptionPaths.forEach((currentOptionPath) => {
328
+ const leafPath = `${currentOptionPath}.${option.shortAlias}`;
329
+ if (allOptionPaths.includes(leafPath)) {
330
+ throw new Error(`Duplicate nested option path: '${leafPath}' discovered for option: '${option.name}'`);
331
+ }
332
+ allOptionPaths.push(leafPath);
333
+ });
334
+ }
335
+ }
336
+ #validateComplexOption(subCommand, complexOption, currentOptionPaths, allOptionPaths, argumentAncestry) {
337
+ if (!isNameLegal(complexOption.name)) {
338
+ throw new Error(`Illegal complex option name: '${complexOption.name}'`);
339
+ }
340
+ if (complexOption.type !== ComplexValueTypeName.COMPLEX) {
341
+ throw new Error(`Illegal type: '${complexOption.type}' for complex option: '${complexOption.name}'`);
342
+ }
343
+ if (Array.isArray(complexOption.defaultValue) && !complexOption.isArray) {
344
+ throw new Error(`Illegal array default value: '${JSON.stringify(complexOption.defaultValue)}' for non-array option: '${complexOption.name}'`);
345
+ }
346
+ if (complexOption.defaultValue) {
347
+ const invalidArguments = [];
348
+ validateOptionValue(complexOption, complexOption.defaultValue, invalidArguments);
349
+ if (invalidArguments.length > 0) {
350
+ throw new Error(`Illegal default value for option: '${complexOption.name}' => ${invalidArguments
351
+ .map((invalidArgument) => getInvalidArgumentString(invalidArgument, true))
352
+ .join(", ")}`);
353
+ }
354
+ }
355
+ if (complexOption.properties.length === 0) {
356
+ throw new Error(`Complex option: '${complexOption.name}' has no properties`);
357
+ }
358
+ complexOption.properties.forEach((property) => {
359
+ const newCurrentOptionPaths = [];
360
+ currentOptionPaths.forEach((currentOptionPath) => {
361
+ newCurrentOptionPaths.push(`${currentOptionPath}.${property.name}`);
362
+ });
363
+ if (property.shortAlias) {
364
+ currentOptionPaths.forEach((currentOptionPath) => {
365
+ newCurrentOptionPaths.push(`${currentOptionPath}.${property.shortAlias}`);
366
+ });
367
+ }
368
+ this.#validateOptionOrComplexOption(subCommand, property, newCurrentOptionPaths, allOptionPaths, [...argumentAncestry, complexOption]);
369
+ });
370
+ }
371
+ }
@@ -0,0 +1,105 @@
1
+ import populateGlobalCommandValue from "./values/globalCommandValuePopulation.js";
2
+ import { validateGlobalCommandArgumentValue, validateOptionValue, validatePositionalValue, } from "./values/argumentValueValidation.js";
3
+ import getLogger from "../util/logger.js";
4
+ import populateSubCommandValues from "./values/subCommandValuePopulation.js";
5
+ const logger = getLogger("parser");
6
+ /**
7
+ * Parse the arguments for the specified {@link CommandClause} assuming it contains a {@link SubCommand}.
8
+ *
9
+ * @param commandClause the clause to parse.
10
+ * @param defaultValues optional default {@link PopulatedArgumentValues} to use for population before parsing the provided arguments.
11
+ */
12
+ export function parseSubCommandClause(commandClause, defaultValues) {
13
+ const command = commandClause.command;
14
+ const potentialArgs = commandClause.potentialArgs;
15
+ const groupCommand = commandClause.groupCommand;
16
+ const invalidArguments = [];
17
+ // check if we need to process any arguments at all
18
+ if (command.options.length === 0 && command.positionals.length === 0) {
19
+ return {
20
+ command,
21
+ groupCommand,
22
+ populatedArgumentValues: {},
23
+ invalidArguments,
24
+ unusedArgs: potentialArgs,
25
+ };
26
+ }
27
+ const { populatedArgumentValues, unusedArgs, invalidArgument } = populateSubCommandValues(command, potentialArgs, defaultValues);
28
+ if (invalidArgument) {
29
+ invalidArguments.push(invalidArgument);
30
+ }
31
+ if (invalidArguments.length === 0) {
32
+ // validate the option values
33
+ command.options.forEach((option) => {
34
+ const validatedValue = validateOptionValue(option, populatedArgumentValues[option.name] || option.defaultValue, invalidArguments);
35
+ if (validatedValue !== undefined) {
36
+ populatedArgumentValues[option.name] = validatedValue;
37
+ }
38
+ });
39
+ logger.debug("Command arguments after options validated: %O with invalid args: %O", populatedArgumentValues, invalidArguments);
40
+ if (invalidArguments.length === 0) {
41
+ // validate the positional values
42
+ command.positionals.forEach((positional) => {
43
+ const validatedValue = validatePositionalValue(positional, populatedArgumentValues[positional.name], invalidArguments);
44
+ if (validatedValue !== undefined) {
45
+ populatedArgumentValues[positional.name] = validatedValue;
46
+ }
47
+ });
48
+ logger.debug("Command arguments after positionals validated: %O with invalid args: %O", populatedArgumentValues, invalidArguments);
49
+ }
50
+ }
51
+ if (groupCommand) {
52
+ return {
53
+ command,
54
+ populatedArgumentValues,
55
+ groupCommand,
56
+ invalidArguments,
57
+ unusedArgs,
58
+ };
59
+ }
60
+ return {
61
+ command,
62
+ populatedArgumentValues,
63
+ invalidArguments,
64
+ unusedArgs: unusedArgs,
65
+ };
66
+ }
67
+ /**
68
+ * Parse the arguments for the specified {@link CommandClause} assuming it contains a {@link GlobalCommand} or {@link GlobalModifierCommand}.
69
+ *
70
+ * @param commandClause the clause to parse.
71
+ * @param defaultValue optional default {@link PopulatedArgumentSingleValueType} to use for population before parsing the provided arguments.
72
+ */
73
+ export function parseGlobalCommandClause(commandClause, defaultValue) {
74
+ const command = commandClause.command;
75
+ const potentialArgs = commandClause.potentialArgs;
76
+ const invalidArguments = [];
77
+ // check if we need to process an argument at all
78
+ if (!command.argument) {
79
+ return {
80
+ command,
81
+ populatedArgumentValues: undefined,
82
+ invalidArguments,
83
+ unusedArgs: potentialArgs,
84
+ };
85
+ }
86
+ let { populatedArgumentValue, unusedArgs, invalidArgument } = populateGlobalCommandValue(command, potentialArgs, defaultValue);
87
+ if (invalidArgument) {
88
+ invalidArguments.push(invalidArgument);
89
+ }
90
+ logger.debug("Command arguments for command: %s after value population: %O with invalid args: %O and unused args: %O", command.name, populatedArgumentValue, invalidArguments, unusedArgs);
91
+ // don't validate the value if the argument is already invalid
92
+ if (invalidArguments.length === 0) {
93
+ const validatedValue = validateGlobalCommandArgumentValue(command, populatedArgumentValue, invalidArguments);
94
+ if (validatedValue !== undefined) {
95
+ populatedArgumentValue = validatedValue;
96
+ }
97
+ }
98
+ logger.debug("Command arguments for command: %s after value validation: %O with invalid args: %O", command.name, populatedArgumentValue, invalidArguments);
99
+ return {
100
+ command,
101
+ populatedArgumentValues: populatedArgumentValue,
102
+ invalidArguments,
103
+ unusedArgs,
104
+ };
105
+ }
File without changes
@@ -0,0 +1,190 @@
1
+ import { isGlobalCommand, isGlobalModifierCommand, isGroupCommand, isSubCommand, } from "../command/CommandTypeGuards.js";
2
+ import getLogger from "../../util/logger.js";
3
+ const logger = getLogger("DefaultCommandRegistry");
4
+ /**
5
+ * Default implementation of a {@link CommandRegistry}.
6
+ */
7
+ export default class DefaultCommandRegistry {
8
+ #commandValidator;
9
+ #subCommandsByName = new Map();
10
+ #groupCommandsByName = new Map();
11
+ #groupCommandsAndMemberSubCommandsByName = new Map();
12
+ #globalCommandsByName = new Map();
13
+ #globalCommandsByShortAlias = new Map();
14
+ #globalModifierCommandsByName = new Map();
15
+ #globalModifierCommandsByShortAlias = new Map();
16
+ #globalModifierCommandsByNameByServiceId = new Map();
17
+ #globalModifierCommandsByShortAliasByServiceId = new Map();
18
+ #globalModifierCommandsByNameWithoutServiceId = new Map();
19
+ #globalModifierCommandsByShortAliasWithoutServiceId = new Map();
20
+ #nonModifierCommandsByName = new Map();
21
+ /**
22
+ * Constructor taking an optional initial list of {@link Command} instances to register.
23
+ *
24
+ * @param commands optional list of {@link Command} instances.
25
+ * @param commandValidator optional {@link CommandValidator} to use for all registered {@link Command} instances.
26
+ */
27
+ constructor(commands, commandValidator) {
28
+ this.#commandValidator = commandValidator;
29
+ commands?.forEach((command) => this.addCommand(command));
30
+ }
31
+ /**
32
+ * Validate a {@link GlobalCommand} or by extension a {@link GlobalModifierCommand} against those registered so far.
33
+ *
34
+ * @throws {Error} if the name of the provided {@link GlobalCommand} is already registered.
35
+ */
36
+ #validateGlobalCommandWithOtherGlobalCommands(globalCommand) {
37
+ if (this.#globalCommandsByName.has(globalCommand.name)) {
38
+ throw new Error(`Command name: ${globalCommand.name} duplicates the name of an existing command`);
39
+ }
40
+ if (this.#globalModifierCommandsByName.has(globalCommand.name)) {
41
+ throw new Error(`Command name: ${globalCommand.name} duplicates the name of an existing command`);
42
+ }
43
+ if (globalCommand.shortAlias !== undefined) {
44
+ if (this.#globalCommandsByShortAlias.has(globalCommand.shortAlias)) {
45
+ throw new Error(`Command name: ${globalCommand.shortAlias} duplicates the short alias of an existing command`);
46
+ }
47
+ if (this.#globalModifierCommandsByShortAlias.has(globalCommand.shortAlias)) {
48
+ throw new Error(`Command name: ${globalCommand.shortAlias} duplicates the short alias of an existing command`);
49
+ }
50
+ }
51
+ }
52
+ /**
53
+ * Validate a non-global {@link Command} against those registered so far.
54
+ *
55
+ * @throws {Error} if the name of the provided {@link Command} is already registered.
56
+ */
57
+ #validateNonGlobalCommandWithOtherNonGlobalCommands(command) {
58
+ if (this.#subCommandsByName.has(command.name)) {
59
+ throw new Error(`Command name: ${command.name} duplicates the name of an existing command`);
60
+ }
61
+ if (this.#groupCommandsByName.has(command.name)) {
62
+ throw new Error(`Command name: ${command.name} duplicates the name of an existing command`);
63
+ }
64
+ }
65
+ getSubCommands() {
66
+ return Array.from(this.#subCommandsByName.values());
67
+ }
68
+ getGroupCommands() {
69
+ return Array.from(this.#groupCommandsByName.values());
70
+ }
71
+ getGlobalCommands() {
72
+ return Array.from(this.#globalCommandsByName.values());
73
+ }
74
+ getGlobalModifierCommands() {
75
+ return Array.from(this.#globalModifierCommandsByName.values());
76
+ }
77
+ /**
78
+ * Add a {@link Command} to the registry optionally specifying a service ID if the command
79
+ * was provided by a {@link ServiceProvider}.
80
+ *
81
+ * @param command the {@link Command} to register.
82
+ * @param serviceId the service ID if the command was provided by a {@link ServiceProvider}.
83
+ */
84
+ addCommand(command, serviceId) {
85
+ logger.debug("Adding command: %s", command.name);
86
+ if (this.#commandValidator !== undefined) {
87
+ this.#commandValidator.validate(command);
88
+ }
89
+ if (isSubCommand(command)) {
90
+ this.#validateNonGlobalCommandWithOtherNonGlobalCommands(command);
91
+ this.#subCommandsByName.set(command.name, command);
92
+ this.#nonModifierCommandsByName.set(command.name, command);
93
+ return;
94
+ }
95
+ if (isGroupCommand(command)) {
96
+ this.#validateNonGlobalCommandWithOtherNonGlobalCommands(command);
97
+ this.#groupCommandsByName.set(command.name, command);
98
+ this.#nonModifierCommandsByName.set(command.name, command);
99
+ const groupCommand = command;
100
+ groupCommand.memberSubCommands.forEach((command) => {
101
+ this.#groupCommandsAndMemberSubCommandsByName.set(`${groupCommand.name}:${command.name}`, {
102
+ groupCommand,
103
+ command,
104
+ });
105
+ });
106
+ return;
107
+ }
108
+ if (isGlobalCommand(command)) {
109
+ this.#validateGlobalCommandWithOtherGlobalCommands(command);
110
+ this.#globalCommandsByName.set(command.name, command);
111
+ if (command.shortAlias !== undefined) {
112
+ this.#globalCommandsByShortAlias.set(command.shortAlias, command);
113
+ }
114
+ this.#nonModifierCommandsByName.set(command.name, command);
115
+ return;
116
+ }
117
+ if (isGlobalModifierCommand(command)) {
118
+ this.#validateGlobalCommandWithOtherGlobalCommands(command);
119
+ this.#globalModifierCommandsByName.set(command.name, command);
120
+ if (command.shortAlias !== undefined) {
121
+ this.#globalModifierCommandsByShortAlias.set(command.shortAlias, command);
122
+ }
123
+ if (serviceId === undefined) {
124
+ this.#globalModifierCommandsByNameWithoutServiceId.set(command.name, command);
125
+ if (command.shortAlias !== undefined) {
126
+ this.#globalModifierCommandsByShortAliasWithoutServiceId.set(command.shortAlias, command);
127
+ }
128
+ }
129
+ else {
130
+ if (!this.#globalModifierCommandsByNameByServiceId.has(serviceId)) {
131
+ this.#globalModifierCommandsByNameByServiceId.set(serviceId, new Map());
132
+ }
133
+ this.#globalModifierCommandsByNameByServiceId.get(serviceId).set(command.name, command);
134
+ if (command.shortAlias !== undefined) {
135
+ if (!this.#globalModifierCommandsByShortAliasByServiceId.has(serviceId)) {
136
+ this.#globalModifierCommandsByShortAliasByServiceId.set(serviceId, new Map());
137
+ }
138
+ this.#globalModifierCommandsByShortAliasByServiceId
139
+ .get(serviceId)
140
+ .set(command.shortAlias, command);
141
+ }
142
+ }
143
+ return;
144
+ }
145
+ }
146
+ getSubCommandByName(name) {
147
+ return this.#subCommandsByName.get(name);
148
+ }
149
+ getGroupCommandByName(name) {
150
+ return this.#groupCommandsByName.get(name);
151
+ }
152
+ getGroupCommandAndMemberSubCommandByJoinedName(groupAndMemberSubCommandName) {
153
+ return this.#groupCommandsAndMemberSubCommandsByName.get(groupAndMemberSubCommandName);
154
+ }
155
+ getGlobalCommandByName(name) {
156
+ return this.#globalCommandsByName.get(name);
157
+ }
158
+ getGlobalModifierCommandByName(name) {
159
+ return this.#globalModifierCommandsByName.get(name);
160
+ }
161
+ getGroupAndMemberCommandsByJoinedName() {
162
+ return this.#groupCommandsAndMemberSubCommandsByName;
163
+ }
164
+ getGlobalModifierCommandsByNameProvidedByService(serviceId) {
165
+ const getGlobalModifierCommandByName = this.#globalModifierCommandsByNameByServiceId.get(serviceId);
166
+ if (getGlobalModifierCommandByName !== undefined) {
167
+ return getGlobalModifierCommandByName;
168
+ }
169
+ return new Map();
170
+ }
171
+ getGlobalModifierCommandsByShortAliasProvidedByService(serviceId) {
172
+ const getGlobalModifierCommandByShortAlias = this.#globalModifierCommandsByShortAliasByServiceId.get(serviceId);
173
+ if (getGlobalModifierCommandByShortAlias !== undefined) {
174
+ return getGlobalModifierCommandByShortAlias;
175
+ }
176
+ return new Map();
177
+ }
178
+ getGlobalModifierCommandsByNameNotProvidedByService() {
179
+ return this.#globalModifierCommandsByNameWithoutServiceId;
180
+ }
181
+ getGlobalModifierCommandsByShortAliasNotProvidedByService() {
182
+ return this.#globalModifierCommandsByShortAliasWithoutServiceId;
183
+ }
184
+ getNonModifierCommandsByName() {
185
+ return this.#nonModifierCommandsByName;
186
+ }
187
+ getGlobalCommandsByShortAlias() {
188
+ return this.#globalCommandsByShortAlias;
189
+ }
190
+ }