主题
发布 / 上传 / 安装
Mods 站点(https://mods-findor-cheat.pages.dev)同时承担两个角色:静态种子仓库 与 上传接口(Cloudflare KV)。
数据来源一览
| 来源 | 地址 | 内容 |
|---|---|---|
| 种子注册表 | GET /registry.json | 官方种子 Mod 的元数据(静态文件,随站点部署) |
| 种子 manifest | GET /mods/<id>/manifest.json | 种子 Mod 的 manifest |
| 种子代码 | GET /mods/<id>/<main> | 种子 Mod 的代码 |
| 上传列表 | GET /api/list-mods | 通过接口上传的 Mod 元数据(KV) |
| 上传 | POST /api/upload-mod | 写入 KV:mod:<id> + 追加 index |
| 删除 | POST /api/delete-mod | 需管理员 token |
客户端浏览页的列表 = registry.json + /api/list-mods 的并集(按 id 去重,种子优先)。
为什么要有并集
上传的 Mod 只存在 KV 里,不会写进 registry.json。如果只读 registry.json,别人上传的 Mod 在浏览页里永远看不到。
方式一:作为种子 Mod 发布
- 在仓库新建
mods/<id>/,放入index.js(或manifest.main指定的文件)与manifest.json - 在根目录
registry.json的mods数组里追加一条元数据(id/name/version/author/description/tags) - 部署站点(Cloudflare Pages)。客户端即可在浏览页看到并安装
mods/
├── hello-world/
│ ├── manifest.json
│ └── index.js
└── your-mod/
├── manifest.json
└── index.js
registry.json
functions/api/{upload-mod,list-mods,delete-mod}.js
wrangler.toml # [[kv_namespaces]] binding = "MODS_REGISTRY"方式二:通过接口上传
在 Mods → 上传 Mod 表单里填写:
| 字段 | 必填 | 说明 |
|---|---|---|
id | ✅ | 仅 a-z 0-9 -,首字符为字母或数字 |
name | ✅ | 显示名 |
url | ✅ | 必须是 http(s):// 开头的代码地址(KV 只存元数据,不存代码) |
version | 默认 1.0.0 | |
description | 说明 | |
author | 默认 anonymous | |
tags | 逗号分隔或数组 | |
hash | 可选校验值 | |
permissions | 声明式能力列表 |
请求示例:
bash
curl -X POST https://mods-findor-cheat.pages.dev/api/upload-mod \
-H 'Content-Type: application/json' \
-d '{"id":"my-mod","name":"我的 Mod","version":"1.0.0","url":"https://example.com/my-mod.js","author":"me"}'响应:
| 状态 | 含义 |
|---|---|
200 { ok: true, mod } | 成功 |
400 | 缺少 id / name / url,或 id 格式非法,或 url 不以 http(s):// 开头 |
409 { error: 'Mod already exists', existing } | 该 id 已存在 |
500 { error: 'KV binding missing (MODS_REGISTRY)' } | 部署缺少 KV 绑定 |
上传后的安装流程(客户端):
- 从
/api/list-mods拿到元数据(含url) - 尝试
GET /mods/<id>/manifest.json;404 时用上传元数据合成 manifest,main即上传的url - 拉取代码:
main是绝对 URL 就直连,否则走/mods/<id>/<main> - 缓存到 IndexedDB → 记录到已安装 → 加载并启用(启用失败会回滚安装)
方式三:云端托管(Supabase Storage)— 推荐
不需要你自备外链:在 UI 里选择代码文件(或直接粘贴代码)提交,服务端会把代码写进 Supabase Storage 的公开 bucket:
mods/<id>/manifest.json 元数据(公开可读)
mods/<id>/index.js Mod 代码(公开可读)- 客户端安装时直接下载公开 URL,不需要任何密钥
- 列表接口
/api/list-mods会合并「云端(Supabase)」与「KV(历史上的外链记录)」,并返回sources: { cloud, kv } - 删除时
/api/delete-mod会同时清理 KV 记录与 Storage 里的mods/<id>/全部对象
安全模型(为什么密钥不在客户端)
| 操作 | 用 publishable key | 用 secret key |
|---|---|---|
| 下载公开对象 | ✅ | ✅ |
| 上传对象 | ❌ 403 new row violates row-level security policy | ✅ |
| 列出对象 | ❌ 返回空数组 | ✅ |
因此 secret key 只存在于服务端环境变量(Cloudflare Pages 的 SUPABASE_URL / SUPABASE_SECRET_KEY),浏览器里永远没有它;客户端只与 /api/upload-mod 通信。请勿把 secret key 写进任何前端代码或公开仓库。
上传请求(代码托管模式)
bash
curl -X POST https://mods-findor-cheat.pages.dev/api/upload-mod \
-H 'Content-Type: application/json' \
-d '{
"id": "my-mod",
"name": "我的 Mod",
"version": "1.0.0",
"author": "me",
"description": "示例",
"tags": ["示例"],
"file": "index.js",
"code": "export function onEnable(ctx){ ctx.ui.notify(\"hi\"); }"
}'也可以用 codeBase64 传 base64 编码后的代码。响应中 mod.url 就是云端的公开下载地址,cloud: true 表示走了云端托管。
上传请求(外链模式)
仍然支持旧行为:只提交元数据 + url(代码放在你自己的服务器上),此时只写 KV。
bash
curl -X POST https://mods-findor-cheat.pages.dev/api/delete-mod \
-H 'Content-Type: application/json' \
-d '{"id":"my-mod","token":"<ADMIN_TOKEN>"}'ADMIN_TOKEN 是 Pages 项目的环境变量;未配置或 token 不匹配返回 401。
本地更新已安装的 Mod
version 变化时,加载器会把代码缓存按版本区分(缓存键含 version),重新安装/更新即可拉到新代码。手动刷新浏览列表:
js
await findorCheat.modLoader.refreshRegistry(); // 同时刷新 registry.json 与 /api/list-mods
findorCheat.modLoader.listAvailable().map(m => m.id);下一步:示例 hello-world · 常见问题排查