Создание и публикация глобального пакета NPM для запуска с помощью CLI


Подход, потребности и реализация нашего пакета для получения света в жизнь!

Привет, Дев,

Вы когда-нибудь сталкивались со сценариями, когда набор функций должен взаимодействовать в нескольких контекстах, таких как веб, мобильный и настольный, или когда приложения A, B или C должны выполнять одни и те же задачи?
Или та знаменитая конфигурация среды, которую нужно повторять в каждом новом проекте, возможно, у вас даже есть репозиторий, содержащий эту конфигурацию, но вы считаете, что она может быть еще более практичной?
Что ж, сегодня мы прокомментируем и создадим именно второй сценарий, при этом стоит добавить, что по сути процесс аналогичен, когда нам нужно удовлетворить первый.

Мы рассмотрим:

  • Почему?
  • Что мы будем делать и как это должно работать
  • Структура
  • Реализация и конфигурация
  • Тестирование на месте
  • Издательство
  • Потребление нашего пакета
  • Наблюдения

Почему?

Стоит отметить, что прежде чем приступить к внедрению, необходимо понять, в каком контексте его следует применять. В нашем случае, учитывая, что мы имеем в качестве функциональности выполнение чего-либо в CLI может иметь несколько причин, среди которых:

  • Выполнение действий в среде;
  • Настройка структуры проектов/папок и ресурсов (очень распространенный и наш случай)

То есть, обычно выполняют какое-то простое и объективное действие для поведения.

Что мы будем делать и как это должно работать

Мы намерены создать простой пакет. Мы хотим выполнить команду A и вместе с ней принести предварительно настроенный проект Nodejs, использующий Express и TypeScript, ничего лишнего. Наша цель здесь — исследовать возможности этой структуры.

Обратите внимание, что наше внимание будет сосредоточено на том, как структурировать наш пакет, поэтому мы не будем рассматривать часть предварительной конфигурации nodejs.

Структура

Мы разделим наш проект на три области, соответственно, директории:

  • project: папка, содержащая наш проект nodejs, который мы будем использовать для того, кто выполнит нашу команду
  • lib: здесь будут находиться файлы, из которых выполняются процессы, которыми обладает наш пакет, то есть здесь будет находиться тот, кто будет отвечать за отправку проекта nodejs запросчику.
  • bin: где будут содержаться файлы, которые должны быть вызваны для выполнения в CLI/терминале. Он, в свою очередь, вызывает скрипты, перечисленные в lib, и использует их, передавая при необходимости параметры.

Реализация и конфигурация

Реализация

Во-первых, давайте создадим файл copyFile.js в нашей папке lib, он должен содержать

const path = require('path');
const fs = require('fs');
const colors = require('colors');
const exec = require('child_process').exec;

exports.copy = (projectName) => {
  console.log(colors.blue('Initializing project...'));

  const projectDir = path.resolve(__dirname, '..', 'project');
  const pathToExecutable = process.cwd();

  const newProjectFolder = path.resolve(pathToExecutable, projectName);
  const existsDirOfProject = fs.existsSync(newProjectFolder); // check if the project already exists

  if (existsDirOfProject) {
    console.log(colors.red('The project already exists'));
    process.exit(1);
  } else {
    fs.mkdirSync(newProjectFolder); // create the project folder
  }

  console.log(colors.blue('Creating project structure...'));
  fs.cpSync(projectDir, newProjectFolder, { recursive: true }); // copy the project folder to the new project folder

  const command = `cd ${newProjectFolder}&&npm install`;
  console.log('--> Executing command: ', command);

  exec(command, (err, stdout, stderr) => {
    if (err) {
      console.log(colors.red(err));
      process.exit(1);
    }
    console.log(colors.green('Project created successfully'));
    console.log(colors.green('Thanks for using the CLI'));
  });
}
Войдите в полноэкранный режим Выход из полноэкранного режима

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

Наше внимание должно быть обращено на следующий файл, в нашей папке bin, где у нас будет index.js:

#!/usr/bin/env node

const colors = require('colors');
const copy = require("../lib/copyFile");

const arguments = process.argv.splice(2);

