@flowscripter/dynamic-cli-framework 1.2.2 → 1.3.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 (166) hide show
  1. package/README/core-service-providers.md +2 -2
  2. package/README/development.md +3 -6
  3. package/README/implementation-details.md +17 -17
  4. package/README/key-concepts.md +17 -17
  5. package/README.md +4 -4
  6. package/bun.lock +0 -2
  7. package/index.ts +22 -30
  8. package/package.json +19 -19
  9. package/src/api/argument/Argument.ts +1 -1
  10. package/src/api/argument/ArgumentValueTypes.ts +3 -10
  11. package/src/api/argument/ComplexOption.ts +5 -9
  12. package/src/api/command/GlobalCommand.ts +1 -4
  13. package/src/api/service/core/ArgumentPrompterService.ts +1 -3
  14. package/src/api/service/core/AsciiBannerGeneratorService.ts +1 -4
  15. package/src/api/service/core/CompletionService.ts +2 -6
  16. package/src/api/service/core/ImagePrinterService.ts +1 -2
  17. package/src/api/service/core/KeyValueService.ts +1 -2
  18. package/src/api/service/core/PrettyPrinterService.ts +1 -4
  19. package/src/api/service/core/PrinterService.ts +8 -9
  20. package/src/api/service/core/PrompterService.ts +4 -11
  21. package/src/api/service/core/ShutdownService.ts +1 -2
  22. package/src/api/service/core/SyntaxHighlighterService.ts +1 -5
  23. package/src/api/service/core/Table.ts +7 -25
  24. package/src/api/service/core/TreePrinterService.ts +1 -2
  25. package/src/cli/BaseCLI.ts +17 -47
  26. package/src/cli/DefaultRuntimeCLI.ts +1 -4
  27. package/src/command/CompletionCommand.ts +19 -45
  28. package/src/command/MultiCommandCliHelpCommand.ts +45 -92
  29. package/src/command/SingleCommandCliHelpCommand.ts +17 -28
  30. package/src/command/UsageCommand.ts +6 -12
  31. package/src/command/VersionCommand.ts +2 -6
  32. package/src/launcher.ts +4 -2
  33. package/src/runtime/DefaultContext.ts +2 -5
  34. package/src/runtime/argument/ArgumentTypeGuards.ts +1 -3
  35. package/src/runtime/command/CommandTypeGuards.ts +5 -14
  36. package/src/runtime/command/CommandValidator.ts +56 -118
  37. package/src/runtime/parser.ts +13 -17
  38. package/src/runtime/registry/CommandRegistry.ts +2 -7
  39. package/src/runtime/registry/DefaultCommandRegistry.ts +32 -84
  40. package/src/runtime/registry/DefaultServiceProviderRegistry.ts +3 -9
  41. package/src/runtime/runner.ts +103 -142
  42. package/src/runtime/scanner.ts +28 -46
  43. package/src/runtime/values/ValuePopulationResult.ts +1 -2
  44. package/src/runtime/values/argumentValueMerge.ts +16 -28
  45. package/src/runtime/values/argumentValueValidation.ts +21 -67
  46. package/src/runtime/values/globalCommandValuePopulation.ts +9 -18
  47. package/src/runtime/values/subCommandValuePopulation.ts +42 -65
  48. package/src/service/argumentPrompter/ArgumentPrompterServiceProvider.ts +3 -10
  49. package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +22 -59
  50. package/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.ts +5 -14
  51. package/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.ts +59 -77
  52. package/src/service/banner/BannerServiceProvider.ts +13 -35
  53. package/src/service/banner/command/NoBannerCommand.ts +2 -8
  54. package/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.ts +5 -10
  55. package/src/service/completion/CompletionServiceProvider.ts +20 -48
  56. package/src/service/completion/DefaultCompletionService.ts +17 -56
  57. package/src/service/completion/shell/ShellHandler.ts +1 -3
  58. package/src/service/completion/shell/fish.ts +1 -1
  59. package/src/service/completion/shell/powershell.ts +2 -12
  60. package/src/service/completion/shell/zsh.ts +1 -1
  61. package/src/service/configuration/ConfigurationServiceProvider.ts +40 -133
  62. package/src/service/configuration/DefaultKeyValueService.ts +6 -20
  63. package/src/service/configuration/DefaultSecretService.ts +10 -14
  64. package/src/service/configuration/command/ConfigCommand.ts +1 -4
  65. package/src/service/configuration/command/DumpConfigCommand.ts +9 -21
  66. package/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.ts +5 -14
  67. package/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.ts +5 -12
  68. package/src/service/imagePrinter/DefaultImagePrinterService.ts +1 -5
  69. package/src/service/imagePrinter/ImagePrinterServiceProvider.ts +1 -4
  70. package/src/service/prettyPrinter/DefaultPrettyPrinterService.ts +4 -12
  71. package/src/service/prettyPrinter/PrettyPrinterServiceProvider.ts +3 -10
  72. package/src/service/printer/DefaultPrinterService.ts +20 -83
  73. package/src/service/printer/PrinterServiceProvider.ts +3 -11
  74. package/src/service/printer/command/DarkModeCommand.ts +3 -10
  75. package/src/service/printer/command/LogLevelCommand.ts +7 -26
  76. package/src/service/printer/command/NoColorCommand.ts +3 -10
  77. package/src/service/printer/command/NoHyperlinksCommand.ts +3 -10
  78. package/src/service/printer/terminal/Progress.ts +99 -90
  79. package/src/service/printer/terminal/Spinner.ts +7 -26
  80. package/src/service/prompter/DefaultPrompterService.ts +2 -6
  81. package/src/service/prompter/PrompterServiceProvider.ts +3 -11
  82. package/src/service/prompter/command/NoPromptCommand.ts +3 -10
  83. package/src/service/prompter/prompt/PromptContext.ts +5 -18
  84. package/src/service/prompter/prompt/promptMultiSelect.ts +6 -21
  85. package/src/service/prompter/prompt/promptOpenUrl.ts +7 -22
  86. package/src/service/prompter/prompt/promptSingleSelect.ts +6 -23
  87. package/src/service/prompter/prompt/promptText.ts +10 -27
  88. package/src/service/prompter/prompt/promptToggle.ts +8 -8
  89. package/src/service/shutdown/ShutdownServiceProvider.ts +3 -10
  90. package/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.ts +13 -26
  91. package/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.ts +8 -21
  92. package/src/service/tableGenerator/DefaultTableGeneratorService.ts +44 -68
  93. package/src/service/tableGenerator/TableGeneratorServiceProvider.ts +7 -16
  94. package/src/service/treePrinter/DefaultTreePrinterService.ts +2 -7
  95. package/src/service/treePrinter/TreePrinterServiceProvider.ts +4 -12
  96. package/src/terminal/ImageRenderer.ts +35 -54
  97. package/src/terminal/PngDecoder.ts +10 -19
  98. package/src/terminal/TtyStyler.ts +11 -9
  99. package/src/terminal/TtyTerminal.ts +2 -10
  100. package/src/terminal/supportsHyperlinks.ts +4 -10
  101. package/src/util/configHelper.ts +3 -10
  102. package/src/util/envVarHelper.ts +50 -88
  103. package/src/util/helpHelper.ts +123 -193
  104. package/src/util/logger.ts +12 -42
  105. package/src/util/runnerHelper.ts +20 -61
  106. package/tests/cli/BaseCLI.test.ts +23 -80
  107. package/tests/command/CompletionCommand.test.ts +1 -6
  108. package/tests/command/MultiCommandCliHelpCommand.test.ts +51 -205
  109. package/tests/command/SingleCommandCliHelpCommand.test.ts +21 -103
  110. package/tests/command/UsageCommand.test.ts +4 -10
  111. package/tests/fixtures/Command.ts +87 -68
  112. package/tests/fixtures/CommandRegistry.ts +1 -3
  113. package/tests/fixtures/Context.ts +3 -11
  114. package/tests/fixtures/ServiceProviderRegistry.ts +1 -1
  115. package/tests/fixtures/prettierPluginFoo.ts +1 -1
  116. package/tests/fixtures/util.ts +2 -8
  117. package/tests/runtime/argument/ArgumentTypeGuards.test.ts +1 -3
  118. package/tests/runtime/command/CommandValidator.test.ts +881 -604
  119. package/tests/runtime/parser.test.ts +222 -246
  120. package/tests/runtime/registry/DefaultCommandRegistry.test.ts +15 -37
  121. package/tests/runtime/registry/DefaultServiceProviderRegistry.test.ts +2 -8
  122. package/tests/runtime/runner.test.ts +231 -281
  123. package/tests/runtime/scanner.test.ts +277 -475
  124. package/tests/runtime/values/argumentValueMerge.test.ts +133 -81
  125. package/tests/runtime/values/argumentValueValidation.test.ts +444 -588
  126. package/tests/runtime/values/globalCommandValuePopulation.test.ts +71 -253
  127. package/tests/runtime/values/subCommandValuePopulation.test.ts +1342 -1570
  128. package/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.ts +3 -12
  129. package/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.ts +36 -45
  130. package/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.ts +2 -8
  131. package/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.ts +40 -62
  132. package/tests/service/banner/BannerServiceProvider.test.ts +5 -18
  133. package/tests/service/banner/command/NoBannerCommand.test.ts +1 -4
  134. package/tests/service/completion/CompletionServiceProvider.test.ts +145 -214
  135. package/tests/service/completion/DefaultCompletionService.test.ts +17 -79
  136. package/tests/service/completion/shell/fish.test.ts +1 -3
  137. package/tests/service/configuration/ConfigurationServiceProvider.test.ts +26 -75
  138. package/tests/service/configuration/DefaultKeyValueService.test.ts +9 -21
  139. package/tests/service/configuration/DefaultSecretService.test.ts +7 -15
  140. package/tests/service/configuration/command/DumpConfigCommand.test.ts +4 -13
  141. package/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.ts +6 -12
  142. package/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.ts +1 -10
  143. package/tests/service/imagePrinter/DefaultImagePrinterService.test.ts +5 -70
  144. package/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.ts +4 -11
  145. package/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.ts +2 -6
  146. package/tests/service/printer/DefaultPrinterService.test.ts +57 -255
  147. package/tests/service/printer/PrinterServiceProvider.test.ts +2 -8
  148. package/tests/service/printer/command/DarkModeCommand.test.ts +4 -12
  149. package/tests/service/printer/command/LogLevelCommand.test.ts +4 -17
  150. package/tests/service/printer/command/NoColorCommand.test.ts +4 -12
  151. package/tests/service/printer/command/NoHyperlinksCommand.test.ts +7 -21
  152. package/tests/service/printer/terminal/Progress.test.ts +1 -3
  153. package/tests/service/printer/terminal/Spinner.test.ts +2 -8
  154. package/tests/service/prompter/DefaultPrompterService.test.ts +52 -69
  155. package/tests/service/prompter/PrompterServiceProvider.test.ts +2 -8
  156. package/tests/service/shutdown/ShutdownServiceProvider.test.ts +1 -3
  157. package/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.ts +13 -99
  158. package/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.ts +2 -7
  159. package/tests/service/tableGenerator/DefaultTableGeneratorService.test.ts +12 -33
  160. package/tests/service/tableGenerator/TableGeneratorServiceProvider.test.ts +2 -2
  161. package/tests/service/treePrinter/DefaultTreePrinterService.test.ts +4 -6
  162. package/tests/service/treePrinter/TreePrinterServiceProvider.test.ts +4 -8
  163. package/tests/terminal/ImageRenderer.test.ts +2 -11
  164. package/tests/terminal/PngDecoder.test.ts +2 -6
  165. package/tests/util/configHelper.test.ts +55 -137
  166. package/tests/util/envVarHelper.test.ts +46 -110
