插件 API 参考文档
UnityAI-Tauri 插件系统完整 API 参考
概述
插件通过 postMessage 协议与主应用通信。所有消息都遵循统一的格式:
typescript
interface Message {
type: string;
payload?: any;
error?: string;
}认证 API
请求 Token
插件 → 主应用
javascript
window.parent.postMessage({
type: 'request_token'
}, '*');主应用 → 插件
javascript
{
type: 'token_response',
payload: {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
}
}说明:
- Token 是 JWT 格式
- 默认有效期 24 小时
- Token 包含用户 ID 和权限信息
- 过期后需要重新请求
错误响应:
javascript
{
type: 'error',
error: 'User not authenticated'
}数据存储 API
保存数据
插件 → 主应用
javascript
window.parent.postMessage({
type: 'save_data',
payload: {
pluginId: 'your-plugin-id',
key: 'settings',
value: JSON.stringify({ theme: 'dark', language: 'zh-CN' })
}
}, '*');参数:
pluginId(string, 必需): 插件唯一标识符key(string, 必需): 数据键名value(string, 必需): 数据值(必须是字符串,复杂对象需要 JSON.stringify)
主应用 → 插件
javascript
{
type: 'api_response',
payload: {
success: true,
message: 'Data saved successfully'
}
}存储限制:
- 单个 value 建议不超过 1MB
- 总存储空间按用户配额管理
- 数据按
user_id + plugin_id + key隔离
读取数据
插件 → 主应用
javascript
window.parent.postMessage({
type: 'get_data',
payload: {
pluginId: 'your-plugin-id'
}
}, '*');参数:
pluginId(string, 必需): 插件唯一标识符
主应用 → 插件
javascript
{
type: 'api_response',
payload: {
data: {
'settings': '{"theme":"dark","language":"zh-CN"}',
'user_preference': '{"notifications":true}',
'note_123': '{"title":"标题","content":"内容"}'
}
}
}说明:
- 返回该插件的所有数据
- 数据以 key-value 对象形式返回
- value 都是字符串,需要 JSON.parse 解析
删除数据
插件 → 主应用
javascript
window.parent.postMessage({
type: 'api_call',
payload: {
endpoint: `/api/plugins/${pluginId}/data/${key}`,
method: 'DELETE'
}
}, '*');参数:
endpoint(string, 必需): API 端点路径method(string, 必需): HTTP 方法(DELETE)
主应用 → 插件
javascript
{
type: 'api_response',
payload: {
success: true,
message: 'Data deleted successfully'
}
}API 调用
通用 API 调用
插件 → 主应用
javascript
window.parent.postMessage({
type: 'api_call',
payload: {
endpoint: '/api/plugins/your-plugin-id/custom-endpoint',
method: 'POST',
body: {
action: 'process',
data: { foo: 'bar' }
}
}
}, '*');参数:
endpoint(string, 必需): API 端点路径method(string, 必需): HTTP 方法(GET, POST, PUT, DELETE)body(object, 可选): 请求体(仅 POST/PUT)
主应用 → 插件
javascript
{
type: 'api_response',
payload: {
// API 返回的数据
}
}说明:
- 主应用会自动添加 Authorization header
- 请求会通过主应用代理,避免 CORS 问题
- 超时时间 30 秒
支持的端点
获取插件信息
GET /api/plugins/{pluginId}返回插件的详细信息(名称、版本、描述等)。
获取用户插件列表
GET /api/user/plugins返回当前用户已安装的所有插件。
评分插件
POST /api/plugins/{pluginId}/rate
Body: { rating: 5 }为插件评分(1-5 星)。
获取用户评分
GET /api/plugins/{pluginId}/rating获取当前用户对该插件的评分。
错误处理
错误响应格式
javascript
{
type: 'error',
error: 'Error message description'
}常见错误
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
User not authenticated | Token 未获取或已过期 | 重新调用 request_token |
Invalid plugin ID | pluginId 不存在或拼写错误 | 检查 pluginId 是否正确 |
Data too large | 数据超过大小限制 | 分片存储或压缩数据 |
Rate limit exceeded | 请求过于频繁 | 添加防抖或节流 |
Permission denied | 插件权限不足 | 检查插件权限配置 |
错误处理示例
javascript
window.addEventListener('message', (event) => {
const { type, payload, error } = event.data;
if (type === 'error') {
console.error('操作失败:', error);
// 根据错误类型处理
if (error.includes('not authenticated')) {
// 重新认证
requestToken();
} else if (error.includes('Rate limit')) {
// 延迟重试
setTimeout(() => retryOperation(), 5000);
} else {
// 显示错误给用户
showErrorMessage(error);
}
}
});安全最佳实践
1. Origin 验证
生产环境必须验证消息来源:
javascript
window.addEventListener('message', (event) => {
// 只接受来自主应用的消息
if (event.origin !== 'https://app.unityai.com') {
return;
}
// 处理消息
});2. Token 安全
javascript
// ❌ 错误:不要在 localStorage 中存储 Token
localStorage.setItem('token', token);
// ✅ 正确:只在内存中保存
let authToken = null;
window.addEventListener('message', (event) => {
if (event.data.type === 'token_response') {
authToken = event.data.payload.token;
}
});3. 数据验证
javascript
// 保存前验证数据
function saveData(key, value) {
// 验证 key
if (!key || typeof key !== 'string') {
throw new Error('Invalid key');
}
// 验证 value 大小
const valueStr = JSON.stringify(value);
if (valueStr.length > 1024 * 1024) { // 1MB
throw new Error('Data too large');
}
// 保存
window.parent.postMessage({
type: 'save_data',
payload: { pluginId: PLUGIN_ID, key, value: valueStr }
}, '*');
}4. XSS 防护
javascript
// ❌ 错误:直接插入 HTML
element.innerHTML = userInput;
// ✅ 正确:使用 textContent 或转义
element.textContent = userInput;
// 或使用 DOMPurify 清理
element.innerHTML = DOMPurify.sanitize(userInput);性能优化
1. 批量操作
javascript
// ❌ 错误:逐个保存
notes.forEach(note => {
saveData(`note_${note.id}`, JSON.stringify(note));
});
// ✅ 正确:批量保存
const batch = notes.reduce((acc, note) => {
acc[`note_${note.id}`] = JSON.stringify(note);
return acc;
}, {});
// 一次性保存所有数据
Object.entries(batch).forEach(([key, value]) => {
saveData(key, value);
});2. 防抖和节流
javascript
// 防抖:延迟执行
let saveTimeout;
function autoSave(data) {
clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
saveData('draft', JSON.stringify(data));
}, 1000);
}
// 节流:限制频率
let lastSaveTime = 0;
function throttledSave(data) {
const now = Date.now();
if (now - lastSaveTime > 1000) {
saveData('draft', JSON.stringify(data));
lastSaveTime = now;
}
}3. 缓存
javascript
let dataCache = null;
let cacheTime = null;
const CACHE_TTL = 60000; // 1 分钟
function loadData(forceRefresh = false) {
if (!forceRefresh && dataCache && Date.now() - cacheTime < CACHE_TTL) {
return Promise.resolve(dataCache);
}
return new Promise((resolve) => {
window.parent.postMessage({
type: 'get_data',
payload: { pluginId: PLUGIN_ID }
}, '*');
const handler = (event) => {
if (event.data.type === 'api_response') {
dataCache = event.data.payload.data;
cacheTime = Date.now();
window.removeEventListener('message', handler);
resolve(dataCache);
}
};
window.addEventListener('message', handler);
});
}TypeScript 类型定义
typescript
// 消息类型
type MessageType =
| 'request_token'
| 'token_response'
| 'save_data'
| 'get_data'
| 'api_call'
| 'api_response'
| 'error';
// 插件消息
interface PluginMessage {
type: MessageType;
payload?: any;
error?: string;
}
// Token 响应
interface TokenResponse {
type: 'token_response';
payload: {
token: string;
};
}
// 数据保存请求
interface SaveDataRequest {
type: 'save_data';
payload: {
pluginId: string;
key: string;
value: string;
};
}
// 数据读取请求
interface GetDataRequest {
type: 'get_data';
payload: {
pluginId: string;
};
}
// API 调用请求
interface ApiCallRequest {
type: 'api_call';
payload: {
endpoint: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
body?: any;
};
}
// API 响应
interface ApiResponse {
type: 'api_response';
payload: any;
}
// 错误响应
interface ErrorResponse {
type: 'error';
error: string;
}
// 插件信息
interface Plugin {
id: string;
name: string;
description?: string;
version: string;
author?: string;
icon_url?: string;
cloud_url: string;
category?: string;
permissions?: string;
average_rating?: number;
total_ratings: number;
}调试技巧
1. 消息日志
javascript
// 记录所有消息
window.addEventListener('message', (event) => {
console.log('[Plugin Message]', {
origin: event.origin,
type: event.data.type,
payload: event.data.payload,
error: event.data.error
});
});2. 性能监控
javascript
// 监控 API 调用时间
function apiCall(endpoint, method, body) {
const startTime = performance.now();
window.parent.postMessage({
type: 'api_call',
payload: { endpoint, method, body }
}, '*');
const handler = (event) => {
if (event.data.type === 'api_response') {
const duration = performance.now() - startTime;
console.log(`API call to ${endpoint} took ${duration}ms`);
window.removeEventListener('message', handler);
}
};
window.addEventListener('message', handler);
}3. 错误追踪
javascript
// 全局错误处理
window.addEventListener('error', (event) => {
console.error('[Plugin Error]', {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
error: event.error
});
});
// Promise 错误处理
window.addEventListener('unhandledrejection', (event) => {
console.error('[Plugin Promise Rejection]', event.reason);
});版本兼容性
| API | 最低版本 | 说明 |
|---|---|---|
request_token | 1.0.0 | 基础认证 |
save_data | 1.0.0 | 数据存储 |
get_data | 1.0.0 | 数据读取 |
api_call | 1.0.0 | API 调用 |
| 批量删除 | 1.1.0 | 支持批量删除数据 |
| 数据加密 | 1.2.0 | 计划中 |
相关资源
获取帮助
- 技术支持:support@unityai.com
- 开发者社区:https://community.unityai.com
- 问题反馈:https://github.com/unityai/plugins/issues
