grouparoo 插件加载处理

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

posted on 2022-02-05 21:33  荣锋亮  阅读(34)  评论(0编辑  收藏  举报

导航