В этом посте мы рассмотрим, как создать CLI-инструмент с помощью Node.js. Единственным требованием является использование Node v18+. Вы можете использовать более низкую версию Node, но вам придется адаптировать часть кода, чтобы он работал.
Инициализация проекта
Создайте папку для вашего проекта и запустите npm init
в этой папке. Это создаст файл package.json
в корне вашего проекта. Вы можете передать флаг -y
, чтобы принять значения по умолчанию.
npm init -y
{
"name": "cli-course",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
По умолчанию системой модулей в проекте будет CommonJS или CJS. Импорт и экспорт в CJS работают следующим образом:
var myModule = require("my-module");
var result = myModule.doSomething();
module.exports = {
result,
};
В модулях ECMAScript или ESM это работает следующим образом:
import myModule from "my-module";
export const result = myModule.doSomething();
Если мы хотим использовать ESM, мы должны включить его в package.json
, установив свойство type
в module
.
{
"name": "cli-course",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module"
}
Разбор аргументов
В Node мы можем получить глобальный доступ к переменной process. Если вы выведете на консоль содержимое process
, то увидите много информации. В свойстве argv
вы можете получить доступ к аргументам, переданным скрипту. Например, запуск node index.js
выведет нечто подобное:
console.log(process.argv);
/**
* Output:
* ["/usr/local/bin/node", "/projects/node-cli-course/index.js"]
*/
Как видите, первые два элемента массива — это путь к исполняемому файлу node и путь к сценарию. Если мы передадим команде дополнительные аргументы, они будут добавлены в массив argv
. Например, при выполнении команды node index.js --name=Jose
будет выведено следующее:
["/usr/local/bin/node", "/projects/node-cli-course/index.js", "--name=jose"]
Мы можем легко разобрать флаги, переданные скрипту, проверяя, какие аргументы начинаются с символа -
.
const flags = [];
process.argv.forEach((arg) => {
if (arg.startsWith("-")) {
flags.push(arg.replaceAll("-", ""));
}
});
При использовании команды (node index.js --hi
) массив flags
будет равен ['hi']
.
И тогда мы сможем что-то сделать с флагом.
if (flags.includes("hi")) {
console.log("Hello World!");
}
Чтение пользовательского ввода
Node имеет встроенный модуль для чтения пользовательского ввода под названием Readline.
Для чтения пользовательского ввода мы должны создать новый интерфейс
и связать его с вводом и выводом. В данном случае мы будем использовать стандартный ввод и вывод, который непосредственно доступен в переменной process
. Используя интерфейсный объект, мы можем очень легко задавать вопросы пользователю.
Как только мы закончим, мы должны закрыть интерфейс, чтобы остановить процесс.
import * as readline from "node:readline/promises";
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const answer = await rl.question("What's your name? ");
console.log(`Your name is ${answer}`);
rl.close();
/**
* Output:
* What's your name? Jose
* Your name is Jose
*/
Сделать скрипт глобально исполняемым
Простой способ сделать скрипт глобально исполняемым — создать новый файл, который будет выполнять скрипт.
Имя этого нового файла должно быть таким же, как имя команды. Например, в нашем случае я хочу использовать имя команды cli-course
. Поэтому я создал файл с именем cli-course
, который выполняет файл моего скрипта.
node index.js
А затем запустите chmod +x cli-course
, чтобы сделать новый файл исполняемым.
Наконец, добавьте путь к проекту в переменную окружения PATH
.
export PATH=$PATH:/path/to/project/
Теперь вы можете глобально запустить скрипт, набрав в терминале cli-course
.
$ cli-course
What's your name? Jose
Your name is Jose
Заключение
Следуя этим шагам, вы можете создать базовый инструмент CLI с помощью Node.js. Мы узнали, как выводить текст на консоль, как разбирать аргументы, как читать пользовательский ввод и как сделать скрипт глобально исполняемым.
Если этого недостаточно, вы можете использовать такие библиотеки, как Inquirer.js. С помощью этой библиотеки вы можете:
- предоставлять обратную связь об ошибках
- задавать вопросы
- анализировать ввод
- проверять ответы
- управлять иерархическими подсказками
Вы сами решаете, нужна ли вам внешняя библиотека или нет для вашего инструмента.
Ресурсы
- process — документация по Node.js
- Readline — документация Node.js
- Inquirer.js