The command handler and argument parser for anything.
- Recursive folder importing
- Configurable message stylings
- Command checks (requirements)
- Custom Command Arguments Parser
- Custom command run function arguments builder
For the best example please see consoleExample.js
You can install this package using
npm i string-commands
And then import using
import { CommandHandler } from "string-commands";
You can pass an object of options into the CommandHandler.
let handler = new CommandHandler({
// inputs must also begin with prefix
// you can set this to an empty string
prefix: "!",
// by default, log uses console
// set to false to disable logging
log: false,
// or put in your own logger
log: myLogger,
// you can also put the functions here to overwrite them,
// instead of overriding them after initialization
// note that these are still optional
transformCommand: () => {},
buildArguments: () => {},
});
Commands are just objects that must have two properties:
name
(string) The name of the commandrun
(function) The 'runner function'
Example Command:
let myCommand = {
name: "ping",
run: (ctx, args) => {
console.log("Pong!");
},
};
By default, the arguments of the runner functions are as follows:
run: (ctx, args) => {}
The arguments of the Runner Functions are defined using CommandHandler#buildArguments
You can change the order, remove, or add new params to the runner functions by overwriting CommandHandler#buildArguments
like so:
handler.buildArguments = (b) => {
return [b.args, b.ctx.username];
}
// which would make you be able to define the runner function as:
let run = (args, username) => {};
There are two ways to register commands:
1. using an object:
handler.registerCommand(cmd);
handler.registerCommand({ ... });
2. from a folder (recursively):
// path is "./commands" by default
handler.registerCommands();
handler.registerCommands(path);
handler.registerCommands("./src/cmds");
If your project has old commands from another command handler that has differient command objects, you can still import them.
You can set the CommandHandler#transformCommand
to a helper function that would 'transform' the exported object into a valid command object.
Example:
let oldCommand = {
help: {
name: "ping"
},
execute: async () => {},
};
handler.transformCommand = (obj) => {
if(!obj.name) obj.name = obj.help.name;
if(!obj.run) obj.run = obj.execute;
return obj;
}
Your commands can also have custom checks. Its recommended to make the checks once and reuse them for commands.
Command Checks are just the same as runner functions, but they must return an object with these props:
pass
(boolean) - set to true if check succeededmessage
(string) - if it failed, the message explaining why
{
checks: [
(ctx, args) => {
// Im an useless check! Gonna make it run!
return { pass: true };
},
(ctx, args) => {
// just you wait until you hear that im after you
return {
pass: false,
message: "Hardcoded Failiure",
};
},
]
}
The argument parser is a complex system that parses and validates given arguments for you. This means no more if-else checks for arguments in every command :D
Argument parser will look into args
of your command objects.
Examples:
Arguments are also just objects. They must have a type
, the rest are parser options
Arguments can have custom names using name
For example, in the code below, the rest: true
field is a parser option
{
name: "say",
args: [{
type: "text",
name: "yourMessage",
rest: true,
}],
run: () => {},
}
String Resolving:
You can also put strings instead of objects, but the side effect is that you cant define other parser options.
args: ["text"]
// a ":" can be used to give it a name
args: ["yourMessage:text"]
// it can also be marked optional and required
args: ["[text]", "<text>"]
// you can use three dots in the end to set `rest: true`
args: ["text..."]
// you can also combine it like so:
args: ["<words:text>..."]
// you can also also turn the whole array into a string
args: "<user:text> <points:number> [comment:string]..."
rest
(boolean) - if set to true, consumes the rest of the input with it
optional
(boolean) - if set to true, this argument is considered optional
name
(string) - define the name of the argument
Options:
min
(number) - Minimum charactersmax
(number) - Maximum characters
Options:
min
(number)max
(number)isInt
(boolean = false) - If the number should be a whole number/no decimals/integer
Arguments parsers are internally called Usage Parsers.
An usage parser is an object, like an argument, but with a parse
function.
// usage parser: "that"
{
// underlying type
type: "text",
// options to pass into underlying type
max: 1024,
// the parse function
async parse(ctx) {
// the user input or parsed value
ctx.arg;
// the options
ctx.opts.foo;
// "custom name"
ctx.name;
}
}
args: [{ type: "that", name: "custom name", foo: 1 }]
What should I return?
If the parsing etc was successful, return an object with parsed
as your value.
If there were any errors etc, return an object with fail: true
and message
set to the error message.
// it doesnt have to be a variable btw
return { parsed: myValue };
return {
fail: true,
message: "Your argument failed the vibe check.",
}
Usage parsers can easily inherit other parsers using type
. ArgumentParser automatically parses the lowest type and builds up from there. This means if you have an usage parser with type set to "number"
, ctx.arg
will be a number instead of a string.
- Subcommands
- Permissions
v.1.0.0:
- Created project
- Added documentation