grouparoo 的插件处理与actionhero 是一致的,只是grouparoo增强扩展了下,支持了插件的自动加载以及reload
参考处理机制
core/src/initializers/plugins.ts 参考代码(主要是核心插件以及UI)
async initialize() {
api.plugins = {
plugins: [],
persistentConnections: {},
validate: this.validatePlugin,
register: this.registerPlugin,
announcePlugins: this.announcePlugins,
templates: this.templates,
};
this.checkPluginEnvironmentVariables();
// --- Add the core plugins --- //
plugin.registerPlugin({
name: "@grouparoo/core",
icon: "/public/@grouparoo/logo.png",
templates: [
SettingTemplate,
ModelTemplate,
GroupTemplate,
ApiKeyTemplate,
TeamTemplate,
TeamMemberTemplate,
],
});
// --- Add the UI pLugin --- //
const pluginManifest = getPluginManifest();
const uiPlugins = pluginManifest.plugins
.filter((p) => p.name.match(/^@grouparoo\/ui-/))
.sort((p) => (p.name.match("config") ? 1 : -1));
if (uiPlugins) {
const relevantUiPlugin =
uiPlugins[
getGrouparooRunMode() === "cli:config" ? uiPlugins.length - 1 : 0
];
if (relevantUiPlugin) {
// 注册插件
this.registerPlugin({
name: relevantUiPlugin.name,
icon: "/public/@grouparoo/logo.png",
});
process.env.GROUPAROO_UI_EDITION = relevantUiPlugin.name.replace(
"@grouparoo/ui-",
""
);
}
}
}
core/src/config/plugins.ts 标准加载入口(actionhero 标准插件注册地方)
因为actionhero restart的时候,配置也会重新加载所以我们的插件配置也是可以直接加载的
import { PluginConfig } from "actionhero";
import path from "path";
import { getPluginManifest } from "../modules/pluginDetails"; // pluginDetails 模块实现了,自定义模块的加载
import InjectedPlugins from "./pluginInjection";
const namespace = "plugins";
const pluginManifestNamespace = "pluginManifest";
declare module "actionhero" {
export interface ActionheroConfigInterface {
[namespace]: ReturnType<typeof DEFAULT[typeof namespace]>;
}
export interface ActionheroConfigInterface {
[pluginManifestNamespace]: ReturnType<
typeof DEFAULT[typeof pluginManifestNamespace]
>;
}
}
function getPluginPath(pluginName: string) {
return path.join(
path.dirname(require.resolve(`${pluginName}/package.json`)),
"..",
pluginName
);
}
const pluginManifest = getPluginManifest();
const parentPlugins: Record<string, { path: string }> = {};
pluginManifest.plugins.map((p) => {
parentPlugins[p.name] = { path: p.path };
});
pluginManifest.missingPlugins.map((p) => {
console.error(`*** Could not find plugin named ${p} ***`);
});
export const DEFAULT = {
[namespace]: () => {
const plugins = Object.assign(
{
"ah-sequelize-plugin": { path: getPluginPath("ah-sequelize-plugin") },
},
parentPlugins,
InjectedPlugins
);
return plugins;
},
pluginManifest: () => {
return {
url:
process.env.GROUPAROO_PLUGIN_MANIFEST_URL ||
"https://www.grouparoo.com/plugins/v1/manifest.json",
};
},
};
- pluginDetails 插件加载格式
会加载package.json 部分的
{
"author": "Grouparoo Inc <hello@grouparoo.com>",
"name": "@grouparoo/example-app",
"description": "A Grouparoo Example Application",
"version": "0.1.0",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@grouparoo/core": "1.0.0",
"@grouparoo/awesome-plugin": "1.0.0"
},
"scripts": {
"start": "cd node_modules/@grouparoo/core && ./bin/start",
"dev": "cd node_modules/@grouparoo/core && ./bin/dev"
},
// 插件加载地方,当然也可以通过dependencies以及devDependencies模式加载
"grouparoo": {
"plugins": ["@grouparoo/awesome-plugin"] // <--- HERE
}
}
说明
grouparoo 包装plugin的模式还是很值得学习参考的,实现了插件的动态处理,但是核心来说还是actionhero比较灵活
参考资料
https://www.grouparoo.com/docs/development/plugins
https://github.com/grouparoo/grouparoo