EduOpenAI Core 文档/开发一个插件

开发一个插件

manifest → 入口 → API 路由 → UI 挂载

目录结构

plugins/<plugin-id>/
plugins/edu-course/
├── manifest.json     # 声明:id/name/version/minCoreVersion/main/permissions/apiRoutes/dependencies
├── index.ts          # 插件入口:Plugin 对象(manifest + apiHandlers)
├── api/              # API handler(由 apiRoutes 分发)
├── components/       # UI 组件(/admin 或用户端页面挂载)
├── lib/              # 插件内部库(数据/工具)
└── migrations/       # 数据迁移(如需要)

manifest.json

manifest.json
{
  "id": "edu-course",
  "name": "EduOpenAI 课程管理插件",
  "version": "1.0.0",
  "minCoreVersion": "0.3.1",
  "main": "index.ts",
  "permissions": ["course:read", "course:write"],
  "apiRoutes": [
    { "method": "GET", "path": "/v1/classrooms", "handler": "list" }
  ],
  "dependencies": ["edu-storage-aliyun"]
}

插件入口 index.ts

index.ts
import type { Plugin } from "@/lib/plugin";
import { list } from "./api/list";

const plugin: Plugin = {
  manifest: {
    id: "edu-course",
    name: "EduOpenAI 课程管理插件",
    version: "1.0.0",
    minCoreVersion: "0.3.1",
    main: "index.ts",
    permissions: ["course:read", "course:write"],
    apiRoutes: [{ method: "GET", path: "/v1/classrooms", handler: "list" }],
    dependencies: [],
  },
  apiHandlers: { list },
};

export default plugin;

注册插件

在 lib/plugin/bootstrap.ts 静态 import 并 registry.register()(对 Next.js bundling 友好,避免 fs 扫描):

lib/plugin/bootstrap.ts
import eduCourse from "@/plugins/edu-course";

const declaredPlugins: Plugin[] = [eduStorageAliyun, eduCourse /* 新增插件在此追加 */];

// bootstrapPlugins():注册 + 激活,全进程仅执行一次(globalThis 标志防热重载重复初始化)

UI 挂载

  • 管理后台:/admin 页面 import 插件组件(登记 PATCH,待扩展点就绪后回迁)
  • 用户端页面:如 /my-assets(PATCH-019)、/docs(PATCH-023)
  • API:自动挂载至 /api/edu/v1/*(Catch-All 路由按 manifest apiRoutes 分发)
技巧
插件 ID 规则:前缀 edu-,小写短横线连接(禁止驼峰/下划线/大写)。版本 semver 管理,minCoreVersion 运行时校验。