@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
@@ -0,0 +1,312 @@
1
+ import type CLI from "../api/CLI.ts";
2
+ import type RunResult from "../api/RunResult.ts";
3
+ import { RunState } from "../api/RunResult.ts";
4
+ import getLogger from "../util/logger.ts";
5
+ import DefaultCommandRegistry from "../runtime/registry/DefaultCommandRegistry.ts";
6
+ import type Command from "../api/command/Command.ts";
7
+ import DefaultServiceProviderRegistry from "../runtime/registry/DefaultServiceProviderRegistry.ts";
8
+ import DefaultContext from "../runtime/DefaultContext.ts";
9
+ import type { ServiceProvider } from "../api/service/ServiceProvider.ts";
10
+ import type CLIConfig from "../api/CLIConfig.ts";
11
+ import type SubCommand from "../api/command/SubCommand.ts";
12
+ import type GlobalCommand from "../api/command/GlobalCommand.ts";
13
+ import {
14
+ SingleCommandCliHelpGlobalCommand,
15
+ SingleCommandCliHelpSubCommand,
16
+ } from "../command/SingleCommandCliHelpCommand.ts";
17
+ import {
18
+ MultiCommandCliHelpGlobalCommand,
19
+ MultiCommandCliHelpSubCommand,
20
+ } from "../command/MultiCommandCliHelpCommand.ts";
21
+ import VersionCommand from "../command/VersionCommand.ts";
22
+ import UsageCommand from "../command/UsageCommand.ts";
23
+ import {
24
+ isGlobalCommand,
25
+ isGlobalModifierCommand,
26
+ isSubCommand,
27
+ } from "../runtime/command/CommandTypeGuards.ts";
28
+ import CommandValidator from "../runtime/command/CommandValidator.ts";
29
+ import ShutdownServiceProvider from "../service/shutdown/ShutdownServiceProvider.ts";
30
+ import ConfigurationServiceProvider from "../service/configuration/ConfigurationServiceProvider.ts";
31
+ import PrinterServiceProvider from "../service/printer/PrinterServiceProvider.ts";
32
+ import { run } from "../runtime/runner.ts";
33
+
34
+ import { WritableStream } from "node:stream/web";
35
+ import Terminal from "../service/printer/terminal/Terminal.ts";
36
+ import PrinterService from "../api/service/core/PrinterService.ts";
37
+ import DefaultPrinterService from "../service/printer/DefaultPrinterService.ts";
38
+ import Styler from "../service/printer/terminal/Styler.ts";
39
+ const logger = getLogger("BaseCLI");
40
+
41
+ /**
42
+ * Base implementation of a {@link CLI}.
43
+ *
44
+ * By default the following service providers are added:
45
+ *
46
+ * * {@link ShutdownServiceProvider}
47
+ * * {@link PrinterServiceProvider}
48
+ * * {@link ConfigurationServiceProvider}
49
+ *
50
+ * NOTE: The `ConfigurationServiceProvider` will not be added if the required `allow-read` and `allow-write`
51
+ * permissions are not granted. It can also be excluded if desired via a constructor argument.
52
+ *
53
+ * By default the following commands are added:
54
+ *
55
+ * * {@link SingleCommandCliHelpSubCommand} or {@link MultiCommandCliHelpSubCommand}
56
+ * * {@link SingleCommandCliHelpGlobalCommand} or {@link MultiCommandCliHelpGlobalCommand}
57
+ * * commands provided by the {@link ConfigurationServiceProvider}.
58
+ * * commands provided by the {@link PrinterServiceProvider}.
59
+ */
60
+ export default class BaseCLI implements CLI {
61
+ readonly #cliConfig: CLIConfig;
62
+ readonly #envVarsEnabled: boolean;
63
+ readonly #configEnabled: boolean;
64
+ readonly #keyValueServiceEnabled: boolean;
65
+ readonly #addedNonModifierCommands: Array<Command>;
66
+ readonly #serviceProviderRegistry: DefaultServiceProviderRegistry;
67
+ readonly #commandRegistry: DefaultCommandRegistry;
68
+ readonly #context: DefaultContext;
69
+ readonly #printerService: PrinterService;
70
+
71
+ /**
72
+ * Constructor configures the instance with the specified CLI application details and WritableStream instances.
73
+ *
74
+ * @param cliConfig the {@link CLIConfig} for the CLI application.
75
+ * @param stdoutWritableStream the WritableStream to use for stderr output.
76
+ * @param stderrWritableStream the WritableStream to use for stderr output.
77
+ * @param stdoutIsColor true if stdout supports color.
78
+ * @param stderrIsColor true if stderr supports color.
79
+ * @param terminal the Terminal implementation to use.
80
+ * @param styler the Styler implementation to use.
81
+ * @param envVarsEnabled optionally support checking env variables for default argument values.
82
+ * @param configEnabled optionally enable configuration file support for default argument values.
83
+ * @param keyValueServiceEnabled optionally provide a {@link KeyValueService} implementation: `configEnabled` must be true in this case
84
+ * @param validateAllCommands optionally force validation of all i.e. include validation of core commands.
85
+ */
86
+ constructor(
87
+ cliConfig: CLIConfig,
88
+ stdoutWritableStream: WritableStream,
89
+ stderrWritableStream: WritableStream,
90
+ stdoutIsColor: boolean,
91
+ stderrIsColor: boolean,
92
+ stderrTerminal: Terminal,
93
+ styler: Styler,
94
+ envVarsEnabled = false,
95
+ configEnabled = false,
96
+ keyValueServiceEnabled = false,
97
+ validateAllCommands = false,
98
+ ) {
99
+ if (cliConfig.name.length === 0) {
100
+ throw new Error("Invalid empty CLI name provided");
101
+ }
102
+ if (cliConfig.name[0].match(/[0-9\-_]/)) {
103
+ throw new Error(
104
+ `Invalid CLI name starting with a digit or dash provided: '${cliConfig.name}'`,
105
+ );
106
+ }
107
+ if (
108
+ (cliConfig.description !== undefined) &&
109
+ (cliConfig.description.length === 0)
110
+ ) {
111
+ throw new Error("Invalid empty CLI description provided");
112
+ }
113
+ if ((cliConfig.version !== undefined) && (cliConfig.version.length === 0)) {
114
+ throw new Error("Invalid empty CLI version provided");
115
+ }
116
+ this.#cliConfig = cliConfig;
117
+ this.#envVarsEnabled = envVarsEnabled;
118
+ this.#configEnabled = configEnabled;
119
+ this.#keyValueServiceEnabled = keyValueServiceEnabled;
120
+ this.#addedNonModifierCommands = [];
121
+
122
+ // create a validator if required
123
+ let commandValidator: CommandValidator | undefined;
124
+ if (validateAllCommands) {
125
+ commandValidator = new CommandValidator(this.#cliConfig);
126
+ }
127
+
128
+ // create a service provider registry
129
+ this.#serviceProviderRegistry = new DefaultServiceProviderRegistry();
130
+
131
+ // create a command registry
132
+ this.#commandRegistry = new DefaultCommandRegistry([], commandValidator);
133
+
134
+ // create a context
135
+ this.#context = new DefaultContext(this.#cliConfig);
136
+
137
+ this.#printerService = new DefaultPrinterService(
138
+ stdoutWritableStream,
139
+ stderrWritableStream,
140
+ stdoutIsColor,
141
+ stderrIsColor,
142
+ stderrTerminal,
143
+ styler,
144
+ );
145
+ }
146
+
147
+ /**
148
+ * Add a {@link ServiceProvider} to the CLI's {@link ServiceProviderRegistry}.
149
+ *
150
+ * This will register the {@link ServiceProvider}, add any provided services to the {@link Context} and register
151
+ * any provided {@link Command} instances.
152
+ *
153
+ * @param serviceProvider the {@link ServiceProvider} to add.
154
+ */
155
+ public addServiceProvider(serviceProvider: ServiceProvider) {
156
+ this.#serviceProviderRegistry.addServiceProvider(serviceProvider);
157
+ }
158
+
159
+ /**
160
+ * Add a {@link Command} to the CLI's {@link CommandRegistry}.
161
+ *
162
+ * If only one non-modifier {@link Command} is added, the CLI will operate as a single command CLI and the provided
163
+ * command will be set as a default command. If more than one command is added, the CLI will operate as a
164
+ * multi-command CLI. In this case the default command will be set to a help command.
165
+ *
166
+ * @param command the {@link Command} to add.
167
+ */
168
+ public addCommand(command: Command) {
169
+ if (!isGlobalModifierCommand(command)) {
170
+ // store the command locally to help determine if this CLI will be a single or multi-command CLI
171
+ this.#addedNonModifierCommands.push(command);
172
+ }
173
+
174
+ // register the command
175
+ this.#commandRegistry.addCommand(command);
176
+ }
177
+
178
+ async run(args: ReadonlyArray<string>): Promise<RunResult> {
179
+ if (this.#addedNonModifierCommands.length === 0) {
180
+ throw new Error(
181
+ "No non-modifier commands added to the CLI, nothing to run!",
182
+ );
183
+ }
184
+
185
+ if (
186
+ (this.#addedNonModifierCommands.length === 1) &&
187
+ !isSubCommand(this.#addedNonModifierCommands[0]) &&
188
+ !isGlobalCommand(this.#addedNonModifierCommands[0])
189
+ ) {
190
+ throw new Error(
191
+ "If only one command is added, if must be a global command or sub-command!",
192
+ );
193
+ }
194
+
195
+ // create and add core services
196
+ this.addServiceProvider(new ShutdownServiceProvider(100));
197
+ this.addServiceProvider(
198
+ new PrinterServiceProvider(
199
+ 80,
200
+ this.#printerService,
201
+ ),
202
+ );
203
+
204
+ const configurationServiceProvider = new ConfigurationServiceProvider(
205
+ 90,
206
+ this.#envVarsEnabled,
207
+ this.#configEnabled,
208
+ this.#keyValueServiceEnabled,
209
+ );
210
+ this.addServiceProvider(configurationServiceProvider);
211
+
212
+ for (
213
+ const serviceProvider of this.#serviceProviderRegistry
214
+ .getServiceProviders()
215
+ ) {
216
+ const serviceInfo = await serviceProvider.provide(this.#cliConfig);
217
+
218
+ if (serviceInfo.service) {
219
+ this.#context.addServiceInstance(
220
+ serviceProvider.serviceId,
221
+ serviceInfo.service,
222
+ );
223
+ }
224
+
225
+ serviceInfo.commands.forEach((command) => {
226
+ this.#commandRegistry.addCommand(command, serviceProvider.serviceId);
227
+ });
228
+ }
229
+
230
+ logger.debug(() => `Running with args: ${args.join(" ")}`);
231
+
232
+ let helpSubCommand: SubCommand | undefined;
233
+ let helpGlobalCommand: GlobalCommand | undefined;
234
+ let defaultCommand: Command | undefined;
235
+
236
+ try {
237
+ // setup help commands and default command based on the number of commands explicitly added via {@link addCommand)
238
+ if (this.#addedNonModifierCommands.length === 1) {
239
+ // a single-command CLI
240
+ defaultCommand = this.#addedNonModifierCommands[0];
241
+ helpSubCommand = new SingleCommandCliHelpSubCommand(
242
+ this.#envVarsEnabled,
243
+ defaultCommand as SubCommand,
244
+ this.#commandRegistry,
245
+ );
246
+ helpGlobalCommand = new SingleCommandCliHelpGlobalCommand(
247
+ this.#envVarsEnabled,
248
+ defaultCommand as SubCommand,
249
+ this.#commandRegistry,
250
+ );
251
+ } else {
252
+ // a multi-command CLI
253
+ helpSubCommand = new MultiCommandCliHelpSubCommand(
254
+ this.#envVarsEnabled,
255
+ this.#commandRegistry,
256
+ );
257
+ helpGlobalCommand = new MultiCommandCliHelpGlobalCommand(
258
+ this.#envVarsEnabled,
259
+ this.#commandRegistry,
260
+ );
261
+ }
262
+
263
+ // register the help commands
264
+ this.#commandRegistry.addCommand(helpSubCommand);
265
+ this.#commandRegistry.addCommand(helpGlobalCommand);
266
+
267
+ // register the version command
268
+ this.#commandRegistry.addCommand(new VersionCommand());
269
+
270
+ // run...
271
+ const runResult = await run(
272
+ args,
273
+ this.#commandRegistry,
274
+ this.#serviceProviderRegistry,
275
+ configurationServiceProvider,
276
+ this.#context,
277
+ defaultCommand,
278
+ );
279
+ // then handle the result...
280
+ if (runResult.runState === RunState.NO_COMMAND) {
281
+ // print usage
282
+ await new UsageCommand(helpGlobalCommand).execute(this.#context);
283
+ } else if (runResult.runState === RunState.PARSE_ERROR) {
284
+ if (
285
+ (runResult.command !== undefined) && (
286
+ isSubCommand(runResult.command) ||
287
+ isGlobalCommand(runResult.command)
288
+ )
289
+ ) {
290
+ // print help on specific command
291
+ await helpSubCommand.execute(
292
+ this.#context,
293
+ { command: runResult.command!.name },
294
+ );
295
+ } else {
296
+ // print usage
297
+ await new UsageCommand(helpGlobalCommand).execute(this.#context);
298
+ }
299
+ }
300
+ return runResult;
301
+ } catch (error) {
302
+ // An unexpected error in the framework
303
+ logger.error("Runtime error: %s", (error as Error).message);
304
+ return {
305
+ runState: RunState.RUNTIME_ERROR,
306
+ error: error as Error,
307
+ };
308
+ } finally {
309
+ await ShutdownServiceProvider.shutdown();
310
+ }
311
+ }
312
+ }
@@ -0,0 +1,54 @@
1
+ import process from "node:process";
2
+ import BaseCLI from "./BaseCLI.ts";
3
+ import type RunResult from "../api/RunResult.ts";
4
+ import { RunState } from "../api/RunResult.ts";
5
+ import type CLIConfig from "../api/CLIConfig.ts";
6
+ import { Writable } from "node:stream";
7
+ import TtyTerminal from "../service/printer/terminal/TtyTerminal.ts";
8
+ import TtyStyler from "../service/printer/terminal/TtyStyler.ts";
9
+ import supportsColor from "supports-color";
10
+
11
+ /**
12
+ * Default Bun and NodeJS implementation of a {@link CLI} using `process.stdout`, `process.stderr` and `process.argv`.
13
+ */
14
+ export default class DefaultRuntimeCLI extends BaseCLI {
15
+ /**
16
+ * Constructor configures the instance with the specified CLI application details
17
+ * and making use of `process.stdout` and `process.stderr`.
18
+ */
19
+ constructor(
20
+ cliConfig: CLIConfig,
21
+ envVarsEnabled = false,
22
+ configEnabled = false,
23
+ keyValueServiceEnabled = false,
24
+ validateAllCommands = false,
25
+ ) {
26
+ super(
27
+ cliConfig,
28
+ Writable.toWeb(process.stdout),
29
+ Writable.toWeb(process.stderr),
30
+ supportsColor.stdout !== false,
31
+ supportsColor.stderr !== false,
32
+ new TtyTerminal(process.stderr),
33
+ new TtyStyler(
34
+ supportsColor.stderr === false ? 1 : supportsColor.stderr.level,
35
+ ),
36
+ envVarsEnabled,
37
+ configEnabled,
38
+ keyValueServiceEnabled,
39
+ validateAllCommands,
40
+ );
41
+ }
42
+
43
+ /**
44
+ * Run the CLI using `process.argv` for the arguments and call `process.exit()` passing the
45
+ * {@link RunState} value resulting from the invocation.
46
+ */
47
+ override async run(): Promise<RunResult> {
48
+ const runResult = await super.run(process.argv);
49
+ if (runResult.runState === RunState.RUNTIME_ERROR) {
50
+ console.error(runResult.error);
51
+ }
52
+ process.exit(runResult.runState);
53
+ }
54
+ }