RaisFastRaisFast
Plugins

Manifest 参考

完整的 manifest.toml Schema — 插件信息、权限、Hook、路由、定时任务、依赖。

每个插件都有一个 manifest.toml,定义插件的身份、权限、Hook、路由和定时任务。

[plugin] — 插件身份

[plugin]
id = "com.example.my-plugin"
name = "My Plugin"
version = "0.1.0"
description = "Does something useful"
author = "Alice"
license = "MIT"
runtime = "js"
entry = "main.js"
字段必填默认值说明
id唯一插件 ID(建议反向域名格式)
name显示名称
version语义版本号
description""描述
author作者
license许可证
runtime"wasm"运行时:js / lua / rhai / wasm
language"rust"语言标识
entry"index.js"入口文件名
wasm"plugin.wasm"WASM 文件路径(仅 runtime = wasm)
sdk_version"v1"SDK 版本

自动检测:runtime = "lua" 且未设置 entry 时,加载器查找 init.luaruntime = "rhai" 时查找 init.rhai

[permissions] — 安全控制

除非显式声明,否则一律拒绝访问。

[permissions]
max_memory_mb = 16
timeout_ms = 5000
database = ["read:products", "write:orders", "categories"]
http = ["api.example.com", "*.github.com"]
config = ["app.*", "jwt.*"]
filesystem = ["read-write"]
字段默认值说明
max_memory_mb32(配置默认)单实例内存上限
timeout_ms配置默认值Hook 执行超时
database[](禁止)数据库表访问权限
http[](禁止)HTTP 白名单
config[](禁止)配置键白名单
filesystem[](禁止)VFS 访问级别

数据库权限

格式权限
"read:TABLE"只读
"write:TABLE"只写
"TABLE"读写
"*"所有表(受保护表除外)

受保护表即使声明 "*" 也不可访问:usersrolespermissionsaudit_logplugin_storageoptionsrbac_rolesrbac_permissionsrbac_role_permissionstenants

SQL 安全:DDL 被阻止(CREATE/DROP/ALTER/TRUNCATE)。UNION、JOIN 和子查询在权限检查中被检测并阻止。

HTTP 白名单

  • 精确域名:api.example.com
  • 通配符子域:*.github.com
  • 路径通配:api.example.com/v1/*

内置 SSRF 防护:阻止 localhost、127.x、10.x、172.16-31.x、192.168.x、169.254.x、::1。

文件系统权限

启用
"read"vfsReadvfsExistsvfsListvfsStat
"write"vfsWritevfsDelete
"read-write"所有 VFS 操作
"*"所有 VFS 操作

[hooks.<name>] — Hook 注册

[hooks.on-content-created]
priority = 50

[hooks.on-content-updating]
priority = 100
match = "product"

[hooks.on-content-updating]
priority = 100
content_types = ["product", "course"]

[hooks.render-markdown]
priority = 10
字段默认值说明
priority100执行顺序(数字越小越先执行)
match按 Content Type 名称匹配
content_types[](全部)仅对指定的 Content Type 触发

Hook 名使用连字符(on-content-created),系统自动转换为下划线(on_content_created)。

[[routes]] — 自定义 API 端点

[[routes]]
method = "GET"
path = "/api/v1/plugins/my-plugin/stats"
handler = "getStats"
auth = "public"

[[routes]]
method = "POST"
path = "/api/v1/plugins/my-plugin/contacts/:contactId"
handler = "updateContact"
auth = "admin"
description = "Update a contact"
字段必填默认说明
methodHTTP 方法
path路由路径,支持 :param 占位符
handler插件中的函数名
authdefaultpublic / member / admin
description描述
permission额外权限要求

处理函数接收 input,包含 { path, method, body, headers, params }。直接返回数据,框架自动包装为 { code: 0, data: ... }

路由输入参数

[[routes]]
method = "POST"
path = "/api/v1/plugins/my-plugin/deals"
handler = "createDeal"

[[routes.input]]
name = "title"
type = "string"
in = "body"
required = true
description = "Deal title"

[[routes.input]]
name = "page"
type = "integer"
in = "query"
default = 1
description = "Page number"
字段必填默认说明
name参数名
in"query"位置:query / body / path / header
type""类型提示
requiredfalse是否必填
description描述
default默认值

路由输出

[routes.output]
description = "Deal list"

[[routes.output.fields]]
name = "id"
type = "string"
description = "Deal ID"

[[routes.output.fields]]
name = "title"
type = "string"
description = "Deal title"

[[cron]] — 定时任务

[[cron]]
label = "Daily Cleanup"
job_type = "daily_cleanup"
cron_expr = "0 0 * * *"
payload = """{"type": "full"}"""
enabled = true
字段必填默认说明
label任务名称
job_type任务类型(传给 on_cron_tick
cron_exprCron 表达式(七段,含秒)
payloadJSON 负载字符串
enabledtrue是否启用

Cron 条目在插件加载时同步到数据库,卸载时移除。

[[content_types]] — 捆绑 Content Type

[[content_types]]
file = "content_types/contact.toml"

插件可以自带 Content Type TOML 文件,安装时自动加载。

[[admin_pages]] — 管理后台页面

[[admin_pages]]
path = "/admin/plugins/crm"
label = "CRM"
icon = "users"
component = "CrmDashboard"
字段必填说明
path页面路径
label显示名称
icon图标名
component前端组件名

[dependencies] — 插件依赖

[dependencies]
"com.example.base" = "1.0.0"

插件按拓扑排序加载,确保依赖先初始化。

完整示例

[plugin]
id = "com.example.crm"
name = "CRM API"
version = "0.1.0"
description = "Sales pipeline and contact management"
author = "Alice"
license = "MIT"
runtime = "js"
entry = "main.js"

[permissions]
max_memory_mb = 16
timeout_ms = 5000
database = ["crm_contacts", "crm_companies", "crm_deals"]
http = ["api.example.com"]
config = ["app.*"]
filesystem = ["read-write"]

[hooks.on-content-created]
priority = 50

[hooks.on-content-updating]
priority = 100
content_types = ["contact"]

[hooks.render-markdown]
priority = 10

[[routes]]
method = "GET"
path = "/api/v1/plugins/crm/pipeline"
handler = "getPipeline"
auth = "public"

[[routes]]
method = "GET"
path = "/api/v1/plugins/crm/pipeline/:dealId"
handler = "getDealDetail"
auth = "member"

[[cron]]
label = "Daily Stats"
job_type = "daily_stats"
cron_expr = "0 0 * * *"
payload = """{"type": "full"}"""

[dependencies]
"com.example.base" = "1.0.0"

On this page