@flowscripter/dynamic-cli-framework 1.7.3 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli-plugin.ts +1 -1
- package/dist/cli-plugin.d.ts +1 -1
- package/dist/cli-plugin.d.ts.map +1 -1
- package/dist/cli-plugin.js +25 -247
- package/dist/index.js +70 -105754
- package/dist/src/api/BaseCLIFeatureOptions.js +0 -0
- package/dist/src/api/CLI.js +0 -0
- package/dist/src/api/CLIConfig.js +0 -0
- package/dist/src/api/Context.js +0 -0
- package/dist/src/api/RunResult.js +73 -0
- package/dist/src/api/argument/Argument.js +0 -0
- package/dist/src/api/argument/ArgumentValueTypes.js +18 -0
- package/dist/src/api/argument/ComplexOption.js +1 -0
- package/dist/src/api/argument/GlobalCommandArgument.js +0 -0
- package/dist/src/api/argument/Option.js +0 -0
- package/dist/src/api/argument/Positional.js +0 -0
- package/dist/src/api/argument/SubCommandArgument.js +1 -0
- package/dist/src/api/command/Command.js +0 -0
- package/dist/src/api/command/GlobalCommand.js +0 -0
- package/dist/src/api/command/GlobalModifierCommand.js +0 -0
- package/dist/src/api/command/GroupCommand.js +0 -0
- package/dist/src/api/command/SubCommand.js +0 -0
- package/dist/src/api/command/UsageExample.js +0 -0
- package/dist/src/api/plugin/CLIPlugin.js +2 -0
- package/dist/src/api/plugin/CommandFactory.js +7 -0
- package/dist/src/api/plugin/ServiceProviderFactory.js +7 -0
- package/dist/src/api/plugin/createCLIPlugin.js +30 -0
- package/dist/src/api/service/ServiceProvider.js +0 -0
- package/dist/src/api/service/core/ArgumentPrompterService.js +1 -0
- package/dist/src/api/service/core/AsciiBannerGeneratorService.js +1 -0
- package/dist/src/api/service/core/CompletionService.js +8 -0
- package/dist/src/api/service/core/DataDumpGeneratorService.js +7 -0
- package/dist/src/api/service/core/ImagePrinterService.js +1 -0
- package/dist/src/api/service/core/KeyValueService.js +7 -0
- package/dist/src/api/service/core/PluginService.js +6 -0
- package/dist/src/api/service/core/PrettyPrinterService.js +1 -0
- package/dist/src/api/service/core/PrinterService.js +42 -0
- package/dist/src/api/service/core/PrompterService.js +10 -0
- package/dist/src/api/service/core/SecretService.js +0 -0
- package/dist/src/api/service/core/ShutdownService.js +1 -0
- package/dist/src/api/service/core/SyntaxHighlighterService.js +1 -0
- package/dist/src/api/service/core/Table.js +49 -0
- package/dist/src/api/service/core/TableGeneratorService.d.ts +1 -0
- package/dist/src/api/service/core/TableGeneratorService.d.ts.map +1 -1
- package/dist/src/api/service/core/TableGeneratorService.js +7 -0
- package/dist/src/api/service/core/TreePrinterService.js +1 -0
- package/dist/src/cli/BaseCLI.d.ts.map +1 -1
- package/dist/src/cli/BaseCLI.js +232 -0
- package/dist/src/cli/DefaultRuntimeCLI.js +20 -0
- package/dist/src/cli/DynamicPluginRuntimeCLI.js +50 -0
- package/dist/src/command/MultiCommandCliHelpCommand.js +238 -0
- package/dist/src/command/SingleCommandCliHelpCommand.js +104 -0
- package/dist/src/command/UsageCommand.js +16 -0
- package/dist/src/command/VersionCommand.js +13 -0
- package/dist/src/launcher.js +61 -0
- package/dist/src/runtime/DefaultContext.js +25 -0
- package/dist/src/runtime/argument/ArgumentTypeGuards.js +3 -0
- package/dist/src/runtime/command/CommandTypeGuards.js +12 -0
- package/dist/src/runtime/command/CommandValidator.js +371 -0
- package/dist/src/runtime/parser.js +105 -0
- package/dist/src/runtime/registry/CommandRegistry.js +0 -0
- package/dist/src/runtime/registry/DefaultCommandRegistry.js +190 -0
- package/dist/src/runtime/registry/DefaultServiceProviderRegistry.js +20 -0
- package/dist/src/runtime/registry/ServiceProviderRegistry.js +0 -0
- package/dist/src/runtime/runner.js +507 -0
- package/dist/src/runtime/scanner.js +244 -0
- package/dist/src/runtime/values/ValuePopulationResult.js +0 -0
- package/dist/src/runtime/values/argumentValueMerge.js +122 -0
- package/dist/src/runtime/values/argumentValueValidation.js +505 -0
- package/dist/src/runtime/values/globalCommandValuePopulation.js +67 -0
- package/dist/src/runtime/values/subCommandValuePopulation.js +549 -0
- package/dist/src/service/argumentPrompter/ArgumentPrompterServiceProvider.js +19 -0
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.js +197 -0
- package/dist/src/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.js +28 -0
- package/dist/src/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.js +233 -0
- package/dist/src/service/asciiBannerGenerator/standard.flf.json +3 -0
- package/dist/src/service/banner/BannerServiceProvider.js +60 -0
- package/dist/src/service/banner/command/NoBannerCommand.js +24 -0
- package/dist/src/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.js +51 -0
- package/dist/src/service/chiselAsciiBannerGenerator/chisel.flf.json +3 -0
- package/dist/src/service/completion/CompletionServiceProvider.d.ts +2 -1
- package/dist/src/service/completion/CompletionServiceProvider.d.ts.map +1 -1
- package/dist/src/service/completion/CompletionServiceProvider.js +159 -0
- package/dist/src/service/completion/DefaultCompletionService.js +279 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts +15 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.js +37 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.d.ts +14 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionGroupCommand.js +10 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts +14 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts.map +1 -0
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.js +67 -0
- package/dist/src/service/completion/shell/ShellHandler.js +0 -0
- package/dist/src/service/completion/shell/bash.js +39 -0
- package/dist/src/service/completion/shell/fish.js +35 -0
- package/dist/src/service/completion/shell/powershell.js +51 -0
- package/dist/src/service/completion/shell/zsh.js +42 -0
- package/dist/src/service/configuration/ConfigurationServiceProvider.js +482 -0
- package/dist/src/service/configuration/DefaultKeyValueService.js +80 -0
- package/dist/src/service/configuration/DefaultSecretService.js +60 -0
- package/dist/src/service/configuration/command/ConfigCommand.js +24 -0
- package/dist/src/service/configuration/command/DumpConfigCommand.js +18 -0
- package/dist/src/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.js +24 -0
- package/dist/src/service/dataDumpGenerator/DefaultDataDumpGeneratorService.js +59 -0
- package/dist/src/service/imagePrinter/DefaultImagePrinterService.js +10 -0
- package/dist/src/service/imagePrinter/ImagePrinterServiceProvider.js +20 -0
- package/dist/src/service/plugin/DefaultPluginService.js +21 -0
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts +1 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts.map +1 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.js +21 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts +17 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginAddSubCommand.js +49 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginGroupCommand.js +21 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginListSubCommand.js +25 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts +17 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.js +24 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts +18 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginSearchSubCommand.js +34 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts +12 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts.map +1 -0
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.js +25 -0
- package/dist/src/service/plugin/command/getPluginId.d.ts +3 -0
- package/dist/src/service/plugin/command/getPluginId.d.ts.map +1 -0
- package/dist/src/service/plugin/command/getPluginId.js +3 -0
- package/dist/src/service/prettyPrinter/DefaultPrettyPrinterService.js +45 -0
- package/dist/src/service/prettyPrinter/PrettyPrinterServiceProvider.js +28 -0
- package/dist/src/service/printer/DefaultPrinterService.js +250 -0
- package/dist/src/service/printer/PrinterServiceProvider.js +43 -0
- package/dist/src/service/printer/command/DarkModeCommand.js +24 -0
- package/dist/src/service/printer/command/LogLevelCommand.js +41 -0
- package/dist/src/service/printer/command/NoColorCommand.js +24 -0
- package/dist/src/service/printer/command/NoHyperlinksCommand.js +21 -0
- package/dist/src/service/printer/terminal/Color.js +15 -0
- package/dist/src/service/printer/terminal/Progress.js +271 -0
- package/dist/src/service/printer/terminal/Spinner.js +83 -0
- package/dist/src/service/printer/terminal/Theme.js +26 -0
- package/dist/src/service/prompter/DefaultPrompterService.js +52 -0
- package/dist/src/service/prompter/PrompterServiceProvider.js +20 -0
- package/dist/src/service/prompter/command/NoPromptCommand.js +21 -0
- package/dist/src/service/prompter/prompt/PromptContext.js +22 -0
- package/dist/src/service/prompter/prompt/promptAcknowledge.js +19 -0
- package/dist/src/service/prompter/prompt/promptMultiSelect.js +74 -0
- package/dist/src/service/prompter/prompt/promptOpenUrl.js +70 -0
- package/dist/src/service/prompter/prompt/promptSingleSelect.js +73 -0
- package/dist/src/service/prompter/prompt/promptText.js +75 -0
- package/dist/src/service/prompter/prompt/promptToggle.js +21 -0
- package/dist/src/service/shutdown/DefaultShutdownService.js +16 -0
- package/dist/src/service/shutdown/ShutdownServiceProvider.js +60 -0
- package/dist/src/service/shutdown/ShutdownState.js +5 -0
- package/dist/src/service/syntaxHighlighter/DefaultSyntaxHighlighterService.js +54 -0
- package/dist/src/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.js +32 -0
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts +3 -1
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.d.ts.map +1 -1
- package/dist/src/service/tableGenerator/DefaultTableGeneratorService.js +344 -0
- package/dist/src/service/tableGenerator/TableGeneratorServiceProvider.js +26 -0
- package/dist/src/service/treePrinter/DefaultTreePrinterService.js +35 -0
- package/dist/src/service/treePrinter/TreePrinterServiceProvider.js +24 -0
- package/dist/src/terminal/Ansi.js +23 -0
- package/dist/src/terminal/ImageRenderer.d.ts.map +1 -1
- package/dist/src/terminal/ImageRenderer.js +166 -0
- package/dist/src/terminal/KeyReader.js +13 -0
- package/dist/src/terminal/PngDecoder.js +115 -0
- package/dist/src/terminal/Styler.js +0 -0
- package/dist/src/terminal/Terminal.js +0 -0
- package/dist/src/terminal/TtyKeyReader.js +87 -0
- package/dist/src/terminal/TtyStyler.js +55 -0
- package/dist/src/terminal/TtyTerminal.js +52 -0
- package/dist/src/terminal/supportsHyperlinks.js +95 -0
- package/dist/src/util/configHelper.js +61 -0
- package/dist/src/util/envVarHelper.js +216 -0
- package/dist/src/util/helpHelper.d.ts.map +1 -1
- package/dist/src/util/helpHelper.js +497 -0
- package/dist/src/util/logger.js +81 -0
- package/dist/src/util/runnerHelper.js +80 -0
- package/package.json +2 -2
- package/src/api/service/core/TableGeneratorService.ts +1 -0
- package/src/cli/BaseCLI.ts +4 -19
- package/src/service/completion/CompletionServiceProvider.ts +16 -3
- package/src/service/completion/command/CompletionCompleteSubCommand.ts +59 -0
- package/src/service/completion/command/CompletionGroupCommand.ts +21 -0
- package/src/{command/CompletionCommand.ts → service/completion/command/CompletionIntegrationSubCommand.ts} +12 -73
- package/src/service/completion/shell/bash.ts +1 -1
- package/src/service/completion/shell/fish.ts +1 -1
- package/src/service/completion/shell/powershell.ts +1 -1
- package/src/service/completion/shell/zsh.ts +1 -1
- package/src/service/plugin/DefaultPluginServiceProvider.ts +2 -2
- package/src/service/plugin/command/PluginAddSubCommand.ts +64 -0
- package/src/service/plugin/command/PluginGroupCommand.ts +27 -0
- package/src/service/plugin/command/PluginListSubCommand.ts +33 -0
- package/src/service/plugin/command/PluginRemoveSubCommand.ts +32 -0
- package/src/service/plugin/command/PluginSearchSubCommand.ts +42 -0
- package/src/service/plugin/command/PluginUpgradeSubCommand.ts +36 -0
- package/src/service/plugin/command/getPluginId.ts +5 -0
- package/src/service/tableGenerator/DefaultTableGeneratorService.ts +6 -1
- package/src/terminal/ImageRenderer.ts +7 -5
- package/src/util/helpHelper.ts +1 -2
- package/dist/src/command/CompletionCommand.d.ts +0 -32
- package/dist/src/command/CompletionCommand.d.ts.map +0 -1
- package/dist/src/command/PluginCommand.d.ts +0 -67
- package/dist/src/command/PluginCommand.d.ts.map +0 -1
- package/dist/tests/cli/BaseCLI.test.d.ts +0 -2
- package/dist/tests/cli/BaseCLI.test.d.ts.map +0 -1
- package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts +0 -2
- package/dist/tests/cli/DynamicPluginRuntimeCLI.test.d.ts.map +0 -1
- package/dist/tests/command/CompletionCommand.test.d.ts +0 -2
- package/dist/tests/command/CompletionCommand.test.d.ts.map +0 -1
- package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts +0 -2
- package/dist/tests/command/MultiCommandCliHelpCommand.test.d.ts.map +0 -1
- package/dist/tests/command/PluginCommand.test.d.ts +0 -2
- package/dist/tests/command/PluginCommand.test.d.ts.map +0 -1
- package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts +0 -2
- package/dist/tests/command/SingleCommandCliHelpCommand.test.d.ts.map +0 -1
- package/dist/tests/command/UsageCommand.test.d.ts +0 -2
- package/dist/tests/command/UsageCommand.test.d.ts.map +0 -1
- package/dist/tests/command/VersionCommand.test.d.ts +0 -2
- package/dist/tests/command/VersionCommand.test.d.ts.map +0 -1
- package/dist/tests/fixtures/CLIConfig.d.ts +0 -3
- package/dist/tests/fixtures/CLIConfig.d.ts.map +0 -1
- package/dist/tests/fixtures/Command.d.ts +0 -20
- package/dist/tests/fixtures/Command.d.ts.map +0 -1
- package/dist/tests/fixtures/CommandRegistry.d.ts +0 -4
- package/dist/tests/fixtures/CommandRegistry.d.ts.map +0 -1
- package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts +0 -10
- package/dist/tests/fixtures/ConfigurationServiceProvider.d.ts.map +0 -1
- package/dist/tests/fixtures/Context.d.ts +0 -4
- package/dist/tests/fixtures/Context.d.ts.map +0 -1
- package/dist/tests/fixtures/ServiceProviderRegistry.d.ts +0 -4
- package/dist/tests/fixtures/ServiceProviderRegistry.d.ts.map +0 -1
- package/dist/tests/fixtures/StreamString.d.ts +0 -10
- package/dist/tests/fixtures/StreamString.d.ts.map +0 -1
- package/dist/tests/fixtures/prettierPluginFoo.d.ts +0 -4
- package/dist/tests/fixtures/prettierPluginFoo.d.ts.map +0 -1
- package/dist/tests/fixtures/util.d.ts +0 -8
- package/dist/tests/fixtures/util.d.ts.map +0 -1
- package/dist/tests/runtime/DefaultContext.test.d.ts +0 -2
- package/dist/tests/runtime/DefaultContext.test.d.ts.map +0 -1
- package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts +0 -2
- package/dist/tests/runtime/argument/ArgumentTypeGuards.test.d.ts.map +0 -1
- package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts +0 -2
- package/dist/tests/runtime/command/CommandTypeGuards.test.d.ts.map +0 -1
- package/dist/tests/runtime/command/CommandValidator.test.d.ts +0 -2
- package/dist/tests/runtime/command/CommandValidator.test.d.ts.map +0 -1
- package/dist/tests/runtime/parser.test.d.ts +0 -2
- package/dist/tests/runtime/parser.test.d.ts.map +0 -1
- package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts +0 -2
- package/dist/tests/runtime/registry/DefaultCommandRegistry.test.d.ts.map +0 -1
- package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts +0 -2
- package/dist/tests/runtime/registry/DefaultServiceProviderRegistry.test.d.ts.map +0 -1
- package/dist/tests/runtime/runner.test.d.ts +0 -2
- package/dist/tests/runtime/runner.test.d.ts.map +0 -1
- package/dist/tests/runtime/scanner.test.d.ts +0 -2
- package/dist/tests/runtime/scanner.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/argumentValueMerge.test.d.ts +0 -2
- package/dist/tests/runtime/values/argumentValueMerge.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/argumentValueValidation.test.d.ts +0 -2
- package/dist/tests/runtime/values/argumentValueValidation.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts +0 -2
- package/dist/tests/runtime/values/globalCommandValuePopulation.test.d.ts.map +0 -1
- package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts +0 -2
- package/dist/tests/runtime/values/subCommandValuePopulation.test.d.ts.map +0 -1
- package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/argumentPrompter/ArgumentPrompterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts +0 -2
- package/dist/tests/service/argumentPrompter/DefaultArgumentPrompterService.test.d.ts.map +0 -1
- package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/asciiBannerGenerator/AsciiBannerGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/asciiBannerGenerator/DefaultAsciiBannerGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/banner/BannerServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/banner/BannerServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts +0 -2
- package/dist/tests/service/banner/command/NoBannerCommand.test.d.ts.map +0 -1
- package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/chiselAsciiBannerGenerator/ChiselFontAsciiBannerGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/completion/CompletionServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/completion/DefaultCompletionService.test.d.ts +0 -2
- package/dist/tests/service/completion/DefaultCompletionService.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/bash.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/bash.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/fish.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/fish.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/powershell.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/powershell.test.d.ts.map +0 -1
- package/dist/tests/service/completion/shell/zsh.test.d.ts +0 -2
- package/dist/tests/service/completion/shell/zsh.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/configuration/ConfigurationServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts +0 -2
- package/dist/tests/service/configuration/DefaultKeyValueService.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/DefaultSecretService.test.d.ts +0 -2
- package/dist/tests/service/configuration/DefaultSecretService.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts +0 -2
- package/dist/tests/service/configuration/command/ConfigCommand.test.d.ts.map +0 -1
- package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts +0 -2
- package/dist/tests/service/configuration/command/DumpConfigCommand.test.d.ts.map +0 -1
- package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/dataDumpGenerator/DataDumpGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/dataDumpGenerator/DefaultDataDumpGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts +0 -2
- package/dist/tests/service/imagePrinter/DefaultImagePrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/imagePrinter/ImagePrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/plugin/DefaultPluginServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts +0 -2
- package/dist/tests/service/prettyPrinter/DefaultPrettyPrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/prettyPrinter/PrettyPrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/printer/DefaultPrinterService.test.d.ts +0 -2
- package/dist/tests/service/printer/DefaultPrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/printer/PrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/DarkModeCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/LogLevelCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/NoColorCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/NoColorCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts +0 -2
- package/dist/tests/service/printer/command/NoHyperlinksCommand.test.d.ts.map +0 -1
- package/dist/tests/service/printer/terminal/Progress.test.d.ts +0 -2
- package/dist/tests/service/printer/terminal/Progress.test.d.ts.map +0 -1
- package/dist/tests/service/printer/terminal/Spinner.test.d.ts +0 -2
- package/dist/tests/service/printer/terminal/Spinner.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts +0 -2
- package/dist/tests/service/prompter/DefaultPrompterService.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/prompter/PrompterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts +0 -2
- package/dist/tests/service/prompter/command/NoPromptCommand.test.d.ts.map +0 -1
- package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts +0 -2
- package/dist/tests/service/prompter/prompt/PromptContext.test.d.ts.map +0 -1
- package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/shutdown/ShutdownServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts +0 -2
- package/dist/tests/service/syntaxHighlighter/DefaultSyntaxHighlighterService.test.d.ts.map +0 -1
- package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/syntaxHighlighter/SyntaxHighlighterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts +0 -2
- package/dist/tests/service/tableGenerator/DefaultTableGeneratorService.test.d.ts.map +0 -1
- package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/tableGenerator/TableGeneratorServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts +0 -2
- package/dist/tests/service/treePrinter/DefaultTreePrinterService.test.d.ts.map +0 -1
- package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts +0 -2
- package/dist/tests/service/treePrinter/TreePrinterServiceProvider.test.d.ts.map +0 -1
- package/dist/tests/terminal/ImageRenderer.test.d.ts +0 -2
- package/dist/tests/terminal/ImageRenderer.test.d.ts.map +0 -1
- package/dist/tests/terminal/PngDecoder.test.d.ts +0 -2
- package/dist/tests/terminal/PngDecoder.test.d.ts.map +0 -1
- package/dist/tests/terminal/supportsHyperlinks.test.d.ts +0 -2
- package/dist/tests/terminal/supportsHyperlinks.test.d.ts.map +0 -1
- package/dist/tests/util/configHelper.test.d.ts +0 -2
- package/dist/tests/util/configHelper.test.d.ts.map +0 -1
- package/dist/tests/util/envVarHelper.test.d.ts +0 -2
- package/dist/tests/util/envVarHelper.test.d.ts.map +0 -1
- package/dist/tests/util/logger.test.d.ts +0 -2
- package/dist/tests/util/logger.test.d.ts.map +0 -1
- package/src/command/PluginCommand.ts +0 -197
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
// Reference: https://fishshell.com/docs/current/completions.html
|
|
5
|
+
export default class FishShellHandler {
|
|
6
|
+
getDefaultConfigPath() {
|
|
7
|
+
return join(homedir(), ".config", "fish", "config.fish");
|
|
8
|
+
}
|
|
9
|
+
getBootstrapScript(cliName, executablePath) {
|
|
10
|
+
return `complete -c ${cliName} -f -a '("${executablePath}" completion:complete fish (commandline -cp) (commandline -C) 2>/dev/null)'`;
|
|
11
|
+
}
|
|
12
|
+
validateEnvironment() {
|
|
13
|
+
const shell = process.env.SHELL || "";
|
|
14
|
+
if (shell.endsWith("/fish")) {
|
|
15
|
+
return Promise.resolve(true);
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const result = Bun.spawnSync(["fish", "--version"]);
|
|
19
|
+
return Promise.resolve(result.exitCode === 0);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return Promise.resolve(false);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
formatCompletions(completions) {
|
|
26
|
+
return completions
|
|
27
|
+
.map((c) => (c.description ? `${c.value}\t${c.description}` : c.value))
|
|
28
|
+
.join("\n");
|
|
29
|
+
}
|
|
30
|
+
parseCompletionContext(args) {
|
|
31
|
+
const line = args[0] || "";
|
|
32
|
+
const cursorPosition = parseInt(args[1] || "0", 10) || line.length;
|
|
33
|
+
return { line, cursorPosition };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
// Reference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/register-argumentcompleter
|
|
5
|
+
export default class PowerShellShellHandler {
|
|
6
|
+
getDefaultConfigPath() {
|
|
7
|
+
if (process.platform === "win32") {
|
|
8
|
+
return join(homedir(), "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
9
|
+
}
|
|
10
|
+
return join(homedir(), ".config", "powershell", "Microsoft.PowerShell_profile.ps1");
|
|
11
|
+
}
|
|
12
|
+
getBootstrapScript(cliName, executablePath) {
|
|
13
|
+
return [
|
|
14
|
+
`Register-ArgumentCompleter -Native -CommandName ${cliName} -ScriptBlock {`,
|
|
15
|
+
` param($wordToComplete, $commandAst, $cursorPosition)`,
|
|
16
|
+
` $completions = & "${executablePath}" completion:complete powershell "$commandAst" "$cursorPosition" 2>$null`,
|
|
17
|
+
` $completions -split '\\n' | ForEach-Object {`,
|
|
18
|
+
` [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)`,
|
|
19
|
+
` }`,
|
|
20
|
+
`}`,
|
|
21
|
+
].join("\n");
|
|
22
|
+
}
|
|
23
|
+
validateEnvironment() {
|
|
24
|
+
try {
|
|
25
|
+
const result = Bun.spawnSync(["pwsh", "--version"], { timeout: 2000 });
|
|
26
|
+
if (result.exitCode === 0) {
|
|
27
|
+
return Promise.resolve(true);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// try powershell fallback
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const result = Bun.spawnSync(["powershell", "-Command", "echo ok"], {
|
|
35
|
+
timeout: 2000,
|
|
36
|
+
});
|
|
37
|
+
return Promise.resolve(result.exitCode === 0);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return Promise.resolve(false);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
formatCompletions(completions) {
|
|
44
|
+
return completions.map((c) => c.value).join("\n");
|
|
45
|
+
}
|
|
46
|
+
parseCompletionContext(args) {
|
|
47
|
+
const line = args[0] || "";
|
|
48
|
+
const cursorPosition = parseInt(args[1] || "0", 10) || line.length;
|
|
49
|
+
return { line, cursorPosition };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
// Reference: https://zsh.sourceforge.io/Doc/Release/Completion-System.html
|
|
5
|
+
export default class ZshShellHandler {
|
|
6
|
+
getDefaultConfigPath() {
|
|
7
|
+
return join(homedir(), ".zshrc");
|
|
8
|
+
}
|
|
9
|
+
getBootstrapScript(cliName, executablePath) {
|
|
10
|
+
return [
|
|
11
|
+
`_${cliName}_completions() {`,
|
|
12
|
+
` local -a completions`,
|
|
13
|
+
` completions=("\${(@f)$("${executablePath}" completion:complete zsh "\${words}" "\${CURSOR}" 2>/dev/null)}")`,
|
|
14
|
+
` _describe '${cliName}' completions`,
|
|
15
|
+
`}`,
|
|
16
|
+
`compdef _${cliName}_completions ${cliName}`,
|
|
17
|
+
].join("\n");
|
|
18
|
+
}
|
|
19
|
+
validateEnvironment() {
|
|
20
|
+
const shell = process.env.SHELL || "";
|
|
21
|
+
if (shell.endsWith("/zsh")) {
|
|
22
|
+
return Promise.resolve(true);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const result = Bun.spawnSync(["zsh", "--version"]);
|
|
26
|
+
return Promise.resolve(result.exitCode === 0);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return Promise.resolve(false);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
formatCompletions(completions) {
|
|
33
|
+
return completions
|
|
34
|
+
.map((c) => (c.description ? `${c.value}:${c.description}` : c.value))
|
|
35
|
+
.join("\n");
|
|
36
|
+
}
|
|
37
|
+
parseCompletionContext(args) {
|
|
38
|
+
const line = args[0] || "";
|
|
39
|
+
const cursorPosition = parseInt(args[1] || "0", 10) || line.length;
|
|
40
|
+
return { line, cursorPosition };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import { Stats } from "node:fs";
|
|
5
|
+
import ConfigCommand from "./command/ConfigCommand.js";
|
|
6
|
+
import getLogger from "../../util/logger.js";
|
|
7
|
+
import DumpConfigCommand from "./command/DumpConfigCommand.js";
|
|
8
|
+
import { KEY_VALUE_SERVICE_ID, SECRET_SENTINEL_PREFIX, } from "../../api/service/core/KeyValueService.js";
|
|
9
|
+
import DefaultKeyValueService from "./DefaultKeyValueService.js";
|
|
10
|
+
import DefaultSecretService from "./DefaultSecretService.js";
|
|
11
|
+
import argumentValueMerge from "../../runtime/values/argumentValueMerge.js";
|
|
12
|
+
import { isGlobalCommand, isGlobalModifierCommand, isSubCommand, } from "../../runtime/command/CommandTypeGuards.js";
|
|
13
|
+
import { getGlobalCommandValueFromEnvVars, getSubCommandValuesFromEnvVars, } from "../../util/envVarHelper.js";
|
|
14
|
+
const logger = getLogger("ConfigurationServiceProvider");
|
|
15
|
+
/**
|
|
16
|
+
* Provides:
|
|
17
|
+
*
|
|
18
|
+
* * Configuration of default command arguments using a configuration file and/or environment variables.
|
|
19
|
+
* * A generic key-value store for commands and services ({@link KeyValueService}).
|
|
20
|
+
*
|
|
21
|
+
* **Default Command Arguments**
|
|
22
|
+
*
|
|
23
|
+
* Configuration of default {@link ArgumentValues} for {@link Command} instances is supported if they
|
|
24
|
+
* have defined {@link Command.enableConfiguration} as `true`.
|
|
25
|
+
*
|
|
26
|
+
* Two sources of configuration are supported and both are expected to be manually managed by the user of the CLI.
|
|
27
|
+
*
|
|
28
|
+
* *Configuration File*
|
|
29
|
+
*
|
|
30
|
+
* A JSON file where the structure matches {@link ArgumentValues} and the defaults are stored
|
|
31
|
+
* under a top level `defaults` property. The second level of properties is used to refer to {@link Command.name}
|
|
32
|
+
* and the contained values are treated as command {@link ArgumentValues}. As an example:
|
|
33
|
+
*
|
|
34
|
+
* ```
|
|
35
|
+
* {
|
|
36
|
+
* "defaults": {
|
|
37
|
+
* "subCommand1": {
|
|
38
|
+
* "arg1": [
|
|
39
|
+
* 1,
|
|
40
|
+
* 2
|
|
41
|
+
* ],
|
|
42
|
+
* "arg2": {
|
|
43
|
+
* "arg3": "foo"
|
|
44
|
+
* }
|
|
45
|
+
* },
|
|
46
|
+
* "command2": {
|
|
47
|
+
* "arg4": true
|
|
48
|
+
* },
|
|
49
|
+
* "globalCommand": "globalArgumentValue"
|
|
50
|
+
* },
|
|
51
|
+
* "key-values": {
|
|
52
|
+
* ...
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* The default location of the configuration file is `$HOME/.<application_name>.json`. If `$HOME` is not defined no
|
|
58
|
+
* default configuration will be used. The location of the configuration file can be modified via the
|
|
59
|
+
* {@link ConfigCommand}.
|
|
60
|
+
*
|
|
61
|
+
* NOTE: You may store default arguments for secrets by manually configuring secrets in your OS
|
|
62
|
+
* credential store and referencing them in the config file using the sentinel format
|
|
63
|
+
* `__SECRET__:<bun_secret_name>`. These values will be resolved from the OS secret store
|
|
64
|
+
* before being returned as default argument values. See "Generic Key-Value Service" below.
|
|
65
|
+
*
|
|
66
|
+
* *Environment Variables*
|
|
67
|
+
*
|
|
68
|
+
* Values are parsed using a key path defined by custom {@link Argument.configurationKey}
|
|
69
|
+
* values or using the default naming scheme defined within {@link Argument.configurationKey}.
|
|
70
|
+
*
|
|
71
|
+
* NOTE: Any values set by environment variables will override those sourced from the configuration file.
|
|
72
|
+
*
|
|
73
|
+
* The argument key path is derived for an argument (or nested argument) as follows:
|
|
74
|
+
*
|
|
75
|
+
* Argument configuration keys are concatenated with a `_` separator.
|
|
76
|
+
* Any arguments which support array values must by suffixed with `_` and an explicit array index.
|
|
77
|
+
* If the root argument in the path does not use a custom {@link Argument.configurationKey} then the key path
|
|
78
|
+
* is additionally suffixed with the {@link CLIConfig.name} and the {@link Command.name} with `_` separators.
|
|
79
|
+
* This is best explained with examples...
|
|
80
|
+
*
|
|
81
|
+
* No custom configuration key examples:
|
|
82
|
+
*
|
|
83
|
+
* * executable: `MyCLI`, command: `globalCommand1`, global command argument => environment variable: `MYCLI_GLOBALCOMMAND1`
|
|
84
|
+
* * executable: `MyCLI`, command: `command1`, simple root argument: `arg1` => environment variable: `MYCLI_COMMAND1_ARG1`
|
|
85
|
+
* * executable: `MyCLI`, command: `command1`, array root argument, 1st element: `arg2[0]` => environment variable: `MYCLI_COMMAND1_ARG2_0`
|
|
86
|
+
* * executable: `MyCLI`, command: `command1`, argument is a digit so it is by default suffixed with `_`: `3` => environment variable: `MYCLI_COMMAND1__3`
|
|
87
|
+
* * executable: `MyCLI`, command: `command1`, nested sub-argument: `arg1.arg2` => environment variable: `MYCLI_COMMAND1_ARG1_ARG2`
|
|
88
|
+
* * executable: `MyCLI`, command: `command1`, nested sub-argument with both levels being arrays and referring to the 2nd element of each: `arg1[1].arg2[1]` => environment variable: `MYCLI_COMMAND1_ARG1_1_ARG2_2`
|
|
89
|
+
*
|
|
90
|
+
* Custom configuration key at the root level (and therefore not prefixed with CLI and command names) examples:
|
|
91
|
+
*
|
|
92
|
+
* * executable: `MyCLI`, command: `globalCommand1`, global command argument`, global command argument configuration key: `FOO` => environment variable: `FOO`
|
|
93
|
+
* * executable: `MyCLI`, command: `command1`, simple root argument: `arg1`, arg1 configuration key: `FOO` => environment variable: `FOO`
|
|
94
|
+
* * executable: `MyCLI`, command: `command1`, array root argument, 1st element: `arg2[0]`, arg1 configuration key: `BAR` => environment variable: `BAR_0`
|
|
95
|
+
*
|
|
96
|
+
* Custom configuration key not at the root level (and therefore prefixed with CLI and command names) examples:
|
|
97
|
+
*
|
|
98
|
+
* * executable: `MyCLI`, command: `command1`, nested sub-argument: `arg1.arg2`, arg2 configuration key: `FOO` => environment variable: `MYCLI_COMMAND1_ARG1_FOO`
|
|
99
|
+
* * executable: `MyCLI`, command: `command1`, nested sub-argument with both levels being arrays and referring to the 2nd element of each: `arg1[1].arg2[1]`, arg2 configuration key: `BAR` => environment variable: `MYCLI_COMMAND1_ARG1_1_BAR_2`
|
|
100
|
+
*
|
|
101
|
+
* NOTE: Any default values from the above configuration sources will be overridden by any arguments provided on the command line.
|
|
102
|
+
*
|
|
103
|
+
* **Generic Key-Value Service**
|
|
104
|
+
*
|
|
105
|
+
* The same configuration file above is used to provide storage for the provided {@link KeyValueService}. The values
|
|
106
|
+
* are stored under a top level `key-values` property. These are expected to not be modified by the user of the CLI.
|
|
107
|
+
*
|
|
108
|
+
* The second and third level of properties is used to scope the key-values to specific command names
|
|
109
|
+
* (via {@link Command.name} values) and specific service IDs (via {@link ServiceProvider.serviceId} values).
|
|
110
|
+
* Both keys and values are string based.
|
|
111
|
+
*
|
|
112
|
+
* Values may be stored as OS-native secrets via {@link KeyValueService.setKey} with `isSecret=true`.
|
|
113
|
+
* When a value is stored as a secret, a sentinel value of the format `__SECRET__:<bun_secret_name>`
|
|
114
|
+
* is stored in the config file instead of the actual value. The actual value is stored in the OS
|
|
115
|
+
* credential store via Bun.secrets. The sentinel prefix `__SECRET__:` is reserved and must not be
|
|
116
|
+
* used for regular key-value data.
|
|
117
|
+
*
|
|
118
|
+
* Secret support requires `secretServiceEnabled=true` in the constructor (which also requires
|
|
119
|
+
* `configEnabled=true`).
|
|
120
|
+
*
|
|
121
|
+
* As an example:
|
|
122
|
+
* ```
|
|
123
|
+
* {
|
|
124
|
+
* "defaults": {
|
|
125
|
+
* ...
|
|
126
|
+
* },
|
|
127
|
+
* "key-values": {
|
|
128
|
+
* "commands": {
|
|
129
|
+
* "command1": {
|
|
130
|
+
* "foo1": "bar1",
|
|
131
|
+
* "foo2": "__SECRET__:command_command1_foo2"
|
|
132
|
+
* },
|
|
133
|
+
* "command2": {
|
|
134
|
+
* "foo1": "bar3"
|
|
135
|
+
* }
|
|
136
|
+
* },
|
|
137
|
+
* "services": {
|
|
138
|
+
* "service-id-1": {
|
|
139
|
+
* "foo1": "bar"
|
|
140
|
+
* }
|
|
141
|
+
* }
|
|
142
|
+
* }
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export default class ConfigurationServiceProvider {
|
|
147
|
+
serviceId = KEY_VALUE_SERVICE_ID;
|
|
148
|
+
servicePriority;
|
|
149
|
+
envVarsEnabled;
|
|
150
|
+
configEnabled;
|
|
151
|
+
keyValueServiceEnabled;
|
|
152
|
+
secretServiceEnabled;
|
|
153
|
+
// the location of the currently managed configuration data
|
|
154
|
+
configLocation;
|
|
155
|
+
// the configuration data to be used by the CLI runner implementation when setting command defaults.
|
|
156
|
+
// ArgumentSingleValueType is for GlobalCommandArgument values, ArgumentValues is for
|
|
157
|
+
// SubCommandArgument values.
|
|
158
|
+
defaultsData = new Map();
|
|
159
|
+
// the configuration data to be used by the CLI runner implementation
|
|
160
|
+
// when updating command scoped access to key-value data via the key-value service.
|
|
161
|
+
#commandKeyValueData = new Map();
|
|
162
|
+
// the configuration data to be used by the CLI runner implementation
|
|
163
|
+
// when updating service scoped access to key-value data via the key-value service.
|
|
164
|
+
#serviceKeyValueData = new Map();
|
|
165
|
+
// the optional service providing scope limited key-value data to commands and other services
|
|
166
|
+
#defaultKeyValueService;
|
|
167
|
+
// the optional service providing OS-native secret storage
|
|
168
|
+
#defaultSecretService;
|
|
169
|
+
#currentCommandNameKeyValueScope;
|
|
170
|
+
#currentServiceIdKeyValueScope;
|
|
171
|
+
/**
|
|
172
|
+
* Create an instance of the service provider with the specified details.
|
|
173
|
+
*
|
|
174
|
+
* @param servicePriority the priority of the service.
|
|
175
|
+
* @param envVarsEnabled optionally support checking env variables for default argument values.
|
|
176
|
+
* @param configEnabled optionally enable configuration file support for default argument values.
|
|
177
|
+
* @param keyValueServiceEnabled optionally provide a {@link KeyValueService} implementation: `configEnabled` must be true in this case
|
|
178
|
+
* @param secretServiceEnabled optionally enable OS-native secret storage via Bun.secrets: `configEnabled` must be true in this case
|
|
179
|
+
*/
|
|
180
|
+
constructor(servicePriority, envVarsEnabled = false, configEnabled = false, keyValueServiceEnabled = false, secretServiceEnabled = false) {
|
|
181
|
+
if (!configEnabled && keyValueServiceEnabled) {
|
|
182
|
+
throw new Error("configEnabled must be true if keyValueServiceEnabled is true");
|
|
183
|
+
}
|
|
184
|
+
if (!configEnabled && secretServiceEnabled) {
|
|
185
|
+
throw new Error("configEnabled must be true if secretServiceEnabled is true");
|
|
186
|
+
}
|
|
187
|
+
this.servicePriority = servicePriority;
|
|
188
|
+
this.envVarsEnabled = envVarsEnabled;
|
|
189
|
+
this.configEnabled = configEnabled;
|
|
190
|
+
this.keyValueServiceEnabled = keyValueServiceEnabled;
|
|
191
|
+
this.secretServiceEnabled = secretServiceEnabled;
|
|
192
|
+
}
|
|
193
|
+
getServiceInfo(cliConfig) {
|
|
194
|
+
const commands = [];
|
|
195
|
+
if (this.configEnabled) {
|
|
196
|
+
commands.push(new ConfigCommand(this, this.servicePriority));
|
|
197
|
+
commands.push(new DumpConfigCommand(this));
|
|
198
|
+
}
|
|
199
|
+
if (this.secretServiceEnabled) {
|
|
200
|
+
this.#defaultSecretService = new DefaultSecretService(cliConfig.name);
|
|
201
|
+
}
|
|
202
|
+
if (this.keyValueServiceEnabled || this.secretServiceEnabled) {
|
|
203
|
+
this.#defaultKeyValueService = new DefaultKeyValueService(this.#defaultSecretService);
|
|
204
|
+
}
|
|
205
|
+
return Promise.resolve({
|
|
206
|
+
// this may be undefined if keyValueServiceEnabled and secretServiceEnabled are false
|
|
207
|
+
service: this.#defaultKeyValueService,
|
|
208
|
+
// this may be empty if configEnabled is false
|
|
209
|
+
commands,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
setConfigLocation(configLocation) {
|
|
213
|
+
this.configLocation = configLocation;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Retrieve the default command argument values (if any) for the provided {@link Command}.
|
|
217
|
+
*
|
|
218
|
+
* This will retrieve values both from the configuration location and environment variables.
|
|
219
|
+
*
|
|
220
|
+
* @param cliConfig the {@link CLIConfig} to use for retrieving configuration keys.
|
|
221
|
+
* @param command the {@link Command} instance to retrieve default argument values for.
|
|
222
|
+
*/
|
|
223
|
+
async getDefaultArgumentValues(cliConfig, command) {
|
|
224
|
+
if (!this.configEnabled) {
|
|
225
|
+
logger.debug("configuration of default values is not enabled");
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
logger.debug("getting default argument values for command: %s", command.name);
|
|
229
|
+
if (command.enableConfiguration === undefined || command.enableConfiguration !== true) {
|
|
230
|
+
logger.debug("enableConfiguration for command: %s is not true", command.name);
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
let result;
|
|
234
|
+
if (isGlobalModifierCommand(command) || isGlobalCommand(command)) {
|
|
235
|
+
const configuredValue = this.defaultsData.get(command.name);
|
|
236
|
+
const envVarValue = this.envVarsEnabled
|
|
237
|
+
? getGlobalCommandValueFromEnvVars(cliConfig, command)
|
|
238
|
+
: undefined;
|
|
239
|
+
// default to environment variable value
|
|
240
|
+
result = envVarValue !== undefined ? envVarValue : configuredValue;
|
|
241
|
+
}
|
|
242
|
+
else if (isSubCommand(command)) {
|
|
243
|
+
const configuredValues = this.defaultsData.get(command.name);
|
|
244
|
+
const envVarValues = this.envVarsEnabled
|
|
245
|
+
? getSubCommandValuesFromEnvVars(cliConfig, command)
|
|
246
|
+
: undefined;
|
|
247
|
+
if (envVarValues === undefined) {
|
|
248
|
+
result = configuredValues;
|
|
249
|
+
}
|
|
250
|
+
else if (configuredValues === undefined) {
|
|
251
|
+
result = envVarValues;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
result = argumentValueMerge(envVarValues, configuredValues);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (result !== undefined && this.#defaultSecretService) {
|
|
258
|
+
result = await this.#resolveSecrets(result);
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
async #resolveSecrets(value) {
|
|
263
|
+
if (typeof value === "string" && value.startsWith(SECRET_SENTINEL_PREFIX)) {
|
|
264
|
+
const bunSecretName = value.slice(SECRET_SENTINEL_PREFIX.length);
|
|
265
|
+
const secretValue = await this.#defaultSecretService.getSecret(bunSecretName);
|
|
266
|
+
if (secretValue === null) {
|
|
267
|
+
throw new Error(`Secret not found in OS secret store for sentinel: '${value}'`);
|
|
268
|
+
}
|
|
269
|
+
return secretValue;
|
|
270
|
+
}
|
|
271
|
+
if (typeof value === "object" && value !== null) {
|
|
272
|
+
if (Array.isArray(value)) {
|
|
273
|
+
const resolved = [];
|
|
274
|
+
for (const item of value) {
|
|
275
|
+
resolved.push(await this.#resolveSecrets(item));
|
|
276
|
+
}
|
|
277
|
+
return resolved;
|
|
278
|
+
}
|
|
279
|
+
const resolved = {};
|
|
280
|
+
for (const [key, val] of Object.entries(value)) {
|
|
281
|
+
resolved[key] = await this.#resolveSecrets(val);
|
|
282
|
+
}
|
|
283
|
+
return resolved;
|
|
284
|
+
}
|
|
285
|
+
return value;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Indicate that the contained {@link DefaultKeyValueService} should be set to have a scope of the provided
|
|
289
|
+
* command name.
|
|
290
|
+
*
|
|
291
|
+
* @param commandName the name of the command to scope the key-value data to.
|
|
292
|
+
*
|
|
293
|
+
* @throws {Error} if an existing scope is set.
|
|
294
|
+
*/
|
|
295
|
+
setCommandKeyValueScope(commandName) {
|
|
296
|
+
if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
|
|
297
|
+
throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
|
|
298
|
+
}
|
|
299
|
+
if (this.#currentCommandNameKeyValueScope) {
|
|
300
|
+
throw new Error(`Attempt to set CommandNameKeyValueScope to ${commandName} when it is currently set to ${this.#currentCommandNameKeyValueScope}`);
|
|
301
|
+
}
|
|
302
|
+
if (this.#currentServiceIdKeyValueScope) {
|
|
303
|
+
throw new Error(`Attempt to set CommandNameKeyValueScope to ${commandName} when ServiceIdKeyValueScope is currently set to ${this.#currentCommandNameKeyValueScope}`);
|
|
304
|
+
}
|
|
305
|
+
this.#currentCommandNameKeyValueScope = commandName;
|
|
306
|
+
logger.debug("currentCommandNameKeyValueScope: %s", commandName);
|
|
307
|
+
if (this.#defaultKeyValueService) {
|
|
308
|
+
if (!this.#commandKeyValueData.has(commandName)) {
|
|
309
|
+
this.#commandKeyValueData.set(commandName, new Map());
|
|
310
|
+
}
|
|
311
|
+
this.#defaultKeyValueService.setKeyValueData(this.#commandKeyValueData.get(commandName));
|
|
312
|
+
}
|
|
313
|
+
if (this.#defaultSecretService) {
|
|
314
|
+
this.#defaultSecretService.setScope("command_" + commandName);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Indicate that the contained {@link DefaultKeyValueService} should be set to have a scope of the provided
|
|
319
|
+
* service ID.
|
|
320
|
+
*
|
|
321
|
+
* @param serviceId the ID of the service to scope the key-value data to.
|
|
322
|
+
*
|
|
323
|
+
* @throws {Error} if an existing scope is set.
|
|
324
|
+
*/
|
|
325
|
+
setServiceKeyValueScope(serviceId) {
|
|
326
|
+
if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
|
|
327
|
+
throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
|
|
328
|
+
}
|
|
329
|
+
if (this.#currentServiceIdKeyValueScope) {
|
|
330
|
+
throw new Error(`Attempt to set ServiceIdKeyValueScope to ${serviceId} when it is currently set to ${this.#currentServiceIdKeyValueScope}`);
|
|
331
|
+
}
|
|
332
|
+
if (this.#currentCommandNameKeyValueScope) {
|
|
333
|
+
throw new Error(`Attempt to set ServiceIdKeyValueScope to ${serviceId} when CommandNameKeyValueScope is currently set to ${this.#currentServiceIdKeyValueScope}`);
|
|
334
|
+
}
|
|
335
|
+
this.#currentServiceIdKeyValueScope = serviceId;
|
|
336
|
+
logger.debug("currentServiceIdKeyValueScope: %s", serviceId);
|
|
337
|
+
if (this.#defaultKeyValueService) {
|
|
338
|
+
if (!this.#serviceKeyValueData.has(serviceId)) {
|
|
339
|
+
this.#serviceKeyValueData.set(serviceId, new Map());
|
|
340
|
+
}
|
|
341
|
+
this.#defaultKeyValueService.setKeyValueData(this.#serviceKeyValueData.get(serviceId));
|
|
342
|
+
}
|
|
343
|
+
if (this.#defaultSecretService) {
|
|
344
|
+
this.#defaultSecretService.setScope("service_" + serviceId);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Indicate that the contained {@link DefaultKeyValueService} should have any current scope cleared.
|
|
349
|
+
*
|
|
350
|
+
* If a scope is currently set and changes have been made to the key-value data, they will be written
|
|
351
|
+
* to the current configuration location.
|
|
352
|
+
*/
|
|
353
|
+
async clearKeyValueScope() {
|
|
354
|
+
if (!this.keyValueServiceEnabled && !this.secretServiceEnabled) {
|
|
355
|
+
throw new Error(`Attempt to use KeyValueService/SecretService which is not enabled`);
|
|
356
|
+
}
|
|
357
|
+
if (this.#defaultKeyValueService && this.#defaultKeyValueService.isDirty()) {
|
|
358
|
+
if (this.configLocation === undefined) {
|
|
359
|
+
throw new Error("Attempt to write updated config with no configLocation set");
|
|
360
|
+
}
|
|
361
|
+
await this.#writeConfig(this.configLocation);
|
|
362
|
+
}
|
|
363
|
+
this.#currentCommandNameKeyValueScope = undefined;
|
|
364
|
+
this.#currentServiceIdKeyValueScope = undefined;
|
|
365
|
+
if (this.#defaultKeyValueService) {
|
|
366
|
+
this.#defaultKeyValueService.clearKeyValueData();
|
|
367
|
+
}
|
|
368
|
+
if (this.#defaultSecretService) {
|
|
369
|
+
this.#defaultSecretService.clearScope();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async initService(context) {
|
|
373
|
+
if (!this.configEnabled) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
let isDefault = false;
|
|
377
|
+
if (this.configLocation === undefined) {
|
|
378
|
+
isDefault = true;
|
|
379
|
+
// default to `$HOME/.<application_name>.json`
|
|
380
|
+
const home = process.env["HOME"];
|
|
381
|
+
if (home) {
|
|
382
|
+
this.configLocation = path.join(home, `.${context.cliConfig.name.replace(/\W/g, "")}.json`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (this.configLocation === undefined) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
let fileInfo;
|
|
389
|
+
try {
|
|
390
|
+
fileInfo = await fs.lstat(this.configLocation);
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
const error = err;
|
|
394
|
+
if (isDefault) {
|
|
395
|
+
logger.debug("Default config file location: %s does not exist or is not visible - ignoring: %s", this.configLocation, error.message);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
throw new Error(`Config file location: '${this.configLocation}' doesn't exist or not visible: ${error.message}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (fileInfo.isDirectory()) {
|
|
403
|
+
throw new Error(`Config file location: '${this.configLocation}' is a directory and not a file!`);
|
|
404
|
+
}
|
|
405
|
+
await this.#readConfig(this.configLocation);
|
|
406
|
+
}
|
|
407
|
+
async #readConfig(location) {
|
|
408
|
+
try {
|
|
409
|
+
logger.debug("Reading config from: %s", location);
|
|
410
|
+
const data = await fs.readFile(location);
|
|
411
|
+
const config = JSON.parse(data.toString());
|
|
412
|
+
if (config === undefined) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
this.defaultsData.clear();
|
|
416
|
+
this.#commandKeyValueData.clear();
|
|
417
|
+
this.#serviceKeyValueData.clear();
|
|
418
|
+
if (config.defaults !== undefined) {
|
|
419
|
+
const defaults = config.defaults;
|
|
420
|
+
Object.keys(defaults).forEach((commandName) => {
|
|
421
|
+
this.defaultsData.set(commandName, defaults[commandName]);
|
|
422
|
+
logger.debug("Set default argument values for command name: %s", commandName);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
if (config["key-values"] !== undefined) {
|
|
426
|
+
const keyValues = config["key-values"];
|
|
427
|
+
if (keyValues.commands !== undefined) {
|
|
428
|
+
const commandKeyValues = keyValues.commands;
|
|
429
|
+
Object.keys(commandKeyValues).forEach((commandName) => {
|
|
430
|
+
this.#commandKeyValueData.set(commandName, new Map(Object.entries(commandKeyValues[commandName])));
|
|
431
|
+
logger.debug("Set default argument values for command name: %s", commandName);
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
if (keyValues.services !== undefined) {
|
|
435
|
+
const serviceKeyValues = keyValues.services;
|
|
436
|
+
Object.keys(serviceKeyValues).forEach((serviceId) => {
|
|
437
|
+
this.#serviceKeyValueData.set(serviceId, new Map(Object.entries(serviceKeyValues[serviceId])));
|
|
438
|
+
logger.debug("Set default argument values for service ID: %s", serviceId);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
throw new Error(`Failed to read config at location: '${this.configLocation}': ${err}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async #writeConfig(location) {
|
|
448
|
+
logger.debug("Writing config to: %s", location);
|
|
449
|
+
try {
|
|
450
|
+
await fs.writeFile(location, this.getConfigString());
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
throw new Error(`Failed to write config at location: '${this.configLocation}': ${err}`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
getConfigString() {
|
|
457
|
+
const config = {};
|
|
458
|
+
if (this.defaultsData.size > 0) {
|
|
459
|
+
config.defaults = Object.fromEntries(this.defaultsData);
|
|
460
|
+
}
|
|
461
|
+
if (this.#commandKeyValueData.size > 0 || this.#serviceKeyValueData.size > 0) {
|
|
462
|
+
config["key-values"] = {};
|
|
463
|
+
if (this.#commandKeyValueData.size > 0) {
|
|
464
|
+
config["key-values"].commands = {};
|
|
465
|
+
for (const [commandName, keyValueData] of this.#commandKeyValueData.entries()) {
|
|
466
|
+
if (keyValueData.size > 0) {
|
|
467
|
+
config["key-values"].commands[commandName] = Object.fromEntries(keyValueData);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (this.#serviceKeyValueData.size > 0) {
|
|
472
|
+
config["key-values"].services = {};
|
|
473
|
+
for (const [serviceId, keyValueData] of this.#serviceKeyValueData.entries()) {
|
|
474
|
+
if (keyValueData.size > 0) {
|
|
475
|
+
config["key-values"].services[serviceId] = Object.fromEntries(keyValueData);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return JSON.stringify(config, null, 2);
|
|
481
|
+
}
|
|
482
|
+
}
|