TauriTavern/docs/API/Extension.md

5.7 KiB
Raw Blame History

window.__TAURITAVERN__.api.extension.store — API 参考

TauriTavern 为第三方扩展提供的全局持久化能力,可选KV JSON 与 Blob 两种数据形态。

数据存储在 data_root/_tauritavern/extension-store/ 下,可随数据根目录一起备份/迁移/清理。

0. 快速上手

await (window.__TAURITAVERN__?.ready ?? window.__TAURITAVERN_MAIN_READY__);
const store = window.__TAURITAVERN__.api.extension.store;

KV JSON 存储

await store.setJson({ namespace: 'my-ext', key: 'settings', value: { enabled: true } });
const settings = await store.getJson({ namespace: 'my-ext', key: 'settings' });

const maybeSettings = await store.tryGetJson({ namespace: 'my-ext', key: 'settings' });
if (!maybeSettings.found) {
  // Use in-code defaults; write only when the user changes settings.
}

JSON 多表(额外 json / table)

不提供 table 时默认使用主表 main。

await store.setJson({
  namespace: 'my-ext',
  table: 'index',
  key: 'v1',
  value: { lastId: 42 },
});

const tables = await store.listTables({ namespace: 'my-ext' });

Blob 存储

await store.setBlob({
  namespace: 'my-ext',
  key: 'icon.png',
  data: myBlob, // Blob | ArrayBuffer | Uint8Array | base64 string
});

const blob = await store.getBlob({ namespace: 'my-ext', key: 'icon.png' });

大文件可用 getBlobStream() 逐块读取;提前停止时应取消流:

const stream = await store.getBlobStream({ namespace: 'my-ext', key: 'archive.bin' });
await stream.pipeTo(destination); // destination 是调用方的 WritableStream

1. KV JSON 方法

所有 KV 方法都支持可选 table 字段:

  • 省略:使用默认主表 main
  • 指定:将数据写入对应 table

什么时候用 KV JSON?

建议绝大多数情况下使用KV JSON,把它当作“扩展的结构化数据存储”:

  • 扩展设置(settings / feature flags)
  • 索引、映射表、状态快照(index / map / progress)
  • 需要 updateJson() 深度合并对象的场景
方法 返回值 说明
getJson({ namespace, key, table? }) Promise<any> 读取 JSON 值
tryGetJson({ namespace, key, table? }) Promise<{ found: boolean; value?: any }> 可选读取;key 不存在时返回 { found: false },其他错误仍抛出
setJson({ namespace, key, value, table? }) Promise<void> 写入 JSON 值(覆盖)
updateJson({ namespace, key, value, table? }) Promise<void> 合并更新:对象会深度合并;非对象直接替换
renameKey({ namespace, key, newKey, table? }) Promise<void> 重命名 key
deleteJson({ namespace, key, table? }) Promise<void> 删除 key
listKeys({ namespace, table? }) Promise<string[]> 列出 table 下所有 key
listTables({ namespace }) Promise<string[]> 列出现有 table(KV 与 Blob 的 union)
deleteTable({ namespace, table }) Promise<void> 删除 table(同时删除该 table 下的 KV 与 Blob)

兼容:updateJSON() 是 updateJson() 的别名;updateKey() 是 renameKey() 的别名。

2. Blob 方法

什么时候用 Blob?

存大型文件时,需要时再用:

  • 图片/音频/压缩包/模型文件等二进制
  • 体积较大、不希望浪费 JSON 格式化算力的内容(例如大段纯文本缓存)
  • 需要直接喂给 Web API 的场景(返回值是 Blob,可 URL.createObjectURL())
方法 返回值 说明
getBlob({ namespace, key, table? }) Promise<Blob> 读取 blob(文件类型 mimeType 基于 key 文件扩展名猜测)
getBlobStream({ namespace, key, table? }) Promise<ReadableStream<Uint8Array>> 按消费速度读取原始字节;取消会关闭 reader
setBlob({ namespace, key, data, table? }) Promise<void> 写入 blob,允许空内容
deleteBlob({ namespace, key, table? }) Promise<void> 删除 blob
listBlobKeys({ namespace, table? }) Promise<string[]> 列出 table 下所有 blob key

3. 命名规则(namespace / table / key)

  • 仅允许字符:[A-Za-z0-9_.-]
  • 不能为空
  • 不能以 . 开头
  • . / .. 不被允许

4. table (多表)的语义

table 是逻辑分组:方便把同一扩展的不同数据域分开放、以及一键清理某个分组(deleteTable)。

当前实现中:

  • 每个 (namespace, table, key) 都是一个独立文件
  • KV JSON:.../kv/<table>/<key>.json
  • Blob:.../blobs/<table>/<key>(原样文件名,不强制扩展名)

示例(以 my-ext 为例):

  • setJson({ namespace: 'my-ext', key: 'settings', value })
    • 存储在data_root/_tauritavern/extension-store/my-ext/kv/main/settings.json
  • setJson({ namespace: 'my-ext', table: 'index', key: 'v1', value })
    • 存储在data_root/_tauritavern/extension-store/my-ext/kv/index/v1.json
  • setBlob({ namespace: 'my-ext', key: 'icon.png', data })
    • 存储在data_root/_tauritavern/extension-store/my-ext/blobs/main/icon.png

小型整体状态可以使用固定 key;持续增长的数据应拆成多个 key,按需读取。

5. 读写边界

  • 写入保存调用时快照,以单文件原子替换发布;失败不暴露部分内容,不承诺断电持久化。页面重载前应等待需要确认的写入完成。
  • 并发修改按发布顺序生效;updateJson() 的读取、合并和发布作为一次原子更新。删除不取消在途写入,没有跨 key 事务。
  • 已打开的读取保持原文件版本,不受后续覆盖或删除影响。
  • getJson() / getBlob() 返回完整值;JSON 写入和 base64 输入仍有整份数据的内存成本。大型二进制优先使用 Blob 写入和 getBlobStream() 读取。