@seaverse/auth-sdk 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +555 -210
- package/dist/auth-modal.css +1 -1
- package/dist/index.cjs +63 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +34 -5
- package/dist/index.js +63 -35
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,103 +1,230 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @seaverse/auth-sdk
|
|
2
2
|
|
|
3
|
-
SeaVerse
|
|
3
|
+
SeaVerse Backend API 客户端 SDK - 提供完整的认证、容器管理、技能市场等功能
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@seaverse/auth-sdk)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
8
|
## 功能特性
|
|
9
9
|
|
|
10
|
-
- 🔐
|
|
11
|
-
- 🌐 **OAuth
|
|
12
|
-
- 🎨
|
|
13
|
-
-
|
|
14
|
-
-
|
|
10
|
+
- 🔐 **用户认证** - 注册、登录、登出、密码重置
|
|
11
|
+
- 🌐 **OAuth登录** - Google、Discord、GitHub 第三方登录
|
|
12
|
+
- 🎨 **登录UI组件** - 开箱即用的精美登录弹窗
|
|
13
|
+
- 📦 **容器管理** - Container 注册、心跳、状态查询
|
|
14
|
+
- 🛍️ **技能市场** - Marketplace Skills 浏览、安装、卸载
|
|
15
|
+
- 🗣️ **语音服务** - Speech Token 获取
|
|
16
|
+
- 🌍 **多环境支持** - Production、Staging、Development、Local
|
|
15
17
|
- ⚡ **TypeScript** - 完整的类型定义
|
|
16
|
-
-
|
|
17
|
-
- 🌍 **多环境支持** - 一键切换生产/测试/开发环境
|
|
18
|
+
- 🔧 **认证集成** - 内置Auth、Hooks系统支持
|
|
18
19
|
|
|
19
20
|
## 安装
|
|
20
21
|
|
|
21
22
|
```bash
|
|
22
|
-
npm install @
|
|
23
|
+
npm install @seaverse/auth-sdk
|
|
24
|
+
# 或
|
|
25
|
+
pnpm add @seaverse/auth-sdk
|
|
23
26
|
```
|
|
24
27
|
|
|
25
|
-
##
|
|
28
|
+
## 核心概念
|
|
29
|
+
|
|
30
|
+
### App ID 和多租户架构
|
|
31
|
+
|
|
32
|
+
**重要**: 从 v0.2.0 开始,`appId` 是初始化 SDK 时的**必需参数**。
|
|
33
|
+
|
|
34
|
+
#### 什么是 App ID?
|
|
35
|
+
|
|
36
|
+
每个应用都有唯一的 `app_id`:
|
|
37
|
+
- `app_id = "your app id"`
|
|
38
|
+
|
|
39
|
+
#### 多租户隔离
|
|
40
|
+
|
|
41
|
+
- 用户数据按 `app_id` 隔离
|
|
42
|
+
- 同一邮箱可在不同应用中注册,使用不同密码
|
|
43
|
+
- 每个应用拥有独立的用户池
|
|
26
44
|
|
|
27
|
-
|
|
45
|
+
#### X-App-ID 请求头
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
SDK 会自动在**每个请求**的请求头中添加 `X-App-ID`,无需手动设置:
|
|
30
48
|
|
|
31
49
|
```typescript
|
|
32
|
-
|
|
50
|
+
const client = new SeaVerseBackendAPIClient({
|
|
51
|
+
appId: 'game-abc123', // SDK 自动将此值添加到所有请求的 X-App-ID header
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// 所有 API 调用都会自动携带 X-App-ID: game-abc123
|
|
55
|
+
await client.login({ email, password });
|
|
56
|
+
await client.getCurrentUser();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 快速开始
|
|
33
60
|
|
|
34
|
-
|
|
61
|
+
### 1. 基本使用
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
|
|
65
|
+
|
|
66
|
+
// 方式1: SeaVerse 平台应用(自动检测环境)
|
|
35
67
|
const client = new SeaVerseBackendAPIClient({
|
|
36
|
-
|
|
68
|
+
appId: 'your app id', // 必需:应用ID
|
|
37
69
|
});
|
|
38
70
|
|
|
39
|
-
//
|
|
71
|
+
// 方式2: 第三方应用(指定环境)
|
|
40
72
|
const client = new SeaVerseBackendAPIClient({
|
|
41
|
-
|
|
73
|
+
appId: 'your app id', // 必需:您的应用ID
|
|
74
|
+
environment: 'production', // 'production' | 'staging' | 'development' | 'local'
|
|
42
75
|
});
|
|
43
|
-
```
|
|
44
76
|
|
|
45
|
-
|
|
77
|
+
// 方式3: 自定义URL
|
|
78
|
+
const client = new SeaVerseBackendAPIClient({
|
|
79
|
+
appId: 'your app id', // 必需:您的应用ID
|
|
80
|
+
baseURL: 'https://custom-api.example.com',
|
|
81
|
+
});
|
|
46
82
|
|
|
47
|
-
|
|
48
|
-
|
|
83
|
+
// 健康检查
|
|
84
|
+
const health = await client.getHealth();
|
|
85
|
+
console.log('Health:', health);
|
|
86
|
+
```
|
|
49
87
|
|
|
50
|
-
|
|
51
|
-
const client = new SeaVerseBackendAPIClient();
|
|
88
|
+
### 2. 用户认证
|
|
52
89
|
|
|
53
|
-
|
|
90
|
+
```typescript
|
|
91
|
+
// 注册新用户
|
|
54
92
|
const registerResult = await client.register({
|
|
55
93
|
email: 'user@example.com',
|
|
56
|
-
password: '
|
|
94
|
+
password: 'SecurePassword123',
|
|
95
|
+
username: 'johndoe', // 可选,未提供则从邮箱自动生成
|
|
96
|
+
invitation_code: 'INVITE123', // 可选
|
|
57
97
|
});
|
|
58
98
|
|
|
59
99
|
// 登录
|
|
60
100
|
const loginResult = await client.login({
|
|
61
101
|
email: 'user@example.com',
|
|
62
|
-
password: '
|
|
102
|
+
password: 'SecurePassword123',
|
|
63
103
|
});
|
|
64
104
|
|
|
65
|
-
// 保存
|
|
105
|
+
// 保存token
|
|
66
106
|
localStorage.setItem('token', loginResult.token);
|
|
67
107
|
|
|
68
|
-
//
|
|
108
|
+
// 获取当前用户信息
|
|
69
109
|
const user = await client.getCurrentUser();
|
|
110
|
+
console.log('User:', user);
|
|
111
|
+
console.log('App ID:', user.app_id); // 多租户应用ID
|
|
112
|
+
console.log('Email verified:', user.email_verified);
|
|
70
113
|
|
|
71
114
|
// 登出
|
|
72
115
|
await client.logout();
|
|
116
|
+
|
|
117
|
+
// 忘记密码
|
|
118
|
+
await client.forgotPassword({
|
|
119
|
+
email: 'user@example.com',
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 重置密码
|
|
123
|
+
await client.resetPassword({
|
|
124
|
+
token: 'reset-token-from-email',
|
|
125
|
+
new_password: 'NewSecurePassword123',
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 3. OAuth 第三方登录
|
|
130
|
+
|
|
131
|
+
#### Google 登录
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// 步骤1: 获取Google授权码后,交换token
|
|
135
|
+
const result = await client.googleCodeToToken({
|
|
136
|
+
code: 'google-auth-code',
|
|
137
|
+
redirectUri: 'https://yourdomain.com/auth/callback',
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
localStorage.setItem('token', result.token);
|
|
141
|
+
|
|
142
|
+
// 解绑Google账号
|
|
143
|
+
await client.unlinkGoogle();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Discord 登录
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const result = await client.discordCodeToToken({
|
|
150
|
+
code: 'discord-auth-code',
|
|
151
|
+
redirectUri: 'https://yourdomain.com/auth/callback',
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 解绑Discord账号
|
|
155
|
+
await client.unlinkDiscord();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### GitHub 登录
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const result = await client.githubCodeToToken({
|
|
162
|
+
code: 'github-auth-code',
|
|
163
|
+
redirectUri: 'https://yourdomain.com/auth/callback',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// 解绑GitHub账号
|
|
167
|
+
await client.unlinkGithub();
|
|
73
168
|
```
|
|
74
169
|
|
|
75
|
-
###
|
|
170
|
+
### 4. 使用登录UI组件
|
|
171
|
+
|
|
172
|
+
SDK 提供精美的登录弹窗组件,支持深色和浅色两种主题:
|
|
173
|
+
|
|
174
|
+
#### 主题对比
|
|
175
|
+
|
|
176
|
+
| 主题 | 设计风格 | 适用场景 |
|
|
177
|
+
|------|---------|---------|
|
|
178
|
+
| **Dark** 🌙 | 动态网格渐变 + 玻璃态效果 | 科技感产品、游戏平台、深色界面应用 |
|
|
179
|
+
| **Light** ☀️ | 提升的卡片设计 + 柔和阴影 | 商务应用、内容平台、浅色界面应用 |
|
|
180
|
+
|
|
181
|
+
#### 基础用法
|
|
76
182
|
|
|
77
183
|
```typescript
|
|
78
|
-
import { SeaVerseBackendAPIClient,
|
|
79
|
-
import '@
|
|
184
|
+
import { SeaVerseBackendAPIClient, AuthModal } from '@seaverse/auth-sdk';
|
|
185
|
+
import '@seaverse/auth-sdk/auth-modal.css'; // 导入样式
|
|
80
186
|
|
|
81
187
|
const client = new SeaVerseBackendAPIClient({
|
|
82
|
-
|
|
188
|
+
appId: 'your app id', // 必需:您的应用ID
|
|
189
|
+
environment: 'production',
|
|
83
190
|
});
|
|
84
191
|
|
|
85
|
-
|
|
192
|
+
// 创建登录弹窗(深色主题)
|
|
193
|
+
const authModal = new AuthModal({
|
|
86
194
|
client,
|
|
87
|
-
theme: 'dark', // 'dark'
|
|
195
|
+
theme: 'dark', // 'dark' | 'light' - 默认为 'dark'
|
|
88
196
|
|
|
197
|
+
// 登录成功回调
|
|
89
198
|
onLoginSuccess: (token, user) => {
|
|
90
199
|
localStorage.setItem('token', token);
|
|
91
200
|
console.log('登录成功:', user);
|
|
92
201
|
},
|
|
93
202
|
|
|
203
|
+
// 注册成功回调
|
|
94
204
|
onSignupSuccess: (token, user) => {
|
|
95
205
|
localStorage.setItem('token', token);
|
|
96
206
|
console.log('注册成功:', user);
|
|
97
207
|
},
|
|
98
208
|
|
|
209
|
+
// 错误回调
|
|
99
210
|
onError: (error) => {
|
|
100
|
-
console.error('
|
|
211
|
+
console.error('认证错误:', error.message);
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
// OAuth配置(可选)
|
|
215
|
+
oauthConfig: {
|
|
216
|
+
google: {
|
|
217
|
+
clientId: 'YOUR_GOOGLE_CLIENT_ID',
|
|
218
|
+
redirectUri: window.location.origin + '/auth/callback',
|
|
219
|
+
},
|
|
220
|
+
discord: {
|
|
221
|
+
clientId: 'YOUR_DISCORD_CLIENT_ID',
|
|
222
|
+
redirectUri: window.location.origin + '/auth/callback',
|
|
223
|
+
},
|
|
224
|
+
github: {
|
|
225
|
+
clientId: 'YOUR_GITHUB_CLIENT_ID',
|
|
226
|
+
redirectUri: window.location.origin + '/auth/callback',
|
|
227
|
+
},
|
|
101
228
|
},
|
|
102
229
|
});
|
|
103
230
|
|
|
@@ -106,127 +233,262 @@ authModal.show('login');
|
|
|
106
233
|
|
|
107
234
|
// 显示注册界面
|
|
108
235
|
authModal.show('signup');
|
|
109
|
-
```
|
|
110
236
|
|
|
111
|
-
|
|
237
|
+
// 隐藏弹窗
|
|
238
|
+
authModal.hide();
|
|
239
|
+
|
|
240
|
+
// 销毁弹窗
|
|
241
|
+
authModal.destroy();
|
|
242
|
+
#### OAuth 配置说明
|
|
112
243
|
|
|
113
|
-
|
|
244
|
+
`oauthConfig` 参数是**完全可选的**:
|
|
245
|
+
|
|
246
|
+
- 如果**不提供** `oauthConfig`,则不会显示任何第三方登录按钮
|
|
247
|
+
- 如果**部分配置**(如只配置 Google),则只显示已配置的按钮
|
|
248
|
+
- 如果**完整配置**所有平台,则显示所有第三方登录按钮
|
|
114
249
|
|
|
115
250
|
```typescript
|
|
116
|
-
|
|
117
|
-
|
|
251
|
+
// 示例1:无OAuth按钮
|
|
252
|
+
const client1 = new SeaVerseBackendAPIClient({ appId: 'your app id' });
|
|
253
|
+
const authModal1 = new AuthModal({
|
|
254
|
+
client: client1,
|
|
255
|
+
theme: 'dark',
|
|
256
|
+
// 不传 oauthConfig,不显示任何OAuth按钮
|
|
257
|
+
});
|
|
118
258
|
|
|
259
|
+
// 示例2:只显示Google登录
|
|
260
|
+
const client2 = new SeaVerseBackendAPIClient({ appId: 'your app id' });
|
|
261
|
+
const authModal2 = new AuthModal({
|
|
262
|
+
client: client2,
|
|
263
|
+
theme: 'light',
|
|
119
264
|
oauthConfig: {
|
|
120
265
|
google: {
|
|
121
266
|
clientId: 'YOUR_GOOGLE_CLIENT_ID',
|
|
122
|
-
redirectUri: '
|
|
123
|
-
},
|
|
124
|
-
discord: {
|
|
125
|
-
clientId: 'YOUR_DISCORD_CLIENT_ID',
|
|
126
|
-
redirectUri: 'https://yourdomain.com/auth/callback',
|
|
127
|
-
},
|
|
128
|
-
github: {
|
|
129
|
-
clientId: 'YOUR_GITHUB_CLIENT_ID',
|
|
130
|
-
redirectUri: 'https://yourdomain.com/auth/callback',
|
|
267
|
+
redirectUri: window.location.origin + '/auth/callback',
|
|
131
268
|
},
|
|
269
|
+
// Discord 和 GitHub 未配置,不会显示这些按钮
|
|
132
270
|
},
|
|
271
|
+
});
|
|
133
272
|
|
|
134
|
-
|
|
135
|
-
|
|
273
|
+
// 示例3:显示所有OAuth按钮
|
|
274
|
+
const client3 = new SeaVerseBackendAPIClient({ appId: 'your app id' });
|
|
275
|
+
const authModal3 = new AuthModal({
|
|
276
|
+
client: client3,
|
|
277
|
+
theme: 'dark',
|
|
278
|
+
oauthConfig: {
|
|
279
|
+
google: { clientId: '...', redirectUri: '...' },
|
|
280
|
+
discord: { clientId: '...', redirectUri: '...' },
|
|
281
|
+
github: { clientId: '...', redirectUri: '...' },
|
|
136
282
|
},
|
|
137
283
|
});
|
|
138
|
-
|
|
139
|
-
authModal.show('login');
|
|
140
284
|
```
|
|
141
285
|
|
|
142
|
-
###
|
|
143
|
-
|
|
144
|
-
在你的回调页面(如 `/auth/callback`)添加:
|
|
286
|
+
### 5. 容器管理
|
|
145
287
|
|
|
146
288
|
```typescript
|
|
147
|
-
|
|
289
|
+
// 列出所有容器
|
|
290
|
+
const containers = await client.listContainers();
|
|
291
|
+
|
|
292
|
+
// 注册新容器
|
|
293
|
+
const result = await client.registerContainer({
|
|
294
|
+
containerId: 'container-123',
|
|
295
|
+
metadata: {
|
|
296
|
+
version: '1.0.0',
|
|
297
|
+
capabilities: ['skill-execution'],
|
|
298
|
+
},
|
|
299
|
+
});
|
|
148
300
|
|
|
149
|
-
|
|
150
|
-
|
|
301
|
+
// 获取容器信息
|
|
302
|
+
const container = await client.getContainer({
|
|
303
|
+
containerId: 'container-123',
|
|
151
304
|
});
|
|
152
305
|
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
window.location.href = '/dashboard';
|
|
158
|
-
},
|
|
159
|
-
onError: (error) => {
|
|
160
|
-
console.error('登录失败:', error);
|
|
161
|
-
window.location.href = '/';
|
|
162
|
-
},
|
|
306
|
+
// 容器心跳
|
|
307
|
+
await client.containerHeartbeat({
|
|
308
|
+
containerId: 'container-123',
|
|
309
|
+
status: 'healthy',
|
|
163
310
|
});
|
|
311
|
+
|
|
312
|
+
// 注销容器
|
|
313
|
+
await client.unregisterContainer({
|
|
314
|
+
containerId: 'container-123',
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// 获取容器统计
|
|
318
|
+
const stats = await client.getContainerStats();
|
|
164
319
|
```
|
|
165
320
|
|
|
166
|
-
###
|
|
321
|
+
### 6. 技能市场
|
|
167
322
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
323
|
+
```typescript
|
|
324
|
+
// 列出市场技能
|
|
325
|
+
const skills = await client.listMarketplaceSkills({
|
|
326
|
+
category: 'productivity',
|
|
327
|
+
page: 1,
|
|
328
|
+
pageSize: 20,
|
|
329
|
+
});
|
|
173
330
|
|
|
174
|
-
|
|
331
|
+
// 获取技能详情
|
|
332
|
+
const skill = await client.getMarketplaceSkill({
|
|
333
|
+
skillId: 'skill-123',
|
|
334
|
+
});
|
|
175
335
|
|
|
176
|
-
|
|
336
|
+
// 安装技能
|
|
337
|
+
await client.installSkill({
|
|
338
|
+
skillId: 'skill-123',
|
|
339
|
+
});
|
|
177
340
|
|
|
178
|
-
|
|
341
|
+
// 列出已安装的技能
|
|
342
|
+
const userSkills = await client.listUserSkills();
|
|
343
|
+
|
|
344
|
+
// 卸载技能
|
|
345
|
+
await client.uninstallSkill({
|
|
346
|
+
skillId: 'skill-123',
|
|
347
|
+
});
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 7. 其他功能
|
|
179
351
|
|
|
180
352
|
```typescript
|
|
181
|
-
//
|
|
182
|
-
await client.
|
|
353
|
+
// 获取API Service Token
|
|
354
|
+
const apiToken = await client.getApiServiceToken();
|
|
183
355
|
|
|
184
|
-
//
|
|
185
|
-
await client.
|
|
356
|
+
// 获取对话状态
|
|
357
|
+
const status = await client.getConversationStatus({
|
|
358
|
+
conversationId: 'conv-123',
|
|
359
|
+
});
|
|
186
360
|
|
|
187
|
-
//
|
|
188
|
-
await client.
|
|
361
|
+
// 获取语音Token
|
|
362
|
+
const speechToken = await client.getSpeechToken();
|
|
363
|
+
```
|
|
189
364
|
|
|
190
|
-
|
|
191
|
-
await client.logout()
|
|
365
|
+
## 高级配置
|
|
192
366
|
|
|
193
|
-
|
|
194
|
-
await client.forgotPassword({ email })
|
|
367
|
+
### 自定义认证
|
|
195
368
|
|
|
196
|
-
|
|
197
|
-
|
|
369
|
+
```typescript
|
|
370
|
+
import { AuthFactory } from '@seaverse/auth-sdk';
|
|
371
|
+
|
|
372
|
+
const client = new SeaVerseBackendAPIClient({
|
|
373
|
+
appId: 'your app id', // 必需:应用ID
|
|
374
|
+
environment: 'production',
|
|
375
|
+
|
|
376
|
+
// 使用JWT认证
|
|
377
|
+
auth: AuthFactory.create({
|
|
378
|
+
type: 'jwt',
|
|
379
|
+
credentials: {
|
|
380
|
+
type: 'jwt',
|
|
381
|
+
token: localStorage.getItem('token'),
|
|
382
|
+
},
|
|
383
|
+
}),
|
|
384
|
+
});
|
|
198
385
|
```
|
|
199
386
|
|
|
200
|
-
###
|
|
387
|
+
### 自定义Hooks
|
|
201
388
|
|
|
202
389
|
```typescript
|
|
203
|
-
|
|
204
|
-
await client.googleCodeToToken({ code })
|
|
390
|
+
import { BuiltInHooks } from '@seaverse/auth-sdk';
|
|
205
391
|
|
|
206
|
-
|
|
207
|
-
|
|
392
|
+
const client = new SeaVerseBackendAPIClient({
|
|
393
|
+
appId: 'your app id', // 必需:应用ID
|
|
394
|
+
environment: 'production',
|
|
395
|
+
|
|
396
|
+
hooks: {
|
|
397
|
+
hooks: [
|
|
398
|
+
// 日志Hook
|
|
399
|
+
BuiltInHooks.createLoggerHook({
|
|
400
|
+
logLevel: 'debug',
|
|
401
|
+
logRequestBody: true,
|
|
402
|
+
logResponseBody: true,
|
|
403
|
+
}),
|
|
404
|
+
|
|
405
|
+
// 请求ID Hook
|
|
406
|
+
BuiltInHooks.createRequestIdHook(),
|
|
407
|
+
|
|
408
|
+
// 自定义Hook
|
|
409
|
+
{
|
|
410
|
+
type: 'beforeRequest',
|
|
411
|
+
name: 'custom-hook',
|
|
412
|
+
priority: 100,
|
|
413
|
+
handler: async (context) => {
|
|
414
|
+
console.log('Before request:', context.config.url);
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
```
|
|
208
421
|
|
|
209
|
-
|
|
210
|
-
await client.githubCodeToToken({ code })
|
|
422
|
+
### 环境配置
|
|
211
423
|
|
|
212
|
-
|
|
213
|
-
await client.unlinkGoogle()
|
|
214
|
-
await client.unlinkDiscord()
|
|
215
|
-
await client.unlinkGithub()
|
|
216
|
-
```
|
|
424
|
+
SDK支持以下环境:
|
|
217
425
|
|
|
218
|
-
|
|
426
|
+
| 环境 | 描述 | BaseURL |
|
|
427
|
+
|------|------|---------|
|
|
428
|
+
| `production` | 生产环境 | `https://api.seaverse.com` |
|
|
429
|
+
| `staging` | 测试环境 | `https://api.staging.seaverse.dev` |
|
|
430
|
+
| `development` | 开发环境 | `https://api.dev.seaverse.dev` |
|
|
431
|
+
| `local` | 本地环境 | `http://localhost:3000` |
|
|
219
432
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
433
|
+
自动检测规则:
|
|
434
|
+
- `*.seaverse.com` → production
|
|
435
|
+
- `*.staging.seaverse.dev` → staging
|
|
436
|
+
- `*.dev.seaverse.dev` → development
|
|
437
|
+
- `localhost` → local
|
|
223
438
|
|
|
224
|
-
|
|
225
|
-
authModal.hide()
|
|
439
|
+
## API 参考
|
|
226
440
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
441
|
+
### 认证相关
|
|
442
|
+
|
|
443
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
444
|
+
|------|------|--------|------|
|
|
445
|
+
| `register()` | `{ email, password, username?, invitation_code? }` | `RegisterResponse` | 注册新用户 |
|
|
446
|
+
| `login()` | `{ email, password }` | `LoginResponse` | 用户登录 |
|
|
447
|
+
| `getCurrentUser()` | - | `User` | 获取当前用户 |
|
|
448
|
+
| `logout()` | - | `SuccessResponse` | 登出 |
|
|
449
|
+
| `forgotPassword()` | `{ email }` | `SuccessResponse` | 忘记密码 |
|
|
450
|
+
| `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
|
|
451
|
+
| `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
|
|
452
|
+
|
|
453
|
+
### OAuth相关
|
|
454
|
+
|
|
455
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
456
|
+
|------|------|--------|------|
|
|
457
|
+
| `googleCodeToToken()` | `{ code, redirectUri }` | `OAuthTokenResponse` | Google登录 |
|
|
458
|
+
| `discordCodeToToken()` | `{ code, redirectUri }` | `OAuthTokenResponse` | Discord登录 |
|
|
459
|
+
| `githubCodeToToken()` | `{ code, redirectUri }` | `OAuthTokenResponse` | GitHub登录 |
|
|
460
|
+
| `unlinkGoogle()` | - | `SuccessResponse` | 解绑Google |
|
|
461
|
+
| `unlinkDiscord()` | - | `SuccessResponse` | 解绑Discord |
|
|
462
|
+
| `unlinkGithub()` | - | `SuccessResponse` | 解绑GitHub |
|
|
463
|
+
|
|
464
|
+
### 容器管理
|
|
465
|
+
|
|
466
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
467
|
+
|------|------|--------|------|
|
|
468
|
+
| `listContainers()` | - | `ContainerListResponse` | 列出容器 |
|
|
469
|
+
| `registerContainer()` | `{ containerId, metadata }` | `SuccessResponse` | 注册容器 |
|
|
470
|
+
| `getContainer()` | `{ containerId }` | `Container` | 获取容器信息 |
|
|
471
|
+
| `unregisterContainer()` | `{ containerId }` | `SuccessResponse` | 注销容器 |
|
|
472
|
+
| `containerHeartbeat()` | `{ containerId, status }` | `SuccessResponse` | 容器心跳 |
|
|
473
|
+
| `getContainerStats()` | - | `ContainerStatsResponse` | 容器统计 |
|
|
474
|
+
|
|
475
|
+
### 技能市场
|
|
476
|
+
|
|
477
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
478
|
+
|------|------|--------|------|
|
|
479
|
+
| `listMarketplaceSkills()` | `{ category?, page?, pageSize? }` | `MarketplaceSkillsListResponse` | 列出市场技能 |
|
|
480
|
+
| `getMarketplaceSkill()` | `{ skillId }` | `MarketplaceSkill` | 获取技能详情 |
|
|
481
|
+
| `installSkill()` | `{ skillId }` | `SuccessResponse` | 安装技能 |
|
|
482
|
+
| `listUserSkills()` | - | `UserInstalledSkillsListResponse` | 列出已安装技能 |
|
|
483
|
+
| `uninstallSkill()` | `{ skillId }` | `SuccessResponse` | 卸载技能 |
|
|
484
|
+
|
|
485
|
+
### 其他
|
|
486
|
+
|
|
487
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
488
|
+
|------|------|--------|------|
|
|
489
|
+
| `getHealth()` | - | `HealthResponse` | 健康检查 |
|
|
490
|
+
| `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | 获取对话状态 |
|
|
491
|
+
| `getSpeechToken()` | - | `SpeechTokenResponse` | 获取语音Token |
|
|
230
492
|
|
|
231
493
|
## 类型定义
|
|
232
494
|
|
|
@@ -234,12 +496,21 @@ authModal.destroy()
|
|
|
234
496
|
// 用户信息
|
|
235
497
|
interface User {
|
|
236
498
|
id?: string;
|
|
499
|
+
app_id?: string | null; // 应用ID(多租户支持)
|
|
237
500
|
email?: string;
|
|
238
501
|
username?: string;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
502
|
+
created_at?: number; // Unix时间戳
|
|
503
|
+
email_verified?: boolean; // 邮箱验证状态
|
|
504
|
+
google_id?: string | null; // Google账号ID
|
|
505
|
+
discord_id?: string | null; // Discord账号ID
|
|
506
|
+
github_id?: string | null; // GitHub账号ID
|
|
507
|
+
|
|
508
|
+
// 已弃用字段(向后兼容)
|
|
509
|
+
createdAt?: number; // @deprecated 使用 created_at
|
|
510
|
+
emailVerified?: boolean; // @deprecated 使用 email_verified
|
|
511
|
+
googleId?: string; // @deprecated 使用 google_id
|
|
512
|
+
discordId?: string; // @deprecated 使用 discord_id
|
|
513
|
+
githubId?: string; // @deprecated 使用 github_id
|
|
243
514
|
}
|
|
244
515
|
|
|
245
516
|
// 登录响应
|
|
@@ -255,119 +526,148 @@ interface RegisterResponse {
|
|
|
255
526
|
userId: string;
|
|
256
527
|
}
|
|
257
528
|
|
|
258
|
-
//
|
|
529
|
+
// AuthModal选项
|
|
530
|
+
interface AuthModalOptions {
|
|
531
|
+
client: SeaVerseBackendAPIClient;
|
|
532
|
+
theme?: 'dark' | 'light';
|
|
533
|
+
onLoginSuccess?: (token: string, user: any) => void;
|
|
534
|
+
onSignupSuccess?: (token: string, user: any) => void;
|
|
535
|
+
onError?: (error: Error) => void;
|
|
536
|
+
oauthConfig?: OAuthConfig;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// OAuth配置
|
|
259
540
|
interface OAuthConfig {
|
|
260
541
|
google?: {
|
|
261
542
|
clientId: string;
|
|
262
543
|
redirectUri: string;
|
|
263
|
-
scope?: string;
|
|
544
|
+
scope?: string;
|
|
264
545
|
};
|
|
265
546
|
discord?: {
|
|
266
547
|
clientId: string;
|
|
267
548
|
redirectUri: string;
|
|
268
|
-
scope?: string;
|
|
549
|
+
scope?: string;
|
|
269
550
|
};
|
|
270
551
|
github?: {
|
|
271
552
|
clientId: string;
|
|
272
553
|
redirectUri: string;
|
|
273
|
-
scope?: string;
|
|
554
|
+
scope?: string;
|
|
274
555
|
};
|
|
275
556
|
}
|
|
276
557
|
```
|
|
277
558
|
|
|
278
559
|
## 完整示例
|
|
279
560
|
|
|
280
|
-
|
|
281
|
-
<!DOCTYPE html>
|
|
282
|
-
<html>
|
|
283
|
-
<head>
|
|
284
|
-
<meta charset="UTF-8">
|
|
285
|
-
<title>登录示例</title>
|
|
286
|
-
<link rel="stylesheet" href="node_modules/@seaverseai/auth-sdk/src/auth-modal.css">
|
|
287
|
-
</head>
|
|
288
|
-
<body>
|
|
289
|
-
<h1>欢迎</h1>
|
|
290
|
-
<button id="loginBtn">登录</button>
|
|
291
|
-
|
|
292
|
-
<script type="module">
|
|
293
|
-
import { SeaVerseBackendAPIClient, createAuthModal } from '@seaverseai/auth-sdk';
|
|
294
|
-
|
|
295
|
-
const client = new SeaVerseBackendAPIClient({
|
|
296
|
-
baseURL: 'https://account-hub.sg.seaverse.dev',
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
const authModal = createAuthModal({
|
|
300
|
-
client,
|
|
301
|
-
theme: 'dark',
|
|
302
|
-
|
|
303
|
-
oauthConfig: {
|
|
304
|
-
google: {
|
|
305
|
-
clientId: 'YOUR_GOOGLE_CLIENT_ID',
|
|
306
|
-
redirectUri: window.location.origin + '/callback.html',
|
|
307
|
-
},
|
|
308
|
-
},
|
|
561
|
+
查看 [examples/auth-sdk-demo](../../examples/auth-sdk-demo) 目录获取完整的可运行示例。
|
|
309
562
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
document.getElementById('loginBtn').onclick = () => {
|
|
317
|
-
authModal.show('login');
|
|
318
|
-
};
|
|
319
|
-
</script>
|
|
320
|
-
</body>
|
|
321
|
-
</html>
|
|
563
|
+
```bash
|
|
564
|
+
# 运行示例
|
|
565
|
+
cd examples/auth-sdk-demo
|
|
566
|
+
pnpm install
|
|
567
|
+
pnpm dev
|
|
322
568
|
```
|
|
323
569
|
|
|
324
|
-
##
|
|
570
|
+
## 从旧版本迁移
|
|
325
571
|
|
|
326
|
-
|
|
327
|
-
import { useEffect, useState } from 'react';
|
|
328
|
-
import { SeaVerseBackendAPIClient, createAuthModal } from '@seaverseai/auth-sdk';
|
|
329
|
-
import '@seaverseai/auth-sdk/src/auth-modal.css';
|
|
572
|
+
### v0.1.x → v0.2.0 升级指南
|
|
330
573
|
|
|
331
|
-
|
|
332
|
-
|
|
574
|
+
#### 1. 向后兼容性
|
|
575
|
+
好消息!v0.2.0 完全向后兼容,现有代码**无需修改**即可继续工作。
|
|
333
576
|
|
|
334
|
-
|
|
335
|
-
const client = new SeaVerseBackendAPIClient({
|
|
336
|
-
baseURL: 'https://account-hub.sg.seaverse.dev',
|
|
337
|
-
});
|
|
577
|
+
#### 2. 推荐的迁移步骤
|
|
338
578
|
|
|
339
|
-
|
|
340
|
-
client,
|
|
341
|
-
onLoginSuccess: (token) => {
|
|
342
|
-
localStorage.setItem('token', token);
|
|
343
|
-
},
|
|
344
|
-
});
|
|
579
|
+
虽然不是必须的,但我们建议逐步迁移到新的字段命名规范:
|
|
345
580
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
581
|
+
```typescript
|
|
582
|
+
// 旧代码(仍然可用)
|
|
583
|
+
const user = await client.getCurrentUser();
|
|
584
|
+
console.log(user.emailVerified); // ⚠️ 已弃用但可用
|
|
585
|
+
console.log(user.createdAt); // ⚠️ 已弃用但可用
|
|
349
586
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
587
|
+
// 新代码(推荐)
|
|
588
|
+
const user = await client.getCurrentUser();
|
|
589
|
+
console.log(user.email_verified); // ✅ 推荐使用
|
|
590
|
+
console.log(user.created_at); // ✅ 推荐使用
|
|
591
|
+
console.log(user.app_id); // ✅ 新字段:多租户支持
|
|
356
592
|
```
|
|
357
593
|
|
|
358
|
-
|
|
594
|
+
#### 3. 注册接口更新
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
// 旧代码(仍然可用)
|
|
598
|
+
await client.register({
|
|
599
|
+
email: 'user@example.com',
|
|
600
|
+
password: 'password123',
|
|
601
|
+
invitationCode: 'INVITE123', // ⚠️ 已弃用但可用
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// 新代码(推荐)
|
|
605
|
+
await client.register({
|
|
606
|
+
email: 'user@example.com',
|
|
607
|
+
password: 'password123',
|
|
608
|
+
username: 'myusername', // ✨ 新功能
|
|
609
|
+
invitation_code: 'INVITE123', // ✅ 推荐使用
|
|
610
|
+
});
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
#### 4. 密码重置接口更新
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
// 旧代码(需要更新)
|
|
617
|
+
await client.resetPassword({
|
|
618
|
+
token: 'reset-token',
|
|
619
|
+
newPassword: 'NewPass123', // ⚠️ 已弃用
|
|
620
|
+
});
|
|
359
621
|
|
|
360
|
-
|
|
622
|
+
// 新代码(推荐)
|
|
623
|
+
await client.resetPassword({
|
|
624
|
+
token: 'reset-token',
|
|
625
|
+
new_password: 'NewPass123', // ✅ 推荐使用
|
|
626
|
+
});
|
|
627
|
+
```
|
|
361
628
|
|
|
362
|
-
|
|
629
|
+
#### 5. TypeScript 类型提示
|
|
363
630
|
|
|
364
|
-
|
|
631
|
+
如果你使用 TypeScript,编译器会自动提示已弃用的字段:
|
|
365
632
|
|
|
366
633
|
```typescript
|
|
367
|
-
|
|
634
|
+
const user = await client.getCurrentUser();
|
|
635
|
+
user.emailVerified; // TypeScript 会显示删除线和弃用警告
|
|
636
|
+
user.email_verified; // ✅ 无警告
|
|
637
|
+
```
|
|
368
638
|
|
|
369
|
-
|
|
370
|
-
|
|
639
|
+
#### 6. 多租户功能(新增)
|
|
640
|
+
|
|
641
|
+
如果你的应用需要支持多租户架构,可以使用新的 `app_id` 字段:
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
const user = await client.getCurrentUser();
|
|
645
|
+
|
|
646
|
+
// 检查用户属于哪个应用
|
|
647
|
+
if (user.app_id === 'seaverse') {
|
|
648
|
+
console.log('SeaVerse平台用户');
|
|
649
|
+
} else if (user.app_id) {
|
|
650
|
+
console.log('第三方应用用户:', user.app_id);
|
|
651
|
+
} else {
|
|
652
|
+
console.log('平台原生用户(无app_id)');
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## 常见问题
|
|
657
|
+
|
|
658
|
+
### 如何处理认证token?
|
|
659
|
+
|
|
660
|
+
```typescript
|
|
661
|
+
// 登录成功后保存token
|
|
662
|
+
const loginResult = await client.login({ email, password });
|
|
663
|
+
localStorage.setItem('token', loginResult.token);
|
|
664
|
+
|
|
665
|
+
// 创建带认证的client
|
|
666
|
+
import { AuthFactory } from '@seaverse/auth-sdk';
|
|
667
|
+
|
|
668
|
+
const authenticatedClient = new SeaVerseBackendAPIClient({
|
|
669
|
+
appId: 'your app id', // 必需:应用ID
|
|
670
|
+
environment: 'production',
|
|
371
671
|
auth: AuthFactory.create({
|
|
372
672
|
type: 'jwt',
|
|
373
673
|
credentials: {
|
|
@@ -378,20 +678,28 @@ const client = new SeaVerseBackendAPIClient({
|
|
|
378
678
|
});
|
|
379
679
|
```
|
|
380
680
|
|
|
381
|
-
###
|
|
681
|
+
### OAuth redirect_uri_mismatch错误?
|
|
682
|
+
|
|
683
|
+
确保OAuth应用配置中的重定向URI与代码中的`redirectUri`完全一致(包括协议、域名、端口、路径)。
|
|
382
684
|
|
|
383
|
-
|
|
685
|
+
### 如何自定义请求超时?
|
|
384
686
|
|
|
385
687
|
```typescript
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
688
|
+
const client = new SeaVerseBackendAPIClient({
|
|
689
|
+
appId: 'your app id', // 必需:应用ID
|
|
690
|
+
environment: 'production',
|
|
691
|
+
timeout: 30000, // 30秒
|
|
692
|
+
});
|
|
390
693
|
```
|
|
391
694
|
|
|
392
|
-
###
|
|
695
|
+
### 本地开发如何连接到本地API?
|
|
393
696
|
|
|
394
|
-
|
|
697
|
+
```typescript
|
|
698
|
+
const client = new SeaVerseBackendAPIClient({
|
|
699
|
+
appId: 'your app id', // 必需:应用ID
|
|
700
|
+
environment: 'local', // 或使用 baseURL: 'http://localhost:3000'
|
|
701
|
+
});
|
|
702
|
+
```
|
|
395
703
|
|
|
396
704
|
## 开发
|
|
397
705
|
|
|
@@ -400,18 +708,55 @@ oauthConfig: {
|
|
|
400
708
|
pnpm install
|
|
401
709
|
|
|
402
710
|
# 构建
|
|
403
|
-
pnpm
|
|
711
|
+
pnpm build
|
|
712
|
+
|
|
713
|
+
# Watch模式
|
|
714
|
+
pnpm dev
|
|
404
715
|
|
|
405
716
|
# 测试
|
|
406
717
|
pnpm test
|
|
407
718
|
```
|
|
408
719
|
|
|
409
|
-
##
|
|
720
|
+
## 相关链接
|
|
410
721
|
|
|
411
|
-
|
|
722
|
+
- 📦 [NPM Package](https://www.npmjs.com/package/@seaverse/auth-sdk)
|
|
723
|
+
- 📖 [示例项目](../../examples/auth-sdk-demo)
|
|
724
|
+
- 🐛 [Issues](https://github.com/seaverseai/sv-sdk/issues)
|
|
725
|
+
- 💬 [Discussions](https://github.com/seaverseai/sv-sdk/discussions)
|
|
412
726
|
|
|
413
|
-
##
|
|
727
|
+
## License
|
|
414
728
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
729
|
+
MIT © [SeaVerse Team](mailto:support@seaverse.com)
|
|
730
|
+
|
|
731
|
+
## 更新日志
|
|
732
|
+
|
|
733
|
+
### v0.2.0 (当前版本)
|
|
734
|
+
- 🔄 **API路径更新**: 所有认证API从 `/api/auth/*` 迁移到 `/sdk/v1/auth/*`
|
|
735
|
+
- 🏢 **多租户支持**: User模型新增 `app_id` 字段,支持多应用隔离
|
|
736
|
+
- 🔑 **重要变更**: `appId` 现在是**必需参数**,SDK 自动在所有请求中添加 `X-App-ID` 请求头
|
|
737
|
+
- ✨ **新功能**:
|
|
738
|
+
- 注册时支持自定义 `username`(可选)
|
|
739
|
+
- 所有字段标准化为 snake_case(保留 camelCase 向后兼容)
|
|
740
|
+
- 📝 **字段更新**:
|
|
741
|
+
- `SeaVerseBackendAPIClientOptions`: 新增必需字段 `appId`
|
|
742
|
+
- `User`: 新增 `app_id`, `created_at`, `email_verified`, `google_id`, `discord_id`, `github_id`
|
|
743
|
+
- `RegisterRequest`: 新增 `username`, `invitation_code`
|
|
744
|
+
- `ResetPasswordRequest`: `newPassword` → `new_password`
|
|
745
|
+
- ⚠️ **Breaking Changes**:
|
|
746
|
+
- 必须提供 `appId` 参数才能初始化 client
|
|
747
|
+
- API 路径变更需要后端支持
|
|
748
|
+
- ✅ **向后兼容**: 除 `appId` 外,所有旧字段仍然可用
|
|
749
|
+
|
|
750
|
+
### v0.1.5
|
|
751
|
+
- 修复OAuth state管理,从sessionStorage切换到localStorage
|
|
752
|
+
- 增强API响应处理
|
|
753
|
+
|
|
754
|
+
### v0.1.4
|
|
755
|
+
- 增强API响应处理
|
|
756
|
+
- 优化错误处理
|
|
757
|
+
|
|
758
|
+
### v0.1.2
|
|
759
|
+
- 更新包名为@seaverse/auth-sdk
|
|
760
|
+
- 添加多环境支持
|
|
761
|
+
|
|
762
|
+
查看完整更新日志:[CHANGELOG.md](./CHANGELOG.md)
|