A mini framework for node.js command-line interfaces based on TypeScript, decorators, DTOs
Clirio is a library for routing terminal command-lines. Clirio promotes using SOLID and data typing (an alternative to commander, args, argparse and etc.).
The author is inspired by angular, nestjs
You can integrate Clirio with other interactive command-line libs (like inquirer, terminal-kit, chalk and etc.)
Clirio starter kit is here
- Clirio
npm install clirio
yarn add clirio
There are 3 easy steps to build Clirio App.
The example for emulating git status
cli command with options
- Create DTO to define input options
import { Option } from 'clirio';
class GitStatusDto {
@Option('--branch, -b')
readonly branch?: string;
@Option('--ignore-submodules')
readonly ignoreSubmodules?: string;
@Option('--short, -s')
readonly short?: null;
}
- Create module to compose a set of commands
import { Module, Command, Options } from 'clirio';
@Module()
export class GitModule {
@Command('git status')
public status(@Options() options: GitStatusDto) {
// use handled data here
console.log(options);
}
}
- Configure the main class
import { Clirio } from 'clirio';
const clirio = new Clirio();
clirio.addModule(GitModule);
clirio.execute();
$ my-cli git status -b master --ignore-submodules all --short
The application will route the command git status
with options to the GitModule.status
method.
{ branch: 'master', ignoreSubmodules: 'all', short: null }
Then use the received data for its intended purpose
The implementation of own cli prefix (like my-cli
) is described in starter kit
The GitStatusOptionsDto
entity can be more typified with additional instructions
import { Clirio, Option, Validate, Transform } from 'clirio';
class GitStatusOptionsDto {
@Option('--branch, -b')
@Validate(Clirio.valid.STRING)
readonly branch: string;
@Option('--ignore-submodules, -i')
@Validate((v) => ['none', 'untracked','dirty', 'all'].includes(v))
readonly ignoreSubmodules: 'none' | 'untracked' | 'dirty' | 'all';
@Option('--short, -s')
@Transform(Clirio.form.FLAG)
readonly short: boolean;
}
@Module()
export class GitModule {
@Command('git status')
public status(@Options() options: GitStatusDto) {
// the "options" data has bean typified, validated, transformed here
console.log(`branch: ${options.branch}`);
console.log(`ignoreSubmodules: ${options.ignoreSubmodules}`);
console.log(`short: ${options.short}`);
}
}
$ my-cli git status -b master --ignore-submodules all --short
branch: master
ignoreSubmodules: all
short: true
All the details are described below
Clirio is developed according to SOLID principles, so it is possible apply OOP, dependency injection and other programming patterns.
Clirio starter kit contains the recommended assembly. But it is possible to integrate any other libraries and custom decorators.
Anatomy of a shell CLI is described in wiki
The author suggests using the following definitions to describe the Clirio specification.
$ node migration-cli.js run 123556 -u user -p pass --db="db-name"
node migration-cli.js | run 123556 -u user -p pass --db="db-name" |
---|---|
launch path | arguments |
node migration-cli.js | run 123556 | -u user -p pass --db="db-name" |
---|---|---|
launch path | command | options |
node migration-cli.js | run | 123556 | -u user | -p pass | --db="db-name" |
---|---|---|---|---|---|
launch path | action | param | option | option | option |
"Arguments" are all space-separated command-line parts after launch path
"Command" are space-separated command-line parts without leading dashes
"Params" are obtained values by matching the command in accordance with the given pattern
"Options" are command-line parts using a leading dashes
Each option is either a key-value or a key. If in the beginning 2 dashes is a long key if one dash is a short key which must be 1 character long:
--name=Alex
, --name Alex
, -n Alex
, --version
, -v
Parsing the command-line (Clirio implementation)
Clirio.parse('test --foo 15 -b -a -r 22');
Clirio.describe(['test', '--foo=15', '-b', '-a', '-r', '22']);
Result
[
{ "type": "action", "key": 0, "value": "test" },
{ "type": "option", "key": "foo", "value": "15" },
{ "type": "option", "key": "b", "value": null },
{ "type": "option", "key": "a", "value": null },
{ "type": "option", "key": "r", "value": "22" }
]
The another example
$ my-cli set-time 10:56 --format=AM -ei 15
type | key | value |
---|---|---|
action | 0 | "set-time" |
action | 1 | "10:56" |
option | "format" | "AM" |
option | "e" | null |
option | "i" | "15" |
- all parts of the command-line without a leading dash will be described as actions
- any action has keys as a numerical index in ascending order
- any option with a missing value will be
null
- any option starting with a single dash will be separated by letters
- all options will be parsed into key-value
- the raw value of any options can be a
string
ornull
The application structure should consist of the following parts:
- the main class -
Clirio
- modules (custom classes or their instances)
- actions (methods in class-modules with decorators )
Clirio
- is the main class which configures the application and links modules
const cli = new Clirio();
cli.setModules([HelloModule, CommonModule, GitModule, MigrationModule]);
cli.execute();
Modules can be instantiated to apply dependency injection
cli.setModules([
HelloModule,
new CommonModule(),
diContainer.resolve(CommonModule),
]);
The example is here
Clirio modules are custom classes with the @Module()
decorator (they can be considered as controllers).
An application can have either one or many modules. Each module contains actions (patterns for commands)
Using a common module
@Module()
export class CommonModule {
@Command('hello there')
public helloThere() {
// ...
}
@Command('migration run')
public migrationRun() {
// ...
}
}
As a result 2 commands will be available:
$ my-cli hello there
$ my-cli migration run
Using multiple modules to separate unrelated commands and structure the code
@Module('hello')
export class HelloModule {
@Command('there')
public helloThere() {
// ...
}
}
@Module('migration')
export class MigrationModule {
@Command('run')
public run() {
// ...
}
}
Clirio actions are methods in class-modules with decorators
@Module()
export class HelloModule {
@Command('hello')
public helloThere() {
console.log('Hello! It works!');
}
@Command('bye')
public help() {
console.log('Bye! See you later');
}
@Empty()
public empty() {
console.log(chalk.yellow('You have not entered anything'));
}
@Failure()
public failure() {
console.log(chalk.red('You have entered a non-existent command'));
}
}
The @Command()
decorator is designed to specify the command pattern
@Module()
export class MigrationModule {
@Command('init')
public initMigration() {}
@Command('migration run|up')
public runMigration() {}
@Command('migration to <name>')
public migrateTo() {}
@Command('migration merge <name1> <name2>')
public mergeMigrations() {}
@Command('migration delete <...names>')
public deleteMigrations() {}
}
The total pattern based on @Module(...)
and @Commands(...)
will be matched with the command-line
Pattern can consist of one or more space-separated arguments
The exact command will be matched
@Command('hello')
@Command('hello my friends')
Command pattern | Matching command-line |
---|---|
hello | hello |
hello there | hello there |
hello my friends | hello my friends |
Using the |
operator to set match variants for params. Multiple command-lines will be matched to one route. The number of space-separated parts of the command-line should be the same.
@Command('migration run|up')
@Command('hello|hey|hi')
Command pattern | Matching command-line |
---|---|
migration run|up | migration run migration up |
hello|hey|hi | hello hey hi |
Using the < >
operator to specify a place for any value. The number of space-separated parts of the command-line should be the same
@Command('hello <first-name> <last-name>')
@Command('set-time <time>')
Command pattern | Matching command-line |
---|---|
hello <first-name> <last-name> | hello Alex Smith hello John Anderson ... etc. |
set-time <time> | set-time 11:50 set-time now set-time 1232343545 ... etc. |
Use Params data control to get the entered values
Using the <... >
operator to specify a place for array of values
This kind of mask can be only one per command pattern and should be at the end
@Command('hello <...all-names>')
@Command('get cities <...cities>')
Command pattern | Matching command-line |
---|---|
hello <...all-names> | hello Alex John Sarah Arthur hello Max ... etc. |
get cities <...cities> | get cities Prague New-York Moscow get cities Berlin ... etc. |
Use Params data control to get the entered values
This pattern is designed for special cases like "help" and "version". This is an exact match of the option key and value. Match variants can be separated by comma
@Command('--help, -h')
@Command('--mode=check')
Command pattern | Matching command-line |
---|---|
--help, -h | --help -h |
--version, -v | --version -v |
--mode=check | --mode=check |
Use Options data control to add other options To avoid problems, do not mix this pattern with the rest ones
The @Empty()
action decorator is a way to catch the case when nothing is entered
Each module can have its own @Empty()
decorator in an action
@Module()
export class CommonModule {
@Command('hello')
public hello() {}
@Empty()
public empty() {
console.log("You haven't entered anything");
}
}
$ my-cli
You haven't entered anything
When a module has a command prefix, it will be matched and ranked
@Module('migration')
export class MigrationModule {
@Command('init')
public initMigration() {}
@Empty()
public empty() {
console.log(
'The migration module requires additional instruction. Type --help',
);
}
}
$ my-cli migration
The migration module requires additional instruction. Type --help
The @Failure()
action decorator is a way to catch the case when the specified command patterns don't match
Each module can have its own @Failure()
decorator in an action
if this decorator is not specified, then a default error will be displayed
@Module()
export class CommonModule {
@Command('hello')
public hello() {}
@Failure()
public failure() {
console.log('There is no such a command!');
}
}
$ my-cli goodbye
There is no such a command!
When a module has a command prefix, it will be matched and ranked
@Module('migration')
export class MigrationModule {
@Command('init')
public initMigration() {}
@Failure()
public failure() {
console.log('The migration module got the wrong instruction');
}
}
$ my-cli migration stop
The migration module got the wrong instruction
Using Parameter Decorators to control input data
The @Params()
and @Options()
decorators provided
@Module()
export class LocatorModule {
@Command('get-location <city>')
public getLocation(@Params() params: unknown, @Options() options: unknown) {
console.log(params);
console.log(options);
}
}
$ my-cli get-location Prague --format=DMS --verbose
{ city: "Prague" }
{ format: "DMS", verbose: true }
To handle incoming data, use DTO (instead of unknown type)
The @Param()
decorator for dto properties provided. It can take a key in an param mask to map DTO properties
export class HelloParamsDto {
@Param('first-name')
readonly firstName?: string;
@Param('last-name')
readonly lastName?: string;
}
@Module()
export class HelloModule {
@Command('hello <first-name> <last-name>')
public hello(@Params() params: HelloParamsDto) {
console.log(params);
}
}
Here the second and third parts of the command-line are the masks for any values that the user enters
The hello
method will be called if the user enters a three-part command. The last 2 parts are passed to the params argument as keys and values
$ my-cli hello Alex Smith
{ firstName: "Alex", lastName: "Smith" }
The @Param()
decorator can have no arguments. In this case DTO properties will map to input keys
If the @Param()
decorator is absent then there will be no mapping
export class HelloParamsDto {
@Param()
readonly 'first-name'?: string;
@Param()
readonly 'last-name'?: string;
}
$ my-cli hello Alex Smith
{ "first-name": "Alex", "last-name": "Smith" }
@Module()
export class GitModule {
@Command('git add <...all-files>')
public add(@Params() params: AddParamsDto) {
// Type checking works for "params" variable
console.log(params.allFiles);
}
}
class AddParamsDto {
@Param('all-files')
readonly allFiles: string[];
}
$ my-cli git add test.txt logo.png
['test.txt', 'logo.png']
The @Options()
decorator provided
@Module()
export class GitModule {
@Command('git status')
public status(@Options() options: GitStatusOptionsDto) {
console.log(options);
}
}
The @Option()
decorator for dto properties provided. It can accept comma-separated key aliases to map DTO properties
class GitStatusOptionsDto {
@Option('--branch, -b')
readonly branch?: string;
@Option('--ignore-submodules, -i')
readonly ignoreSubmodules?: string;
@Option('--short, -s')
@Transform(Clirio.form.FLAG)
readonly short?: boolean;
}
$ my-cli git status --branch=master --ignore-submodules=all --short
$ my-cli git status --branch master --ignore-submodules all --short
$ my-cli git status -b master -i all -s
Each input data will lead to one result:
{ branch: 'master', ignoreSubmodules: 'all', short: true }
If the @Option()
decorator is absent then there will be no mapping
$ my-cli git status --branch=master --ignore-submodules=all --short
{ branch: 'master', "ignore-submodule": 'all', short: true }
DTOs used to control inputs can have additional decorators, including custom ones
All incoming key values can be null
or string
either an array
of null
or a string
type Value = string | null | (string | null)[];
@Module()
export class SomeModule {
@Command('set-limit <limit>')
public setLimit(
@Params() params: SetLimitParamsDto,
@Options() options: SetLimitOptionDto,
) {
console.log(params);
console.log(options);
}
}
Clirio provides the @Validate()
and @Transform()
decorators
In this example it is possible use them for DTO properties SetLimitParamsDto
, SetLimitOptionDto
import { Option, Validate, Transform } from 'clirio';
import { MyCustomDecorator } from 'src/my-decorators';
class SetLimitParamsDto {
@Param('limit')
@Validate((v) => /^[0-9]+$/.test(v)) // checking for numbers only
@Transform((v) => Number(v)) // string to number
@MyCustomDecorator() // will be handled in "Pipe"
readonly limit: number;
}
The @Envs()
decorator provided
import { Envs } from 'clirio';
@Module('migration')
export class MigrationModule {
@Command('test-connect')
public testConnect(@Envs() envs: TestConnectEnvsDto) {
// ...
}
}
The @Env()
decorator for dto properties provided
import { Env } from 'clirio';
export class TestConnectEnvsDto {
@Env('DB_HOST')
readonly host: string;
@Env('DB_PORT')
@Transform((v) => Number(v))
readonly port: number;
@Env('DB_USER')
readonly user: string;
@Env('DB_PASSWORD')
readonly password: string;
}
The @Validate()
decorator provided to check input params and options.
It must be used for DTO properties in conjunction with @Option()
or @Param()
(this depends on the type of controlled data)
The @Validate()
takes a function or an array of functions as an argument. Each function must return boolean
or null
:
- if
false
is returned then an error throws - if
null
is returned then the key validation clause skips - if
true
is returned then the key validation will complete successfully
import { Module, Command, Options } from 'clirio';
@Module()
export class GitModule {
@Command('git status')
public status(@Options() options: GitStatusDto) {
console.log(options);
}
}
import { Option, Validate } from 'clirio';
class GitStatusDto {
@Option('--branch, -b')
@Validate((v) => typeof v === 'string')
readonly branch: string;
@Option('--ignore-submodules')
@Validate(
(v) => v === undefined || ['none', 'untracked', 'dirty', 'all'].includes(v),
)
readonly ignoreSubmodules?: 'none' | 'untracked' | 'dirty' | 'all';
@Option('--short, -s')
readonly short?: boolean;
}
$ my-cli git status --ignore-submodules
The "branch" option is wrong
For any case of failed validation, the same error will be thrown The "%KEY_NAME%" %DATA_TYPE% is wrong
To have more flexible validations, use Pipes
It is possible to configure throwing errors on unknown keys or in options
class OptionsDto {
@Option('--id')
@Validate([(v) => v === undefined || null, /^[0-9]+$/.test(v)])
readonly id?: number;
}
class OptionsDto {
@Option('--id')
@Validate([Clirio.valid.OPTIONAL, Clirio.valid.NUMBER])
readonly id?: number;
}
class OptionsDto {
@Option('--type')
@Validate([Clirio.valid.NULLABLE, Clirio.valid.STRING])
readonly type: string | null;
}
The @Transform()
decorator provided to transform input params and options.
It must be used for DTO properties in conjunction with @Option()
or @Param()
(this depends on the type of controlled data)
The @Transform()
takes a transform function as an argument
import { Option, Transform } from 'clirio';
class SetAutoParamsDto {
@Param();
@Transform((v) => v.toUpperCase())
readonly model: string;
@Param('speed-limit')
@Transform((v) => Number(v))
readonly speedLimit: number;
}
class SetAutoOptionsDto {
@Option('--turbo')
@Transform((v) => v === null || v === 'yes')
readonly turbo: boolean;
}
import { Module, Command, Options } from 'clirio';
@Module('auto')
export class AutoModule {
@Command('set <model> <speed-limit>')
public set(
@Params() params: SetAutoParamsDto,
@Options() options: SetAutoOptionsDto,
) {
console.log(params);
console.log(options);
}
}
$ my-cli auto set bmw 300 --turbo=yes
{ model: 'BMW', speedLimit: 300 }
{ turbo: true }
@Module()
export class SumModule {
@Command('sum <first> <second>')
public sum(@Params() params: SumParamsDto) {
console.log(params.first + params.second);
}
}
Without transformation
class SumParamsDto {
@Param()
readonly first: unknown;
@Param()
readonly second: unknown;
}
$ my-cli sum 5 15
'515'
With transformation
class SumParamsDto {
@Param()
@Transform((v) => Number(v))
readonly first: number;
@Param()
@Transform((v) => Number(v))
readonly second: number;
}
$ my-cli sum 5 15
20
class SetAutoOptionsDto {
@Option('--turbo')
@Transform(Clirio.form.FLAG)
readonly turbo: boolean;
}
Pipes are designed to validate and transform controlled data (params and options).
Using pipes is more functional than the @Validate()
and @Transform()
decorators and gives more flexibility
import { ClirioPipe, PipeContext, ClirioValidationError } from 'clirio';
export class CustomPipe implements ClirioPipe {
transform(data: any, input: PipeContext): any | never {
// controlled params
if (input.dataType === 'params') {
// validation
if (check(data)) {
throw new ClirioValidationError('error message', {
dataType: input.dataType,
propertyName: 'typeId',
});
}
// transformation
return { ...data };
}
// controlled options
if (input.dataType === 'options') {
// validation
if (check(data)) {
throw new ClirioValidationError('error message', {
dataType: input.dataType,
propertyName: 'typeId',
});
}
// transformation
return { ...data };
}
return data;
}
}
The input: PipeContext
argument contains the value input.entity (it is a DTO). It is possible to extract reflection data and use custom decorators.
The @Pipe()
decorator provided
@Module()
export class MigrationModule {
@Command('migration up <migration-id>')
@Pipe(MigrationUpPipe)
public up(
@Params() params: MigrationUpParamsDto,
@Options() options: MigrationUpOptionsDto,
) {
console.log('transformed params after pipes:', params);
console.log('transformed options after pipes:', options);
}
}
export class MigrationUpParamsDto {
@Param('migration-id')
readonly migrationId: number;
}
import { ClirioPipe, PipeContext, ClirioValidationError } from 'clirio';
export class MigrationUpPipe implements ClirioPipe {
transform(data: any, input: PipeContext): any | never {
if (input.dataType === 'params') {
// validation
if (/^[0-9]+$/.test(data.migrationId)) {
throw new ClirioValidationError('"migration-id" is not number', {
dataType: input.dataType,
propertyName: 'migrationId',
});
}
// transformation string to number
return { migrationId: Number(data.migrationId) };
}
return data;
}
}
It is possible to add pipes for each action or globally for all at once
const cli = new Clirio();
cli.addModule(MigrationModule);
cli.setGlobalPipe(CommonPipe);
cli.execute();
Exceptions can be thrown in pipes or actions. Special exceptions designed to complete the script with the desired result
- ClirioValidationError
- ClirioCommonError
import { Module, Command, ClirioCommonError } from 'clirio';
@Module()
export class CommonModule {
@Command('check')
public check() {
throw new ClirioCommonError('Not working!', { code: 'CUSTOM_ERR_CODE' });
}
}
import { Clirio, ClirioValidationError, ClirioCommonError } from 'clirio';
const cli = new Clirio();
cli.setModules([GitModule]);
cli.execute().catch((err) => {
if (err instanceof ClirioValidationError) {
console.log('Validation error', err.message);
process.exit(9);
}
if (err instanceof ClirioCommonError) {
console.log('Common error', err.message);
process.exit(5);
}
console.log('unknown error', err.message);
process.exit(1);
});
Filters are designed to catch exceptions
@Module('ping')
export class PingModule {
@Command('pong')
@Filter(PingPongFilter)
public pong() {
throw new ClirioCommonError('Not working!', { code: 'CUSTOM_ERR_CODE' });
}
}
import {
ClirioCommonError,
ClirioFilter,
ClirioValidationError,
FilterContext,
} from 'clirio';
export class PingPongFilter implements ClirioFilter {
catch(
error: Error | ClirioCommonError | ClirioValidationError,
context: FilterContext,
): void | never {
if (error instanceof ClirioValidationError) {
console.log('Validation error', error.message);
process.exit(9);
}
if (error instanceof ClirioCommonError) {
console.log('Common error', error.message);
process.exit(5);
}
console.log('unknown error', error.message);
process.exit(1);
}
}
It is possible to add filters for each action or apply them globally to all actions at once
const cli = new Clirio();
cli.addModule(MigrationModule);
cli.setGlobalFilter(CommonFilter);
cli.execute();
Special case for the command as an option designed
@Module()
export class CommonModule {
@Command('--help')
public help() {
console.log('Description of commands is here');
}
}
$ my-cli --help
Description of commands is here
It is possible to implement any other commands
@Command('-m, --man')
@Command('help|h')
@Command('man <command>')
The @Helper()
decorator provided to handle the help mode
import { Module, Command, Helper, ClirioHelper } from 'clirio';
@Module()
export class CommonModule {
@Command('hello there', {
description: 'Say hello there',
})
public helloThere() {
// ...
}
@Command('-h, --help')
public help(@Helper() helper: ClirioHelper) {
const dump = helper.dumpAll();
console.log(ClirioHelper.formatDump(dump));
}
}
$ my-cli --help
The ClirioHelper
class provides api for getting descriptions of actions and methods for formatting it
The dumpAll
method returns description for all commands. It is possible to do custom formatting
The dumpThisModule
method returns description for the current module.
@Module('ping')
export class PingModule {
@Command('test')
public test() {
console.log('ping test');
}
@Command('-h, --help')
public help(@Helper() helper: ClirioHelper) {
const dump = helper.dumpThisModule();
console.log(ClirioHelper.formatDump(dump));
}
}
$ my-cli ping --help
Hidden commands
The hidden
option in the Command()
decorator lets hide description of the command in displaying help
import { Module, Command, Hidden } from 'clirio';
@Module()
export class Module {
@Command('debug', { hidden: true })
public debug() {
// ...
}
@Command('hello there', {
description: 'Say hello there',
})
public helloThere() {
// ...
}
}
The ClirioHelper.formatDump
will ignore description of the debug
command in this case
import { Module, Command } from 'clirio';
@Module()
export class CommonModule {
@Command('-v, --version')
public version() {
console.log('1.3.1');
}
}
$ my-cli --version
1.3.1
Setting the global configuration
Parameters:
- config: Object
Returns:
- Clirio
cli.setConfig({
allowUncontrolledOptions: false,
});
Param | Description | Default |
---|---|---|
allowUncontrolledOptions | Clirio can throw Error if DTO are not specified for options but it will be got in the command-line | true |
sets global pipe
Parameters:
- pipe: ClirioPipe
Returns:
- Clirio
cli.setGlobalPipe(CommonPipe);
sets global filter
Parameters:
- pipe: ClirioFilter
Returns:
- Clirio
cli.setGlobalFilter(CommonFilter);
adds one module
Parameters:
- module: Constructor | Constructor['prototype']
Returns:
- Clirio
cli.addModule(PingModule);
cli.addModule(new MigrationModule());
sets several modules
Parameters:
- modules (Constructor | Constructor['prototype'])[]
Returns:
- Clirio
cli.setModules([HelloModule, new MigrationModule()]);
sets arguments of the command-line
Arguments will be determined automatically but it is possible to set them manually. This option is useful for testing and debugging the application
Parameters:
- args: string[]
Returns:
- Clirio
cli.setArgs(['git', 'add', 'test.txt', 'logo.png']);
launches Clirio App
Parameters:
no parameters
Returns:
- Promise
await cli.execute();
Clirio class has static methods and values
an object of check functions for validation
Clirio.valid.BOOLEAN;
Clirio.valid.NUMBER;
Key | Checks if the value is |
---|---|
OPTIONAL |
undefined then it returns true otherwise it returns null
|
REQUIRED |
undefined then it returns false otherwise it returns null
|
NULLABLE |
null then it returns true otherwise it returns null
|
NULL | null |
NUMBER | null |
INTEGER |
number (integer) or a string that resembles an integer |
STRING | string |
BOOLEAN |
boolean or string that resembles boolean ("true" or"false" ) |
FLAG |
null or string that resembles boolean ("true" or "false" ) |
KEY_VALUE |
string or array of string in the key=value format ("DB_USER=user" ) |
export class MigrationRunOptionsDto {
@Option('--id')
@Validate(Clirio.valid.NUMBER)
readonly id: number;
@Option('--start-date, -b')
@Validate([Clirio.valid.NULLABLE, Clirio.valid.STRING])
readonly startDate: string;
}
Clirio.form.BOOLEAN;
Clirio.form.NUMBER;
an object of functions for transformation
Key | transforms into |
---|---|
NUMBER | number |
STRING | string |
BOOLEAN | boolean |
FLAG |
boolean (from null or "true" or "false" ) |
KEY_VALUE |
object from the key=value format or array of ones ("DB_USER=user" ) |
ARRAY |
array (if the value is originally an array, that array will be returned) |
PLAIN |
string or null (if the value is originally an array, the first element will be returned) |
export class MigrationRunOptionsDto {
@Option('--env, -e')
@Transform(Clirio.form.KEY_VALUE)
readonly envs: Record<string, string>;
@Option('--id, -i')
@Transform(Clirio.form.ARRAY)
readonly id: string[];
@Option('-f, --format')
@Transform(Clirio.form.PLAIN)
readonly format: string;
}
parses and describes the command-line
Arguments will be determined automatically but it is possible to set them manually. This option is useful for testing and debugging the application
Parameters:
- commandLine: string
Returns:
Array<
| {
type: 'option';
key: string;
value: string | null;
}
| {
type: 'action';
key: number;
value: string;
}
>;
Clirio.parse('foo -a --bbb');
describes arguments of the command-line
Parameters:
- args: string[]
Returns:
Array<{
type: ArgType;
key: string;
value: string | null;
}>;
Clirio.describe(['foo', '-a', '--bbb']);
Clirio works with decorators. More about decorators
The @Command()
decorator specifies the command pattern
Parameters:
- command: string [optional] - command pattern
- options: object [optional] - extra options
- options.description: string [optional] - description for the help mode
- options.hidden: boolean [optional]- hiding the action in the help mode
The @Empty()
decorator catches the case when nothing is entered
The @Env()
decorator maps DTO properties in Envs DTO
The @Envs()
decorator controls environments
Parameters: no parameters
The @Filter()
decorator catches exceptions in actions or pipe
Parameters: no parameters
The @Failure()
decorator catches the case when the specified command patterns don't match
Parameters: no parameters
The @Helper()
decorator handles the help mode
Parameters: no parameters
The @Module()
decorator makes classes as controllers in to configure Clirio app
Parameters:
- command: string [optional] - command prefix
- options: object [optional] - extra options
- options.description: string [optional] - description for the help mode
- options.hidden: boolean [optional] - hiding the module in the help mode
The @Option()
decorator maps DTO properties in options DTO
Parameters:
- key: string [optional] - comma separated key aliases
- options: object [optional] - extra options
- options.description: string [optional] - description for the help mode
- options.hidden: boolean [optional] - hiding the option in the help mode
The @Options()
decorator controls input options
Parameters: no parameters
The @Param()
decorator maps DTO properties in params DTO
Parameters:
- key: string [optional] - comma separated key aliases
- options: object [optional] - extra options
- options.description: string [optional] - description for the help mode
- options.hidden: boolean [optional] - hiding the param in the help mode
The @Params()
decorator controls input params
Parameters: no parameters
The @Pipe()
decorator validates and transforms controlled data (params and options).
Parameters:
- pipe: ClirioPipe
The @Transform()
decorator transforms input params and options
Parameters:
- value: a function or an array of functions
(value: any) => boolean | null
(value: any) => (boolean | null)[]
The @Validate()
decorator validates input params and options
Parameters:
- value: a transform function
(value: any) => any