Storage API
Storage API
概述
插件存储 SDK 提供两类能力:
- 文件型持久化存储(
usePluginStorage) - SQLite 结构化存储(
usePluginSqlite,需sdkapi >= 260215)
介绍
快速开始
import { usePluginStorage } from '@talex-touch/utils/plugin/sdk'
const storage = usePluginStorage()
// 保存配置
await storage.setFile('settings.json', { theme: 'dark', fontSize: 14 })
// 读取配置
const settings = await storage.getFile('settings.json')
console.log(settings) // { theme: 'dark', fontSize: 14 }
SQLite 快速开始(结构化数据)
import { usePluginSqlite } from '@talex-touch/utils/plugin/sdk'
const sqlite = usePluginSqlite()
await sqlite.execute(
'CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, done INTEGER NOT NULL DEFAULT 0)'
)
await sqlite.execute('INSERT INTO todos (title, done) VALUES (?, ?)', ['Write docs', 0])
const result = await sqlite.query<{ id: number; title: string; done: number }>(
'SELECT id, title, done FROM todos ORDER BY id DESC LIMIT 20'
)
console.log(result.rows)
容量限制
- 每个插件 10MB,超出后写入会被拒绝
- 数据存储在
<userData>/config/plugins/<pluginName>/目录下 - 系统自动处理文件名清理,防止路径遍历攻击
SQLite 权限要求
使用 usePluginSqlite() 时,插件 manifest 必须声明:
{
"sdkapi": 260428,
"permissions": {
"required": ["storage.sqlite"],
"optional": []
},
"permissionReasons": {
"storage.sqlite": "将插件业务数据存储到本地 SQLite 数据库"
}
}
API 参考
获取 Storage 实例
import { usePluginStorage } from '@talex-touch/utils/plugin/sdk'
const storage = usePluginStorage()
注意:必须在插件渲染器上下文中调用。
文件操作
getFile(fileName)
读取存储文件内容。
const config = await storage.getFile('config.json')
// 如果文件不存在,返回 null
| 参数 | 类型 | 说明 |
|---|---|---|
fileName | string | 文件名(支持子目录如 data/cache.json) |
| 返回值 | Promise<any> | 文件内容(自动 JSON 解析),不存在返回 null |
setFile(fileName, content)
写入存储文件。
await storage.setFile('settings.json', {
theme: 'dark',
shortcuts: ['Cmd+K']
})
// 返回 { success: true }
| 参数 | 类型 | 说明 |
|---|---|---|
fileName | string | 文件名 |
content | any | 要存储的内容(自动 JSON 序列化) |
| 返回值 | Promise<{ success: boolean, error?: string }> | 操作结果 |
deleteFile(fileName)
删除存储文件。
await storage.deleteFile('old-cache.json')
listFiles()
列出插件所有存储文件。
const files = await storage.listFiles()
// ['settings.json', 'data/cache.json']
clearAll()
清空插件所有存储数据。
await storage.clearAll()
// ⚠️ 此操作不可逆
SQLite 操作
execute(sql, params?)
执行插入/更新/删除/DDL 语句。
query<T>(sql, params?)
执行查询语句并返回类型化行数据。
transaction(statements)
在一个事务中执行多条语句(全成功或全回滚)。
const sqlite = usePluginSqlite()
await sqlite.transaction([
{
sql: 'INSERT INTO todos (title, done) VALUES (?, ?)',
params: ['A', 0]
},
{
sql: 'INSERT INTO todos (title, done) VALUES (?, ?)',
params: ['B', 0]
}
])
高级功能
getStats()
获取存储统计信息。
const stats = await storage.getStats()
// {
// totalSize: 1024, // 总大小(字节)
// fileCount: 3, // 文件数量
// limit: 10485760, // 容量限制(10MB)
// usagePercent: 0.01 // 使用率
// }
getTree()
获取存储目录树结构。
const tree = await storage.getTree()
// [
// { name: 'settings.json', type: 'file', size: 256 },
// { name: 'data', type: 'directory', children: [...] }
// ]
getFileDetails(fileName)
获取文件详细信息。
const details = await storage.getFileDetails('settings.json')
// {
// name: 'settings.json',
// size: 256,
// createdAt: 1702123456789,
// modifiedAt: 1702123456789
// }
openFolder()
在系统文件管理器中打开插件存储目录。
await storage.openFolder()
// 打开 Finder/Explorer
监听变更
监听存储文件的变化,适用于多窗口同步场景。
const unsubscribe = storage.onDidChange('settings.json', (data) => {
console.log('配置已更新:', data)
// 重新加载配置
})
// 停止监听
unsubscribe()
技术原理
- 数据以文件形式保存在插件独立目录中,避免跨插件访问。
- 写入时自动进行文件名清理与 JSON 序列化,降低安全风险。
- SQLite 数据文件位于
<userData>/modules/plugins/<pluginName>/data/plugin-sdk.sqlite。
最佳实践
1. 结构化配置管理
interface PluginSettings {
theme: 'light' | 'dark'
language: string
shortcuts: Record<string, string>
}
async function loadSettings(): Promise<PluginSettings> {
const defaults: PluginSettings = {
theme: 'dark',
language: 'zh-CN',
shortcuts: {}
}
const saved = await storage.getFile('settings.json')
return { ...defaults, ...saved }
}
async function saveSettings(settings: PluginSettings) {
await storage.setFile('settings.json', settings)
}
2. 缓存过期处理
interface CacheEntry<T> {
data: T
expiresAt: number
}
async function getCached<T>(key: string): Promise<T | null> {
const entry = await storage.getFile(`cache/${key}.json`) as CacheEntry<T> | null
if (!entry) return null
if (Date.now() > entry.expiresAt) {
await storage.deleteFile(`cache/${key}.json`)
return null
}
return entry.data
}
async function setCache<T>(key: string, data: T, ttlMs: number = 3600000) {
const entry: CacheEntry<T> = {
data,
expiresAt: Date.now() + ttlMs
}
await storage.setFile(`cache/${key}.json`, entry)
}
3. 容量监控
async function checkStorageQuota() {
const stats = await storage.getStats()
if (stats.usagePercent > 0.8) {
console.warn('[Plugin] 存储空间使用超过 80%,考虑清理旧数据')
// 清理过期缓存
await cleanExpiredCache()
}
}
调试技巧
- 查看当前存储内容:使用
openFolder()直接查看文件 - DevTools 调试:
pnpm core:dev模式下会在 Console 打印存储变更日志 - IPC 命令:使用
plugin:storage:get-file直接查询
类型定义
interface StorageStats {
totalSize: number
fileCount: number
limit: number
usagePercent: number
}
interface StorageTreeNode {
name: string
type: 'file' | 'directory'
size?: number
children?: StorageTreeNode[]
}
interface FileDetails {
name: string
size: number
createdAt: number
modifiedAt: number
}