@@ -2,10 +2,7 @@ import process from "node:process";
2
2
  import path from "node:path";
3
3
  import fs from "node:fs/promises";
4
4
  import { Stats } from "node:fs";
5
- import type {
6
- ServiceInfo,
7
- ServiceProvider,
8
- } from "../../api/service/ServiceProvider.ts";
5
+ import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
9
6
  import ConfigCommand from "./command/ConfigCommand.ts";
10
7
  import type {
11
8
  ArgumentSingleValueType,
@@ -131,7 +128,7 @@ const logger = getLogger("ConfigurationServiceProvider");
131
128
  * are stored under a top level `key-values` property. These are expected to not be modified by the user of the CLI.
132
129
  *
133
130
  * The second and third level of properties is used to scope the key-values to specific command names
134
- * (via {@link Command.name} values) and specific service IDs (via {@link ServiceInfo.serviceId} values).
131
+ * (via {@link Command.name} values) and specific service IDs (via {@link ServiceProvider.serviceId} values).
135
132
  * Both keys and values are string based.
136
133
  *
137
134
  * Values may be stored as OS-native secrets via {@link KeyValueService.setKey} with `isSecret=true`.
@@ -183,10 +180,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
183
180
  // the configuration data to be used by the CLI runner implementation when setting command defaults.
184
181
  // ArgumentSingleValueType is for GlobalCommandArgument values, ArgumentValues is for
185
182
  // SubCommandArgument values.
186
- public defaultsData: Map<
187
- string,
188
- ArgumentValues | ArgumentSingleValueType
189
- > = new Map();
183
+ public defaultsData: Map<string, ArgumentValues | ArgumentSingleValueType> = new Map();
190
184
 
191
185
  // the configuration data to be used by the CLI runner implementation
192
186
  // when updating command scoped access to key-value data via the key-value service.
@@ -222,14 +216,10 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
222
216
  secretServiceEnabled = false,
223
217
  ) {
224
218
  if (!configEnabled && keyValueServiceEnabled) {
225
- throw new Error(
226
- "configEnabled must be true if keyValueServiceEnabled is true",
227
- );
219
+ throw new Error("configEnabled must be true if keyValueServiceEnabled is true");
228
220
  }
229
221
  if (!configEnabled && secretServiceEnabled) {
230
- throw new Error(
231
- "configEnabled must be true if secretServiceEnabled is true",
232
- );
222
+ throw new Error("configEnabled must be true if secretServiceEnabled is true");
233
223
  }
234
224
  this.servicePriority = servicePriority;
235
225
  this.envVarsEnabled = envVarsEnabled;
@@ -249,9 +239,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
249
239
  this.#defaultSecretService = new DefaultSecretService(cliConfig.name);
250
240
  }
