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

  • 4 года назад

Я только что закончил работу над CLI приложением на NodeJS, sike - инструмент для оповещения пользователей через заданный интервал времени, определенное количество раз. Оповещения задаются при помощи командной строки.

Эта статья описывает процесс создания простого cli приложения, которое работает как echo. Пользователь сможет выполнить что-то в этом роде:

cli -m hello

и терминал просто выведет “hello”.

Мы также добавим тестирование и покажем как опубликовать проект на npm. Скачать мой node-cli-boilerplate можно здесь.

Итак, с чего начать проект?

Для начала нам потребуется установленный node.js. Если вы планируете использовать gulp.js, то его также необходимо установить.

Структура репозитория

Создадим структуру директорий и сам репозиторий (необязательно использовать coffeescript и gulp, я их подключил так как использую их в своей работе).

cli -
   |- bin
        - cli
   |- lib
        - main.js
        - cli.js
   |- src
        |- coffee
            |- lib
                - main.coffee
                - cli.coffee
            |- test
                - test.coffee
   |- test
        - test.js
   — .gitignore
   — index.js
   — gulpfile.js
   — package.json
   — Makefile
   — README.md

Файл package.json

Этот файл имеет большое значение для проекта. Он задает такие детали вашего проекта, как зависимости и не только.

{
"name": "node-cli-boilerplate",
"description": "a node cli boilerplate",
"version”: “0.0.1",
"main”: “index.js",
"author": {
    "name": "jh3y",
    "email": "jh3y@users.noreply.github.com"
},
"repository": {
    "type": "git",
    "url": "git@github.com:jh3y/node-cli-boilerplate.git"
},
"bugs": {
    "url": "https://github.com/jh3y/node-cli-boilerplate/issues"
},
"licenses": [
    {
        "type": "MIT"
    }
],
"preferGlobal": true,
"bin": {
    "cli": "./bin/cli"
},
"engines": {
    "node": ">= 0.8.0"
},
"dependencies": {
    "commander": "^2.2.0",
    "colors": "^0.6.2"
},
"keywords": [],
"devDependencies": {
        "mocha": "^1.18.2",
        "gulp": "^3.6.1",
        "gulp-coffee": "^1.4.2",
        "gulp-plumber": "^0.6.1"
    }
}

Возможно вы уже сталкивались с таким типом файлов. Если нет, то разобраться в нем не составит большого труда. Три основных пункта при работе с node это main, bin и preferGlobal. main задает точку входа нашего приложения, bin определяет соответствие команд и исполняемых файлов, указанных через символические ссылки. preferGlobal выдает предупреждения при попытке локальной установки вместо глобальной, что особенно полезно, так как мы создаем приложение для командной строки. Более подробную информацию о package.json вы найдёте здесь{:target="_blank"}.

Зависимости

Очень важно, чтобы были установлены все зависимости. Если они указаны в package.json, то вы сможете их установить следующей командой:

npm install

В противном случае зависимости придется устанавливать вручную, установив флаг save-dev в false.

Заметка: использование mocha, gulp, gulp-coffee и gulp-plumer зависит от того будете ли вы использовать coffescript и тестирование.

index.js

index.js - главная точка входа. Этот файл должен всегда присутствовать.

module.exports = require(‘./lib/cli.js’);

Таким образом мы предлагаем другим разработчикам использовать нашу логику в своих приложениях. Например:

var cli = require(‘node-cli-boilerplate’);

bin/cli

bin/clie - исполняемый файл

#!/usr/bin/env node
require(‘../lib/main.js’);

Это точка входа приложения при запуске из командной строки.

Файлы lib

cli.js

cli.js - логика приложения. Напомню, наше приложения повторяет echo, поэтому оно содержит всего одну функцию print, которая передает введенное сообщение пользователю.

(function() {
var colors, pkg, print;
colors = require("colors");
pkg = require("../package.json");
exports.print = print = function(options) {
    if (options && options.message && typeof options.message  ===  'string') {
        return console.log("[", "node-cli-boilerplate".white,   "]", options.message.toString().cyan);
    } else {
        throw new Error('no message defined to print!');
    }
};
}).call(this);

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

main.js

main.js - обрабатывает аргументы командной строки. Мы воспользуемся commander.js. commander.js упрощает работу с параметрами и аргументами. Для нашего приложения мы используем один аргумент - сообщение. Задается он при помощи флага -m/--message.

(function() {
var cli, colors, err, pkg, program;
program = require("commander");
colors = require("colors");
pkg = require("../package.json");
cli = require("./cli");
program.version(pkg.version)
       .option("-m, —message [message]”, “set message to be printed.");
program.on("—help", function() {
  console.log("Examples:");
  console.log("");
  console.log(" $ " + "cli" + " —message hello");
});
program.parse(process.argv);
if (process.argv.length === 2) {
  program.help();
} else {
  try {
    cli.print({
      message: program.message
    });
  } catch (_error) {
    err = _error;
    console.log("[", "node-cli-boilerplate".white, "]",       err.toString().red);
  }
}
}).call(this);

Мы добавили пример использования нашего приложения к справочной информации при помощи commander. Последнее что осталось, это выполнить функцию print из аргументов полученных от commander. Но сначала надо проверить наличие этого аргумента и в противном случае выдать справку об использовании приложения. Запуск функции окружён блоком try/catch на случай возникновения ошибок.

Запуск приложения

На этом все. Если вы дошли со мной до конца, то поздравляю. Вы создали свое первое CLI приложение для NodeJS!

Существует два способа запуска приложения.

Первый метод - сделать файл bin исполняемым и запустить его как показано:

chmod u+x bin/cli
./bin/cli -m hello

Второй метод - использовать npm link. Таким образом мы создадим глобальную символическую ссылку и сможем запускать cli в любом месте в терминале:

cli -m hello

Публикация приложения

Для публикации приложения требуется зарегистрироваться на npm. Это можно сделать следующим образом:

npm adduser

где необходимо ввести свои реквизиты. Теперь публикуем приложение!

npm publish

Послу публикации приложение доступно для установки кому угодно.

npm install -g node-cli-boilerplate

После чего cli приложение будет доступно из командной строки. Чтобы отменить публикацию выполните следующую команду:

npm unpublish node-cli-boilerplate@0.0.1

Тестирование (дополнительно)

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

Makefile

Вы уже заметили Makefile в структуре нашего репозитория.

test:
@./node_modules/.bin/mocha -u tdd —reporter spec
.PHONY: test

Этот файл позволяет использовать тестирование mocha командой:

make test

test.js

В test.js указываются тесты для нашего приложения при помощи mocha.

(function() {
var assert, cli;
assert = require("assert");
cli = require("../lib/cli");
suite("cli", function() {
  return suite("print", function() {
    return test("should throw an error when empty options",  function() {
      return assert.throws((function() {
        return cli.print();
      }), Error);
    });
  });
});
}).call(this);

Мы создали простейший тест, который вызывает исключение в случае наличия флага сообщения, но отсутствия текста сообщения.

Заключение

Поздравляю, если вы добрались до конца! Я понимаю, что статья довольно длинная, но надеюсь, что вы не зря потратили время и получили навыки написания приложений для командной строки. Если я что-то пропустил и совершил какие-то ошибки, буду рад слышать ваши замечания.