if (arguments.length === 0) {
  console.log(colors.red("Please provide a project name"));
  process.exit(1);
} else {
  copy.copy(arguments[0]);
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Обратите внимание на первую строку кода. Здесь мы используем shebang, который является ничем иным, как объявлением того, какой компилятор должен интерпретировать наш код. Предполагается, что в Windows нет поддержки этой функции, и именно поэтому NPM позаботится о создании файла .cmd в глобальной папке вашего NPM, чтобы ваша операционная система использовала узел в качестве интерпретатора для нашего сценария.

После импорта библиотек, которые мы будем использовать, обратите внимание, что мы принимаем аргументы с помощью process.argv.splice(2). Получается, что когда наш пользователь выполняет аргумент npx ourPackage, переменная process.argv должна вернуть массив строк, в первой позиции которого будет путь к интерпретатору nodejs, а во второй — путь, по которому выполняется файл.

В данном случае нас интересуют только аргументы, передаваемые команде, которая запускает наш скрипт, этот аргумент идет сразу после цитируемых данных, поэтому мы просто обращаем на них внимание.

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

Просто, не так ли?

Конфигурация

Здесь нам нужно настроить наш package.json. Следуйте за нитью:

{
  "name": "basic-node-ts-config",
  "version": "1.0.0",
  "description": "Configuração básica para um ambiente de desenvolvimento com NodeJs + TypeScript",
  "main": "./lib/copyFile.js",
  "preferGlobal": true,
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "bin": {
    "create-node-basic": "./bin/index.js"
  },
  "keywords": [
    "node",
    "typescript",
    "config"
  ],
  "author": "Mateus Cardoso dos Santos",
  "license": "ISC",
  "dependencies": {
    "colors": "^1.4.0"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mugarate12/basic-node-ts-config.git"
  },
  "bugs": {
    "url": "https://github.com/mugarate12/basic-node-ts-config/issues"
  },
  "homepage": "https://github.com/mugarate12/basic-node-ts-config"
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Мы выделим три свойства:

  • main: здесь интересно иметь наш файл, из которого экспортируются все функции нашего проекта, и это имеет важный фактор: NPM не препятствует установке нашего пакета локально, поэтому в main мы должны сообщить, какой файл имеет функциональные возможности, даже если это не наша цель, чтобы он использовался таким образом.
  • preferGlobal: Как уже говорилось, NPM не препятствует установке нашего пакета локально, однако мы можем указать, что мы предпочитаем, чтобы пакет был глобальным. Это по-прежнему не предотвратит локальную установку, но выдаст предупреждение о том, что мы предпочитаем использовать его иначе.
  • bin: Здесь мы указываем команды и скрипты, которые должны быть ими выполнены. Как вы могли заметить, это должны быть скрипты, которые будут выполняться в терминале, поэтому давайте убедимся, что мы правильно указали то, что нам нужно.

Тестирование на месте

Конечно, будет полезно протестировать наш пакет локально перед его публикацией, и для этого в NPM есть очень интересная функция. Просто запустите обычную установку, используя флаг -g, указывающий на каталог, а точнее, на наш проект. Это установит наш пакет глобально, и он будет доступен для тестирования нашей команды.

npm install -g path/to/project
Войдите в полноэкранный режим Выход из полноэкранного режима

Стоит также сказать, что после того, как мы это сделали, нет необходимости устанавливать этот пакет снова, если мы что-то изменим в проекте. Наш менеджер пакетов создаст связь между нашим локальным каталогом и установкой пакета, и нам останется только беспокоиться о разработке.

Если предположить, что речь идет о нашем проекте, мы могли бы провести тестирование с помощью:

create-node-basic [NOME_DO_PROJETO]
Войдите в полноэкранный режим Выход из полноэкранного режима

Издательство

Наконец, мы подошли к последним шагам!
Я упомяну только сам процесс, потому что он довольно прост, но нам нужно иметь в виду пару моментов. Шаги таковы:

  • Создайте учетную запись на NPM и подтвердите ее по электронной почте.
  • Войдите в свой аккаунт, выполнив a:
npm login
Войдите в полноэкранный режим Выход из полноэкранного режима
  • Если все прошло успешно, приведенная ниже команда должна вернуть ваше имя пользователя:
npm whoami
Войдите в полноэкранный режим Выход из полноэкранного режима
  • Когда все будет выровнено, опубликуйте пакет с:
npm publish
Войдите в полноэкранный режим Выход из полноэкранного режима

И это все! Наш проект опубликован!

Использование нашего пакета

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

npm install -g [NOME_DO_PACOTE]
Войдите в полноэкранный режим Выход из полноэкранного режима
create-node-basic [NOME_DO_PROJETO]
Войдите в полноэкранный режим Выход из полноэкранного режима

Или мы можем использовать для этого npx, что будет:

npx create-node-basic [NOME_DO_PROJETO]
Войдите в полноэкранный режим Выход из полноэкранного режима

Примечания

  • Есть очень важная деталь, которую следует упомянуть: если мы публикуем пакет для изучения и тестирования, мы должны удалить его из NPM в течение 72 часов. Это связано с тем, что по истечении этого срока удалить его будет невозможно.
  • Нашей главной целью было изучить, как эта функция может помочь нам в n-ых сценариях, поэтому, пожалуйста, добавьте свои наблюдения, критику и комментарии, если вы считаете это необходимым.
  • Создайте файл .gitignore и файл .npmignore, они оба выполняют одну и ту же функцию, каждый для своей платформы.
  • Репозиторий: https://github.com/mugarate12/basic-node-ts-config

Спасибо за внимание, обнимаю!

Оцените статью
devanswers.ru
Добавить комментарий