@seaverse/auth-sdk 0.2.5 → 0.3.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 +480 -10
- package/dist/index.cjs +1086 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +389 -9
- package/dist/index.js +1086 -41
- package/dist/index.js.map +1 -1
- package/dist/toast.css +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,12 +10,14 @@ SeaVerse Backend API 客户端 SDK - 提供完整的认证、容器管理、技
|
|
|
10
10
|
- 🔐 **用户认证** - 注册、登录、登出、密码重置
|
|
11
11
|
- 🌐 **OAuth登录** - Google、Discord、GitHub 第三方登录
|
|
12
12
|
- 🎨 **登录UI组件** - 开箱即用的精美登录弹窗
|
|
13
|
+
- ✨ **Toast 通知** - 现代化玻璃态提示,CSS 自动注入
|
|
13
14
|
- 📦 **容器管理** - Container 注册、心跳、状态查询
|
|
14
15
|
- 🛍️ **技能市场** - Marketplace Skills 浏览、安装、卸载
|
|
15
16
|
- 🗣️ **语音服务** - Speech Token 获取
|
|
16
17
|
- 🌍 **多环境支持** - Production、Staging、Development、Local
|
|
17
18
|
- ⚡ **TypeScript** - 完整的类型定义
|
|
18
19
|
- 🔧 **认证集成** - 内置Auth、Hooks系统支持
|
|
20
|
+
- 🔄 **响应格式兼容** - 自动兼容多种API响应格式
|
|
19
21
|
|
|
20
22
|
## 安装
|
|
21
23
|
|
|
@@ -80,6 +82,16 @@ const client = new SeaVerseBackendAPIClient({
|
|
|
80
82
|
baseURL: 'https://custom-api.example.com',
|
|
81
83
|
});
|
|
82
84
|
|
|
85
|
+
// 方式4: 启用请求重试(默认禁用)
|
|
86
|
+
const client = new SeaVerseBackendAPIClient({
|
|
87
|
+
appId: 'your app id',
|
|
88
|
+
retryOptions: {
|
|
89
|
+
maxRetries: 3, // 最多重试 3 次
|
|
90
|
+
retryDelay: 1000, // 初始延迟 1000ms,每次重试延迟加倍
|
|
91
|
+
retryStatusCodes: [408, 429, 500, 502, 503, 504], // 这些状态码会触发重试
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
83
95
|
// 健康检查
|
|
84
96
|
const health = await client.getHealth();
|
|
85
97
|
console.log('Health:', health);
|
|
@@ -245,6 +257,12 @@ const authModal = new AuthModal({
|
|
|
245
257
|
console.log('注册成功:', user);
|
|
246
258
|
},
|
|
247
259
|
|
|
260
|
+
// 邀请码需求回调(可选)
|
|
261
|
+
onInviteCodeRequired: (userId, email) => {
|
|
262
|
+
console.log('需要邀请码激活账户:', userId, email);
|
|
263
|
+
// AuthModal 会自动显示邀请码输入界面
|
|
264
|
+
},
|
|
265
|
+
|
|
248
266
|
// 错误回调
|
|
249
267
|
onError: (error) => {
|
|
250
268
|
console.error('认证错误:', error.message);
|
|
@@ -272,15 +290,35 @@ authModal.hide();
|
|
|
272
290
|
authModal.destroy();
|
|
273
291
|
```
|
|
274
292
|
|
|
293
|
+
**✨ 新特性:自动 Toast 通知**
|
|
294
|
+
|
|
295
|
+
AuthModal 内置了现代化的 Toast 通知系统,无需额外配置:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Toast 会自动显示,CSS 自动注入
|
|
299
|
+
// - 注册成功 → 绿色成功提示
|
|
300
|
+
// - 账号已存在 → 黄色警告提示
|
|
301
|
+
// - 登录失败 → 红色错误提示
|
|
302
|
+
// - 重置密码 → 蓝色信息提示
|
|
303
|
+
|
|
304
|
+
// 你也可以单独使用 Toast(CSS 自动注入)
|
|
305
|
+
import { Toast } from '@seaverse/auth-sdk';
|
|
306
|
+
|
|
307
|
+
Toast.success('操作成功', '数据已保存');
|
|
308
|
+
Toast.error('操作失败', '请稍后重试');
|
|
309
|
+
Toast.warning('注意', '账号已存在');
|
|
310
|
+
Toast.info('提示', '邮件已发送');
|
|
311
|
+
```
|
|
312
|
+
|
|
275
313
|
#### 重置密码流程
|
|
276
314
|
|
|
277
315
|
AuthModal 支持完整的密码重置流程:
|
|
278
316
|
|
|
279
317
|
1. **用户触发忘记密码**:在登录界面点击 "Forgot Password?" 链接
|
|
280
|
-
2. **发送重置邮件**:输入邮箱后,系统发送带有 `
|
|
281
|
-
3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `
|
|
318
|
+
2. **发送重置邮件**:输入邮箱后,系统发送带有 `reset_token` 的重置链接
|
|
319
|
+
3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `reset_token` 参数并显示重置密码表单
|
|
282
320
|
4. **设置新密码**:用户输入并确认新密码后提交
|
|
283
|
-
5. **自动清理 URL**:重置成功后自动清除 URL 中的 `
|
|
321
|
+
5. **自动清理 URL**:重置成功后自动清除 URL 中的 `reset_token` 参数
|
|
284
322
|
|
|
285
323
|
整个流程无需额外代码,AuthModal 会自动处理:
|
|
286
324
|
|
|
@@ -292,11 +330,11 @@ const authModal = new AuthModal({
|
|
|
292
330
|
});
|
|
293
331
|
|
|
294
332
|
// 2. 用户点击邮件中的重置链接后,AuthModal 会自动:
|
|
295
|
-
// - 检测 URL 中的 ?
|
|
333
|
+
// - 检测 URL 中的 ?reset_token=xxx 参数
|
|
296
334
|
// - 显示重置密码表单
|
|
297
335
|
// - 用户提交新密码
|
|
298
336
|
// - 调用 client.resetPassword() API
|
|
299
|
-
// - 清理 URL 中的
|
|
337
|
+
// - 清理 URL 中的 reset_token 参数
|
|
300
338
|
// - 显示成功消息
|
|
301
339
|
```
|
|
302
340
|
|
|
@@ -454,7 +492,207 @@ await client.uninstallSkill({
|
|
|
454
492
|
});
|
|
455
493
|
```
|
|
456
494
|
|
|
457
|
-
### 7.
|
|
495
|
+
### 7. 邀请码管理
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
// 列出我的邀请码
|
|
499
|
+
const invites = await client.listInvites({
|
|
500
|
+
status: 'active',
|
|
501
|
+
page: 1,
|
|
502
|
+
page_size: 20,
|
|
503
|
+
});
|
|
504
|
+
console.log('我的邀请码:', invites.data.invites);
|
|
505
|
+
|
|
506
|
+
// 获取邀请码统计
|
|
507
|
+
const stats = await client.getInviteStats();
|
|
508
|
+
console.log('总邀请码数:', stats.data.total_codes);
|
|
509
|
+
console.log('活跃邀请码:', stats.data.active_codes);
|
|
510
|
+
console.log('总使用次数:', stats.data.total_uses);
|
|
511
|
+
|
|
512
|
+
// 获取邀请码详情
|
|
513
|
+
const invite = await client.getInvite('inv_abc123');
|
|
514
|
+
console.log('邀请码:', invite.data.code);
|
|
515
|
+
console.log('已使用:', invite.data.used_count);
|
|
516
|
+
console.log('最大使用次数:', invite.data.max_uses);
|
|
517
|
+
|
|
518
|
+
// 获取邀请码使用记录
|
|
519
|
+
const usages = await client.getInviteUsages('inv_abc123', {
|
|
520
|
+
page: 1,
|
|
521
|
+
page_size: 20,
|
|
522
|
+
});
|
|
523
|
+
console.log('使用记录:', usages.data.usages);
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
### 8. 邮箱验证与邀请码绑定
|
|
527
|
+
|
|
528
|
+
#### 邮箱验证(自动登录)
|
|
529
|
+
|
|
530
|
+
用户注册后会收到验证邮件,邮件中包含验证链接,格式为:`frontend_url?verify_token=xxx`
|
|
531
|
+
|
|
532
|
+
**方式一:使用 AuthModal 自动处理(推荐)**
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
import { AuthModal } from '@seaverse/auth-sdk';
|
|
536
|
+
|
|
537
|
+
// 创建 AuthModal 实例
|
|
538
|
+
const modal = new AuthModal({
|
|
539
|
+
client,
|
|
540
|
+
onLoginSuccess: (token, user) => {
|
|
541
|
+
localStorage.setItem('token', token);
|
|
542
|
+
console.log('邮箱验证并登录成功:', user);
|
|
543
|
+
},
|
|
544
|
+
onError: (error) => {
|
|
545
|
+
console.error('邮箱验证失败:', error);
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// AuthModal 会自动检测 URL 中的 verify_token 参数
|
|
550
|
+
// 检测到后会自动:
|
|
551
|
+
// 1. 调用 verifyEmail() API 验证邮箱
|
|
552
|
+
// 2. 获取返回的 JWT token 并自动登录
|
|
553
|
+
// 3. 触发 onLoginSuccess 回调
|
|
554
|
+
// 4. 清理 URL 中的 verify_token 参数
|
|
555
|
+
// 5. 显示成功消息
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**调试提示**:
|
|
559
|
+
|
|
560
|
+
如果邮箱验证出现问题,请检查浏览器控制台日志:
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
// 正常情况应该看到:
|
|
564
|
+
[AuthModal] Detected verify_token, starting email verification...
|
|
565
|
+
[AuthModal] Email verification successful: { id: "xxx", email: "user@example.com", ... }
|
|
566
|
+
|
|
567
|
+
// 如果验证失败,会看到:
|
|
568
|
+
[AuthModal] Email verification failed: Error: ...
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**方式二:手动处理邮箱验证**
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
// 验证邮箱(从邮件链接中获取 verify_token)
|
|
575
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
576
|
+
const verifyToken = urlParams.get('verify_token');
|
|
577
|
+
|
|
578
|
+
if (verifyToken) {
|
|
579
|
+
const result = await client.verifyEmail(verifyToken);
|
|
580
|
+
|
|
581
|
+
// 自动登录:保存返回的 token
|
|
582
|
+
localStorage.setItem('token', result.data.token);
|
|
583
|
+
localStorage.setItem('refreshToken', result.data.refreshToken);
|
|
584
|
+
|
|
585
|
+
console.log('邮箱验证成功,已自动登录:', result.data.user);
|
|
586
|
+
|
|
587
|
+
// 重定向到主页
|
|
588
|
+
window.location.href = '/';
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
#### 邀请码绑定(账户激活)
|
|
593
|
+
|
|
594
|
+
当使用外部邮箱注册或 OAuth 登录但未提供邀请码时,会创建临时账户并需要后续绑定邀请码激活。后端会重定向到 `frontend_url?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx`。
|
|
595
|
+
|
|
596
|
+
**方式一:使用 AuthModal 自动处理(推荐)**
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
import { AuthModal } from '@seaverse/auth-sdk';
|
|
600
|
+
|
|
601
|
+
// 创建 AuthModal 实例
|
|
602
|
+
const modal = new AuthModal({
|
|
603
|
+
client,
|
|
604
|
+
onLoginSuccess: (token, user) => {
|
|
605
|
+
localStorage.setItem('token', token);
|
|
606
|
+
console.log('登录成功:', user);
|
|
607
|
+
},
|
|
608
|
+
onInviteCodeRequired: (userId, email) => {
|
|
609
|
+
// 可选:当需要邀请码时的自定义处理
|
|
610
|
+
console.log('需要邀请码激活账户:', userId, email);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// AuthModal 会自动检测 URL 中的以下参数组合:
|
|
615
|
+
// - error_code=INVITE_CODE_REQUIRED
|
|
616
|
+
// - user_id 或 temp_user_id(用户ID)
|
|
617
|
+
// - email(可选,用户邮箱)
|
|
618
|
+
//
|
|
619
|
+
// 检测到后会自动:
|
|
620
|
+
// 1. 显示邀请码输入界面
|
|
621
|
+
// 2. 用户输入邀请码后调用 bindInviteCode() API
|
|
622
|
+
// 3. 激活成功后自动登录(保存 token)
|
|
623
|
+
// 4. 清理 URL 中的参数
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**调试提示**:
|
|
627
|
+
|
|
628
|
+
如果邀请码弹窗没有出现,请检查浏览器控制台是否有以下日志:
|
|
629
|
+
|
|
630
|
+
```javascript
|
|
631
|
+
// 正常情况应该看到:
|
|
632
|
+
[AuthModal] Detected INVITE_CODE_REQUIRED: {
|
|
633
|
+
errorCode: "INVITE_CODE_REQUIRED",
|
|
634
|
+
userId: "xxx",
|
|
635
|
+
tempUserId: null,
|
|
636
|
+
email: "user@example.com",
|
|
637
|
+
fullURL: "http://localhost:8001/?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx"
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// 如果 user_id 缺失,会看到错误提示:
|
|
641
|
+
[AuthModal] Missing user_id in URL parameters.
|
|
642
|
+
// 并弹出 alert 显示完整 URL,方便排查后端重定向问题
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**方式二:手动处理邀请码绑定**
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
// 1. 检查 URL 中是否需要邀请码
|
|
649
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
650
|
+
const errorCode = urlParams.get('error_code');
|
|
651
|
+
const userId = urlParams.get('user_id');
|
|
652
|
+
|
|
653
|
+
if (errorCode === 'INVITE_CODE_REQUIRED' && userId) {
|
|
654
|
+
// 2. 显示邀请码输入界面(自定义 UI)
|
|
655
|
+
const inviteCode = await showInviteCodeInput(); // 你的自定义UI
|
|
656
|
+
|
|
657
|
+
// 3. 绑定邀请码
|
|
658
|
+
const result = await client.bindInviteCode({
|
|
659
|
+
user_id: userId,
|
|
660
|
+
invite_code: inviteCode
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
// 4. 激活成功,自动登录
|
|
664
|
+
localStorage.setItem('token', result.data.token);
|
|
665
|
+
localStorage.setItem('refreshToken', result.data.refreshToken);
|
|
666
|
+
console.log('账户激活成功:', result.data.user);
|
|
667
|
+
|
|
668
|
+
// 5. 重定向到主页
|
|
669
|
+
window.location.href = '/';
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**方式三:使用静态方法处理**
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
import { AuthModal } from '@seaverse/auth-sdk';
|
|
677
|
+
|
|
678
|
+
// AuthModal 提供静态方法处理邀请码场景
|
|
679
|
+
const inviteCodeInfo = AuthModal.handleInviteCodeRequired(
|
|
680
|
+
{ client },
|
|
681
|
+
(userId, email) => {
|
|
682
|
+
// 自定义处理逻辑
|
|
683
|
+
const code = prompt(`请输入邀请码激活账户 (${email}):`);
|
|
684
|
+
if (code) {
|
|
685
|
+
client.bindInviteCode({ user_id: userId, invite_code: code })
|
|
686
|
+
.then(res => {
|
|
687
|
+
localStorage.setItem('token', res.data.token);
|
|
688
|
+
window.location.reload();
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
);
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### 9. 其他功能
|
|
458
696
|
|
|
459
697
|
```typescript
|
|
460
698
|
// 获取API Service Token
|
|
@@ -526,6 +764,105 @@ const client = new SeaVerseBackendAPIClient({
|
|
|
526
764
|
});
|
|
527
765
|
```
|
|
528
766
|
|
|
767
|
+
### 请求重试配置
|
|
768
|
+
|
|
769
|
+
SDK 支持自定义 HTTP 请求重试策略。**默认情况下重试功能是禁用的(maxRetries: 0)**,以确保请求的可预测性。
|
|
770
|
+
|
|
771
|
+
#### 默认行为(禁用重试)
|
|
772
|
+
|
|
773
|
+
```typescript
|
|
774
|
+
const client = new SeaVerseBackendAPIClient({
|
|
775
|
+
appId: 'your app id',
|
|
776
|
+
// retryOptions 未设置,默认不重试
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
// 如果请求失败,会立即返回错误,不会重试
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
#### 启用基础重试
|
|
783
|
+
|
|
784
|
+
```typescript
|
|
785
|
+
import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
|
|
786
|
+
|
|
787
|
+
const client = new SeaVerseBackendAPIClient({
|
|
788
|
+
appId: 'your app id',
|
|
789
|
+
retryOptions: {
|
|
790
|
+
maxRetries: 3, // 最多重试 3 次
|
|
791
|
+
retryDelay: 1000, // 初始延迟 1000ms (1秒)
|
|
792
|
+
// 默认会对以下状态码重试:[408, 429, 500, 502, 503, 504]
|
|
793
|
+
},
|
|
794
|
+
});
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
**重试策略说明**:
|
|
798
|
+
- 采用**指数退避**算法:第1次等待1秒,第2次等待2秒,第3次等待4秒
|
|
799
|
+
- 自动重试的 HTTP 状态码:
|
|
800
|
+
- `408` - Request Timeout(请求超时)
|
|
801
|
+
- `429` - Too Many Requests(限流)
|
|
802
|
+
- `500` - Internal Server Error(服务器内部错误)
|
|
803
|
+
- `502` - Bad Gateway(网关错误)
|
|
804
|
+
- `503` - Service Unavailable(服务不可用)
|
|
805
|
+
- `504` - Gateway Timeout(网关超时)
|
|
806
|
+
- 网络错误(无响应)也会触发重试
|
|
807
|
+
|
|
808
|
+
#### 自定义重试状态码
|
|
809
|
+
|
|
810
|
+
```typescript
|
|
811
|
+
const client = new SeaVerseBackendAPIClient({
|
|
812
|
+
appId: 'your app id',
|
|
813
|
+
retryOptions: {
|
|
814
|
+
maxRetries: 5,
|
|
815
|
+
retryDelay: 2000,
|
|
816
|
+
retryStatusCodes: [503, 504], // 只对 503 和 504 重试
|
|
817
|
+
},
|
|
818
|
+
});
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
#### 自定义重试逻辑
|
|
822
|
+
|
|
823
|
+
```typescript
|
|
824
|
+
import type { RetryOptions } from '@seaverse/auth-sdk';
|
|
825
|
+
|
|
826
|
+
const retryOptions: RetryOptions = {
|
|
827
|
+
maxRetries: 3,
|
|
828
|
+
retryDelay: 1000,
|
|
829
|
+
// 自定义判断逻辑:只对特定错误重试
|
|
830
|
+
shouldRetry: (error) => {
|
|
831
|
+
// 只对服务不可用错误重试
|
|
832
|
+
if (error.response?.status === 503) {
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
// 对没有响应的网络错误重试
|
|
836
|
+
if (!error.response) {
|
|
837
|
+
return true;
|
|
838
|
+
}
|
|
839
|
+
return false;
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
const client = new SeaVerseBackendAPIClient({
|
|
844
|
+
appId: 'your app id',
|
|
845
|
+
retryOptions,
|
|
846
|
+
});
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
#### RetryOptions 类型定义
|
|
850
|
+
|
|
851
|
+
```typescript
|
|
852
|
+
interface RetryOptions {
|
|
853
|
+
maxRetries?: number; // 最大重试次数,默认 0(禁用)
|
|
854
|
+
retryDelay?: number; // 初始重试延迟(毫秒),默认 1000
|
|
855
|
+
retryStatusCodes?: number[]; // 触发重试的状态码列表
|
|
856
|
+
shouldRetry?: (error: AxiosError) => boolean; // 自定义重试判断函数
|
|
857
|
+
}
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
**使用建议**:
|
|
861
|
+
- ⚠️ **生产环境建议禁用重试**(默认行为),避免在业务逻辑错误时产生重复请求
|
|
862
|
+
- ✅ 仅在网络不稳定的场景启用重试,如移动端应用、弱网环境
|
|
863
|
+
- ✅ 确保后端 API 支持幂等性操作,避免重试导致的副作用
|
|
864
|
+
- ✅ 对于关键业务(如支付),建议使用自定义 `shouldRetry` 仔细控制重试逻辑
|
|
865
|
+
|
|
529
866
|
### 环境配置
|
|
530
867
|
|
|
531
868
|
SDK支持以下环境:
|
|
@@ -550,14 +887,53 @@ SDK支持以下环境:
|
|
|
550
887
|
| 方法 | 参数 | 返回值 | 说明 |
|
|
551
888
|
|------|------|--------|------|
|
|
552
889
|
| `register()` | `{ email, password, username?, invitation_code?, frontend_url? }` | `RegisterResponse` | 注册新用户,frontend_url 为邮箱验证链接的前端URL,默认为 window.location.origin |
|
|
553
|
-
| `login()` | `{ email, password }` | `LoginResponse` |
|
|
890
|
+
| `login()` | `{ email, password, frontend_url? }` | `LoginResponse` | 用户登录,frontend_url 用于未验证邮箱时发送验证邮件,默认为 https://seaverse.ai/ |
|
|
554
891
|
| `getCurrentUser()` | - | `User` | 获取当前用户 |
|
|
555
892
|
| `logout()` | - | `SuccessResponse` | 登出 |
|
|
893
|
+
| `verifyEmail()` | `verifyToken: string` | `EmailVerificationResponse` | 验证邮箱并返回自动登录 token |
|
|
894
|
+
| `bindInviteCode()` | `{ user_id, invite_code }` | `BindInviteCodeResponse` | 绑定邀请码激活临时账户并自动登录 |
|
|
556
895
|
| `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | 忘记密码,frontend_url 默认为 window.location.origin |
|
|
557
896
|
| `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
|
|
558
897
|
| `setToken()` | `token: string` | `void` | 设置认证 token(OAuth 登录后使用) |
|
|
559
898
|
| `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
|
|
560
899
|
|
|
900
|
+
#### 注册流程说明
|
|
901
|
+
|
|
902
|
+
`register()` 方法支持三种注册流程,SDK 会根据后端响应自动处理:
|
|
903
|
+
|
|
904
|
+
**流程 1: 立即激活(默认)**
|
|
905
|
+
```typescript
|
|
906
|
+
const response = await client.register({ email, password });
|
|
907
|
+
// response.success === true
|
|
908
|
+
// response.requiresEmailVerification === undefined (或 false)
|
|
909
|
+
// response.requiresInvitationCode === undefined (或 false)
|
|
910
|
+
// → SDK 自动调用 login() 并触发 onSignupSuccess 回调
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
**流程 2: 需要邮箱验证**
|
|
914
|
+
```typescript
|
|
915
|
+
const response = await client.register({ email, password });
|
|
916
|
+
// response.success === true
|
|
917
|
+
// response.requiresEmailVerification === true
|
|
918
|
+
// → SDK 显示 Toast 提示用户检查邮箱
|
|
919
|
+
// → 不会自动调用 login(),用户需要点击邮件中的验证链接
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
**流程 3: 需要邀请码激活**
|
|
923
|
+
```typescript
|
|
924
|
+
const response = await client.register({ email, password });
|
|
925
|
+
// response.success === true
|
|
926
|
+
// response.requiresInvitationCode === true
|
|
927
|
+
// response.tempUserId === "temp_xxx"
|
|
928
|
+
// → SDK 显示邀请码输入表单
|
|
929
|
+
// → 不会自动调用 login(),用户需要输入邀请码
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
**重要提示**:
|
|
933
|
+
- AuthModal 会自动处理这三种流程,无需手动判断
|
|
934
|
+
- 只有在无需验证或激活的情况下,才会自动调用 `login()`
|
|
935
|
+
- 这避免了在邮箱未验证或账户未激活时产生不必要的登录请求
|
|
936
|
+
|
|
561
937
|
### OAuth相关
|
|
562
938
|
|
|
563
939
|
| 方法 | 参数 | 返回值 | 说明 |
|
|
@@ -590,6 +966,15 @@ SDK支持以下环境:
|
|
|
590
966
|
| `listUserSkills()` | - | `UserInstalledSkillsListResponse` | 列出已安装技能 |
|
|
591
967
|
| `uninstallSkill()` | `{ skillId }` | `SuccessResponse` | 卸载技能 |
|
|
592
968
|
|
|
969
|
+
### 邀请码管理
|
|
970
|
+
|
|
971
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
972
|
+
|------|------|--------|------|
|
|
973
|
+
| `listInvites()` | `{ page?, page_size?, status? }` | `ListInvitesResponse` | 列出我的邀请码 |
|
|
974
|
+
| `getInviteStats()` | - | `InviteStatsResponse` | 获取邀请码统计 |
|
|
975
|
+
| `getInvite()` | `inviteId: string` | `InviteCodeDetailResponse` | 获取邀请码详情 |
|
|
976
|
+
| `getInviteUsages()` | `inviteId: string, { page?, page_size? }` | `ListInviteUsagesResponse` | 获取邀请码使用记录 |
|
|
977
|
+
|
|
593
978
|
### 其他
|
|
594
979
|
|
|
595
980
|
| 方法 | 参数 | 返回值 | 说明 |
|
|
@@ -598,6 +983,74 @@ SDK支持以下环境:
|
|
|
598
983
|
| `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | 获取对话状态 |
|
|
599
984
|
| `getSpeechToken()` | - | `SpeechTokenResponse` | 获取语音Token |
|
|
600
985
|
|
|
986
|
+
## 响应格式兼容性
|
|
987
|
+
|
|
988
|
+
### 自动响应解包
|
|
989
|
+
|
|
990
|
+
从 v0.2.5 开始,SDK 自动兼容两种API响应格式,无需手动处理:
|
|
991
|
+
|
|
992
|
+
**格式 1: 包装格式**(推荐)
|
|
993
|
+
```json
|
|
994
|
+
{
|
|
995
|
+
"data": {
|
|
996
|
+
"token": "eyJhbGc...",
|
|
997
|
+
"user": { ... }
|
|
998
|
+
},
|
|
999
|
+
"success": true
|
|
1000
|
+
}
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
**格式 2: 扁平格式**(向后兼容)
|
|
1004
|
+
```json
|
|
1005
|
+
{
|
|
1006
|
+
"token": "eyJhbGc...",
|
|
1007
|
+
"user": { ... }
|
|
1008
|
+
}
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
SDK 会自动检测响应格式并提取正确的数据:
|
|
1012
|
+
|
|
1013
|
+
```typescript
|
|
1014
|
+
// 无论后端返回哪种格式,以下代码都能正常工作
|
|
1015
|
+
const loginResult = await client.login({
|
|
1016
|
+
email: 'user@example.com',
|
|
1017
|
+
password: 'password123',
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
console.log(loginResult.token); // ✅ 始终能正确获取 token
|
|
1021
|
+
console.log(loginResult.user); // ✅ 始终能正确获取 user
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
### 受影响的方法
|
|
1025
|
+
|
|
1026
|
+
以下方法已实现自动响应解包:
|
|
1027
|
+
|
|
1028
|
+
- ✅ `login()` - 登录接口
|
|
1029
|
+
- ✅ `register()` - 注册接口
|
|
1030
|
+
- ✅ `getCurrentUser()` - 获取当前用户
|
|
1031
|
+
|
|
1032
|
+
### 实现原理
|
|
1033
|
+
|
|
1034
|
+
SDK 内部通过以下逻辑自动处理响应格式:
|
|
1035
|
+
|
|
1036
|
+
```typescript
|
|
1037
|
+
const response = await httpClient.request(config);
|
|
1038
|
+
const responseData = response.data;
|
|
1039
|
+
|
|
1040
|
+
// 检测并解包
|
|
1041
|
+
if (responseData.data && typeof responseData.data === 'object') {
|
|
1042
|
+
// 包装格式: 提取 data 字段
|
|
1043
|
+
return responseData.data;
|
|
1044
|
+
}
|
|
1045
|
+
// 扁平格式: 直接返回
|
|
1046
|
+
return responseData;
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
这意味着:
|
|
1050
|
+
- 🔄 **后端格式变更无需前端修改** - 后端可以自由调整响应格式
|
|
1051
|
+
- 🔧 **渐进式迁移** - 可以逐步将不同接口迁移到新格式
|
|
1052
|
+
- ✅ **向后兼容** - 旧代码无需修改即可继续工作
|
|
1053
|
+
|
|
601
1054
|
## 错误处理
|
|
602
1055
|
|
|
603
1056
|
### 错误响应格式
|
|
@@ -846,8 +1299,17 @@ interface LoginResponse {
|
|
|
846
1299
|
// 注册响应
|
|
847
1300
|
interface RegisterResponse {
|
|
848
1301
|
success: boolean;
|
|
849
|
-
message
|
|
850
|
-
userId
|
|
1302
|
+
message?: string;
|
|
1303
|
+
userId?: string;
|
|
1304
|
+
// 邮箱验证相关
|
|
1305
|
+
requiresEmailVerification?: boolean; // 是否需要邮箱验证
|
|
1306
|
+
// 邀请码激活相关
|
|
1307
|
+
requiresInvitationCode?: boolean; // 是否需要邀请码激活
|
|
1308
|
+
tempUserId?: string; // 临时用户ID(需要激活)
|
|
1309
|
+
// 错误信息
|
|
1310
|
+
error?: string;
|
|
1311
|
+
code?: string; // 如 'ACCOUNT_EXISTS'
|
|
1312
|
+
details?: Record<string, any>;
|
|
851
1313
|
}
|
|
852
1314
|
|
|
853
1315
|
// AuthModal选项
|
|
@@ -856,6 +1318,7 @@ interface AuthModalOptions {
|
|
|
856
1318
|
theme?: 'dark' | 'light';
|
|
857
1319
|
onLoginSuccess?: (token: string, user: any) => void;
|
|
858
1320
|
onSignupSuccess?: (token: string, user: any) => void;
|
|
1321
|
+
onInviteCodeRequired?: (userId: string, email: string) => void; // 当需要邀请码激活时的回调
|
|
859
1322
|
onError?: (error: Error) => void;
|
|
860
1323
|
returnUrl?: string; // OAuth 登录后返回的 URL,可选,默认为 window.location.origin
|
|
861
1324
|
enableOAuth?: {
|
|
@@ -1033,7 +1496,14 @@ MIT © [SeaVerse Team](mailto:support@seaverse.com)
|
|
|
1033
1496
|
|
|
1034
1497
|
## 更新日志
|
|
1035
1498
|
|
|
1036
|
-
### v0.2.
|
|
1499
|
+
### v0.2.5 (当前版本)
|
|
1500
|
+
- 🔄 **响应格式兼容**: 自动兼容包装格式和扁平格式的API响应
|
|
1501
|
+
- 修复登录时提示 "Invalid response from server" 的问题
|
|
1502
|
+
- `login()`, `register()`, `getCurrentUser()` 方法自动解包 `data` 字段
|
|
1503
|
+
- 支持两种格式: `{ data: {...}, success: true }` 和 `{ ... }`
|
|
1504
|
+
- 📝 **文档更新**: 新增响应格式兼容性章节
|
|
1505
|
+
|
|
1506
|
+
### v0.2.0
|
|
1037
1507
|
- 🔄 **API路径更新**: 所有认证API从 `/api/auth/*` 迁移到 `/sdk/v1/auth/*`
|
|
1038
1508
|
- 🏢 **多租户支持**: User模型新增 `app_id` 字段,支持多应用隔离
|
|
1039
1509
|
- 🔑 **重要变更**: `appId` 现在是**必需参数**,SDK 自动在所有请求中添加 `X-App-ID` 请求头
|