Разработка плагина
В данном руководстве рассмотрим основы разработки плагина Runium.
Создадим плагин some-plugin, который:
- будет загружаться Runium
- добавит новый макрос
- добавит хуки проекта
В каком виде существует плагин
Runium умеет загружать плагины двумя способами: как npm-пакеты и как отдельные файлы. Контракт у них одинаковый - меняется только способ доставки модуля.
npm-пакет
Этот вариант подходит для плагина, который планируется переиспользовать, публиковать или устанавливать вместе с зависимостями.
package.json сообщает Node.js формат модуля и указывает точку входа через main. Сначала пакет устанавливается в то же окружение, где установлен Runium, а затем добавляется по имени:
npm install runium-some-plugin
runium plugin add runium-some-pluginЕсли Runium установлен глобально, пакет также должен быть установлен глобально. Для локальной установки оба пакета должны находиться в одном проекте. Подробнее об этом способе подключения см. в руководстве по командам плагинов.
Отдельный файл
Для небольшого локального расширения не обязательно создавать и публиковать пакет. Плагин можно поместить в один файл и подключить напрямую:
runium plugin add --file /absolute/path/to/runium-some-plugin.mjsТакой файл должен иметь расширение .mjs. Runium загружает плагины как ES-модули, а Node.js определяет формат файла по расширению и ближайшему package.json. Для .js результат зависит от значения "type": вне npm-пакета файл может быть ошибочно воспринят как CommonJS. Расширение .mjs однозначно обозначает ES-модуль независимо от каталога и окружающих package.json, поэтому экспорт default будет интерпретирован предсказуемо.
TIP
В этом руководстве создаем npm-пакет: при таком подходе удобнее разделять функционал на несколько файлов и использовать зависимости. При необходимости его собранную точку входа можно распространять отдельно как .mjs.
Подготовка проекта
Для разработки плагина рекомендуется использовать TypeScript и пакет @runium/types-plugin.
TIP
Также описание типов доступно в справочнике Plugin и справочнике глобального объекта runium. Это может полезно при разработке на чистом JavaScript.
Начнем с отдельного npm-пакета:
mkdir runium-some-plugin
cd runium-some-plugin
npm init -y
npm install --save-dev @runium/types-plugin typescript @types/nodeПриведите package.json к следующему виду:
{
"name": "runium-some-plugin",
"version": "1.0.0",
"type": "module",
"main": "dist/index.js",
"scripts": {
"build": "tsc"
},
"keywords": ["runium", "runium-plugin"],
"devDependencies": {
"@runium/types-plugin": "latest",
"@types/node": "latest",
"typescript": "latest"
}
}А рядом создайте tsconfig.json:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"rootDir": "src",
"outDir": "dist",
"strict": true,
"skipLibCheck": true,
"types": ["node", "@runium/types-plugin"]
},
"include": ["src/**/*.ts"]
}Создайте каталог src.
Теперь TypeScript знает о глобальном объекте runium, исходники находятся в src, а готовый ESM-модуль появится в dist.
Шаг 1. Оживляем плагин
Реализуем минимальный модуль, который Runium сможет загрузить и распознать.
Создайте src/index.ts. Плагин экспортирует синхронную фабрику: Runium вызовет ее при старте и получит описание плагин.
import type { Plugin } from '@runium/types-plugin';
export default function (): Plugin {
return {
name: 'some-plugin',
};
}TIP
Подробнее о свойствах возвращаемого объекта можно узнать справочнике.
Пока единственная возможность плагина - сообщить свое имя. Этого уже достаточно, чтобы проверить всю цепочку от TypeScript до Runium:
npm run build
runium plugin add --file ./dist/index.js
runium plugin listРезультат: some-plugin появился в списке плагинов. У нас есть маленькая, но рабочая основа, которую можно развивать.
Шаг 2. Добавляем макрос
Добавим собственный макрос для использования в JSON-конфигурации проекта.
Макрос принимает строки и возвращает строку. Добавим макрос $greet(name), который возвращает приветствие для переданного имени.
import type { Plugin } from '@runium/types-plugin';
export default function (): Plugin {
return {
name: 'some-plugin',
project: {
macros: {
greet(name: string): string {
return `Hello, ${name}!`;
},
},
},
};
}Используем новый макрос в проекте:
{
"id": "example",
"tasks": [
{
"id": "welcome",
"options": {
"command": "echo",
"arguments": ["$greet(Runium)"]
}
}
]
}Результат: перед запуском конфигурации Runium заменяет $greet(Runium) на Hello, Runium!.
Шаг 3. Подключаем хуки проекта
Добавим хуки проекта.
import type { Plugin } from '@runium/types-plugin';
export default function (): Plugin {
return {
name: 'some-plugin',
hooks: {
project: {
async beforeConfigRead(path) {
runium.output.log('Reading config from:', path);
// здесь знаем, какой файл конфигурации будет прочитан
},
async afterConfigRead(content) {
runium.output.log('Config read:', content);
// здесь получаем содержимое файла конфигурации
// можем преобразовать его (например, преобразовать формат из YAML в JSON)
return content;
},
async afterConfigParse(config) {
runium.output.log('Parsed config:', config);
// здесь получаем объект конфигурации
// можем преобразовать его (например, изменить или удалить свойства)
return config;
},
async beforeStart({ name }) {
// здесь проект готов к запуску
// можем, например, подписаться на события изменения состояния задач
runium.output.log('Starting project:', name ?? 'unnamed');
},
},
},
project: {
macros: {
greet(name: string): string {
return `Hello, ${name}!`;
},
},
},
};
}Запустите любой проект Runium, runium project start, чтобы проверить вызов хуков на каждом этапе.
Результат: плагин теперь участвует в жизненном цикле проекта.
Что дальше?
- Справочник по плагину - полный список свойств и методов, которые может возвращать плагин: хуки, макросы, задачи, действия, триггеры и расширение схемы.
- Глобальный объект
runium- описание API, доступного плагину во время выполнения: работа с профилем, вводом-выводом, параметрами запуска и другими возможностями. - Исходный код официальных плагинов на GitHub или GitVerse - здесь можно найти примеры регистрации команд, триггеров, новых типов задач и пр.
