КАК: Создание приложения node cli

Первые шаги по созданию собственного приложения с интерфейсом командной строки

Я только что закончил писать свое первое приложение node cli; Sike, инструмент, который помогает предупреждать пользователя через заданные промежутки времени, времени или продолжительности с помощью сообщений командной строки и срабатывания системных шумов / звонков.

Это пошаговое руководство по созданию простого CLI инструмента, который действует как эхо. Пользователь сможет сделать что-то вроде:

cli -m hello

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

Мы также проведем тестирование и покажем, как опубликовать его в npm реестре.

Для тех, кто находится в лагере TL; DR, вы можете взять мой node-cli-template здесь.

Итак, как начать писать инструмент node cli?

Вам необходимо установить node.js, если он еще не установлен. Если вы собираетесь использовать gulp функции этого пошагового руководства, вам также понадобится установленный gulp-cli.

Структура репо

Создайте репо и содержащую его структуру. Вам не нужно использовать ни 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”,
 “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"
 }
}

Вы можете сгенерировать это с помощью npm init.

Возможно, вы уже знакомы с файлом package.json. Но если нет, должно быть довольно просто, что определяет каждый раздел файла. Если вы раньше не работали с node, в этом проекте есть три важных поля: main , bin и preferGlobal. main определяет точку входа в наше приложение, а bin определяет сопоставление имени команды с исполняемым файлом, который будет символически связан в вашей системе. preferGlobal вызовет предупреждение для пользователя, если он попытается установить приложение локально, а не глобально, что является намерением, поскольку мы создаем приложение командной строки. Для получения дополнительной информации обязательно прочтите про package.json здесь.

Зависимости

Важно, чтобы были установлены все зависимости, необходимые для приложения. Если package.json имеет определенные зависимости и установлен, вы можете просто запустить

npm install or npm i

index.js

index.js - основная точка входа и минимальна.

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

Это просто демонстрация логики cli приложения на случай, если кто-то захочет использовать логику из приложения в своей собственной. Например;

var cli = require('node-cli-boilerplate');

bin / cli

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

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

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

lib файлы

cli.js

cli.js - это особая логика приложения. Помните, что это простое приложение типа эхо, поэтому есть только одна функция. Эта функция возвращает введенное сообщение пользователю.

(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.

Полное решение для интерфейсов командной строки« node.js , вдохновленное Ruby commander ».

commander.js упрощает обработку опций / аргументов. Для нашего приложения echo у нас есть только один вариант; message. Эта опция вызывается с флагом -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, чтобы показать примеры использования приложения.

Последнее, что нужно сделать в main.js , - это вызвать нашу print функцию с аргументами, полученными от командующего. Однако перед этим нам нужно убедиться, что в приложение переданы аргументы, а если нет, использовать командир для вывода справочной информации.

Вызов заключен в ловушку попытки также на тот случай, если приложение выбрасывает какие-либо ошибки.

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

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

Есть два способа запустить приложение.

Первый способ - сделать файл bin исполняемым, а затем запустить этот файл со следующими параметрами.

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

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

cli -m hello

Ссылка npm в папке пакета создаст глобально установленную символическую ссылку от префикса / имени-пакета к текущей папке. - npmjs.org

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

Чтобы опубликовать приложение, вам необходимо стать пользователем npm реестра, если вы еще этого не сделали. Это достигается с помощью

npm adduser

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

Тогда опубликуйте!

npm publish

Как только приложение будет опубликовано, его сможет установить любой желающий.

npm install -g <<Your app name>>

Если в какой-то момент вы решите, что хотите unpublish, просто используйте

npm unpublish <<Your app name>>@<<version>>

Хотя при этом нужно быть очень осторожным.

Тестирование (необязательно)

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

Для тестирования мы будем использовать mocha.

Makefile

Возможно, вы заметили, что ранее в нашей структуре репо был Makefile.

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

Этот файл позволяет нам запустить наш тест мокко, используя make с

make test

Это чисто предпочтение и необязательно. Приглашаем вас написать свои тестовые сценарии в package.json. Однако я предпочитаю разделять любые задачи на Makefile.

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);

У нас есть только один простой тест, который проверяет, что приложение выдает ошибку, если установлен флаг message, но message не передается в качестве аргумента.

Резюме

Если тебе удалось зайти так далеко

Молодец!

Я понимаю, что это был длинный пост, но, надеюсь, он поможет, если вы новичок в написании node приложений командной строки.

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