TauriTavern/docs/API/Extension.md

140 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `window.__TAURITAVERN__.api.extension.store` — API 参考
TauriTavern 为第三方扩展提供的**全局**持久化能力,可选KV JSON 与 Blob 两种数据形态。
数据存储在 `data_root/_tauritavern/extension-store/` 下,可随数据根目录一起备份/迁移/清理。
## 0. 快速上手
```js
await (window.__TAURITAVERN__?.ready ?? window.__TAURITAVERN_MAIN_READY__);
const store = window.__TAURITAVERN__.api.extension.store;
```
### KV JSON 存储
```js
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`。
```js
await store.setJson({
namespace: 'my-ext',
table: 'index',
key: 'v1',
value: { lastId: 42 },
});
const tables = await store.listTables({ namespace: 'my-ext' });
```
### Blob 存储
```js
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()` 逐块读取;提前停止时应取消流:
```js
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()` 读取。