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 运行时校验。
