@flowscripter/dynamic-cli-framework 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.github/workflows/check-bun-dependencies.yml +9 -0
  2. package/.github/workflows/lint-pr-message.yml +11 -0
  3. package/.github/workflows/release-bun-library.yml +8 -0
  4. package/.github/workflows/validate-bun-library-pr.yml +8 -0
  5. package/LICENSE +21 -0
  6. package/README.md +1475 -0
  7. package/bun.lock +63 -0
  8. package/index.ts +89 -0
  9. package/package.json +23 -0
  10. package/src/api/CLI.ts +17 -0
  11. package/src/api/CLIConfig.ts +19 -0
  12. package/src/api/Context.ts +25 -0
  13. package/src/api/RunResult.ts +142 -0
  14. package/src/api/argument/Argument.ts +36 -0
  15. package/src/api/argument/ArgumentValueTypes.ts +87 -0
  16. package/src/api/argument/ComplexOption.ts +31 -0
  17. package/src/api/argument/GlobalCommandArgument.ts +17 -0
  18. package/src/api/argument/Option.ts +32 -0
  19. package/src/api/argument/Positional.ts +27 -0
  20. package/src/api/argument/SubCommandArgument.ts +20 -0
  21. package/src/api/command/Command.ts +22 -0
  22. package/src/api/command/GlobalCommand.ts +33 -0
  23. package/src/api/command/GlobalModifierCommand.ts +12 -0
  24. package/src/api/command/GroupCommand.ts +20 -0
  25. package/src/api/command/SubCommand.ts +41 -0
  26. package/src/api/command/UsageExample.ts +21 -0
  27. package/src/api/service/ServiceProvider.ts +52 -0
  28. package/src/api/service/core/AsciiBannerGeneratorService.ts +35 -0
  29. package/src/api/service/core/KeyValueService.ts +28 -0
  30. package/src/api/service/core/PrinterService.ts +266 -0
  31. package/src/api/service/core/ShutdownService.ts +12 -0
  32. package/src/api/service/core/SyntaxHighlighterService.ts +42 -0
  33. package/src/cli/BaseCLI.ts +312 -0
  34. package/src/cli/DefaultRuntimeCLI.ts +54 -0
  35. package/src/command/MultiCommandCliHelpCommand.ts +394 -0
  36. package/src/command/SingleCommandCliHelpCommand.ts +183 -0
  37. package/src/command/UsageCommand.ts +35 -0
  38. package/src/command/VersionCommand.ts +22 -0
  39. package/src/launcher.ts +127 -0
  40. package/src/runtime/DefaultContext.ts +32 -0
  41. package/src/runtime/argument/ArgumentTypeGuards.ts +8 -0
  42. package/src/runtime/command/CommandTypeGuards.ts +30 -0
  43. package/src/runtime/command/CommandValidator.ts +549 -0
  44. package/src/runtime/parser.ts +219 -0
  45. package/src/runtime/registry/CommandRegistry.ts +121 -0
  46. package/src/runtime/registry/DefaultCommandRegistry.ts +318 -0
  47. package/src/runtime/registry/DefaultServiceProviderRegistry.ts +26 -0
  48. package/src/runtime/registry/ServiceProviderRegistry.ts +11 -0
  49. package/src/runtime/runner.ts +697 -0
  50. package/src/runtime/scanner.ts +417 -0
  51. package/src/runtime/values/ValuePopulationResult.ts +41 -0
  52. package/src/runtime/values/argumentValueMerge.ts +201 -0
  53. package/src/runtime/values/argumentValueValidation.ts +610 -0
  54. package/src/runtime/values/globalCommandValuePopulation.ts +96 -0
  55. package/src/runtime/values/subCommandValuePopulation.ts +680 -0
  56. package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +45 -0
  57. package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +38 -0
  58. package/src/service/asciiBannerGenerator/standard.flf.json +3 -0
  59. package/src/service/banner/BannerServiceProvider.ts +99 -0
  60. package/src/service/banner/command/NoBannerCommand.ts +42 -0
  61. package/src/service/configuration/ConfigurationServiceProvider.ts +571 -0
  62. package/src/service/configuration/DefaultKeyValueService.ts +60 -0
  63. package/src/service/configuration/command/ConfigCommand.ts +43 -0
  64. package/src/service/configuration/command/DumpConfigCommand.ts +47 -0
  65. package/src/service/printer/DefaultPrinterService.ts +256 -0
  66. package/src/service/printer/PrinterServiceProvider.ts +61 -0
  67. package/src/service/printer/command/DarkModeCommand.ts +43 -0
  68. package/src/service/printer/command/LogLevelCommand.ts +68 -0
  69. package/src/service/printer/command/NoColorCommand.ts +43 -0
  70. package/src/service/printer/terminal/Ansi.ts +10 -0
  71. package/src/service/printer/terminal/Color.ts +14 -0
  72. package/src/service/printer/terminal/Progress.ts +373 -0
  73. package/src/service/printer/terminal/Spinner.ts +100 -0
  74. package/src/service/printer/terminal/Styler.ts +5 -0
  75. package/src/service/printer/terminal/Terminal.ts +8 -0
  76. package/src/service/printer/terminal/Theme.ts +34 -0
  77. package/src/service/printer/terminal/TtyStyler.ts +39 -0
  78. package/src/service/printer/terminal/TtyTerminal.ts +65 -0
  79. package/src/service/shutdown/DefaultShutdownService.ts +9 -0
  80. package/src/service/shutdown/ShutdownServiceProvider.ts +55 -0
  81. package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +52 -0
  82. package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +51 -0
  83. package/src/util/configHelper.ts +95 -0
  84. package/src/util/envVarHelper.ts +338 -0
  85. package/src/util/helpHelper.ts +751 -0
  86. package/src/util/logger.ts +84 -0
  87. package/src/util/runnerHelper.ts +112 -0
  88. package/tests/cli/BaseCLI.test.ts +344 -0
  89. package/tests/command/MultiCommandCliHelpCommand.test.ts +650 -0
  90. package/tests/command/SingleCommandCliHelpCommand.test.ts +384 -0
  91. package/tests/command/UsageCommand.test.ts +53 -0
  92. package/tests/command/VersionCommand.test.ts +36 -0
  93. package/tests/fixtures/CLIConfig.ts +9 -0
  94. package/tests/fixtures/Command.ts +229 -0
  95. package/tests/fixtures/CommandRegistry.ts +8 -0
  96. package/tests/fixtures/ConfigurationServiceProvider.ts +28 -0
  97. package/tests/fixtures/Context.ts +33 -0
  98. package/tests/fixtures/ServiceProviderRegistry.ts +16 -0
  99. package/tests/fixtures/StreamString.ts +37 -0
  100. package/tests/fixtures/util.ts +41 -0
  101. package/tests/runtime/DefaultContext.test.ts +20 -0
  102. package/tests/runtime/argument/ArgumentTypeGuards.test.ts +49 -0
  103. package/tests/runtime/command/CommandTypeGuards.test.ts +43 -0
  104. package/tests/runtime/command/CommandValidator.test.ts +816 -0
  105. package/tests/runtime/parser.test.ts +766 -0
  106. package/tests/runtime/registry/DefaultCommandRegistry.test.ts +166 -0
  107. package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +42 -0
  108. package/tests/runtime/runner.test.ts +1298 -0
  109. package/tests/runtime/scanner.test.ts +1113 -0
  110. package/tests/runtime/values/argumentValueMerge.test.ts +314 -0
  111. package/tests/runtime/values/argumentValueValidation.test.ts +1020 -0
  112. package/tests/runtime/values/globalCommandValuePopulation.test.ts +662 -0
  113. package/tests/runtime/values/subCommandValuePopulation.test.ts +2658 -0
  114. package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +22 -0
  115. package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +70 -0
  116. package/tests/service/asciiBannerGenerator/__snapshots__/DefaultAsciiBannerGeneratorService.test.ts.snap +22 -0
  117. package/tests/service/asciiBannerGenerator/small.flf.json +3 -0
  118. package/tests/service/configuration/ConfigurationServiceProvider.test.ts +249 -0
  119. package/tests/service/configuration/DefaultKeyValueService.test.ts +65 -0
  120. package/tests/service/launchBanner/BannerServiceProvider.test.ts +49 -0
  121. package/tests/service/launchBanner/__snapshots__/BannerServiceProvider.test.ts.snap +3 -0
  122. package/tests/service/launchBanner/command/NoBannerCommand.test.ts +21 -0
  123. package/tests/service/printer/DefaultPrinterService.test.ts +409 -0
  124. package/tests/service/printer/PrinterServiceProvider.test.ts +29 -0
  125. package/tests/service/printer/command/LogLevelCommand.test.ts +58 -0
  126. package/tests/service/printer/terminal/Progress.test.ts +40 -0
  127. package/tests/service/printer/terminal/Spinner.test.ts +57 -0
  128. package/tests/service/shutdown/ShutdownServiceProvider.test.ts +13 -0
  129. package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +123 -0
  130. package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +41 -0
  131. package/tests/util/configHelper.test.ts +275 -0
  132. package/tests/util/envVarHelper.test.ts +318 -0
  133. package/tests/util/logger.test.ts +10 -0
