@twin.org/cli-core 0.0.2-next.9 → 0.0.3-next.2
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/dist/es/cliBase.js +122 -0
- package/dist/es/cliBase.js.map +1 -0
- package/dist/es/cliDisplay.js +166 -0
- package/dist/es/cliDisplay.js.map +1 -0
- package/dist/es/cliOptions.js +36 -0
- package/dist/es/cliOptions.js.map +1 -0
- package/dist/es/cliParam.js +248 -0
- package/dist/es/cliParam.js.map +1 -0
- package/dist/es/cliUtils.js +235 -0
- package/dist/es/cliUtils.js.map +1 -0
- package/dist/es/commands/global.js +61 -0
- package/dist/es/commands/global.js.map +1 -0
- package/dist/es/index.js +14 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/ICliOptions.js +2 -0
- package/dist/es/models/ICliOptions.js.map +1 -0
- package/dist/es/models/ICliOutputOptionsConsole.js +2 -0
- package/dist/es/models/ICliOutputOptionsConsole.js.map +1 -0
- package/dist/es/models/ICliOutputOptionsEnv.js +2 -0
- package/dist/es/models/ICliOutputOptionsEnv.js.map +1 -0
- package/dist/es/models/ICliOutputOptionsJson.js +2 -0
- package/dist/es/models/ICliOutputOptionsJson.js.map +1 -0
- package/dist/es/models/cliOutputOptions.js +2 -0
- package/dist/es/models/cliOutputOptions.js.map +1 -0
- package/dist/types/cliBase.d.ts +1 -1
- package/dist/types/cliDisplay.d.ts +5 -0
- package/dist/types/cliParam.d.ts +10 -9
- package/dist/types/index.d.ts +11 -11
- package/dist/types/models/cliOutputOptions.d.ts +3 -3
- package/docs/changelog.md +296 -0
- package/docs/reference/classes/CLIDisplay.md +20 -0
- package/docs/reference/classes/CLIParam.md +62 -50
- package/docs/reference/classes/CLIUtils.md +10 -10
- package/locales/.validate-ignore +1 -0
- package/locales/en.json +0 -1
- package/package.json +25 -14
- package/dist/cjs/index.cjs +0 -878
- package/dist/esm/index.mjs +0 -849
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Coerce, I18n, Is } from "@twin.org/core";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { CLIDisplay } from "./cliDisplay.js";
|
|
6
|
+
import { addGlobalOptions, handleGlobalOptions, initGlobalOptions, initLocales } from "./commands/global.js";
|
|
7
|
+
/**
|
|
8
|
+
* The main entry point for the CLI.
|
|
9
|
+
*/
|
|
10
|
+
export class CLIBase {
|
|
11
|
+
/**
|
|
12
|
+
* Execute the command line processing.
|
|
13
|
+
* @param options The options for the CLI.
|
|
14
|
+
* @param localesDirectory The path to load the locales from.
|
|
15
|
+
* @param argv The process arguments.
|
|
16
|
+
* @returns The exit code.
|
|
17
|
+
*/
|
|
18
|
+
async execute(options, localesDirectory, argv) {
|
|
19
|
+
initGlobalOptions(localesDirectory);
|
|
20
|
+
initLocales("en");
|
|
21
|
+
try {
|
|
22
|
+
process.title = options.title;
|
|
23
|
+
if (!argv.includes("--version") && !argv.includes("-v")) {
|
|
24
|
+
CLIDisplay.header(options.title, options.version, options.icon);
|
|
25
|
+
}
|
|
26
|
+
const program = new Command();
|
|
27
|
+
let outputWidth = options.overrideOutputWidth;
|
|
28
|
+
let outputErrWidth = options.overrideOutputWidth;
|
|
29
|
+
if (Is.undefined(outputWidth) && process.stdout.isTTY) {
|
|
30
|
+
outputWidth = process.stdout.columns;
|
|
31
|
+
outputErrWidth = process.stderr.columns;
|
|
32
|
+
}
|
|
33
|
+
program
|
|
34
|
+
.name(options.appName)
|
|
35
|
+
.version(options.version)
|
|
36
|
+
.usage("[command]")
|
|
37
|
+
.showHelpAfterError()
|
|
38
|
+
.configureOutput({
|
|
39
|
+
writeOut: str => CLIDisplay.write(str),
|
|
40
|
+
writeErr: str => CLIDisplay.writeError(str),
|
|
41
|
+
getOutHelpWidth: () => outputWidth,
|
|
42
|
+
getErrHelpWidth: () => outputErrWidth,
|
|
43
|
+
outputError: (str, write) => CLIDisplay.error(str.replace(/^error: /, ""), false)
|
|
44
|
+
})
|
|
45
|
+
.exitOverride(err => {
|
|
46
|
+
// By default commander still calls process.exit on exit
|
|
47
|
+
// which we don't want as we might have subsequent
|
|
48
|
+
// processing to handle, so instead we throw the exit code
|
|
49
|
+
// as a way to skip the process.exit call.
|
|
50
|
+
// If the error code is commander.help then we return 0 as
|
|
51
|
+
// we don't want displaying help to be an error.
|
|
52
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
53
|
+
throw new Error(err.code === "commander.help" ? "0" : err.exitCode.toString());
|
|
54
|
+
});
|
|
55
|
+
if (options.showDevToolWarning ?? false) {
|
|
56
|
+
program.hook("preAction", () => CLIDisplay.warning(I18n.formatMessage("warn.common.devOnlyTool")));
|
|
57
|
+
}
|
|
58
|
+
this.configureRoot(program);
|
|
59
|
+
addGlobalOptions(program, options.supportsLang ?? true, options.supportsEnvFiles ?? false);
|
|
60
|
+
// We parse the options before building the command
|
|
61
|
+
// in case the language has been set, then the
|
|
62
|
+
// help for the options will be in the correct language.
|
|
63
|
+
program.parseOptions(argv);
|
|
64
|
+
handleGlobalOptions(program);
|
|
65
|
+
const commandCount = this.buildCommands(program);
|
|
66
|
+
if (commandCount === 0) {
|
|
67
|
+
program.usage(" ");
|
|
68
|
+
}
|
|
69
|
+
await program.parseAsync(argv);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
CLIDisplay.spinnerStop();
|
|
73
|
+
let exitCode;
|
|
74
|
+
// We have no control over the response from commander
|
|
75
|
+
// so we have to do some checking and coercion here
|
|
76
|
+
// to get a valid exit code.
|
|
77
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
78
|
+
if (error instanceof Error) {
|
|
79
|
+
// This error could be the exit code we errored with
|
|
80
|
+
// from the exitOverride so parse and resolve with it
|
|
81
|
+
exitCode = Coerce.number(error.message);
|
|
82
|
+
}
|
|
83
|
+
if (Is.integer(exitCode)) {
|
|
84
|
+
return exitCode;
|
|
85
|
+
}
|
|
86
|
+
CLIDisplay.error(error);
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Configure any options or actions at the root program level.
|
|
93
|
+
* @param program The root program command.
|
|
94
|
+
*/
|
|
95
|
+
configureRoot(program) {
|
|
96
|
+
program.action(() => {
|
|
97
|
+
program.help();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the commands for the CLI, override in derived class to supply your own.
|
|
102
|
+
* @param program The main program that the commands will be added to.
|
|
103
|
+
* @returns The commands for the CLI.
|
|
104
|
+
*/
|
|
105
|
+
getCommands(program) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build the commands for the CLI.
|
|
110
|
+
* @param program The main program that the commands are added to.
|
|
111
|
+
* @returns The number of commands added.
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
buildCommands(program) {
|
|
115
|
+
const commands = this.getCommands(program);
|
|
116
|
+
for (const command of commands) {
|
|
117
|
+
program.addCommand(command.copyInheritedSettings(program));
|
|
118
|
+
}
|
|
119
|
+
return commands.length;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=cliBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliBase.js","sourceRoot":"","sources":["../../src/cliBase.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Coerce, I18n, Is } from \"@twin.org/core\";\nimport { Command } from \"commander\";\nimport { CLIDisplay } from \"./cliDisplay.js\";\nimport {\n\taddGlobalOptions,\n\thandleGlobalOptions,\n\tinitGlobalOptions,\n\tinitLocales\n} from \"./commands/global.js\";\nimport type { ICliOptions } from \"./models/ICliOptions.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport abstract class CLIBase {\n\t/**\n\t * Execute the command line processing.\n\t * @param options The options for the CLI.\n\t * @param localesDirectory The path to load the locales from.\n\t * @param argv The process arguments.\n\t * @returns The exit code.\n\t */\n\tpublic async execute(\n\t\toptions: ICliOptions,\n\t\tlocalesDirectory: string,\n\t\targv: string[]\n\t): Promise<number> {\n\t\tinitGlobalOptions(localesDirectory);\n\t\tinitLocales(\"en\");\n\n\t\ttry {\n\t\t\tprocess.title = options.title;\n\n\t\t\tif (!argv.includes(\"--version\") && !argv.includes(\"-v\")) {\n\t\t\t\tCLIDisplay.header(options.title, options.version, options.icon);\n\t\t\t}\n\n\t\t\tconst program = new Command();\n\n\t\t\tlet outputWidth = options.overrideOutputWidth;\n\t\t\tlet outputErrWidth = options.overrideOutputWidth;\n\t\t\tif (Is.undefined(outputWidth) && process.stdout.isTTY) {\n\t\t\t\toutputWidth = process.stdout.columns;\n\t\t\t\toutputErrWidth = process.stderr.columns;\n\t\t\t}\n\n\t\t\tprogram\n\t\t\t\t.name(options.appName)\n\t\t\t\t.version(options.version)\n\t\t\t\t.usage(\"[command]\")\n\t\t\t\t.showHelpAfterError()\n\t\t\t\t.configureOutput({\n\t\t\t\t\twriteOut: str => CLIDisplay.write(str),\n\t\t\t\t\twriteErr: str => CLIDisplay.writeError(str),\n\t\t\t\t\tgetOutHelpWidth: () => outputWidth as number,\n\t\t\t\t\tgetErrHelpWidth: () => outputErrWidth as number,\n\t\t\t\t\toutputError: (str, write) => CLIDisplay.error(str.replace(/^error: /, \"\"), false)\n\t\t\t\t})\n\t\t\t\t.exitOverride(err => {\n\t\t\t\t\t// By default commander still calls process.exit on exit\n\t\t\t\t\t// which we don't want as we might have subsequent\n\t\t\t\t\t// processing to handle, so instead we throw the exit code\n\t\t\t\t\t// as a way to skip the process.exit call.\n\t\t\t\t\t// If the error code is commander.help then we return 0 as\n\t\t\t\t\t// we don't want displaying help to be an error.\n\t\t\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\t\t\tthrow new Error(err.code === \"commander.help\" ? \"0\" : err.exitCode.toString());\n\t\t\t\t});\n\n\t\t\tif (options.showDevToolWarning ?? false) {\n\t\t\t\tprogram.hook(\"preAction\", () =>\n\t\t\t\t\tCLIDisplay.warning(I18n.formatMessage(\"warn.common.devOnlyTool\"))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.configureRoot(program);\n\n\t\t\taddGlobalOptions(program, options.supportsLang ?? true, options.supportsEnvFiles ?? false);\n\n\t\t\t// We parse the options before building the command\n\t\t\t// in case the language has been set, then the\n\t\t\t// help for the options will be in the correct language.\n\t\t\tprogram.parseOptions(argv);\n\t\t\thandleGlobalOptions(program);\n\n\t\t\tconst commandCount = this.buildCommands(program);\n\t\t\tif (commandCount === 0) {\n\t\t\t\tprogram.usage(\" \");\n\t\t\t}\n\n\t\t\tawait program.parseAsync(argv);\n\t\t} catch (error) {\n\t\t\tCLIDisplay.spinnerStop();\n\n\t\t\tlet exitCode;\n\t\t\t// We have no control over the response from commander\n\t\t\t// so we have to do some checking and coercion here\n\t\t\t// to get a valid exit code.\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tif (error instanceof Error) {\n\t\t\t\t// This error could be the exit code we errored with\n\t\t\t\t// from the exitOverride so parse and resolve with it\n\t\t\t\texitCode = Coerce.number(error.message);\n\t\t\t}\n\n\t\t\tif (Is.integer(exitCode)) {\n\t\t\t\treturn exitCode;\n\t\t\t}\n\t\t\tCLIDisplay.error(error);\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Configure any options or actions at the root program level.\n\t * @param program The root program command.\n\t */\n\tprotected configureRoot(program: Command): void {\n\t\tprogram.action(() => {\n\t\t\tprogram.help();\n\t\t});\n\t}\n\n\t/**\n\t * Get the commands for the CLI, override in derived class to supply your own.\n\t * @param program The main program that the commands will be added to.\n\t * @returns The commands for the CLI.\n\t */\n\tprotected getCommands(program: Command): Command[] {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Build the commands for the CLI.\n\t * @param program The main program that the commands are added to.\n\t * @returns The number of commands added.\n\t * @internal\n\t */\n\tprivate buildCommands(program: Command): number {\n\t\tconst commands = this.getCommands(program);\n\n\t\tfor (const command of commands) {\n\t\t\tprogram.addCommand(command.copyInheritedSettings(program));\n\t\t}\n\n\t\treturn commands.length;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { clearLine, cursorTo } from "node:readline";
|
|
4
|
+
import { inspect } from "node:util";
|
|
5
|
+
import { Coerce, ErrorHelper, I18n, Is } from "@twin.org/core";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
/**
|
|
8
|
+
* Display utilities for the CLI.
|
|
9
|
+
*/
|
|
10
|
+
export class CLIDisplay {
|
|
11
|
+
/**
|
|
12
|
+
* The interval ID for the spinner.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
static _spinnerIntervalId;
|
|
16
|
+
/**
|
|
17
|
+
* The default output method for writing standard messages.
|
|
18
|
+
* @param buffer The message to output.
|
|
19
|
+
*/
|
|
20
|
+
static write = buffer => process.stdout.write(buffer);
|
|
21
|
+
/**
|
|
22
|
+
* The default output method for writing error messages.
|
|
23
|
+
* @param buffer The message to output.
|
|
24
|
+
*/
|
|
25
|
+
static writeError = buffer => process.stderr.write(buffer);
|
|
26
|
+
/**
|
|
27
|
+
* The default output method for clearing the current line.
|
|
28
|
+
*/
|
|
29
|
+
static clearLine = () => {
|
|
30
|
+
clearLine(process.stdout, 0);
|
|
31
|
+
cursorTo(process.stdout, 0);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Display the header for the CLI.
|
|
35
|
+
* @param title The title of the CLI.
|
|
36
|
+
* @param version The version of the CLI.
|
|
37
|
+
* @param icon The icon for the CLI.
|
|
38
|
+
*/
|
|
39
|
+
static header(title, version, icon) {
|
|
40
|
+
const titleVersion = `${title} v${version}`;
|
|
41
|
+
CLIDisplay.write(`${icon} ${chalk.underline.bold.blue(titleVersion)}\n`);
|
|
42
|
+
CLIDisplay.write("\n");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Display an error message.
|
|
46
|
+
* @param error The error to display.
|
|
47
|
+
* @param lineBreaks Whether to add a line break after the error.
|
|
48
|
+
*/
|
|
49
|
+
static error(error, lineBreaks = true) {
|
|
50
|
+
CLIDisplay.writeError("❗ ");
|
|
51
|
+
CLIDisplay.writeError(chalk.red(I18n.formatMessage("cli.progress.error")));
|
|
52
|
+
if (lineBreaks) {
|
|
53
|
+
CLIDisplay.writeError("\n");
|
|
54
|
+
}
|
|
55
|
+
const formatted = ErrorHelper.formatErrors(error, true);
|
|
56
|
+
CLIDisplay.writeError(chalk.red(formatted.map(e => `\t${e}`).join("\n")));
|
|
57
|
+
if (lineBreaks) {
|
|
58
|
+
CLIDisplay.writeError("\n");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Display an error message in simple form.
|
|
63
|
+
* @param error The error to display.
|
|
64
|
+
*/
|
|
65
|
+
static errorMessage(error) {
|
|
66
|
+
CLIDisplay.writeError("❗ ");
|
|
67
|
+
CLIDisplay.writeError(chalk.red(error));
|
|
68
|
+
CLIDisplay.writeError("\n");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Display a section.
|
|
72
|
+
* @param label The label for the section.
|
|
73
|
+
*/
|
|
74
|
+
static section(label) {
|
|
75
|
+
CLIDisplay.write(chalk.hex("#FFA500").bold.underline(label));
|
|
76
|
+
CLIDisplay.write("\n\n");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Display a value with a label.
|
|
80
|
+
* @param label The label for the value.
|
|
81
|
+
* @param value The value to display.
|
|
82
|
+
* @param indentLevel The level of indentation.
|
|
83
|
+
*/
|
|
84
|
+
static value(label, value, indentLevel = 0) {
|
|
85
|
+
CLIDisplay.write("\t".repeat(indentLevel));
|
|
86
|
+
if (Is.stringValue(label)) {
|
|
87
|
+
CLIDisplay.write(chalk.hex("#FFA500").bold(`${label}: `));
|
|
88
|
+
}
|
|
89
|
+
CLIDisplay.write(Coerce.string(value) ?? "");
|
|
90
|
+
CLIDisplay.write("\n");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Display a task with a label.
|
|
94
|
+
* @param label The label for the value.
|
|
95
|
+
* @param task The task to display.
|
|
96
|
+
*/
|
|
97
|
+
static task(label, task) {
|
|
98
|
+
CLIDisplay.write("➡️ ");
|
|
99
|
+
if (Is.empty(task)) {
|
|
100
|
+
CLIDisplay.write(chalk.cyan(label));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
CLIDisplay.write(chalk.cyan(`${label}: `));
|
|
104
|
+
CLIDisplay.write(task);
|
|
105
|
+
}
|
|
106
|
+
CLIDisplay.write("\n");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Display a break.
|
|
110
|
+
*/
|
|
111
|
+
static break() {
|
|
112
|
+
CLIDisplay.write("\n");
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Display formatted and colorized JSON.
|
|
116
|
+
* @param obj The object to display.
|
|
117
|
+
*/
|
|
118
|
+
static json(obj) {
|
|
119
|
+
CLIDisplay.write(inspect(obj, false, null, true));
|
|
120
|
+
CLIDisplay.write("\n");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Display a warning.
|
|
124
|
+
* @param label The label for the warning.
|
|
125
|
+
*/
|
|
126
|
+
static warning(label) {
|
|
127
|
+
CLIDisplay.write("⚠️ ");
|
|
128
|
+
CLIDisplay.write(chalk.hex("#FFA500").bold(label));
|
|
129
|
+
CLIDisplay.write("\n\n");
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Display the processing is done.
|
|
133
|
+
*/
|
|
134
|
+
static done() {
|
|
135
|
+
CLIDisplay.write("🎉 ");
|
|
136
|
+
CLIDisplay.write(chalk.greenBright.bold(I18n.formatMessage("cli.progress.done")));
|
|
137
|
+
CLIDisplay.write("\n");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Start the spinner.
|
|
141
|
+
* @param i18nMessage The message to display with the spinner.
|
|
142
|
+
* @param spinnerCharacters The characters to use in the spinner.
|
|
143
|
+
* @param interval The interval for the spinner.
|
|
144
|
+
*/
|
|
145
|
+
static spinnerStart(i18nMessage = "cli.progress.pleaseWait", spinnerCharacters = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"], interval = 100) {
|
|
146
|
+
let spinnerIndex = 0;
|
|
147
|
+
if (CLIDisplay._spinnerIntervalId) {
|
|
148
|
+
clearInterval(CLIDisplay._spinnerIntervalId);
|
|
149
|
+
}
|
|
150
|
+
CLIDisplay._spinnerIntervalId = setInterval(() => {
|
|
151
|
+
CLIDisplay.clearLine();
|
|
152
|
+
CLIDisplay.write(`${spinnerCharacters[spinnerIndex++ % spinnerCharacters.length]} ${I18n.formatMessage(i18nMessage)}`);
|
|
153
|
+
}, interval);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Stop the spinner.
|
|
157
|
+
*/
|
|
158
|
+
static spinnerStop() {
|
|
159
|
+
if (CLIDisplay._spinnerIntervalId) {
|
|
160
|
+
clearInterval(CLIDisplay._spinnerIntervalId);
|
|
161
|
+
CLIDisplay._spinnerIntervalId = undefined;
|
|
162
|
+
}
|
|
163
|
+
CLIDisplay.clearLine();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=cliDisplay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliDisplay.js","sourceRoot":"","sources":["../../src/cliDisplay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { clearLine, cursorTo } from \"node:readline\";\nimport { inspect } from \"node:util\";\nimport { Coerce, ErrorHelper, I18n, Is } from \"@twin.org/core\";\nimport chalk from \"chalk\";\n\n/**\n * Display utilities for the CLI.\n */\nexport class CLIDisplay {\n\t/**\n\t * The interval ID for the spinner.\n\t * @internal\n\t */\n\tprivate static _spinnerIntervalId: NodeJS.Timeout | number | undefined;\n\n\t/**\n\t * The default output method for writing standard messages.\n\t * @param buffer The message to output.\n\t */\n\tpublic static write: (buffer: string | Uint8Array) => void = buffer =>\n\t\tprocess.stdout.write(buffer);\n\n\t/**\n\t * The default output method for writing error messages.\n\t * @param buffer The message to output.\n\t */\n\tpublic static writeError: (buffer: string | Uint8Array) => void = buffer =>\n\t\tprocess.stderr.write(buffer);\n\n\t/**\n\t * The default output method for clearing the current line.\n\t */\n\tpublic static clearLine: () => void = () => {\n\t\tclearLine(process.stdout, 0);\n\t\tcursorTo(process.stdout, 0);\n\t};\n\n\t/**\n\t * Display the header for the CLI.\n\t * @param title The title of the CLI.\n\t * @param version The version of the CLI.\n\t * @param icon The icon for the CLI.\n\t */\n\tpublic static header(title: string, version: string, icon: string): void {\n\t\tconst titleVersion = `${title} v${version}`;\n\t\tCLIDisplay.write(`${icon} ${chalk.underline.bold.blue(titleVersion)}\\n`);\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Display an error message.\n\t * @param error The error to display.\n\t * @param lineBreaks Whether to add a line break after the error.\n\t */\n\tpublic static error(error: unknown, lineBreaks: boolean = true): void {\n\t\tCLIDisplay.writeError(\"❗ \");\n\t\tCLIDisplay.writeError(chalk.red(I18n.formatMessage(\"cli.progress.error\")));\n\t\tif (lineBreaks) {\n\t\t\tCLIDisplay.writeError(\"\\n\");\n\t\t}\n\n\t\tconst formatted = ErrorHelper.formatErrors(error, true);\n\t\tCLIDisplay.writeError(chalk.red(formatted.map(e => `\\t${e}`).join(\"\\n\")));\n\t\tif (lineBreaks) {\n\t\t\tCLIDisplay.writeError(\"\\n\");\n\t\t}\n\t}\n\n\t/**\n\t * Display an error message in simple form.\n\t * @param error The error to display.\n\t */\n\tpublic static errorMessage(error: string): void {\n\t\tCLIDisplay.writeError(\"❗ \");\n\t\tCLIDisplay.writeError(chalk.red(error));\n\t\tCLIDisplay.writeError(\"\\n\");\n\t}\n\n\t/**\n\t * Display a section.\n\t * @param label The label for the section.\n\t */\n\tpublic static section(label: string): void {\n\t\tCLIDisplay.write(chalk.hex(\"#FFA500\").bold.underline(label));\n\t\tCLIDisplay.write(\"\\n\\n\");\n\t}\n\n\t/**\n\t * Display a value with a label.\n\t * @param label The label for the value.\n\t * @param value The value to display.\n\t * @param indentLevel The level of indentation.\n\t */\n\tpublic static value(label: string, value: unknown, indentLevel: number = 0): void {\n\t\tCLIDisplay.write(\"\\t\".repeat(indentLevel));\n\t\tif (Is.stringValue(label)) {\n\t\t\tCLIDisplay.write(chalk.hex(\"#FFA500\").bold(`${label}: `));\n\t\t}\n\t\tCLIDisplay.write(Coerce.string(value) ?? \"\");\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Display a task with a label.\n\t * @param label The label for the value.\n\t * @param task The task to display.\n\t */\n\tpublic static task(label: string, task?: string): void {\n\t\tCLIDisplay.write(\"➡️ \");\n\t\tif (Is.empty(task)) {\n\t\t\tCLIDisplay.write(chalk.cyan(label));\n\t\t} else {\n\t\t\tCLIDisplay.write(chalk.cyan(`${label}: `));\n\t\t\tCLIDisplay.write(task);\n\t\t}\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Display a break.\n\t */\n\tpublic static break(): void {\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Display formatted and colorized JSON.\n\t * @param obj The object to display.\n\t */\n\tpublic static json(obj: unknown): void {\n\t\tCLIDisplay.write(inspect(obj, false, null, true));\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Display a warning.\n\t * @param label The label for the warning.\n\t */\n\tpublic static warning(label: string): void {\n\t\tCLIDisplay.write(\"⚠️ \");\n\t\tCLIDisplay.write(chalk.hex(\"#FFA500\").bold(label));\n\t\tCLIDisplay.write(\"\\n\\n\");\n\t}\n\n\t/**\n\t * Display the processing is done.\n\t */\n\tpublic static done(): void {\n\t\tCLIDisplay.write(\"🎉 \");\n\t\tCLIDisplay.write(chalk.greenBright.bold(I18n.formatMessage(\"cli.progress.done\")));\n\t\tCLIDisplay.write(\"\\n\");\n\t}\n\n\t/**\n\t * Start the spinner.\n\t * @param i18nMessage The message to display with the spinner.\n\t * @param spinnerCharacters The characters to use in the spinner.\n\t * @param interval The interval for the spinner.\n\t */\n\tpublic static spinnerStart(\n\t\ti18nMessage: string = \"cli.progress.pleaseWait\",\n\t\tspinnerCharacters: string[] = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"],\n\t\tinterval: number = 100\n\t): void {\n\t\tlet spinnerIndex = 0;\n\t\tif (CLIDisplay._spinnerIntervalId) {\n\t\t\tclearInterval(CLIDisplay._spinnerIntervalId);\n\t\t}\n\t\tCLIDisplay._spinnerIntervalId = setInterval(() => {\n\t\t\tCLIDisplay.clearLine();\n\t\t\tCLIDisplay.write(\n\t\t\t\t`${spinnerCharacters[spinnerIndex++ % spinnerCharacters.length]} ${I18n.formatMessage(i18nMessage)}`\n\t\t\t);\n\t\t}, interval);\n\t}\n\n\t/**\n\t * Stop the spinner.\n\t */\n\tpublic static spinnerStop(): void {\n\t\tif (CLIDisplay._spinnerIntervalId) {\n\t\t\tclearInterval(CLIDisplay._spinnerIntervalId);\n\t\t\tCLIDisplay._spinnerIntervalId = undefined;\n\t\t}\n\t\tCLIDisplay.clearLine();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { I18n } from "@twin.org/core";
|
|
4
|
+
/**
|
|
5
|
+
* Utilities for getting standard options.
|
|
6
|
+
*/
|
|
7
|
+
export class CLIOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Get the options for output.
|
|
10
|
+
* @param command The command to add the options to.
|
|
11
|
+
* @param opts The options of what to include.
|
|
12
|
+
* @param opts.noConsole Do not output to the console.
|
|
13
|
+
* @param opts.json Output to a JSON file.
|
|
14
|
+
* @param opts.env Output to an environment file.
|
|
15
|
+
* @param opts.mergeJson Merge existing JSON file.
|
|
16
|
+
* @param opts.mergeEnv Merge existing environment file.
|
|
17
|
+
*/
|
|
18
|
+
static output(command, opts) {
|
|
19
|
+
if (opts.noConsole) {
|
|
20
|
+
command.option(I18n.formatMessage("cli.options.no-console.param"), I18n.formatMessage("cli.options.no-console.description"));
|
|
21
|
+
}
|
|
22
|
+
if (opts.json) {
|
|
23
|
+
command.option(I18n.formatMessage("cli.options.json.param"), I18n.formatMessage("cli.options.json.description"));
|
|
24
|
+
}
|
|
25
|
+
if (opts.mergeJson) {
|
|
26
|
+
command.option(I18n.formatMessage("cli.options.merge-json.param"), I18n.formatMessage("cli.options.merge-json.description"));
|
|
27
|
+
}
|
|
28
|
+
if (opts.env) {
|
|
29
|
+
command.option(I18n.formatMessage("cli.options.env.param"), I18n.formatMessage("cli.options.env.description"));
|
|
30
|
+
}
|
|
31
|
+
if (opts.mergeEnv) {
|
|
32
|
+
command.option(I18n.formatMessage("cli.options.merge-env.param"), I18n.formatMessage("cli.options.merge-env.description"));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=cliOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliOptions.js","sourceRoot":"","sources":["../../src/cliOptions.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAGtC;;GAEG;AACH,MAAM,OAAO,UAAU;IACtB;;;;;;;;;OASG;IACI,MAAM,CAAC,MAAM,CACnB,OAAgB,EAChB,IAMC;QAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,MAAM,CACb,IAAI,CAAC,aAAa,CAAC,8BAA8B,CAAC,EAClD,IAAI,CAAC,aAAa,CAAC,oCAAoC,CAAC,CACxD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CACb,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,EAC5C,IAAI,CAAC,aAAa,CAAC,8BAA8B,CAAC,CAClD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,MAAM,CACb,IAAI,CAAC,aAAa,CAAC,8BAA8B,CAAC,EAClD,IAAI,CAAC,aAAa,CAAC,oCAAoC,CAAC,CACxD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CACb,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAC3C,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,CACjD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CACb,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,EACjD,IAAI,CAAC,aAAa,CAAC,mCAAmC,CAAC,CACvD,CAAC;QACH,CAAC;IACF,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { I18n } from \"@twin.org/core\";\nimport type { Command } from \"commander\";\n\n/**\n * Utilities for getting standard options.\n */\nexport class CLIOptions {\n\t/**\n\t * Get the options for output.\n\t * @param command The command to add the options to.\n\t * @param opts The options of what to include.\n\t * @param opts.noConsole Do not output to the console.\n\t * @param opts.json Output to a JSON file.\n\t * @param opts.env Output to an environment file.\n\t * @param opts.mergeJson Merge existing JSON file.\n\t * @param opts.mergeEnv Merge existing environment file.\n\t */\n\tpublic static output(\n\t\tcommand: Command,\n\t\topts: {\n\t\t\tnoConsole: boolean;\n\t\t\tjson: boolean;\n\t\t\tenv: boolean;\n\t\t\tmergeJson: boolean;\n\t\t\tmergeEnv: boolean;\n\t\t}\n\t): void {\n\t\tif (opts.noConsole) {\n\t\t\tcommand.option(\n\t\t\t\tI18n.formatMessage(\"cli.options.no-console.param\"),\n\t\t\t\tI18n.formatMessage(\"cli.options.no-console.description\")\n\t\t\t);\n\t\t}\n\t\tif (opts.json) {\n\t\t\tcommand.option(\n\t\t\t\tI18n.formatMessage(\"cli.options.json.param\"),\n\t\t\t\tI18n.formatMessage(\"cli.options.json.description\")\n\t\t\t);\n\t\t}\n\t\tif (opts.mergeJson) {\n\t\t\tcommand.option(\n\t\t\t\tI18n.formatMessage(\"cli.options.merge-json.param\"),\n\t\t\t\tI18n.formatMessage(\"cli.options.merge-json.description\")\n\t\t\t);\n\t\t}\n\t\tif (opts.env) {\n\t\t\tcommand.option(\n\t\t\t\tI18n.formatMessage(\"cli.options.env.param\"),\n\t\t\t\tI18n.formatMessage(\"cli.options.env.description\")\n\t\t\t);\n\t\t}\n\t\tif (opts.mergeEnv) {\n\t\t\tcommand.option(\n\t\t\t\tI18n.formatMessage(\"cli.options.merge-env.param\"),\n\t\t\t\tI18n.formatMessage(\"cli.options.merge-env.description\")\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { Coerce, Converter, GeneralError, Guards, Is, Url } from "@twin.org/core";
|
|
4
|
+
/**
|
|
5
|
+
* Parameter utilities for the CLI.
|
|
6
|
+
*/
|
|
7
|
+
export class CLIParam {
|
|
8
|
+
/**
|
|
9
|
+
* Check the option to see if it exists.
|
|
10
|
+
* @param optionName The name of the option.
|
|
11
|
+
* @param optionValue The option value.
|
|
12
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
13
|
+
* @returns The final option value.
|
|
14
|
+
* @throws An error if the option is invalid.
|
|
15
|
+
*/
|
|
16
|
+
static env(optionName, optionValue, allowEnvVar) {
|
|
17
|
+
if (allowEnvVar && optionValue?.startsWith("!")) {
|
|
18
|
+
const envValueName = optionValue.slice(1);
|
|
19
|
+
// This is reading from an env var so it really has no choice
|
|
20
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
21
|
+
const envValue = process.env[envValueName];
|
|
22
|
+
if (Is.empty(envValue)) {
|
|
23
|
+
throw new GeneralError("commands", "commands.common.missingEnv", {
|
|
24
|
+
option: optionName,
|
|
25
|
+
value: envValueName
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
optionValue = envValue;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return optionValue;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check the option to see if the String exists.
|
|
36
|
+
* @param optionName The name of the option.
|
|
37
|
+
* @param optionValue The option value.
|
|
38
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
39
|
+
* @returns The final option value.
|
|
40
|
+
* @throws An error if the option is invalid.
|
|
41
|
+
*/
|
|
42
|
+
static stringValue(optionName, optionValue, allowEnvVar = true) {
|
|
43
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
44
|
+
Guards.stringValue("commands", optionName, optionValue);
|
|
45
|
+
return optionValue;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check the option to see if the value exists in the specific array.
|
|
49
|
+
* @param optionName The name of the option.
|
|
50
|
+
* @param optionValue The option value.
|
|
51
|
+
* @param validValues The valid values.
|
|
52
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
53
|
+
* @returns The final option value.
|
|
54
|
+
* @throws An error if the option is invalid.
|
|
55
|
+
*/
|
|
56
|
+
static arrayOneOf(optionName, optionValue, validValues, allowEnvVar = true) {
|
|
57
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
58
|
+
Guards.arrayOneOf("commands", optionName, optionValue, validValues);
|
|
59
|
+
return optionValue;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check the option to see if it is a url.
|
|
63
|
+
* @param optionName The name of the option.
|
|
64
|
+
* @param optionValue The option value.
|
|
65
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
66
|
+
* @returns The final option value.
|
|
67
|
+
* @throws An error if the option is invalid.
|
|
68
|
+
*/
|
|
69
|
+
static url(optionName, optionValue, allowEnvVar = true) {
|
|
70
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
71
|
+
Url.guard("commands", optionName, optionValue);
|
|
72
|
+
return optionValue;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check the option to see if it exists and is a number.
|
|
76
|
+
* @param optionName The name of the option.
|
|
77
|
+
* @param optionValue The option value.
|
|
78
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
79
|
+
* @param minValue The minimum value.
|
|
80
|
+
* @param maxValue The maximum value.
|
|
81
|
+
* @returns The final option value.
|
|
82
|
+
* @throws An error if the option is invalid.
|
|
83
|
+
*/
|
|
84
|
+
static number(optionName, optionValue, allowEnvVar = true, minValue = 0, maxValue) {
|
|
85
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
86
|
+
const coerced = Coerce.number(optionValue);
|
|
87
|
+
if (Is.number(coerced)) {
|
|
88
|
+
if (Is.number(minValue) && coerced < minValue) {
|
|
89
|
+
throw new GeneralError("commands", "commands.common.optionMinValue", {
|
|
90
|
+
option: optionName,
|
|
91
|
+
value: optionValue,
|
|
92
|
+
minValue
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else if (Is.number(maxValue) && coerced > maxValue) {
|
|
96
|
+
throw new GeneralError("commands", "commands.common.optionMaxValue", {
|
|
97
|
+
option: optionName,
|
|
98
|
+
value: optionValue,
|
|
99
|
+
maxValue
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return coerced;
|
|
103
|
+
}
|
|
104
|
+
Guards.number("commands", optionName, optionValue);
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check the option to see if it exists and is an integer.
|
|
109
|
+
* @param optionName The name of the option.
|
|
110
|
+
* @param optionValue The option value.
|
|
111
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
112
|
+
* @param minValue The minimum value.
|
|
113
|
+
* @param maxValue The maximum value.
|
|
114
|
+
* @returns The final option value.
|
|
115
|
+
* @throws An error if the option is invalid.
|
|
116
|
+
*/
|
|
117
|
+
static integer(optionName, optionValue, allowEnvVar = true, minValue = 0, maxValue) {
|
|
118
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
119
|
+
const coerced = Coerce.number(optionValue);
|
|
120
|
+
if (Is.integer(coerced)) {
|
|
121
|
+
if (Is.number(minValue) && coerced < minValue) {
|
|
122
|
+
throw new GeneralError("commands", "commands.common.optionMinValue", {
|
|
123
|
+
option: optionName,
|
|
124
|
+
value: optionValue,
|
|
125
|
+
minValue
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else if (Is.number(maxValue) && coerced > maxValue) {
|
|
129
|
+
throw new GeneralError("commands", "commands.common.optionMaxValue", {
|
|
130
|
+
option: optionName,
|
|
131
|
+
value: optionValue,
|
|
132
|
+
maxValue
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return coerced;
|
|
136
|
+
}
|
|
137
|
+
Guards.integer("commands", optionName, optionValue);
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check the option to see if it exists and is a big number.
|
|
142
|
+
* @param optionName The name of the option.
|
|
143
|
+
* @param optionValue The option value.
|
|
144
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
145
|
+
* @param minValue The minimum value.
|
|
146
|
+
* @param maxValue The maximum value.
|
|
147
|
+
* @returns The final option value.
|
|
148
|
+
* @throws An error if the option is invalid.
|
|
149
|
+
*/
|
|
150
|
+
static bigint(optionName, optionValue, allowEnvVar = true, minValue = 0n, maxValue) {
|
|
151
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
152
|
+
const coerced = Coerce.bigint(optionValue);
|
|
153
|
+
if (Is.bigint(coerced)) {
|
|
154
|
+
if (Is.bigint(minValue) && coerced < minValue) {
|
|
155
|
+
throw new GeneralError("commands", "commands.common.optionMinValue", {
|
|
156
|
+
option: optionName,
|
|
157
|
+
value: optionValue,
|
|
158
|
+
minValue
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else if (Is.bigint(maxValue) && coerced > maxValue) {
|
|
162
|
+
throw new GeneralError("commands", "commands.common.optionMaxValue", {
|
|
163
|
+
option: optionName,
|
|
164
|
+
value: optionValue,
|
|
165
|
+
maxValue
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return coerced;
|
|
169
|
+
}
|
|
170
|
+
Guards.bigint("commands", optionName, optionValue);
|
|
171
|
+
return 0n;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check the option to see if it exists and is a boolean.
|
|
175
|
+
* @param optionName The name of the option.
|
|
176
|
+
* @param optionValue The option value.
|
|
177
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
178
|
+
* @returns The final option value.
|
|
179
|
+
* @throws An error if the option is invalid.
|
|
180
|
+
*/
|
|
181
|
+
static boolean(optionName, optionValue, allowEnvVar = true) {
|
|
182
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
183
|
+
const coerced = Coerce.boolean(optionValue);
|
|
184
|
+
if (Is.boolean(coerced)) {
|
|
185
|
+
return coerced;
|
|
186
|
+
}
|
|
187
|
+
Guards.boolean("commands", optionName, optionValue);
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Check the option to see if it exists and is hex.
|
|
192
|
+
* @param optionName The name of the option.
|
|
193
|
+
* @param optionValue The option value.
|
|
194
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
195
|
+
* @returns The final option value.
|
|
196
|
+
* @throws An error if the option is invalid.
|
|
197
|
+
*/
|
|
198
|
+
static hex(optionName, optionValue, allowEnvVar = true) {
|
|
199
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
200
|
+
if (Is.stringHex(optionValue, true)) {
|
|
201
|
+
return Converter.hexToBytes(optionValue);
|
|
202
|
+
}
|
|
203
|
+
throw new GeneralError("commands", "commands.common.optionInvalidHex", {
|
|
204
|
+
option: optionName,
|
|
205
|
+
value: optionValue
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check the option to see if it exists and is base64.
|
|
210
|
+
* @param optionName The name of the option.
|
|
211
|
+
* @param optionValue The option value.
|
|
212
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
213
|
+
* @returns The final option value.
|
|
214
|
+
* @throws An error if the option is invalid.
|
|
215
|
+
*/
|
|
216
|
+
static base64(optionName, optionValue, allowEnvVar = true) {
|
|
217
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
218
|
+
if (Is.stringBase64(optionValue)) {
|
|
219
|
+
return Converter.base64ToBytes(optionValue);
|
|
220
|
+
}
|
|
221
|
+
throw new GeneralError("commands", "commands.common.optionInvalidBase64", {
|
|
222
|
+
option: optionName,
|
|
223
|
+
value: optionValue
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Check the option to see if it exists and is hex or base64.
|
|
228
|
+
* @param optionName The name of the option.
|
|
229
|
+
* @param optionValue The option value.
|
|
230
|
+
* @param allowEnvVar Allow the option to be read from an env var.
|
|
231
|
+
* @returns The final option value.
|
|
232
|
+
* @throws An error if the option is invalid.
|
|
233
|
+
*/
|
|
234
|
+
static hexBase64(optionName, optionValue, allowEnvVar = true) {
|
|
235
|
+
optionValue = CLIParam.env(optionName, optionValue, allowEnvVar);
|
|
236
|
+
if (Is.stringHex(optionValue, true)) {
|
|
237
|
+
return Converter.hexToBytes(optionValue);
|
|
238
|
+
}
|
|
239
|
+
else if (Is.stringBase64(optionValue)) {
|
|
240
|
+
return Converter.base64ToBytes(optionValue);
|
|
241
|
+
}
|
|
242
|
+
throw new GeneralError("commands", "commands.common.optionInvalidHexBase64", {
|
|
243
|
+
option: optionName,
|
|
244
|
+
value: optionValue
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=cliParam.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliParam.js","sourceRoot":"","sources":["../../src/cliParam.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Coerce, Converter, GeneralError, Guards, Is, Url } from \"@twin.org/core\";\n\n/**\n * Parameter utilities for the CLI.\n */\nexport class CLIParam {\n\t/**\n\t * Check the option to see if it exists.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static env(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean\n\t): string | undefined {\n\t\tif (allowEnvVar && optionValue?.startsWith(\"!\")) {\n\t\t\tconst envValueName = optionValue.slice(1);\n\t\t\t// This is reading from an env var so it really has no choice\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tconst envValue = process.env[envValueName];\n\t\t\tif (Is.empty(envValue)) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.missingEnv\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: envValueName\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\toptionValue = envValue;\n\t\t\t}\n\t\t}\n\t\treturn optionValue;\n\t}\n\n\t/**\n\t * Check the option to see if the String exists.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static stringValue(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): string {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tGuards.stringValue(\"commands\", optionName, optionValue);\n\t\treturn optionValue;\n\t}\n\n\t/**\n\t * Check the option to see if the value exists in the specific array.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param validValues The valid values.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static arrayOneOf<T = string>(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tvalidValues: T[],\n\t\tallowEnvVar: boolean = true\n\t): T {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tGuards.arrayOneOf<T>(\"commands\", optionName, optionValue as T, validValues);\n\t\treturn optionValue as T;\n\t}\n\n\t/**\n\t * Check the option to see if it is a url.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static url(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): string {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tUrl.guard(\"commands\", optionName, optionValue);\n\t\treturn optionValue;\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is a number.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @param minValue The minimum value.\n\t * @param maxValue The maximum value.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static number(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true,\n\t\tminValue: number = 0,\n\t\tmaxValue?: number\n\t): number {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tconst coerced = Coerce.number(optionValue);\n\t\tif (Is.number(coerced)) {\n\t\t\tif (Is.number(minValue) && coerced < minValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMinValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tminValue\n\t\t\t\t});\n\t\t\t} else if (Is.number(maxValue) && coerced > maxValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMaxValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tmaxValue\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn coerced;\n\t\t}\n\t\tGuards.number(\"commands\", optionName, optionValue);\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is an integer.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @param minValue The minimum value.\n\t * @param maxValue The maximum value.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static integer(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true,\n\t\tminValue: number = 0,\n\t\tmaxValue?: number\n\t): number {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tconst coerced = Coerce.number(optionValue);\n\t\tif (Is.integer(coerced)) {\n\t\t\tif (Is.number(minValue) && coerced < minValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMinValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tminValue\n\t\t\t\t});\n\t\t\t} else if (Is.number(maxValue) && coerced > maxValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMaxValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tmaxValue\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn coerced;\n\t\t}\n\t\tGuards.integer(\"commands\", optionName, optionValue);\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is a big number.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @param minValue The minimum value.\n\t * @param maxValue The maximum value.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static bigint(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true,\n\t\tminValue: bigint = 0n,\n\t\tmaxValue?: bigint\n\t): bigint {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tconst coerced = Coerce.bigint(optionValue);\n\t\tif (Is.bigint(coerced)) {\n\t\t\tif (Is.bigint(minValue) && coerced < minValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMinValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tminValue\n\t\t\t\t});\n\t\t\t} else if (Is.bigint(maxValue) && coerced > maxValue) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.common.optionMaxValue\", {\n\t\t\t\t\toption: optionName,\n\t\t\t\t\tvalue: optionValue,\n\t\t\t\t\tmaxValue\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn coerced;\n\t\t}\n\t\tGuards.bigint(\"commands\", optionName, optionValue);\n\t\treturn 0n;\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is a boolean.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static boolean(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): boolean {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\t\tconst coerced = Coerce.boolean(optionValue);\n\t\tif (Is.boolean(coerced)) {\n\t\t\treturn coerced;\n\t\t}\n\t\tGuards.boolean(\"commands\", optionName, optionValue);\n\t\treturn false;\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is hex.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static hex(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): Uint8Array {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\n\t\tif (Is.stringHex(optionValue, true)) {\n\t\t\treturn Converter.hexToBytes(optionValue);\n\t\t}\n\t\tthrow new GeneralError(\"commands\", \"commands.common.optionInvalidHex\", {\n\t\t\toption: optionName,\n\t\t\tvalue: optionValue\n\t\t});\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is base64.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static base64(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): Uint8Array {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\n\t\tif (Is.stringBase64(optionValue)) {\n\t\t\treturn Converter.base64ToBytes(optionValue);\n\t\t}\n\t\tthrow new GeneralError(\"commands\", \"commands.common.optionInvalidBase64\", {\n\t\t\toption: optionName,\n\t\t\tvalue: optionValue\n\t\t});\n\t}\n\n\t/**\n\t * Check the option to see if it exists and is hex or base64.\n\t * @param optionName The name of the option.\n\t * @param optionValue The option value.\n\t * @param allowEnvVar Allow the option to be read from an env var.\n\t * @returns The final option value.\n\t * @throws An error if the option is invalid.\n\t */\n\tpublic static hexBase64(\n\t\toptionName: string,\n\t\toptionValue: string | undefined,\n\t\tallowEnvVar: boolean = true\n\t): Uint8Array {\n\t\toptionValue = CLIParam.env(optionName, optionValue, allowEnvVar);\n\n\t\tif (Is.stringHex(optionValue, true)) {\n\t\t\treturn Converter.hexToBytes(optionValue);\n\t\t} else if (Is.stringBase64(optionValue)) {\n\t\t\treturn Converter.base64ToBytes(optionValue);\n\t\t}\n\t\tthrow new GeneralError(\"commands\", \"commands.common.optionInvalidHexBase64\", {\n\t\t\toption: optionName,\n\t\t\tvalue: optionValue\n\t\t});\n\t}\n}\n"]}
|