Matey

Matey - модуль для построения обработчиков консольных команд с субкомандами, аргументами, опциями и флагами.

Matey содержит две основные сущности: Cli и ComandBuilder. Cli - это класс, который хранит все команды, промежуточное программное обеспечение. CommandBuilder - это класс, который позволяет создавать команды, добавлять их в Cli и настраивать их (опции, флаги, аргументы, субкоманды и т.д.).

Команды могут быть вложенными, что позволяет создавать сложные консольные приложения.

Планируется поддержка диалогового ввода-вывода.


Оглавление

Использование

Схематичный пример

🔧 Аргументы-опции(которые хранят какое-то полезное значение) каждой команды описываются в виде

const argA_1: ICommandArgument = {
  name: 'argA_1',
  description: 'argA_1 description',
  type: ArgumentType.OPTION,
  valueValidator: (val: string) => val.length > 0,
  optionNameRequired: true,
  required: true,
};

🚩 Аргументы-флаги(наличие которых само по себе влияет на логику обработчика) каждой команды описываются в виде

const argA_2: ICommandArgument = {
  name: 'argA_2',
  description: 'argA_2 description',
  type: ArgumentType.FLAG,
  required: false,
};

⚡ Сама команда собирается так

const cmdA = new CliCommandBuilder()
  .setName('cmdA')
  .setDescription('cmdA description')
  .addArgument(argA_1)
  .addArgument(argA_2)
  .addSubcommand(subA)
  .setHandler(handlerA)
  .build();

🛡️ После создания команды, ее можно добавить в _Cli_
При необходимости, можно добавить промежуточное программное обеспечение (middleware)

const cli = new Cli();
cli
  .addCommand(cmdA)
  .addCommand(cmdB)
  .addCommand(cmdC)
  .use(rexExpA, handlerA)
  .use(rexExpB, handlerB);

🚀 Выполнение команды происходит так

cli.execute`cmdA --argA_1 "Hello" --argA_2 150`;

Пример использования (отправка email)

Команда для отправки email выглядит одним из следующих вариантов:

  • email <email> <message>
  • email --email <email> --msg <message>

Обработчик команды будет принимать два аргумента: --email и --msg, затем будет "отправлять" сообщение по указанному адресу.

const emailHandler = (options: HandlerArgs) => {
  console.log(
    `Email sent to ${options['--email']} with message: ${
      options['--msg']
    }`,
  );
};

Добавить команду и ее аргументы можно с помощью CommandBuilder:

import {
  ArgumentType,
  Cli,
  CliCommandBuilder,
  HandlerArgs,
  validateFunctions,
} from '../mod.ts';

const emailCommand = new CliCommandBuilder()
  .setName('email')
  .setDescription('Send an email to a specified email address')
  .addArgument({
    name: '--email',
    description: 'The email address to send the email to',
    type: ArgumentType.OPTION,
    valueValidator: validateFunctions.emailValidate,
    required: true,
  })
  .addArgument({
    name: '--msg',
    description: 'The message to include in the email',
    type: ArgumentType.OPTION,
    required: true,
  })
  .setHandler(emailHandler)
  .build();

Вместо validateFunctions.emailValidate можно использовать свою функцию вида string => boolean

Экземпляр Cli хранит все команды и промежуточное программное обеспечение. Добавить команду в Cli можно с помощью метода addCommand, выполнить команду с помощью метода execute:

const cli = new Cli();
cli.addCommand(emailCommand);

await cli.execute`email example@example.com "Hello, World!"`;

Typing SVG


Пример генерации коммита с помощью OpenAI API.

Middleware

Если перед срабатыванием обработчика команды нужно дополнительно обработать запрос, можно использовать middleware-функции. Данные функции возвращают true/false. Обработчик команды срабатывает в том случае, если все middleware-функции вернули true. Если хотя бы одна из них вернула false, цепочка обработки прерывается.

//middleware.ts
const helpMiddleware = {
  pattern: / help /,
  handler: (lexemes: ILexeme[]) => {
    const toHelpCmds = lexemes.filter((lexeme) => {
      return lexeme.type === LexemeType.COMMAND;
    }).map((cmd) => cmd.content);
    console.log(`Find commands ${toHelpCmds} `);
    return false;
  },
};