251
241
  if (this.keyValueServiceEnabled || this.secretServiceEnabled) {
252
- this.#defaultKeyValueService = new DefaultKeyValueService(
253
- this.#defaultSecretService,
254
- );
242
+ this.#defaultKeyValueService = new DefaultKeyValueService(this.#defaultSecretService);
255
243
  }
256
244
  return Promise.resolve({
257
245
  // this may be undefined if keyValueServiceEnabled and secretServiceEnabled are false
@@ -276,68 +264,39 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
276
264
  public async getDefaultArgumentValues(
277
265
  cliConfig: CLIConfig,
278
266
  command: Command,
279
- ): Promise<
280
- PopulatedArgumentValues | PopulatedArgumentValueType | undefined
281
- > {
267
+ ): Promise<PopulatedArgumentValues | PopulatedArgumentValueType | undefined> {
282
268
  if (!this.configEnabled) {
283
- logger.debug(
284
- "configuration of default values is not enabled",
285
- );
269
+ logger.debug("configuration of default values is not enabled");
286
270
  return undefined;
287
271
  }
288
272
 
289
- logger.debug(
290
- "getting default argument values for command: %s",
291
- command.name,
292
- );
273
+ logger.debug("getting default argument values for command: %s", command.name);
293
274
 
294
- if (
295
- (command.enableConfiguration === undefined) ||
296
- (command.enableConfiguration !== true)
297
- ) {
298
- logger.debug(
299
- "enableConfiguration for command: %s is not true",
300
- command.name,
301
- );
275
+ if (command.enableConfiguration === undefined || command.enableConfiguration !== true) {
276
+ logger.debug("enableConfiguration for command: %s is not true", command.name);
302
277
  return undefined;
303
278
  }
304
279
 
305
- let result:
306
- | PopulatedArgumentValues
307
- | PopulatedArgumentValueType
308
- | undefined;
280
+ let result: PopulatedArgumentValues | PopulatedArgumentValueType | undefined;
309
281
 
310
282
  if (isGlobalModifierCommand(command) || isGlobalCommand(command)) {
311
- const configuredValue = this.defaultsData.get(
312
- command.name,
313
- ) as ArgumentSingleValueType;
283
+ const configuredValue = this.defaultsData.get(command.name) as ArgumentSingleValueType;
314
284
  const envVarValue = this.envVarsEnabled
315
- ? getGlobalCommandValueFromEnvVars(
316
- cliConfig,
317
- command,
318
- )
285
+ ? getGlobalCommandValueFromEnvVars(cliConfig, command)
319
286
  : undefined;
320
287
  // default to environment variable value
321
288
  result = envVarValue !== undefined ? envVarValue : configuredValue;
322
289
  } else if (isSubCommand(command)) {
323
- const configuredValues = this.defaultsData.get(
324
- command.name,
325
- ) as ArgumentValues;
290
+ const configuredValues = this.defaultsData.get(command.name) as ArgumentValues;
326
291
  const envVarValues = this.envVarsEnabled
327
- ? getSubCommandValuesFromEnvVars(
328
- cliConfig,
329
- command,
330
- )
292
+ ? getSubCommandValuesFromEnvVars(cliConfig, command)
331
293
  : undefined;
332
294
  if (envVarValues === undefined) {
333
295
  result = configuredValues;
334
296
  } else if (configuredValues === undefined) {
335
297
  result = envVarValues;
336
298
  } else {
337
- result = argumentValueMerge(
338
- envVarValues,
339
- configuredValues,
340
- ) as PopulatedArgumentValues;
299
+ result = argumentValueMerge(envVarValues, configuredValues) as PopulatedArgumentValues;
341
300
  }
342
301
  }
343
302
 
@@ -353,17 +312,13 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
353
312
  ): Promise<PopulatedArgumentValues | PopulatedArgumentValueType> {
354
313
  if (typeof value === "string" && value.startsWith(SECRET_SENTINEL_PREFIX)) {
355
314
  const bunSecretName = value.slice(SECRET_SENTINEL_PREFIX.length);
356
- const secretValue = await this.#defaultSecretService!.getSecret(
357
- bunSecretName,
358
- );
315
+ const secretValue = await this.#defaultSecretService!.getSecret(bunSecretName);
359
316
  if (secretValue === null) {
360
- throw new Error(
361
- `Secret not found in OS secret store for sentinel: '${value}'`,
362
- );
317
+ throw new Error(`Secret not found in OS secret store for sentinel: '${value}'`);
363
318
  }
364
319
  return secretValue;
365
320
  }
366
- if ((typeof value === "object") && (value !== null)) {
321
+ if (typeof value === "object" && value !== null) {
367
322
  if (Array.isArray(value)) {
368
323
  const resolved = [];
369
324
  for (const item of value) {
@@ -373,9 +328,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
373
328
  }
374
329
  const resolved: Record<string, unknown> = {};
375
330
  for (const [key, val] of Object.entries(value)) {
376
- resolved[key] = await this.#resolveSecrets(
377
- val as PopulatedArgumentValueType,
378
- );
331
+ resolved[key] = await this.#resolveSecrets(val as PopulatedArgumentValueType);
379
332
  }
380
333
  return resolved as unknown as PopulatedArgumentValues;
381
334
  }
@@ -392,9 +345,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
392
345
  */
393
346
  public setCommandKeyValueScope(commandName: string): void {
394
347
  if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
395
- throw new Error(
396
- `Attempt to use KeyValueService/SecretService which is not enabled`,
397
- );
348
+ throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
398
349
  }
399
350
  if (this.#currentCommandNameKeyValueScope) {
400
351
  throw new Error(
@@ -414,9 +365,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
414
365
  if (!this.#commandKeyValueData.has(commandName)) {
415
366
  this.#commandKeyValueData.set(commandName, new Map());
416
367
  }
417
- this.#defaultKeyValueService.setKeyValueData(
418
- this.#commandKeyValueData.get(commandName)!,
419
- );
368
+ this.#defaultKeyValueService.setKeyValueData(this.#commandKeyValueData.get(commandName)!);
420
369
  }
421
370
  if (this.#defaultSecretService) {
422
371
  this.#defaultSecretService.setScope("command_" + commandName);
@@ -433,9 +382,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
433
382
  */
434
383
  public setServiceKeyValueScope(serviceId: string): void {
435
384
  if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
436
- throw new Error(
437
- `Attempt to use KeyValueService/SecretService which is not enabled`,
438
- );
385
+ throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
439
386
  }
440
387
  if (this.#currentServiceIdKeyValueScope) {
441
388
  throw new Error(
@@ -455,9 +402,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
455
402
  if (!this.#serviceKeyValueData.has(serviceId)) {
456
403
  this.#serviceKeyValueData.set(serviceId, new Map());
457
404
  }
458
- this.#defaultKeyValueService.setKeyValueData(
459
- this.#serviceKeyValueData.get(serviceId)!,
460
- );
405
+ this.#defaultKeyValueService.setKeyValueData(this.#serviceKeyValueData.get(serviceId)!);
461
406
  }
462
407
  if (this.#defaultSecretService) {
463
408
  this.#defaultSecretService.setScope("service_" + serviceId);
@@ -472,18 +417,11 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
472
417
  */
473
418
  public async clearKeyValueScope(): Promise<void> {
474
419
  if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
475
- throw new Error(
476
- `Attempt to use KeyValueService/SecretService which is not enabled`,
477
- );
420
+ throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
478
421
  }
479
- if (
480
- this.#defaultKeyValueService &&
481
- this.#defaultKeyValueService.isDirty()
482
- ) {
422
+ if (this.#defaultKeyValueService && this.#defaultKeyValueService.isDirty()) {
483
423
  if (this.configLocation === undefined) {
484
- throw new Error(
485
- "Attempt to write updated config with no configLocation set",
486
- );
424
+ throw new Error("Attempt to write updated config with no configLocation set");
487
425
  }
488
426
  await this.#writeConfig(this.configLocation);
489
427
  }
@@ -509,10 +447,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
509
447
  // default to `$HOME/.<application_name>.json`
510
448
  const home = process.env["HOME"];
511
449
  if (home) {
512
- this.configLocation = path.join(
513
- home,
514
- `.${context.cliConfig.name.replace(/\W/g, "")}.json`,
515
- );
450
+ this.configLocation = path.join(home, `.${context.cliConfig.name.replace(/\W/g, "")}.json`);
516
451
  }
517
452
  }
518
453
  if (this.configLocation === undefined) {
@@ -561,14 +496,8 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
561
496
  if (config.defaults !== undefined) {
562
497
  const defaults = config.defaults;
563
498
  Object.keys(defaults).forEach((commandName) => {
564
- this.defaultsData.set(
565
- commandName,
566
- defaults[commandName] as ArgumentValues,
567
- );
568
- logger.debug(
569
- "Set default argument values for command name: %s",
570
- commandName,
571
- );
499
+ this.defaultsData.set(commandName, defaults[commandName] as ArgumentValues);
500
+ logger.debug("Set default argument values for command name: %s", commandName);
572
501
  });
573
502
  }
574
503
  if (config["key-values"] !== undefined) {
@@ -580,10 +509,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
580
509
  commandName,
581
510
  new Map(Object.entries(commandKeyValues[commandName])),
582
511
  );
583
- logger.debug(
584
- "Set default argument values for command name: %s",
585
- commandName,
586
- );
512
+ logger.debug("Set default argument values for command name: %s", commandName);
587
513
  });
588
514
  }
589
515
  if (keyValues.services !== undefined) {
@@ -593,17 +519,12 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
593
519
  serviceId,
594
520
  new Map(Object.entries(serviceKeyValues[serviceId])),
595
521
  );
596
- logger.debug(
597
- "Set default argument values for service ID: %s",
598
- serviceId,
599
- );
522
+ logger.debug("Set default argument values for service ID: %s", serviceId);
600
523
  });
601
524
  }
602
525
  }
