Перейти к содержанию

Создание CLI-приложения

Node.js позволяет создавать CLI-приложения, взаимодействие с которыми осуществляется через интерфейс командной строки.

Для начала необходимо установить модули commander и inquirer. Commander предоставляет гибкое API для обработки команд и параметров командной строки, а inquirer позволяет пользователю взаимодействовать с приложением через консоль в процессе его работы.

npm install commander inquirer --save

Рассмотрим пример консольного Node.js приложения, которое создает конфигурационные файлы в одном из трех форматов: json, txt или cfg (по умолчанию). Также предусмотрим возможность просматривать список уже созданных файлов.

app.js

#!/usr/bin/env node

const commander = require('commander'),
  { prompt } = require('inquirer'),
  chalk = require('chalk'),
  fs = require('fs')

commander
  .version('1.0.0')
  .description('Configuration files creator.')

commander
  .command('create <name>')
  .option('--extension <value>', 'File extension')
  .alias('c')
  .description('Create new configuration file.')
  .action((name, cmd) => {
    if (
      cmd.extension &&
      !['json', 'txt', 'cfg'].includes(cmd.extension)
    ) {
      console.log(chalk.red('\nExtension is not allowed.'))
    } else {
      prompt([
        {
          type: 'input',
          name: 'charset',
          message: 'Charset: ',
        },
        {
          type: 'input',
          name: 'max_ram_usage',
          message: 'Max RAM usage, Mb: ',
        },
        {
          type: 'input',
          name: 'max_cpu_usage',
          message: 'Max CPU usage, %: ',
        },
        {
          type: 'input',
          name: 'check_updates_interval',
          message: 'Updates interval, ms: ',
        },
        {
          type: 'input',
          name: 'processes_count',
          message: 'Processes count: ',
        },
      ]).then((options) => {
        if (cmd.extension && cmd.extension === 'json') {
          fs.writeFileSync(
            `files/${name}.${cmd.extension}`,
            JSON.stringify(options)
          )
        } else {
          let data = ''
          for (let item in options)
            data += `${item}=${options[item]} \n`

          fs.writeFileSync(`files/${name}.cfg`, data)
        }
        console.log(
          chalk.green(
            `\nFile "${name}.${
              cmd.extension || 'cfg'
            }" created.`
          )
        )
      })
    }
  })

commander
  .command('all')
  .alias('a')
  .description('Show all configuration files.')
  .action(() => {
    const files = fs.readdirSync('files')

    let data = ''
    for (let file of files) data += `${file} \n`

    console.log(
      chalk.grey(`\nConfiguration files: \n\n${data}`)
    )
  })

commander.parse(process.argv)

При создании Node.js CLI-приложения можно указать его метаданные: версию и описание.

commander
  .version('1.0.0')
  .description('Configuration files creator.')

Чтобы узнать версию, выполните следующую команду.

node app.js --version

Для просмотра списка возможных команд и их опций укажите параметр --help.

node app.js --help

Команды описываются с помощью метода command() модуля commander, которому параметром передается имя команды с названием задаваемого ей параметра, заключенного в угловые скобки.

command('create <name>')

Для описания самой команды имеется метод description().

description('Create new configuration file.')

Метод option() позволяет задать дополнительные необязательные аргументы команды. Самому методу передаются два аргумента:

  • имя параметра;
  • описание параметра (необязательно).
option('--extension <value>', 'File extension')

Краткая форма записи команды задается методом alias().

alias('a')

В методе action() описывается логика обработки создаваемой command() команды. Параметрами action() принимает все значения основных параметров команды, а последним параметром объект с дополнительными параметрами, заданными методом option().

action((name, cmd) => {})

После описания всех команд обязательно необходимо вызвать метод parse() и передать ему все параметры командной строки.

commander.parse(process.argv)

Для ввода параметров конфигурационного файла в приведенном примере Node.js CLI-приложения используется модуль inquirer. С помощью его метода prompt задается массив параметров, которые должен заполнить пользователь. Сам метод возвращает объект Promise с заполненными данными в виде объекта.

prompt([
  {
    type: 'input',
    name: 'charset',
    message: 'Charset: ',
  },
]).then((options) => {})

Вводимый пользователем параметр описывается объектом со следующими свойствами:

  • type - тип поля, возможные значения: input, number, confirm, list, rawlist, expand, checkbox, password и editor;
  • name - имя параметра;
  • message - текст, который будет отображаться пользователю при запросе ввода параметра;
  • default - значение параметра по умолчанию.

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

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

В app.js в самом начале уже имеется следующая строка.

#!/usr/bin/env node

Она указывает, что обработка данного файла должна осуществляться Node.js.

Теперь обновим файл package.json.

{
  "name": "cfg",
  "preferGlobal": true,
  "bin": "./app.js"
}

И выполним из директории проекта следующую команду.

npm link

Теперь созданное Node.js CLI-приложение может вызываться глобально из командной строки следующим образом.

cfg all