Finae-X is a command-line interface (CLI) tool that allows you to perform various tasks and operations from the command line. It provides a simple and intuitive way to interact with your applications and execute commands.
Add imports path to deno.json
{
"imports": {
"finae-x/": "https://deno.land/x/finae_x/"
}
}
To quickly get started with Finae-X, you can follow the code snippet above. It demonstrates how to use the Program class to create a CLI program and define commands, arguments, and options.
import { Program } from 'finae-x/mod.ts';
import { CommandType, ProgramType } from 'finae-x/types.d.ts';
const program: ProgramType.Type = new Program('MY CLI', 'description', {
version: '1.0.0',
});
program
.command('main', 'description')
.action(() => console.log('main'));
program
.command('side', 'description')
.argument('name', 'description')
.action((argument: any, cmd: CommandType.Type) => console.log(argument.name));
program
.command('section', 'description')
.option('name', 'description')
.action((option: any, cmd: CommandType.Type) => console.log(option.name));
program
.command('bar', 'description')
.argument('name', 'description')
.option('name', 'description')
.action((argument: any, option: any) => console.log(argument.name, option.name));
program
.command('satset', 'description')
.argument('name', 'description')
.option('name', 'description')
.action(function () {
console.log(this.arg);
console.log(this.opt);
});
let result: ProgramType.ReturnExec;
result = await program.exec('main');
result = await program.exec('side ferdy');
result = await program.exec('section --name shelby');
result = await program.exec('bar dugem --name lorem');
Run command to view sample output
deno run -A https://deno.land/x/finae_x/example/main.ts ferdiansyah0611 10
deno run -A https://deno.land/x/finae_x/example/drink.ts
deno run -A https://deno.land/x/finae_x/example/pizza.ts
deno run -A https://deno.land/x/finae_x/example/prompt.ts
Explain the use of program:
It imports the Program class from the specified module and creates a new instance of the program with the given name, description, and version.
import { Program } from 'finae-x/mod.ts';
import { ProgramType } from 'finae-x/types.d.ts';
const program: ProgramType.Type = new Program('MY CLI', 'description', {
version: '1.0.0',
// stderr: (err) => throw err,
// suggestAfterError: true
});
It shows how to use the exec method to execute various commands, including passing arguments and options.
await program.exec('--help');
await program.exec('cmd --help');
await program.exec('cmd arg1 arg2 --opt1 data1 --opt2 data2');
It uses the addOption method to define options with their respective descriptions. The second option also demonstrates how to specify a data type for the option using a callback function.
import { OptionType } from 'finae-x/types.d.ts';
program.addOption('--verbose', description);
program.addOption('--global', description, (cls: OptionType.Type) => cls.number());
It uses the hook method to register callback functions for events such as pre-action, post-action, pre-error, and post-error.
import { CommandType } from 'finae-x/types.d.ts';
program.hook('preAction', (_cmd: CommandType.Type | null) => {
console.log('preAction');
});
program.hook('postAction', (_cmd: CommandType.Type | null) => {
console.log('postAction');
});
program.hook('preError', (_cmd: CommandType.Type | null) => {
console.log('preError');
});
program.hook('postError', (_cmd: CommandType.Type | null) => {
console.log('postError');
});
It uses the error method to display custom error messages.
program.error('Your input is invalid');
It uses the usage method to specify a custom usage message, which in this case is set to 'program.test.ts'.
program.usage('program.test.ts');
Explain the use of commands:
It defines a command named "side" with a description. It also defines an argument named "name" with a description. When this command is executed, the value of the "name" argument is printed to the console.
program
.command('side', 'description')
.argument('name', 'description')
.action((argument: any) => console.log(argument.name));
The program has a root command named "root" with a description. It also has two sub-commands: "sub" and "world". When the "sub" command is executed, it prints "sub" to the console. Similarly, when the "world" command is executed, it prints "world" to the console. Additionally, the "down" command is a sub-command of "root" and has its own sub-command "data".
import { CommandType } from 'finae-x/types.d.ts';
const root: CommandType.Type = program.command('root', 'description');
// it will be 'root sub'
root
.command('sub', 'description')
.action(() => console.log('sub'));
// it will be 'root world'
root
.command('world', 'description')
.action(() => console.log('world'));
const down: CommandType.Type = root.command('down', 'description');
// it will be 'root down data'
down.command('data').action(() => console.log('data'));
The "side" command is defined with a description. By using the allowUnknownOption() method, the command allows unrecognized options to be passed. Additionally, the command defines an option named "name" with a description.
program
.command('side', 'description')
.allowUnknownOption()
.option('--name', 'description');
// ...
The program has a root command named "root" with a description. When the command is executed, it prints "root" to the console. The execute() method is used to trigger the execution of the command, and it takes an object containing arguments and options as parameters. In this example, no arguments or options are passed.
const root = program
.command('root', 'description')
.action(() => console.log('root'));
await root.execute({
argument: [],
options: {},
});
Command support multiple aliases.
program
.command('install', 'description')
.alias('i', 'in')
.action(() => console.log('install'));
Explain the use of argument:
Can provide their default values.
import { ArgumentType } from 'finae-x/types.d.ts';
program
.command('main', 'description')
.argument('name', 'description', (cls: ArgumentType.Type) => cls.default('ferdiansyah'))
.action(() => console.log('main'));
There are several data types such as string, float, and number. String as default type.
program
.command('main', 'description')
.argument('str', 'description', (cls: ArgumentType.Type) => cls.string('default'))
.argument('number', 'description', (cls: ArgumentType.Type) => cls.number(100))
.argument('float', 'description', (cls: ArgumentType.Type) => cls.float(10.10));
Supports selection based on parameter data.
program
.command('main', 'description')
.argument('style', 'description', (cls: ArgumentType.Type) => cls.include(['css', 'less', 'sass', 'scss']));
Supports exceptions based on parameter data.
program
.command('main', 'description')
.argument('format', 'description', (cls: ArgumentType.Type) => cls.exclude(['mp3', 'mp4']));
Supports unlimited values, making it an array.
program
.command('main', 'description')
.argument('name', 'description', (cls: ArgumentType.Type) => cls.variadic());
Supports custom validation, must return a value.
program
.command('main', 'description')
.argument('name', 'description', (cls: ArgumentType.Type) =>
cls.validator((value: string | number) => {
if (typeof value === 'string' && value.includes('xxx')) return value.replaceAll('xxx', '[removed]');
return value;
}));
Explain the use of options:
Can provide their default values.
import { OptionType } from 'finae-x/types.d.ts';
program
.command('main', 'description')
.option('name', 'description', (cls: OptionType.Type) => cls.default('ferdiansyah'))
.action(() => console.log('main'));
There are several data types such as string, boolean, float, and number. String as default type.
program
.command('main', 'description')
.option('str', 'description', (cls: OptionType.Type) => cls.string('default'))
.option('number', 'description', (cls: OptionType.Type) => cls.number(100))
.option('float', 'description', (cls: OptionType.Type) => cls.float(10.10));
.option('is', 'description', (cls: OptionType.Type) => cls.boolean());
Supports selection based on parameter data.
program
.command('main', 'description')
.option('style', 'description', (cls: OptionType.Type) => cls.include(['css', 'less', 'sass', 'scss']));
Supports exceptions based on parameter data.
program
.command('main', 'description')
.option('format', 'description', (cls: OptionType.Type) => cls.exclude(['mp3', 'mp4']));
Supports unlimited values, making it an array.
program
.command('main', 'description')
.option('name', 'description', (cls: OptionType.Type) => cls.variadic())
.option('number', 'description', (cls: OptionType.Type) => cls.number().variadic());
Supports custom validation, must return a value.
program
.command('main', 'description')
.option('name', 'description', (cls) =>
cls.validator((value: string | number) => {
if (typeof value === 'string' && value.includes('xxx')) return value.replaceAll('xxx', '[removed]');
return value;
}));
Commands will give an error if these options run simultaneously.
program
.command('main', 'description')
.option('port', 'description', (cls: OptionType.Type) => cls.conflicts('default-port', 'default-config'))
.option('default-port', 'description');
.option('default-config', 'description');
Options will provide a default value to the specified options if the options do not have a value during execution.
program
.command('main', 'description')
.option('port', 'description', (cls: OptionType.Type) => cls.implies({ 'default-port': 3721 }))
.option('default-port', 'description');
Commands will give an error if the options do not have a value.
program
.command('main', 'description')
.option('port', 'description', (cls: OptionType.Type) => cls.required());
Options will provide a default value to the specified environment if the options do not have a value during execution.
program
.command('main', 'description')
.option('port', 'description', (cls: OptionType.Type) => cls.env('PORT'));
Hidden from Help
Hides options from help output.
program
.command('main', 'description')
.option('name', 'description', (cls: OptionType.Type) => cls.hideHelp());
Explain the use of help:
Customize synopsis and description for help.
program.helpOption('-h, --helper', 'show help command');
You can add section output help with specified position: 'afterArgument' | 'afterCommand' | 'afterOption' | 'firstLine' | 'lastLine'
.
const data = [
['title', 'a'.repeat(50)],
];
program.makeSectionHelp('afterArgument', 'afterArgument:', null, data);
program.makeSectionHelp('afterCommand', 'afterCommand:', null, data);
program.makeSectionHelp('afterOption', 'afterOption:', null, data);
program.makeSectionHelp('firstLine', 'firstLine:', null, data);
program.makeSectionHelp('lastLine', 'lastLine:', null, data);
Raw text support with empty name and data.
program.makeSectionHelp(
'afterArgument',
null,
null,
[],
`
Important!
This is raw text
`,
);
You can set raw output.
program.setHelpRaw((info, command) => {
let cmd, argument, option;
function eachCMD(array: CommandType.Type[]) {
return array.map((val) => {
const detail = val.getInformation();
return ` ${detail.name} \t${detail.description.toUpperCase()}`;
}).join('\n');
}
if (command) {
cmd = eachCMD(command.getNested());
argument = command.getArgument().map((val) => {
const detail = val.getInformation();
return ` ${detail.synopsis} (${detail.config.type})\n ${detail.description.toUpperCase()}\n`;
}).join('\n');
option = command.getOption().map((val) => {
const detail = val.getInformation();
return ` ${detail.synopsis} (${detail.config.type})\n ${detail.description.toUpperCase()}\n`;
}).join('\n');
} else {
cmd = eachCMD(program.getAllCommands());
}
let text = `${info.name} v${info.version}`;
if (cmd) {
text += `\n\nCommand\n${cmd}`;
}
if (argument) {
text += `\n\nArgument\n${argument}`;
}
if (option) {
text += `\nOption\n\n${option}`;
}
return text;
});
Support manual to show help, pass false
to argument to get output.
program.showHelp();
const output = program.showHelp(false);
console.log(output);
Explains other features:
Activate this feature if you want to add an error message to a suggestion.
const program: ProgramType.Type = new Program('MY CLI', 'description', {
version: '1.0.0',
suggestAfterError: true,
});
You can change the error message with the specified key.
import { ProgramType } from 'finae-x/types.d.ts';
import message from 'finae-x/src/helpers/message.ts';
import stderr from 'finae-x/src/helpers/stderr.ts';
message.update({
isRequired: '%s \'%s\' harus di isi',
isNotType: '%s \'%s\' bukan sebuah type %s',
isNotIn: '%s \'%s\' tidak termasuk dalam: %s',
isExlude: '%s \'%s\' termasuk dalam pengecualian: %s',
cmdNotFound: 'Command \'%s\' tidak ditemukan.',
optionsUnknown: 'Pilihan tidak teridentifikasi \'%s\'',
actionNotFound: 'Aksi tidak didefinisikan untuk command \'%s\'',
mustHaveOneLength: '%s \'%s\' harus memiliki minimal punya 1 data',
isConflictsOption: 'Pilihan \'%s\' tidak bisa digunakan dengan pilihan \'%s\'',
suggest: 'Apakah maksud kamu \'%s\' ?',
exceededArgument: 'Argumen telah melewati batas',
});
const program: ProgramType.Type = new Program('MY CLI', 'description', {
version: '1.0.0',
stderr(error) {
if (Array.isArray(error)) {
error = error.map((value) => value.replace('Arguments', 'Argumen').replace('Options', 'Pilihan'));
}
stderr(error);
},
});