package/bun.lock ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "@flowscripter/dynamic-plugin-framework",
6
+ "dependencies": {
7
+ "emphasize": "^7.0.0",
8
+ "fastest-levenshtein": "^1.0.16",
9
+ "figlet": "^1.8.0",
10
+ "highlight.js": "^11.11.1",
11
+ "supports-color": "^10.0.0",
12
+ "ts-log": "^2.2.7",
13
+ },
14
+ "devDependencies": {
15
+ "@types/bun": "^1.2.2",
16
+ },
17
+ "peerDependencies": {
18
+ "typescript": "^5.7.3",
19
+ },
20
+ },
21
+ },
22
+ "packages": {
23
+ "@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="],
24
+
25
+ "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
26
+
27
+ "@types/node": ["@types/node@22.13.4", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg=="],
28
+
29
+ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
30
+
31
+ "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
32
+
33
+ "bun-types": ["bun-types@1.2.2", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg=="],
34
+
35
+ "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
36
+
37
+ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
38
+
39
+ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
40
+
41
+ "emphasize": ["emphasize@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "chalk": "^5.0.0", "highlight.js": "~11.9.0", "lowlight": "~3.1.0" } }, "sha512-jdFCDyt+YetBXO12VwK4AiLsMCvkZ3IBxMVIJddB+25EwIL0VETBgpvPkJl63+JyAgaQ5Wja10qWMoXXC95JNg=="],
42
+
43
+ "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="],
44
+
45
+ "figlet": ["figlet@1.8.0", "", { "bin": { "figlet": "bin/index.js" } }, "sha512-chzvGjd+Sp7KUvPHZv6EXV5Ir3Q7kYNpCr4aHrRW79qFtTefmQZNny+W1pW9kf5zeE6dikku2W50W/wAH2xWgw=="],
46
+
47
+ "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],
48
+
49
+ "lowlight": ["lowlight@3.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.0.0", "highlight.js": "~11.9.0" } }, "sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ=="],
50
+
51
+ "supports-color": ["supports-color@10.0.0", "", {}, "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ=="],
52
+
53
+ "ts-log": ["ts-log@2.2.7", "", {}, "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg=="],
54
+
55
+ "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="],
56
+
57
+ "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
58
+
59
+ "emphasize/highlight.js": ["highlight.js@11.9.0", "", {}, "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw=="],
60
+
61
+ "lowlight/highlight.js": ["highlight.js@11.9.0", "", {}, "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw=="],
62
+ }
63
+ }
package/index.ts ADDED
@@ -0,0 +1,89 @@
1
+ // Argument API
2
+ export type { default as Argument } from "./src/api/argument/Argument.ts";
3
+ export type {
4
+ ArgumentSingleValueType,
5
+ ArgumentValues,
6
+ ArgumentValueType,
7
+ PopulatedArgumentSingleValueType,
8
+ PopulatedArgumentValues,
9
+ PopulatedArgumentValueType,
10
+ } from "./src/api/argument/ArgumentValueTypes.ts";
11
+ export {
12
+ ArgumentValueTypeName,
13
+ ComplexValueTypeName,
14
+ } from "./src/api/argument/ArgumentValueTypes.ts";
15
+ export type { default as ComplexOption } from "./src/api/argument/ComplexOption.ts";
16
+ export type { default as SubCommandArgument } from "./src/api/argument/SubCommandArgument.ts";
17
+ export type { default as GlobalCommandArgument } from "./src/api/argument/GlobalCommandArgument.ts";
18
+ export type { default as Option } from "./src/api/argument/Option.ts";
19
+ export type { default as Positional } from "./src/api/argument/Positional.ts";
20
+
21
+ // Command API
22
+ export type { default as Command } from "./src/api/command/Command.ts";
23
+ export type { default as GlobalCommand } from "./src/api/command/GlobalCommand.ts";
24
+ export type { default as GlobalModifierCommand } from "./src/api/command/GlobalModifierCommand.ts";
25
+ export type { default as GroupCommand } from "./src/api/command/GroupCommand.ts";
26
+ export type { default as SubCommand } from "./src/api/command/SubCommand.ts";
27
+ export type { default as UsageExample } from "./src/api/command/UsageExample.ts";
28
+
29
+ // Service API
30
+ export type {
31
+ ServiceInfo,
32
+ ServiceProvider,
33
+ } from "./src/api/service/ServiceProvider.ts";
34
+
35
+ // Registry API
36
+ export type { default as CommandRegistry } from "./src/runtime/registry/CommandRegistry.ts";
37
+ export type { default as ServiceProviderRegistry } from "./src/runtime/registry/ServiceProviderRegistry.ts";
38
+
39
+ // Core Services
40
+ export { ASCII_BANNER_GENERATOR_SERVICE_ID } from "./src/api/service/core/AsciiBannerGeneratorService.ts";
41
+ export type { default as AsciiBannerGeneratorService } from "./src/api/service/core/AsciiBannerGeneratorService.ts";
42
+ export { default as DefaultAsciiBannerGeneratorService } from "./src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts";
43
+ export { default as AsciiBannerGeneratorServiceProvider } from "./src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts";
44
+
45
+ export { default as BannerServiceProvider } from "./src/service/banner/BannerServiceProvider.ts";
46
+
47
+ export { KEY_VALUE_SERVICE_ID } from "./src/api/service/core/KeyValueService.ts";
48
+ export type { default as KeyValueService } from "./src/api/service/core/KeyValueService.ts";
49
+ export { default as DefaultKeyValueService } from "./src/service/configuration/DefaultKeyValueService.ts";
50
+ export { default as ConfigurationServiceProvider } from "./src/service/configuration/ConfigurationServiceProvider.ts";
51
+
52
+ export { PRINTER_SERVICE_ID } from "./src/api/service/core/PrinterService.ts";
53
+ export type {
54
+ default as PrinterService,
55
+ } from "./src/api/service/core/PrinterService.ts";
56
+ export { Icon, Level } from "./src/api/service/core/PrinterService.ts";
57
+ export { default as DefaultPrinterService } from "./src/service/printer/DefaultPrinterService.ts";
58
+ export { default as PrinterServiceProvider } from "./src/service/printer/PrinterServiceProvider.ts";
59
+
60
+ export { SHUTDOWN_SERVICE_ID } from "./src/api/service/core/ShutdownService.ts";
61
+ export type { default as ShutdownService } from "./src/api/service/core/ShutdownService.ts";
62
+ export { default as DefaultShutdownService } from "./src/service/shutdown/DefaultShutdownService.ts";
63
+ export { default as ShutdownServiceProvider } from "./src/service/shutdown/ShutdownServiceProvider.ts";
64
+
65
+ export { SYNTAX_HIGHLIGHTER_SERVICE_ID } from "./src/api/service/core/SyntaxHighlighterService.ts";
66
+ export type { default as SyntaxHighlighterService } from "./src/api/service/core/SyntaxHighlighterService.ts";
67
+ export { default as DefaultSyntaxHighlighterService } from "./src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts";
68
+ export { default as SyntaxHighlighterServiceProvider } from "./src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts";
69
+
70
+ // CLI API
71
+ export type { InvalidArgument } from "./src/api/RunResult.ts";
72
+ export type { default as Context } from "./src/api/Context.ts";
73
+ export type {
74
+ default as RunResult,
75
+ InvalidArgumentReason,
76
+ RunState,
77
+ } from "./src/api/RunResult.ts";
78
+ export type { default as CLIConfig } from "./src/api/CLIConfig.ts";
79
+ export type { default as CLI } from "./src/api/CLI.ts";
80
+
81
+ // Core CLI
82
+ export { default as BaseCLI } from "./src/cli/BaseCLI.ts";
83
+ export { default as DefaultRuntimeCLI } from "./src/cli/DefaultRuntimeCLI.ts";
84
+
85
+ // Convenience functions
86
+ export {
87
+ launchMultiCommandCLI,
88
+ launchSingleCommandCLI,
89
+ } from "./src/launcher.ts";
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@flowscripter/dynamic-cli-framework",
3
+ "module": "index.ts",
4
+ "type": "module",
5
+ "version": "1.0.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "devDependencies": {
10
+ "@types/bun": "^1.2.2"
11
+ },
12
+ "peerDependencies": {
13
+ "typescript": "^5.7.3"
14
+ },
15
+ "dependencies": {
16
+ "emphasize": "^7.0.0",
17
+ "fastest-levenshtein": "^1.0.16",
18
+ "figlet": "^1.8.0",
19
+ "highlight.js": "^11.11.1",
20
+ "supports-color": "^10.0.0",
21
+ "ts-log": "^2.2.7"
22
+ }
23
+ }
package/src/api/CLI.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interface to be implemented by a CLI application.
3
+ */
4
+ import type RunResult from "./RunResult.ts";
5
+ import type CLIConfig from "./CLIConfig.ts";
6
+
7
+ export default interface CLI {
8
+ /**
9
+ * Run the CLI with the provided arguments which do not include the invoked executable name.
10
+ *
11
+ * @param args the arguments to parse.
12
+ * @param cliConfig the {@link CLIConfig} for the CLI application.
13
+ *
14
+ * @return result of parsing arguments and running appropriate {@link Command} instances.
15
+ */
16
+ run(args: ReadonlyArray<string>, cliConfig: CLIConfig): Promise<RunResult>;
17
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Interface specifying common configuration for a {@link CLI} application.
3
+ */
4
+ export default interface CLIConfig {
5
+ /**
6
+ * Name of the CLI application.
7
+ */
8
+ readonly name: string;
9
+
10
+ /**
11
+ * Optional description of the CLI application.
12
+ */
13
+ readonly description?: string;
14
+
15
+ /**
16
+ * Version of the CLI application.
17
+ */
18
+ readonly version: string;
19
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Interface allowing a {@link CLI} to pass context to a {@link Command} instance.
3
+ */
4
+ import type CLIConfig from "./CLIConfig.ts";
5
+
6
+ export default interface Context {
7
+ /**
8
+ * The {@link CLIConfig} in use by the {@link CLI}.
9
+ */
10
+ readonly cliConfig: CLIConfig;
11
+
12
+ /**
13
+ * Return the service identified by the specified ID.
14
+ *
15
+ * @param id the ID of the service to retrieve.
16
+ */
17
+ getServiceById(id: string): unknown;
18
+
19
+ /**
20
+ * Check if the specified service exists in the context.
21
+ *
22
+ * @param id the ID of the desired service.
23
+ */
24
+ doesServiceExist(id: string): boolean;
25
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * State of a {@link CLI} after invocation.
3
+ */
4
+ import type Command from "./command/Command.ts";
5
+ import type Argument from "./argument/Argument.ts";
6
+ import type ComplexOption from "./argument/ComplexOption.ts";
7
+ import type {
8
+ PopulatedArgumentValues,
9
+ PopulatedArgumentValueType,
10
+ } from "./argument/ArgumentValueTypes.ts";
11
+
12
+ export enum RunState {
13
+ /**
14
+ * Arguments were successfully parsed and the specified command(s) were successfully executed.
15
+ */
16
+ SUCCESS = 0,
17
+
18
+ /**
19
+ * The arguments supplied were invalid or could not be parsed.
20
+ */
21
+ PARSE_ERROR = 1,
22
+
23
+ /**
24
+ * Arguments were successfully parsed but no command was discovered.
25
+ */
26
+ NO_COMMAND = 2,
27
+
28
+ /**
29
+ * Arguments were successfully parsed and command(s) discovered but command execution failed.
30
+ */
31
+ EXECUTION_ERROR = 3,
32
+
33
+ /**
34
+ * General runtime error related to the framework.
35
+ */
36
+ RUNTIME_ERROR = 4,
37
+ }
38
+
39
+ /**
40
+ * Possible reasons for an invalid argument.
41
+ */
42
+ export enum InvalidArgumentReason {
43
+ /**
44
+ * The argument value was not specified.
45
+ */
46
+ MISSING_VALUE = 0,
47
+
48
+ /**
49
+ * The value specified was not the correct type for the argument.
50
+ */
51
+ INCORRECT_VALUE_TYPE = 1,
52
+
53
+ /**
54
+ * The argument does not support multiple values.
55
+ */
56
+ ILLEGAL_MULTIPLE_VALUES = 2,
57
+
58
+ /**
59
+ * The value specified was not one of the defined allowable values for the argument.
60
+ */
61
+ ILLEGAL_VALUE = 3,
62
+
63
+ /**
64
+ * The arguments specified resulted in a sparse array of values.
65
+ */
66
+ ILLEGAL_SPARSE_ARRAY = 4,
67
+
68
+ /**
69
+ * The argument specified an unknown complex option property.
70
+ */
71
+ UNKNOWN_PROPERTY = 5,
72
+
73
+ /**
74
+ * Complex option nesting exceeds maximum of {@link MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH}.
75
+ */
76
+ NESTING_DEPTH_EXCEEDED = 6,
77
+
78
+ /**
79
+ * Array value nesting exceeds maximum of {@link MAXIMUM_ARGUMENT_ARRAY_SIZE}.
80
+ */
81
+ ARRAY_SIZE_EXCEEDED = 7,
82
+
83
+ /**
84
+ * Attempt to set a primitive value on a complex object object.
85
+ */
86
+ OPTION_IS_COMPLEX = 8,
87
+ }
88
+
89
+ /**
90
+ * Details of an invalid parsed argument.
91
+ */
92
+ export interface InvalidArgument {
93
+ /**
94
+ * A reason for the parsing error
95
+ */
96
+ readonly reason: InvalidArgumentReason;
97
+
98
+ /**
99
+ * The name of the argument specified (if it was able to be populated)
100
+ */
101
+ readonly name?: string;
102
+
103
+ /**
104
+ * The {@link Argument} (if it was able to be populated)
105
+ */
106
+ readonly argument?: Argument | ComplexOption;
107
+
108
+ /**
109
+ * The argument value (if it was able to be populated).
110
+ *
111
+ * NOTE: This value is unlikely to be valid as it is the cause of the invalid argument error.
112
+ */
113
+ readonly value?:
114
+ | PopulatedArgumentValues
115
+ | PopulatedArgumentValueType
116
+ | Array<PopulatedArgumentValues | PopulatedArgumentValueType>;
117
+ }
118
+
119
+ /**
120
+ * Result of a {@link CLI} invocation.
121
+ */
122
+ export default interface RunResult {
123
+ /**
124
+ * The state after processing the invocation.
125
+ */
126
+ readonly runState: RunState;
127
+
128
+ /**
129
+ * Populated if {@link runState} is {@link RunState.SUCCESS}, {@link RunState.PARSE_ERROR} or {@link RunState.EXECUTION_ERROR}.
130
+ */
131
+ readonly command?: Command;
132
+
133
+ /**
134
+ * Populated if {@link runState} is {@link RunState.PARSE_ERROR}
135
+ */
136
+ readonly invalidArguments?: ReadonlyArray<InvalidArgument>;
137
+
138
+ /**
139
+ * Populated if {@link runState} is {@link RunState.EXECUTION_ERROR} or {@link RunState.RUNTIME_ERROR}.
140
+ */
141
+ readonly error?: Error;
142
+ }
@@ -0,0 +1,36 @@
1
+ import type {
2
+ ArgumentSingleValueType,
3
+ ArgumentValueTypeName,
4
+ } from "./ArgumentValueTypes.ts";
5
+
6
+ /**
7
+ * Interface to be implemented by all {@link Command} arguments.
8
+ */
9
+ export default interface Argument {
10
+ /**
11
+ * Type of the argument value.
12
+ */
13
+ readonly type: ArgumentValueTypeName;
14
+
15
+ /**
16
+ * Optional list of values that the value must match.
17
+ */
18
+ readonly allowableValues?: ReadonlyArray<ArgumentSingleValueType>;
19
+
20
+ /**
21
+ * Optional configuration key to use for the argument. Must consist of alphanumeric non-whitespace uppercase
22
+ * ASCII or `_` characters. Must not start with a digit.
23
+ *
24
+ * If not specified a default configuration key is determined as follows: The {@link Argument.name} is capitalized
25
+ * and any `-` characters are replaced with `_` characters. If the result starts with a digit, it is
26
+ * prefixed with `_`. Some examples:
27
+ *
28
+ * * name: `FooBar` => configuration key: `FOOBAR`
29
+ * * name: `Hello-World-` => configuration key: `HELLO_WORLD_`
30
+ * * name: `3` => configuration key: `_3`
31
+ *
32
+ * NOTE: Regardless of whether a {@link configurationKey} is specified, or the default is relied upon,
33
+ * it will only be used if the parent {@link Command} has specified {@link Command.enableConfiguration} as `true`.
34
+ */
35
+ readonly configurationKey?: string;
36
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The type of single {@link Argument} values which are supported.
3
+ *
4
+ * NOTE: JavaScript does not have a special runtime value for INTEGER so this is covered by `number`.
5
+ * NOTE: `string` is also used for PASSWORD values.
6
+ */
7
+ export type ArgumentSingleValueType = number | string | boolean;
8
+
9
+ /**
10
+ * The type of the value to be parsed as an argument can be: `boolean`, `number` or `string` or an array of these.
11
+ */
12
+ export type ArgumentValueType =
13
+ | ArgumentSingleValueType
14
+ | Array<ArgumentSingleValueType>;
15
+
16
+ /**
17
+ * A container object for populated argument values.
18
+ *
19
+ * The following are all valid examples:
20
+ *
21
+ * * `{ }`
22
+ * * `{ foo: 1 }`
23
+ * * `{ foo: true }`
24
+ * * `{ foo: 'bar' }`
25
+ * * `{ foo: [ 1, 2 ] }`
26
+ * * `{ foo: [ true, true ] }`
27
+ * * `{ foo: [ 'bar', 'gar' ] }`
28
+ * * `{ foo: { a: 1 } }`
29
+ * * `{ foo: { a: { b: 'c'} } }`
30
+ * * `{ foo: [ { a: { b: 'c'} }, { a: { b: 'c'} } ] }`
31
+ *
32
+ * An array of arrays is not allowed, so the following is an INVALID example:
33
+ *
34
+ * * `{ foo: [ [ 1, 2 ], [3, 4 ] ] }`
35
+ */
36
+ export type ArgumentValues = {
37
+ [argName: string]:
38
+ | ArgumentValueType
39
+ | ArgumentValues
40
+ | Array<ArgumentValues>;
41
+ };
42
+
43
+ /**
44
+ * Enum of possible {@link Argument} value types.
45
+ */
46
+ export enum ArgumentValueTypeName {
47
+ STRING = 0,
48
+ NUMBER = 1,
49
+ INTEGER = 2,
50
+ BOOLEAN = 3,
51
+ SECRET,
52
+ }
53
+
54
+ /**
55
+ * Only possible value for {@link ComplexOption.type}.
56
+ */
57
+ export enum ComplexValueTypeName {
58
+ COMPLEX = 5,
59
+ }
60
+
61
+ /**
62
+ * Populated single value type is very similar to {@link ArgumentSingleValueType} but allows for an illegal
63
+ * undefined value.
64
+ */
65
+ export type PopulatedArgumentSingleValueType =
66
+ | ArgumentSingleValueType
67
+ | undefined;
68
+
69
+ /**
70
+ * Populated argument value types are very similar to {@link ArgumentValueType} but allow for illegal
71
+ * undefined values.
72
+ */
73
+ export type PopulatedArgumentValueType =
74
+ | PopulatedArgumentSingleValueType
75
+ | Array<PopulatedArgumentSingleValueType>;
76
+
77
+ /**
78
+ * Populated values are very similar to {@link ArgumentValues} but allow for illegal
79
+ * undefined properties and array entries.
80
+ */
81
+ export interface PopulatedArgumentValues {
82
+ [argName: string]:
83
+ | PopulatedArgumentValueType
84
+ | PopulatedArgumentValues
85
+ | Array<PopulatedArgumentValues | undefined>
86
+ | undefined;
87
+ }
@@ -0,0 +1,31 @@
1
+ import type Option from "./Option.ts";
2
+ import type {
3
+ ArgumentValues,
4
+ ComplexValueTypeName,
5
+ } from "./ArgumentValueTypes.ts";
6
+
7
+ export const MAXIMUM_COMPLEX_OPTION_NESTING_DEPTH = 10;
8
+
9
+ /**
10
+ * A container option argument for defining {@link SubCommand} nested argument hierarchies.
11
+ */
12
+ export default interface ComplexOption extends
13
+ Omit<
14
+ Option,
15
+ "type" | "defaultValue" | "allowableValues"
16
+ > {
17
+ /**
18
+ * Type of the argument value.
19
+ */
20
+ readonly type: ComplexValueTypeName;
21
+
22
+ /**
23
+ * List of child {@link Option} properties.
24
+ */
25
+ readonly properties: ReadonlyArray<Option | ComplexOption>;
26
+
27
+ /**
28
+ * Default value for the argument if not specified.
29
+ */
30
+ readonly defaultValue?: ArgumentValues | Array<ArgumentValues>;
31
+ }
@@ -0,0 +1,17 @@
1
+ import type Argument from "./Argument.ts";
2
+ import type { ArgumentSingleValueType } from "./ArgumentValueTypes.ts";
3
+
4
+ /**
5
+ * Interface to be implemented by a single {@link Argument} defined by a {@link GlobalCommand}.
6
+ */
7
+ export default interface GlobalCommandArgument extends Argument {
8
+ /**
9
+ * Default value for the argument if not specified.
10
+ */
11
+ readonly defaultValue?: ArgumentSingleValueType;
12
+
13
+ /**
14
+ * If this is `true` the argument does not need to be specified nor have a default value. The default is `false`.
15
+ */
16
+ readonly isOptional?: boolean;
17
+ }
@@ -0,0 +1,32 @@
1
+ import type { ArgumentValueType } from "./ArgumentValueTypes.ts";
2
+ import type SubCommandArgument from "./SubCommandArgument.ts";
3
+
4
+ /**
5
+ * Interface for {@link SubCommand} option arguments.
6
+ */
7
+ export default interface Option extends SubCommandArgument {
8
+ /**
9
+ * Optional short alias for the option.
10
+ *
11
+ * Must consist of a single alphanumeric non-whitespace ASCII character.
12
+ */
13
+ readonly shortAlias?: string;
14
+
15
+ /**
16
+ * Default value for the argument if not specified.
17
+ */
18
+ readonly defaultValue?: ArgumentValueType;
19
+
20
+ /**
21
+ * If this is `true` the option does not need to be specified nor have a default value.
22
+ */
23
+ readonly isOptional?: boolean;
24
+
25
+ /**
26
+ * If this is `true` the option can be specified multiple times and all values will be returned in an array
27
+ * matching the order provided.
28
+ *
29
+ * NOTE: If {@link isOptional} is `false`, at least one instance of the option must be specified.
30
+ */
31
+ readonly isArray?: boolean;
32
+ }
@@ -0,0 +1,27 @@
1
+ import type SubCommandArgument from "./SubCommandArgument.ts";
2
+
3
+ /**
4
+ * Interface for {@link SubCommand} positional arguments.
5
+ */
6
+ export default interface Positional extends SubCommandArgument {
7
+ /**
8
+ * If this is `true` the argument can be specified one or multiple times and all values will be returned in
9
+ * an array matching the order provided.
10
+ *
11
+ * NOTE: If {@link isVarargOptional} is `true`, the argument can specified zero, one or multiple times.
12
+ *
13
+ * NOTE: There can be only one positional with this set and it must be the last the last item if there
14
+ * are multiple positionals defined.
15
+ */
16
+ readonly isVarargMultiple?: boolean;
17
+
18
+ /**
19
+ * If this is `true` the argument can be specified zero or once i.e. it does not need to be specified.
20
+ *
21
+ * NOTE: If {@link isVarargMultiple} is `true`, the argument can specified zero, one or multiple times.
22
+ *
23
+ * NOTE: There can be only one positional with this set and it must be the last the last item if there
24
+ * are multiple positionals defined.
25
+ */
26
+ readonly isVarargOptional?: boolean;
27
+ }
@@ -0,0 +1,20 @@
1
+ import type Argument from "./Argument.ts";
2
+
3
+ export const MAXIMUM_ARGUMENT_ARRAY_SIZE = 255;
4
+
5
+ /**
6
+ * Interface to be implemented by all {@link SubCommand} arguments.
7
+ */
8
+ export default interface SubCommandArgument extends Argument {
9
+ /**
10
+ * Name of the argument.
11
+ *
12
+ * Must consist of alphanumeric non-whitespace ASCII or `_` and `-` characters. Cannot start with `-`.
13
+ */
14
+ readonly name: string;
15
+
16
+ /**
17
+ * Optional description of the argument.
18
+ */
19
+ readonly description?: string;
20
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Common interface for all command types.
3
+ */
4
+ export default interface Command {
5
+ /**
6
+ * Name of the command.
7
+ *
8
+ * Must consist of alphanumeric non-whitespace ASCII or `_` and `-` characters. Cannot start with `-`.
9
+ */
10
+ readonly name: string;
11
+
12
+ /**
13
+ * Optional description of the command.
14
+ */
15
+ readonly description?: string;
16
+
17
+ /**
18
+ * Optionally enable support for populating argument values via configuration. If this is `true` then
19
+ * default argument values may be sourced using a configuration source provided by the CLI runtime.
20
+ */
21
+ readonly enableConfiguration?: boolean;
22
+ }