@nu-art/cli-params 0.401.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.
@@ -0,0 +1,80 @@
1
+ import { BaseCliParam, CliParams } from './types.js';
2
+ /**
3
+ * Type-safe CLI parameter resolver and parser.
4
+ *
5
+ * Parses command-line arguments (`process.argv`) into a typed object based on
6
+ * parameter definitions. Supports:
7
+ * - Multiple keys/aliases per parameter
8
+ * - Type validation and conversion
9
+ * - Default values and initial values
10
+ * - Option validation (restrict to specific values)
11
+ * - Array parameters (collect multiple values)
12
+ * - Dependencies (set other params based on current param)
13
+ * - Quoted string handling
14
+ *
15
+ * **Usage**:
16
+ * ```typescript
17
+ * const resolver = CLIParamsResolver.create(
18
+ * { keys: ['--name', '-n'], keyName: 'name', type: 'string', description: 'Name' },
19
+ * { keys: ['--count'], keyName: 'count', type: 'number', defaultValue: 1 }
20
+ * );
21
+ * const params = resolver.resolveParamValue();
22
+ * // params.name: string, params.count: number
23
+ * ```
24
+ *
25
+ * @template T - Array of BaseCliParam definitions
26
+ * @template Output - Resolved parameters object type
27
+ */
28
+ export declare class CLIParamsResolver<T extends BaseCliParam<string, any>[], Output extends CliParams<T> = CliParams<T>> {
29
+ /** Processed parameters with all required fields filled */
30
+ private params;
31
+ /**
32
+ * Creates a CLIParamsResolver instance.
33
+ *
34
+ * @template T - Array of BaseCliParam definitions
35
+ * @param params - Parameter definitions
36
+ * @returns New CLIParamsResolver instance
37
+ */
38
+ static create<T extends BaseCliParam<string, any>[]>(...params: T): CLIParamsResolver<T, CliParams<T>>;
39
+ /**
40
+ * Creates a CLIParamsResolver and processes parameters.
41
+ *
42
+ * @param params - Parameter definitions (may be incomplete)
43
+ */
44
+ private constructor();
45
+ /**
46
+ * Parses command-line arguments into a typed parameters object.
47
+ *
48
+ * **Parsing Behavior**:
49
+ * - Splits arguments by `=` (e.g., `--key=value`)
50
+ * - Strips quotes from values and unescapes quotes
51
+ * - Processes values using parameter processors
52
+ * - Validates against options if provided
53
+ * - Handles dependencies (sets dependent params)
54
+ * - Accumulates array values (removes duplicates)
55
+ * - Applies initial values for missing params
56
+ * - Warns when overriding non-array values
57
+ *
58
+ * **Input Format**: `--key=value` or `--key value` (space-separated not supported)
59
+ *
60
+ * @param inputParams - Command-line arguments (default: `process.argv.slice(2)`)
61
+ * @returns Typed object with resolved parameter values
62
+ * @throws Error if value not in options, or if required value missing
63
+ */
64
+ resolveParamValue(inputParams?: string[]): Output;
65
+ /**
66
+ * Find the matching param by finding it's key in the current argument
67
+ * Go over the app params and find the CLIParam object representing it
68
+ * @param inputParam The current console argument being parsed
69
+ * @returns The CliParam or undefined if not found
70
+ * @private
71
+ */
72
+ private findMatchingParamToResolve;
73
+ /**
74
+ * Translate BaseCLIParams passed to the constructor to CLIParams
75
+ * @param params User input of CLI params being passed to the constructor
76
+ * @private
77
+ * @returns CLI Params filled with all mandatory data
78
+ */
79
+ private translate;
80
+ }
@@ -0,0 +1,150 @@
1
+ import { asArray, exists, filterDuplicates, StaticLogger } from '@nu-art/ts-common';
2
+ import { DefaultProcessorsMapper } from './consts.js';
3
+ /**
4
+ * Type-safe CLI parameter resolver and parser.
5
+ *
6
+ * Parses command-line arguments (`process.argv`) into a typed object based on
7
+ * parameter definitions. Supports:
8
+ * - Multiple keys/aliases per parameter
9
+ * - Type validation and conversion
10
+ * - Default values and initial values
11
+ * - Option validation (restrict to specific values)
12
+ * - Array parameters (collect multiple values)
13
+ * - Dependencies (set other params based on current param)
14
+ * - Quoted string handling
15
+ *
16
+ * **Usage**:
17
+ * ```typescript
18
+ * const resolver = CLIParamsResolver.create(
19
+ * { keys: ['--name', '-n'], keyName: 'name', type: 'string', description: 'Name' },
20
+ * { keys: ['--count'], keyName: 'count', type: 'number', defaultValue: 1 }
21
+ * );
22
+ * const params = resolver.resolveParamValue();
23
+ * // params.name: string, params.count: number
24
+ * ```
25
+ *
26
+ * @template T - Array of BaseCliParam definitions
27
+ * @template Output - Resolved parameters object type
28
+ */
29
+ export class CLIParamsResolver {
30
+ /** Processed parameters with all required fields filled */
31
+ params;
32
+ /**
33
+ * Creates a CLIParamsResolver instance.
34
+ *
35
+ * @template T - Array of BaseCliParam definitions
36
+ * @param params - Parameter definitions
37
+ * @returns New CLIParamsResolver instance
38
+ */
39
+ static create(...params) {
40
+ return new CLIParamsResolver(params);
41
+ }
42
+ /**
43
+ * Creates a CLIParamsResolver and processes parameters.
44
+ *
45
+ * @param params - Parameter definitions (may be incomplete)
46
+ */
47
+ constructor(params) {
48
+ this.params = this.translate(params);
49
+ }
50
+ /**
51
+ * Parses command-line arguments into a typed parameters object.
52
+ *
53
+ * **Parsing Behavior**:
54
+ * - Splits arguments by `=` (e.g., `--key=value`)
55
+ * - Strips quotes from values and unescapes quotes
56
+ * - Processes values using parameter processors
57
+ * - Validates against options if provided
58
+ * - Handles dependencies (sets dependent params)
59
+ * - Accumulates array values (removes duplicates)
60
+ * - Applies initial values for missing params
61
+ * - Warns when overriding non-array values
62
+ *
63
+ * **Input Format**: `--key=value` or `--key value` (space-separated not supported)
64
+ *
65
+ * @param inputParams - Command-line arguments (default: `process.argv.slice(2)`)
66
+ * @returns Typed object with resolved parameter values
67
+ * @throws Error if value not in options, or if required value missing
68
+ */
69
+ resolveParamValue(inputParams = process.argv.slice(2, process.argv.length)) {
70
+ const runtimeParams = inputParams.reduce((output, inputParam) => {
71
+ let [key, value] = inputParam.split('=');
72
+ const cliParamToResolve = this.findMatchingParamToResolve(key);
73
+ if (!cliParamToResolve)
74
+ return output;
75
+ if (value && value.startsWith('"') && value.endsWith('"')) {
76
+ value = value.slice(1, -1);
77
+ value = value.replace(/\\"/g, '"');
78
+ }
79
+ const finalValue = cliParamToResolve.process(value, cliParamToResolve.defaultValue);
80
+ // validate options if exits
81
+ if (cliParamToResolve.options && !cliParamToResolve.options.includes(finalValue))
82
+ throw new Error(`value not supported for param: ${cliParamToResolve.name}, supported values: ${cliParamToResolve.options.join(', ')}`);
83
+ const keyName = cliParamToResolve.keyName;
84
+ if (exists(cliParamToResolve.dependencies))
85
+ cliParamToResolve.dependencies?.forEach(dependency => {
86
+ // If dependency value is a function, call it with the current param's processed value
87
+ const dependencyValue = typeof dependency.value === 'function'
88
+ ? dependency.value(finalValue)
89
+ : dependency.value;
90
+ output[dependency.param.keyName] = dependencyValue;
91
+ });
92
+ if (cliParamToResolve.isArray) {
93
+ let currentValues = output[keyName];
94
+ currentValues = filterDuplicates([...(currentValues ?? []), ...asArray(finalValue)]);
95
+ output[keyName] = currentValues;
96
+ return output;
97
+ }
98
+ //if already exists and the value ain't an array warn that the value will be overridden
99
+ if (output[keyName])
100
+ StaticLogger.logWarning(`this param does not accept multiple values, overriding prev value: ${output[keyName]}`);
101
+ //Apply a single value to the object
102
+ output[keyName] = finalValue;
103
+ return output;
104
+ }, {});
105
+ this.params.filter(param => exists(param.initialValue) && !exists(runtimeParams[param.keyName])).forEach(param => {
106
+ runtimeParams[param.keyName] = param.initialValue;
107
+ });
108
+ return runtimeParams;
109
+ }
110
+ /**
111
+ * Find the matching param by finding it's key in the current argument
112
+ * Go over the app params and find the CLIParam object representing it
113
+ * @param inputParam The current console argument being parsed
114
+ * @returns The CliParam or undefined if not found
115
+ * @private
116
+ */
117
+ findMatchingParamToResolve(inputParam) {
118
+ let matchingParam;
119
+ this.params.forEach((param) => {
120
+ param.keys.forEach((key) => {
121
+ if (inputParam === key)
122
+ matchingParam = param;
123
+ if (inputParam.startsWith(`${key}=`))
124
+ matchingParam = param;
125
+ });
126
+ });
127
+ return matchingParam;
128
+ }
129
+ /**
130
+ * Translate BaseCLIParams passed to the constructor to CLIParams
131
+ * @param params User input of CLI params being passed to the constructor
132
+ * @private
133
+ * @returns CLI Params filled with all mandatory data
134
+ */
135
+ translate(params) {
136
+ return params.map(param => {
137
+ //If name is not defined apply key name as the param name
138
+ if (!param.name)
139
+ param.name = param.keyName;
140
+ //If no processor is passed apply default by type
141
+ if (!param.process) {
142
+ param.process = DefaultProcessorsMapper[param.type.split('[')[0].trim()];
143
+ }
144
+ //Determine if value is array by the param type TODO: improve this chunk of code, this is not strict enough
145
+ if (!exists(param.isArray) && param.type.includes('[]'))
146
+ param.isArray = true;
147
+ return param;
148
+ });
149
+ }
150
+ }
package/consts.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { TypedMap } from '@nu-art/ts-common';
2
+ import { CliParam } from './types.js';
3
+ /**
4
+ * Default processor for boolean CLI parameters.
5
+ *
6
+ * Returns the defaultValue or `true` if the flag is present
7
+ *
8
+ * @param input - Optional input string (flag presence indicator)
9
+ * @param defaultValue - Optional default value if flag is absent
10
+ * @returns `true` if flag is present, otherwise `defaultValue ?? false`
11
+ */
12
+ export declare const DefaultProcessor_Boolean: CliParam<any, boolean>['process'];
13
+ /**
14
+ * Default processor for string CLI parameters.
15
+ *
16
+ * Returns the input string, or defaultValue if input is empty/missing.
17
+ * Throws if input is empty and no default is provided.
18
+ *
19
+ * @param input - Optional input string
20
+ * @param defaultValue - Optional default value
21
+ * @returns Processed string value
22
+ * @throws Error if input is empty and no default provided
23
+ */
24
+ export declare const DefaultProcessor_String: CliParam<any, string>['process'];
25
+ /**
26
+ * Default processor for number CLI parameters.
27
+ *
28
+ * Parses the input as a number, or returns defaultValue if input is missing.
29
+ * Throws if input is not a valid number or if input is empty and no default provided.
30
+ *
31
+ * @param input - Optional input string
32
+ * @param defaultValue - Optional default value
33
+ * @returns Parsed number value
34
+ * @throws Error if input is not a number or missing with no default
35
+ */
36
+ export declare const DefaultProcessor_Number: CliParam<any, number>['process'];
37
+ /**
38
+ * Map of default processors by type name.
39
+ *
40
+ * Used by CLIParamsResolver to assign processors when not provided.
41
+ * Keys match the type strings from `TypeOfTypeAsString`.
42
+ */
43
+ export declare const DefaultProcessorsMapper: TypedMap<CliParam<any, any>['process']>;
package/consts.js ADDED
@@ -0,0 +1,64 @@
1
+ import { exists } from '@nu-art/ts-common';
2
+ /**
3
+ * Default processor for boolean CLI parameters.
4
+ *
5
+ * Returns the defaultValue or `true` if the flag is present
6
+ *
7
+ * @param input - Optional input string (flag presence indicator)
8
+ * @param defaultValue - Optional default value if flag is absent
9
+ * @returns `true` if flag is present, otherwise `defaultValue ?? false`
10
+ */
11
+ export const DefaultProcessor_Boolean = (input, defaultValue) => {
12
+ return defaultValue ?? true;
13
+ };
14
+ /**
15
+ * Default processor for string CLI parameters.
16
+ *
17
+ * Returns the input string, or defaultValue if input is empty/missing.
18
+ * Throws if input is empty and no default is provided.
19
+ *
20
+ * @param input - Optional input string
21
+ * @param defaultValue - Optional default value
22
+ * @returns Processed string value
23
+ * @throws Error if input is empty and no default provided
24
+ */
25
+ export const DefaultProcessor_String = (input, defaultValue) => {
26
+ if (!input || !input.length) {
27
+ if (!exists(defaultValue))
28
+ throw new Error('expected string value');
29
+ return defaultValue;
30
+ }
31
+ return input;
32
+ };
33
+ /**
34
+ * Default processor for number CLI parameters.
35
+ *
36
+ * Parses the input as a number, or returns defaultValue if input is missing.
37
+ * Throws if input is not a valid number or if input is empty and no default provided.
38
+ *
39
+ * @param input - Optional input string
40
+ * @param defaultValue - Optional default value
41
+ * @returns Parsed number value
42
+ * @throws Error if input is not a number or missing with no default
43
+ */
44
+ export const DefaultProcessor_Number = (input, defaultValue) => {
45
+ if (!input) {
46
+ if (!exists(defaultValue))
47
+ throw new Error('expected number value');
48
+ return defaultValue;
49
+ }
50
+ if (isNaN(Number(input)))
51
+ throw new Error('expected number value');
52
+ return Number(input);
53
+ };
54
+ /**
55
+ * Map of default processors by type name.
56
+ *
57
+ * Used by CLIParamsResolver to assign processors when not provided.
58
+ * Keys match the type strings from `TypeOfTypeAsString`.
59
+ */
60
+ export const DefaultProcessorsMapper = {
61
+ string: DefaultProcessor_String,
62
+ boolean: DefaultProcessor_Boolean,
63
+ number: DefaultProcessor_Number,
64
+ };
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './consts.js';
3
+ export * from './CLIParamsResolver.js';
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './consts.js';
3
+ export * from './CLIParamsResolver.js';
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@nu-art/cli-params",
3
+ "version": "0.401.2",
4
+ "description": "Shell command execution framework with interactive sessions, CLI parameter resolution, and plugin system for building and executing shell scripts programmatically",
5
+ "type": "module",
6
+ "keywords": [
7
+ "shell",
8
+ "command-execution",
9
+ "cli",
10
+ "bash",
11
+ "interactive-shell",
12
+ "shell-scripts",
13
+ "cli-params",
14
+ "command-line",
15
+ "nu-art",
16
+ "thunderstorm",
17
+ "cli-params",
18
+ "typescript"
19
+ ],
20
+ "homepage": "https://github.com/nu-art-js/thunderstorm",
21
+ "bugs": {
22
+ "url": "https://github.com/nu-art-js/thunderstorm/issues?q=is%3Aissue+label%3Acli-params"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+ssh://git@github.com:nu-art-js/thunderstorm.git",
27
+ "directory": "_thunderstorm/cli-params"
28
+ },
29
+ "publishConfig": {
30
+ "directory": "dist"
31
+ },
32
+ "license": "Apache-2.0",
33
+ "author": "TacB0sS",
34
+ "files": [
35
+ "**/*"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsc"
39
+ },
40
+ "dependencies": {
41
+ "@nu-art/ts-common": "0.401.2"
42
+ },
43
+ "devDependencies": {
44
+ "@nu-art/testalot": "0.401.2"
45
+ },
46
+ "unitConfig": {
47
+ "type": "typescript-lib"
48
+ },
49
+ "exports": {
50
+ ".": {
51
+ "types": "./index.d.ts",
52
+ "import": "./index.js"
53
+ }
54
+ }
55
+ }
package/types.d.ts ADDED
@@ -0,0 +1,56 @@
1
+ import { Primitive, TypeOfTypeAsString } from '@nu-art/ts-common';
2
+ export type CliParams<T extends BaseCliParam<string, any>[]> = {
3
+ [K in T[number]['keyName']]: NonNullable<Extract<T[number], {
4
+ keyName: K;
5
+ }>['defaultValue']>;
6
+ };
7
+ export type DependencyParam<T extends Primitive | Primitive[]> = {
8
+ param: BaseCliParam<string, T>;
9
+ value: T | ((currentValue: any) => T);
10
+ };
11
+ /**
12
+ * Base CLI parameter definition (before processing).
13
+ *
14
+ * Defines a command-line parameter with keys, type, and optional features.
15
+ * Can be incomplete (missing name/process) and will be filled by CLIParamsResolver.
16
+ *
17
+ * **Features**:
18
+ * - Multiple keys (aliases): `['--help', '-h']`
19
+ * - Type validation: `'string'`, `'number'`, `'boolean'`, `'string[]'`, etc.
20
+ * - Options validation: Restrict values to specific options
21
+ * - Dependencies: Set other params based on this param's value
22
+ * - Array support: Collect multiple values
23
+ *
24
+ * @template K - Key name type (string literal)
25
+ * @template V - Value type (primitive or array)
26
+ */
27
+ export type BaseCliParam<K extends string, V extends Primitive | Primitive[]> = {
28
+ /** Array of CLI keys/aliases (e.g., `['--help', '-h']`) */
29
+ keys: string[];
30
+ /** Unique key name for the resolved object */
31
+ keyName: K;
32
+ /** Type string representation (e.g., `'string'`, `'number[]'`) */
33
+ type: TypeOfTypeAsString<V>;
34
+ /** Human-readable description */
35
+ description: string;
36
+ /** Optional parameter name (defaults to keyName) */
37
+ name?: string;
38
+ /** Optional array of allowed values (validates input) */
39
+ options?: string[];
40
+ /** Initial value if param not provided */
41
+ initialValue?: V;
42
+ /** Default value if param provided but empty */
43
+ defaultValue?: V;
44
+ /** Optional processor function (defaults by type) */
45
+ process?: (value?: string, defaultValue?: V) => V;
46
+ /** Whether this param accepts multiple values (array) */
47
+ isArray?: true;
48
+ /** Optional grouping for help/validation */
49
+ group?: string;
50
+ /** Parameters that depend on this one */
51
+ dependencies?: DependencyParam<any>[];
52
+ };
53
+ export type CliParam<K extends string, V extends Primitive | Primitive[]> = BaseCliParam<K, V> & {
54
+ name: string;
55
+ process: (value?: string, defaultValue?: V) => V;
56
+ };
package/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};