603
526
  } catch (err) {
604
- throw new Error(
605
- `Failed to read config at location: '${this.configLocation}': ${err}`,
606
- );
527
+ throw new Error(`Failed to read config at location: '${this.configLocation}': ${err}`);
607
528
  }
608
529
  }
609
530
 
@@ -613,9 +534,7 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
613
534
  try {
614
535
  await fs.writeFile(location, this.getConfigString());
615
536
  } catch (err) {
616
- throw new Error(
617
- `Failed to write config at location: '${this.configLocation}': ${err}`,
618
- );
537
+ throw new Error(`Failed to write config at location: '${this.configLocation}': ${err}`);
619
538
  }
620
539
  }
621
540
 
@@ -631,33 +550,21 @@ export default class ConfigurationServiceProvider implements ServiceProvider {
631
550
  if (this.defaultsData.size > 0) {
632
551
  config.defaults = Object.fromEntries(this.defaultsData);
633
552
  }
634
- if (
635
- (this.#commandKeyValueData.size > 0) ||
636
- (this.#serviceKeyValueData.size > 0)
637
- ) {
553
+ if (this.#commandKeyValueData.size > 0 || this.#serviceKeyValueData.size > 0) {
638
554
  config["key-values"] = {};
639
555
  if (this.#commandKeyValueData.size > 0) {
640
556
  config["key-values"].commands = {};
641
- for (
642
- const [commandName, keyValueData] of this.#commandKeyValueData
643
- .entries()
644
- ) {
557
+ for (const [commandName, keyValueData] of this.#commandKeyValueData.entries()) {
645
558
  if (keyValueData.size > 0) {
646
- config["key-values"].commands[commandName] = Object.fromEntries(
647
- keyValueData,
648
- );
559
+ config["key-values"].commands[commandName] = Object.fromEntries(keyValueData);
649
560
  }
650
561
  }
651
562
  }
652
563
  if (this.#serviceKeyValueData.size > 0) {
653
564
  config["key-values"].services = {};
654
- for (
655
- const [serviceId, keyValueData] of this.#serviceKeyValueData.entries()
656
- ) {
565
+ for (const [serviceId, keyValueData] of this.#serviceKeyValueData.entries()) {
657
566
  if (keyValueData.size > 0) {
658
- config["key-values"].services[serviceId] = Object.fromEntries(
659
- keyValueData,
660
- );
567
+ config["key-values"].services[serviceId] = Object.fromEntries(keyValueData);
661
568
  }
662
569
  }
663
570
  }
@@ -13,9 +13,7 @@ export default class DefaultKeyValueService implements KeyValueService {
13
13
 
14
14
  public setKeyValueData(keyValueData: Map<string, string>) {
15
15
  if (this.#keyValueData) {
16
- throw new Error(
17
- "Attempt to overwrite key-value data, it should be cleared first",
18
- );
16
+ throw new Error("Attempt to overwrite key-value data, it should be cleared first");
19
17
  }
20
18
  this.#keyValueData = keyValueData;
21
19
  this.#dirty = false;
@@ -41,16 +39,12 @@ export default class DefaultKeyValueService implements KeyValueService {
41
39
 
42
40
  if (value.startsWith(SECRET_SENTINEL_PREFIX)) {
43
41
  if (!this.#secretService) {
44
- throw new Error(
45
- "Secret sentinel found but no secret service is available",
46
- );
42
+ throw new Error("Secret sentinel found but no secret service is available");
47
43
  }
48
44
  const bunSecretName = value.slice(SECRET_SENTINEL_PREFIX.length);
49
45
  const secretValue = await this.#secretService.getSecret(bunSecretName);
50
46
  if (secretValue === null) {
51
- throw new Error(
52
- `Secret not found in OS secret store for key: '${key}'`,
53
- );
47
+ throw new Error(`Secret not found in OS secret store for key: '${key}'`);
54
48
  }
55
49
  return secretValue;
56
50
  }
@@ -60,26 +54,18 @@ export default class DefaultKeyValueService implements KeyValueService {
60
54
 
61
55
  public hasKey(key: string): Promise<boolean> {
62
56
  if (this.#keyValueData === undefined) {
63
- return Promise.reject(
64
- new Error("Attempt to access undefined key-value data"),
65
- );
57
+ return Promise.reject(new Error("Attempt to access undefined key-value data"));
66
58
  }
67
59
  return Promise.resolve(this.#keyValueData.has(key));
68
60
  }
69
61
 
70
- public async setKey(
71
- key: string,
72
- value: string,
73
- isSecret = false,
74
- ): Promise<void> {
62
+ public async setKey(key: string, value: string, isSecret = false): Promise<void> {
75
63
  if (this.#keyValueData === undefined) {
76
64
  throw new Error("Attempt to access undefined key-value data");
77
65
  }
78
66
  if (isSecret) {
79
67
  if (!this.#secretService) {
80
- throw new Error(
81
- "Attempt to set a secret but no secret service is available",
82
- );
68
+ throw new Error("Attempt to set a secret but no secret service is available");
83
69
  }
84
70
  const bunSecretName = await this.#secretService.setSecret(key, value);
85
71
  this.#keyValueData.set(key, SECRET_SENTINEL_PREFIX + bunSecretName);
@@ -4,11 +4,9 @@ import { secrets as bunSecrets } from "bun";
4
4
  const MAX_NAME_LENGTH = 255;
5
5
  const MAX_VALUE_BYTES = 2047;
6
6
 
7
- interface SecretsApi {
7
+ export interface SecretsApi {
8
8
  get(options: { service: string; name: string }): Promise<string | null>;
9
- set(
10
- options: { service: string; name: string; value: string },
11
- ): Promise<void>;
9
+ set(options: { service: string; name: string; value: string }): Promise<void>;
12
10
  delete(options: { service: string; name: string }): Promise<boolean>;
13
11
  }
14
12
 
@@ -45,14 +43,10 @@ export default class DefaultSecretService implements SecretService {
45
43
  }
46
44
  const name = this.#scope + "_" + DefaultSecretService.#sanitize(key);
47
45
  if (name.length > MAX_NAME_LENGTH) {
48
- throw new Error(
49
- `Secret name exceeds ${MAX_NAME_LENGTH} characters: '${name}'`,
50
- );
46
+ throw new Error(`Secret name exceeds ${MAX_NAME_LENGTH} characters: '${name}'`);
51
47
  }
52
48
  if (new TextEncoder().encode(value).byteLength > MAX_VALUE_BYTES) {
53
- throw new Error(
54
- `Secret value exceeds ${MAX_VALUE_BYTES} bytes`,
55
- );
49
+ throw new Error(`Secret value exceeds ${MAX_VALUE_BYTES} bytes`);
56
50
  }
57
51
  await this.#secrets.set({
58
52
  service: this.#serviceName,
@@ -77,9 +71,11 @@ export default class DefaultSecretService implements SecretService {
77
71
  }
78
72
 
79
73
  public async hasSecret(bunSecretName: string): Promise<boolean> {
80
- return (await this.#secrets.get({
81
- service: this.#serviceName,
82
- name: bunSecretName,
83
- })) !== null;
74
+ return (
75
+ (await this.#secrets.get({
76
+ service: this.#serviceName,
77
+ name: bunSecretName,
78
+ })) !== null
79
+ );
84
80
  }
85
81
  }
@@ -30,10 +30,7 @@ export default class ConfigCommand implements GlobalModifierCommand {
30
30
  this.executePriority = executePriority;
31
31
  }
32
32
 
33
- public execute(
34
- _context: Context,
35
- argumentValue: ArgumentSingleValueType,
36
- ): Promise<void> {
33
+ public execute(_context: Context, argumentValue: ArgumentSingleValueType): Promise<void> {
37
34
  const configLocation = argumentValue as string;
38
35
 
39
36
  this.#configurationServiceProvider.setConfigLocation(configLocation);
@@ -2,13 +2,9 @@ import type Context from "../../../api/Context.ts";
2
2
  import type GlobalCommand from "../../../api/command/GlobalCommand.ts";
3
3
  import type ConfigurationServiceProvider from "../ConfigurationServiceProvider.ts";
4
4
  import type PrinterService from "../../../api/service/core/PrinterService.ts";
5
- import {
6
- PRINTER_SERVICE_ID,
7
- } from "../../../api/service/core/PrinterService.ts";
5
+ import { PRINTER_SERVICE_ID } from "../../../api/service/core/PrinterService.ts";
8
6
  import type SyntaxHighlighterService from "../../../api/service/core/SyntaxHighlighterService.ts";
9
- import {
10
- SYNTAX_HIGHLIGHTER_SERVICE_ID,
11
- } from "../../../api/service/core/SyntaxHighlighterService.ts";
7
+ import { SYNTAX_HIGHLIGHTER_SERVICE_ID } from "../../../api/service/core/SyntaxHighlighterService.ts";
12
8
 
13
9
  /**
14
10
  * Command which dumps the configuration loaded by the {@link ConfigurationServiceProvider}.
@@ -19,29 +15,21 @@ export default class DumpConfigCommand implements GlobalCommand {
19
15
 
20
16
  readonly #configurationServiceProvider: ConfigurationServiceProvider;
21
17
 
22
- public constructor(
23
- configurationServiceProvider: ConfigurationServiceProvider,
24
- ) {
18
+ public constructor(configurationServiceProvider: ConfigurationServiceProvider) {
25
19
  this.#configurationServiceProvider = configurationServiceProvider;
26
20
  }
27
21
 
28
- public async execute(
29
- context: Context,
30
- ): Promise<void> {
31
- const printerService = context.getServiceById(
32
- PRINTER_SERVICE_ID,
33
- ) as PrinterService;
22
+ public async execute(context: Context): Promise<void> {
23
+ const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
34
24
  const syntaxHighlighterService = context.getServiceById(
35
25
  SYNTAX_HIGHLIGHTER_SERVICE_ID,
36
26
  ) as SyntaxHighlighterService;
37
27
 
38
28
  await printerService.print(
39
- `${
40
- syntaxHighlighterService.highlight(
41
- this.#configurationServiceProvider.getConfigString(),
42
- "json",
43
- )
44
- }\n`,
29
+ `${syntaxHighlighterService.highlight(
30
+ this.#configurationServiceProvider.getConfigString(),
31
+ "json",
32
+ )}\n`,
45
33
  );
46
34
  }
47
35
  }
@@ -1,7 +1,4 @@
1
- import type {
2
- ServiceInfo,
3
- ServiceProvider,
4
- } from "../../api/service/ServiceProvider.ts";
1
+ import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
5
2
  import DefaultDataDumpGeneratorService from "./DefaultDataDumpGeneratorService.ts";
6
3
  import { DATA_DUMP_GENERATOR_SERVICE_ID } from "../../api/service/core/DataDumpGeneratorService.ts";
7
4
  import type Context from "../../api/Context.ts";
@@ -9,14 +6,11 @@ import type PrinterService from "../../api/service/core/PrinterService.ts";
9
6
  import { PRINTER_SERVICE_ID } from "../../api/service/core/PrinterService.ts";
10
7
  import type CLIConfig from "../../api/CLIConfig.ts";
11
8
 
12
- export default class DataDumpGeneratorServiceProvider
13
- implements ServiceProvider {
9
+ export default class DataDumpGeneratorServiceProvider implements ServiceProvider {
14
10
  readonly serviceId: string = DATA_DUMP_GENERATOR_SERVICE_ID;
15
11
  readonly #defaultService: DefaultDataDumpGeneratorService;
16
12
 
17
- public constructor(
18
- readonly servicePriority: number,
19
- ) {
13
+ public constructor(readonly servicePriority: number) {
20
14
  this.#defaultService = new DefaultDataDumpGeneratorService();
21
15
  }
22
16
 
@@ -28,13 +22,10 @@ export default class DataDumpGeneratorServiceProvider
28
22
  }
29
23
 
30
24
  initService(context: Context): Promise<void> {
31
- const printerService = context.getServiceById(
32
- PRINTER_SERVICE_ID,
33
- ) as PrinterService;
25
+ const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
34
26
 
35
27
  this.#defaultService.colorEnabled = printerService.colorEnabled;
36
- this.#defaultService.colorFunction = printerService.color
37
- .bind(printerService);
28
+ this.#defaultService.colorFunction = printerService.color.bind(printerService);
38
29
 
39
30
  return Promise.resolve(undefined);
40
31
  }
@@ -6,17 +6,11 @@ import {
6
6
  type HexDumpGenerateOptions,
7
7
  } from "../../api/service/core/DataDumpGeneratorService.ts";
8
8
 
9
- export default class DefaultDataDumpGeneratorService
10
- implements DataDumpGeneratorService {
9
+ export default class DefaultDataDumpGeneratorService implements DataDumpGeneratorService {
11
10
  colorEnabled = true;
12
- colorFunction: (text: string, hexFormattedColor: string) => string = (text) =>
13
- text;
11
+ colorFunction: (text: string, hexFormattedColor: string) => string = (text) => text;
14
12
 
15
- #colorByte(
16
- text: string,
17
- byteValue: number,
18
- colorScheme?: ByteRangeColor[],
19
- ): string {
13
+ #colorByte(text: string, byteValue: number, colorScheme?: ByteRangeColor[]): string {
20
14
  if (!this.colorEnabled || !colorScheme) {
21
15
  return text;
22
16
  }
@@ -56,9 +50,8 @@ export default class DefaultDataDumpGeneratorService
56
50
  const byteValue = data[byteIndex]!;
57
51
  let rendered: string;
58
52
  if (format === DumpFormat.ASCII) {
59
- rendered = byteValue >= 0x20 && byteValue <= 0x7e
60
- ? String.fromCharCode(byteValue)
61
- : ".";
53
+ rendered =
54
+ byteValue >= 0x20 && byteValue <= 0x7e ? String.fromCharCode(byteValue) : ".";
62
55
  } else {
63
56
  rendered = byteValue.toString(16).toUpperCase().padStart(2, "0");
64
57
  }
@@ -14,10 +14,6 @@ export default class DefaultImagePrinterService implements ImagePrinterService {
14
14
  widthPercentage: number = 100,
15
15
  hexFormattedBackgroundColor?: string,
16
16
  ): Promise<string> {
17
- return this.#renderer.renderImage(
18
- imageBuffer,
19
- widthPercentage,
20
- hexFormattedBackgroundColor,
21
- );
17
+ return this.#renderer.renderImage(imageBuffer, widthPercentage, hexFormattedBackgroundColor);
22
18
  }
23
19
  }
@@ -1,7 +1,4 @@
1
- import type {
2
- ServiceInfo,
3
- ServiceProvider,
4
- } from "../../api/service/ServiceProvider.ts";
1
+ import type { ServiceInfo, ServiceProvider } from "../../api/service/ServiceProvider.ts";
5
2
  import DefaultImagePrinterService from "./DefaultImagePrinterService.ts";
6
3
  import { IMAGE_PRINTER_SERVICE_ID } from "../../api/service/core/ImagePrinterService.ts";
7
4
  import type Context from "../../api/Context.ts";
@@ -6,16 +6,13 @@ import type { Plugin } from "prettier";
6
6
  * Default implementation of {@link PrettyPrinterService} which provides by default the
7
7
  * syntaxes built into prettier.
8
8
  */
9
- export default class DefaultPrettyPrinterService
10
- implements PrettyPrinterService {
9
+ export default class DefaultPrettyPrinterService implements PrettyPrinterService {
11
10
  #registeredSyntaxes = new Array<string>();
12
11
  #syntaxNameToPluginnMap = new Map<string, Plugin>();
13
12
 
14
13
  async #populateBuiltInSyntaxes(): Promise<void> {
15
14
  const languages = (await prettier.getSupportInfo()).languages;
16
- this.#registeredSyntaxes = languages.map((language) =>
17
- language.name.toLowerCase()
18
- );
15
+ this.#registeredSyntaxes = languages.map((language) => language.name.toLowerCase());
19
16
  }
20
17
 
21
18
  async getRegisteredSyntaxes(): Promise<ReadonlyArray<string>> {
@@ -38,9 +35,7 @@ export default class DefaultPrettyPrinterService
38
35
 
39
36
  const options: prettier.Options = { parser: syntaxName };
40
37
 
41
- const syntaxPlugin = this.#syntaxNameToPluginnMap.get(
42
- name,
43
- );
38
+ const syntaxPlugin = this.#syntaxNameToPluginnMap.get(name);
44
39
  if (syntaxPlugin) {
45
40
  options.plugins = [syntaxPlugin];
46
41
  }
@@ -48,10 +43,7 @@ export default class DefaultPrettyPrinterService
48
43
  return prettier.format(text, options);
49
44
  }
50
45
 
51
- async registerSyntax(
52
- syntaxName: string,
53
- syntaxPlugin: Plugin,
54
- ): Promise<void> {
46
+ async registerSyntax(syntaxName: string, syntaxPlugin: Plugin): Promise<void> {
55
47
  if (this.#registeredSyntaxes.length === 0) {
56
48
  await this.#populateBuiltInSyntaxes();
57
49
  }