@seaverse/auth-sdk 0.2.6 → 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 CHANGED
@@ -10,6 +10,7 @@ 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 获取
@@ -81,6 +82,16 @@ const client = new SeaVerseBackendAPIClient({
81
82
  baseURL: 'https://custom-api.example.com',
82
83
  });
83
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
+
84
95
  // 健康检查
85
96
  const health = await client.getHealth();
86
97
  console.log('Health:', health);
@@ -246,6 +257,12 @@ const authModal = new AuthModal({
246
257
  console.log('注册成功:', user);
247
258
  },
248
259
 
260
+ // 邀请码需求回调(可选)
261
+ onInviteCodeRequired: (userId, email) => {
262
+ console.log('需要邀请码激活账户:', userId, email);
263
+ // AuthModal 会自动显示邀请码输入界面
264
+ },
265
+
249
266
  // 错误回调
250
267
  onError: (error) => {
251
268
  console.error('认证错误:', error.message);
@@ -273,15 +290,35 @@ authModal.hide();
273
290
  authModal.destroy();
274
291
  ```
275
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
+
276
313
  #### 重置密码流程
277
314
 
278
315
  AuthModal 支持完整的密码重置流程:
279
316
 
280
317
  1. **用户触发忘记密码**:在登录界面点击 "Forgot Password?" 链接
281
- 2. **发送重置邮件**:输入邮箱后,系统发送带有 `verify_token` 的重置链接
282
- 3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `verify_token` 参数并显示重置密码表单
318
+ 2. **发送重置邮件**:输入邮箱后,系统发送带有 `reset_token` 的重置链接
319
+ 3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `reset_token` 参数并显示重置密码表单
283
320
  4. **设置新密码**:用户输入并确认新密码后提交
284
- 5. **自动清理 URL**:重置成功后自动清除 URL 中的 `verify_token` 参数
321
+ 5. **自动清理 URL**:重置成功后自动清除 URL 中的 `reset_token` 参数
285
322
 
286
323
  整个流程无需额外代码,AuthModal 会自动处理:
287
324
 
@@ -293,11 +330,11 @@ const authModal = new AuthModal({
293
330
  });
294
331
 
295
332
  // 2. 用户点击邮件中的重置链接后,AuthModal 会自动:
296
- // - 检测 URL 中的 ?verify_token=xxx 参数
333
+ // - 检测 URL 中的 ?reset_token=xxx 参数
297
334
  // - 显示重置密码表单
298
335
  // - 用户提交新密码
299
336
  // - 调用 client.resetPassword() API
300
- // - 清理 URL 中的 verify_token 参数
337
+ // - 清理 URL 中的 reset_token 参数
301
338
  // - 显示成功消息
302
339
  ```
303
340
 
@@ -455,7 +492,207 @@ await client.uninstallSkill({
455
492
  });
456
493
  ```
457
494
 
458
- ### 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. 其他功能
459
696
 
460
697
  ```typescript
461
698
  // 获取API Service Token
@@ -527,6 +764,105 @@ const client = new SeaVerseBackendAPIClient({
527
764
  });
528
765
  ```
529
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
+
530
866
  ### 环境配置
531
867
 
532
868
  SDK支持以下环境:
@@ -551,14 +887,53 @@ SDK支持以下环境:
551
887
  | 方法 | 参数 | 返回值 | 说明 |
552
888
  |------|------|--------|------|
553
889
  | `register()` | `{ email, password, username?, invitation_code?, frontend_url? }` | `RegisterResponse` | 注册新用户,frontend_url 为邮箱验证链接的前端URL,默认为 window.location.origin |
554
- | `login()` | `{ email, password }` | `LoginResponse` | 用户登录 |
890
+ | `login()` | `{ email, password, frontend_url? }` | `LoginResponse` | 用户登录,frontend_url 用于未验证邮箱时发送验证邮件,默认为 https://seaverse.ai/ |
555
891
  | `getCurrentUser()` | - | `User` | 获取当前用户 |
556
892
  | `logout()` | - | `SuccessResponse` | 登出 |
893
+ | `verifyEmail()` | `verifyToken: string` | `EmailVerificationResponse` | 验证邮箱并返回自动登录 token |
894
+ | `bindInviteCode()` | `{ user_id, invite_code }` | `BindInviteCodeResponse` | 绑定邀请码激活临时账户并自动登录 |
557
895
  | `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | 忘记密码,frontend_url 默认为 window.location.origin |
558
896
  | `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
559
897
  | `setToken()` | `token: string` | `void` | 设置认证 token(OAuth 登录后使用) |
560
898
  | `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
561
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
+
562
937
  ### OAuth相关
563
938
 
564
939
  | 方法 | 参数 | 返回值 | 说明 |
@@ -591,6 +966,15 @@ SDK支持以下环境:
591
966
  | `listUserSkills()` | - | `UserInstalledSkillsListResponse` | 列出已安装技能 |
592
967
  | `uninstallSkill()` | `{ skillId }` | `SuccessResponse` | 卸载技能 |
593
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
+
594
978
  ### 其他
595
979
 
596
980
  | 方法 | 参数 | 返回值 | 说明 |
@@ -915,8 +1299,17 @@ interface LoginResponse {
915
1299
  // 注册响应
916
1300
  interface RegisterResponse {
917
1301
  success: boolean;
918
- message: string;
919
- userId: string;
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>;
920
1313
  }
921
1314
 
922
1315
  // AuthModal选项
@@ -925,6 +1318,7 @@ interface AuthModalOptions {
925
1318
  theme?: 'dark' | 'light';
926
1319
  onLoginSuccess?: (token: string, user: any) => void;
927
1320
  onSignupSuccess?: (token: string, user: any) => void;
1321
+ onInviteCodeRequired?: (userId: string, email: string) => void; // 当需要邀请码激活时的回调
928
1322
  onError?: (error: Error) => void;
929
1323
  returnUrl?: string; // OAuth 登录后返回的 URL,可选,默认为 window.location.origin
930
1324
  enableOAuth?: {