项目数据库 API 让扩展通过稳定契约使用项目数据集合。扩展只认识自己在 manifest 中声明的逻辑别名,不接触项目文件路径或真实集合 id;Studio 负责创建、选择、绑定和版本兼容检查。
声明数据依赖
在 extension.json 的 dataDependencies 中为每项依赖声明别名、契约和版本范围:
{
"id": "example.inventory",
"name": "背包系统",
"version": "1.0.0",
"sdkVersion": "^1.9.8",
"entry": "dist/index.js",
"dataDependencies": {
"items": {
"name": "道具目录",
"description": "背包和商店共同读取的道具定义",
"contract": "community.avg.item-catalog",
"version": "^1.0.0",
"access": "read",
"autoCreate": {
"name": "道具目录",
"contractVersion": "1.0.0",
"runtimePolicy": "readonly",
"schema": {
"type": "object",
"required": ["name", "price"],
"columns": [
{ "key": "name", "label": "名称", "type": "text" },
{ "key": "price", "label": "价格", "type": "number" },
{ "key": "icon", "label": "图标", "type": "image" }
]
}
}
}
}
}
| 字段 | 说明 |
|---|
contract | 社区或团队约定的稳定契约 id |
version | 扩展接受的 semver 范围 |
access | read 或 runtime-write |
optional | 可选依赖;缺失时不阻止扩展继续使用其它能力 |
autoCreate | 缺少兼容集合时的创建模板;设为 false 时必须由创作者手工绑定 |
同一契约可以由多个扩展共享。契约升级时用新的 contractVersion 表示实际创建版本,并让消费方逐步扩大或调整接受范围。
获取集合
在剧本方法或其它已注入上下文的位置,通过依赖别名获取集合:
static listAffordableItems = method({
title: "查询可购买道具",
async run(ctx) {
const items = ctx.database.collection("items");
return items.find(
{ price: { $lte: 100 } },
{ sort: { price: 1 }, limit: 20 },
);
},
});
collection() 接收的是 manifest 中的 items 别名,不是 Studio 数据集合页面里的表名或内部 id。依赖完成绑定后,集合始终可用,不需要连接或关闭数据库。
const items = ctx.database.collection("items");
const one = await items.getById("item-id");
const result = await items.find(
{
$and: [
{ category: "medicine" },
{ price: { $gte: 10, $lte: 100 } },
],
},
{ sort: { price: 1 }, skip: 0, limit: 50 },
);
字段过滤支持 $eq、$ne、$gt、$gte、$lt、$lte、$in、$contains 和 $exists,也可以用 $and / $or 组合。所有方法均为异步 API,不应依赖当前 JSON 文件实现或同步读取项目目录。
新增、更新和删除
需要写入的依赖应声明 access: "runtime-write",数据表运行时策略也必须允许写入:
const inventory = ctx.database.collection("inventory");
const created = await inventory.insertOne({ itemId: "key", count: 1 });
await inventory.updateOne(
{ id: created.id },
{ $inc: { count: 1 }, $set: { equipped: true } },
);
await inventory.deleteOne({ id: created.id });
记录 id 由宿主生成且不可修改。更新操作支持 $set、$unset、$inc、$push 和 $pull;返回值包含命中与实际修改的记录数。
监听变化
const stopWatching = ctx.database.collection("inventory").watch(() => {
// 重新查询并刷新界面
});
// 界面卸载或扩展停止时
stopWatching();
监听器只通知集合有效数据发生变化,不直接携带完整记录。收到通知后重新调用 find(),可以避免事件载荷和当前数据不同步。
运行时策略与权限
| 策略 | 扩展写入结果 |
|---|
readonly | 拒绝运行时写入,只允许查询 |
session | 只保留到本次游戏关闭 |
archive | 保存到当前玩家存档 |
profile | 保存到跨存档共享档案 |
扩展身份彼此隔离,只能通过自己声明并完成绑定的别名访问集合。不要绕过 API 读取 databases/ 文件,也不要假设另一扩展的别名、真实集合 id 或底层存储格式。
删除字段或收窄契约前,先发布兼容迁移并确认所有消费扩展已经升级。Studio 会检查契约版本,但不会替业务数据自动推断复杂迁移规则。
创作者如何建立和维护数据表,见项目数据集合。