@seaverse/auth-sdk 0.2.2 → 0.2.3

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
@@ -96,6 +96,14 @@ const registerResult = await client.register({
96
96
  invitation_code: 'INVITE123', // 可选
97
97
  });
98
98
 
99
+ // 检查注册结果
100
+ if (registerResult.success) {
101
+ console.log('注册成功:', registerResult);
102
+ } else if (registerResult.code === 'ACCOUNT_EXISTS') {
103
+ console.log('账户已存在,请直接登录');
104
+ console.log('错误详情:', registerResult.details);
105
+ }
106
+
99
107
  // 登录
100
108
  const loginResult = await client.login({
101
109
  email: 'user@example.com',
@@ -560,6 +568,222 @@ SDK支持以下环境:
560
568
  | `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | 获取对话状态 |
561
569
  | `getSpeechToken()` | - | `SpeechTokenResponse` | 获取语音Token |
562
570
 
571
+ ## 错误处理
572
+
573
+ ### 错误响应格式
574
+
575
+ 所有 API 错误都遵循统一的响应格式:
576
+
577
+ ```typescript
578
+ interface ApiError {
579
+ success: false; // 错误时始终为 false
580
+ error: string; // 人类可读的错误消息
581
+ code?: string; // 机器可读的错误码
582
+ details?: any; // 额外的错误详情
583
+ }
584
+ ```
585
+
586
+ ### 错误码
587
+
588
+ SDK 提供了标准的错误码枚举:
589
+
590
+ ```typescript
591
+ import { ErrorCode } from '@seaverse/auth-sdk';
592
+
593
+ // 账户相关错误
594
+ ErrorCode.ACCOUNT_EXISTS // 账户已存在
595
+ ErrorCode.ACCOUNT_NOT_FOUND // 账户不存在
596
+ ErrorCode.ACCOUNT_SUSPENDED // 账户已被暂停
597
+ ErrorCode.INVALID_CREDENTIALS // 登录凭证无效
598
+ ErrorCode.EMAIL_NOT_VERIFIED // 邮箱未验证
599
+
600
+ // 验证相关错误
601
+ ErrorCode.INVALID_EMAIL // 无效的邮箱地址
602
+ ErrorCode.INVALID_PASSWORD // 无效的密码
603
+ ErrorCode.PASSWORD_TOO_WEAK // 密码强度不够
604
+
605
+ // 邀请码相关错误
606
+ ErrorCode.INVALID_INVITATION_CODE // 无效的邀请码
607
+ ErrorCode.INVITATION_REQUIRED // 需要邀请码
608
+
609
+ // Token 相关错误
610
+ ErrorCode.INVALID_TOKEN // 无效的 token
611
+ ErrorCode.TOKEN_EXPIRED // Token 已过期
612
+
613
+ // 内部错误
614
+ ErrorCode.INTERNAL_ERROR // 服务器内部错误
615
+ ```
616
+
617
+ ### 错误处理最佳实践
618
+
619
+ #### 1. 注册时处理重复用户
620
+
621
+ 由于后端在账户已存在时返回 200 OK(成功响应),所以前端不会抛出异常,而是在响应体中包含错误信息。
622
+
623
+ ```typescript
624
+ import { ErrorCode } from '@seaverse/auth-sdk';
625
+
626
+ const result = await client.register({
627
+ email: 'user@example.com',
628
+ password: 'password123',
629
+ });
630
+
631
+ // 检查响应中的 success 字段
632
+ if (result.success) {
633
+ console.log('注册成功:', result);
634
+ // 进行后续操作,如自动登录
635
+ } else if (result.code === ErrorCode.ACCOUNT_EXISTS) {
636
+ // 账户已存在,提示用户
637
+ const { email, app_id } = result.details;
638
+ console.log(`账户 ${email} 已存在于应用 ${app_id} 中`);
639
+
640
+ // 显示友好的提示信息
641
+ alert('This email is already registered. Please login instead.');
642
+
643
+ // 或者引导用户去登录
644
+ showLoginModal();
645
+ } else {
646
+ // 处理其他错误
647
+ console.error('注册失败:', result.error);
648
+ }
649
+ ```
650
+
651
+ #### 2. 登录时处理各种错误
652
+
653
+ ```typescript
654
+ try {
655
+ const result = await client.login({
656
+ email: 'user@example.com',
657
+ password: 'wrong-password',
658
+ });
659
+ console.log('登录成功:', result);
660
+ } catch (error) {
661
+ const errorCode = error.response?.data?.code;
662
+
663
+ switch (errorCode) {
664
+ case ErrorCode.INVALID_CREDENTIALS:
665
+ showError('用户名或密码错误');
666
+ break;
667
+ case ErrorCode.EMAIL_NOT_VERIFIED:
668
+ showError('请先验证您的邮箱');
669
+ showResendVerificationButton();
670
+ break;
671
+ case ErrorCode.ACCOUNT_SUSPENDED:
672
+ showError('您的账户已被暂停,请联系管理员');
673
+ break;
674
+ default:
675
+ showError('登录失败,请稍后重试');
676
+ }
677
+ }
678
+ ```
679
+
680
+ #### 3. 通用错误处理函数
681
+
682
+ ```typescript
683
+ import { ErrorCode } from '@seaverse/auth-sdk';
684
+
685
+ function handleApiError(error: any) {
686
+ const apiError = error.response?.data;
687
+
688
+ if (!apiError) {
689
+ // 网络错误或其他未知错误
690
+ return {
691
+ title: '网络错误',
692
+ message: '请检查您的网络连接',
693
+ };
694
+ }
695
+
696
+ // 根据错误码返回用户友好的消息
697
+ const errorMessages: Record<string, { title: string; message: string }> = {
698
+ [ErrorCode.ACCOUNT_EXISTS]: {
699
+ title: '账户已存在',
700
+ message: '该邮箱已注册,请直接登录',
701
+ },
702
+ [ErrorCode.INVALID_CREDENTIALS]: {
703
+ title: '登录失败',
704
+ message: '用户名或密码错误',
705
+ },
706
+ [ErrorCode.EMAIL_NOT_VERIFIED]: {
707
+ title: '邮箱未验证',
708
+ message: '请先验证您的邮箱地址',
709
+ },
710
+ [ErrorCode.INVALID_INVITATION_CODE]: {
711
+ title: '邀请码无效',
712
+ message: '请检查您的邀请码是否正确',
713
+ },
714
+ [ErrorCode.TOKEN_EXPIRED]: {
715
+ title: '登录已过期',
716
+ message: '请重新登录',
717
+ },
718
+ };
719
+
720
+ return errorMessages[apiError.code] || {
721
+ title: '操作失败',
722
+ message: apiError.error || '发生未知错误',
723
+ };
724
+ }
725
+
726
+ // 使用示例
727
+ try {
728
+ await client.register({ email, password });
729
+ } catch (error) {
730
+ const { title, message } = handleApiError(error);
731
+ showNotification(title, message);
732
+ }
733
+ ```
734
+
735
+ #### 4. TypeScript 类型安全的错误处理
736
+
737
+ ```typescript
738
+ import { ErrorCode, models } from '@seaverse/auth-sdk';
739
+
740
+ async function safeRegister(email: string, password: string) {
741
+ // Register API now returns 200 OK for both success and account exists cases
742
+ const result = await client.register({ email, password });
743
+
744
+ if (result.success) {
745
+ return {
746
+ success: true,
747
+ data: result,
748
+ };
749
+ } else if (result.code === ErrorCode.ACCOUNT_EXISTS) {
750
+ // TypeScript knows the type of details
751
+ const details = result.details as models.AccountExistsErrorDetails;
752
+ return {
753
+ success: false,
754
+ error: 'ACCOUNT_EXISTS',
755
+ email: details.email,
756
+ appId: details.app_id,
757
+ };
758
+ } else {
759
+ return {
760
+ success: false,
761
+ error: result.error || 'Unknown error',
762
+ };
763
+ }
764
+ }
765
+
766
+ // Usage
767
+ const registerResult = await safeRegister('user@example.com', 'password123');
768
+ if (registerResult.success) {
769
+ console.log('Registration successful');
770
+ } else if (registerResult.error === 'ACCOUNT_EXISTS') {
771
+ console.log(`Account already exists: ${registerResult.email}`);
772
+ }
773
+ ```
774
+
775
+ ### HTTP 状态码对照
776
+
777
+ | HTTP状态码 | 错误码示例 | 说明 |
778
+ |-----------|----------|------|
779
+ | 200 OK | `ACCOUNT_EXISTS` | 账户已存在(业务错误但返回成功响应) |
780
+ | 400 Bad Request | `INVALID_EMAIL`, `PASSWORD_TOO_WEAK` | 请求参数无效 |
781
+ | 401 Unauthorized | `INVALID_CREDENTIALS`, `TOKEN_EXPIRED` | 认证失败 |
782
+ | 403 Forbidden | `EMAIL_NOT_VERIFIED`, `ACCOUNT_SUSPENDED` | 权限不足 |
783
+ | 500 Internal Server Error | `INTERNAL_ERROR` | 服务器内部错误 |
784
+
785
+ **注意**:对于注册接口,账户已存在的情况会返回 200 OK,但在响应体中 `success: false` 和 `code: "ACCOUNT_EXISTS"`。这样设计是为了前端能够更容易地处理这种常见的业务场景。
786
+
563
787
  ## 类型定义
564
788
 
565
789
  ```typescript
package/dist/index.cjs CHANGED
@@ -1136,9 +1136,37 @@ function resolveBaseURL(options) {
1136
1136
  * Type definitions for SeaVerse Dispatcher API
1137
1137
  * Generated from auth.yaml OpenAPI specification
1138
1138
  */
1139
+ // ============================================================================
1140
+ // Error Types
1141
+ // ============================================================================
1142
+ /**
1143
+ * Error codes for authentication system
1144
+ */
1145
+ exports.ErrorCode = void 0;
1146
+ (function (ErrorCode) {
1147
+ // Account errors
1148
+ ErrorCode["ACCOUNT_EXISTS"] = "ACCOUNT_EXISTS";
1149
+ ErrorCode["ACCOUNT_NOT_FOUND"] = "ACCOUNT_NOT_FOUND";
1150
+ ErrorCode["ACCOUNT_SUSPENDED"] = "ACCOUNT_SUSPENDED";
1151
+ ErrorCode["INVALID_CREDENTIALS"] = "INVALID_CREDENTIALS";
1152
+ ErrorCode["EMAIL_NOT_VERIFIED"] = "EMAIL_NOT_VERIFIED";
1153
+ // Validation errors
1154
+ ErrorCode["INVALID_EMAIL"] = "INVALID_EMAIL";
1155
+ ErrorCode["INVALID_PASSWORD"] = "INVALID_PASSWORD";
1156
+ ErrorCode["PASSWORD_TOO_WEAK"] = "PASSWORD_TOO_WEAK";
1157
+ // Invitation errors
1158
+ ErrorCode["INVALID_INVITATION_CODE"] = "INVALID_INVITATION_CODE";
1159
+ ErrorCode["INVITATION_REQUIRED"] = "INVITATION_REQUIRED";
1160
+ // Token errors
1161
+ ErrorCode["INVALID_TOKEN"] = "INVALID_TOKEN";
1162
+ ErrorCode["TOKEN_EXPIRED"] = "TOKEN_EXPIRED";
1163
+ // Internal errors
1164
+ ErrorCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
1165
+ })(exports.ErrorCode || (exports.ErrorCode = {}));
1139
1166
 
1140
1167
  var models = /*#__PURE__*/Object.freeze({
1141
- __proto__: null
1168
+ __proto__: null,
1169
+ get ErrorCode () { return exports.ErrorCode; }
1142
1170
  });
1143
1171
 
1144
1172
  /**
@@ -2444,13 +2472,22 @@ class AuthModal {
2444
2472
  this.showMessage('Account Created', response.message || 'Your account has been created successfully!');
2445
2473
  }
2446
2474
  }
2475
+ else if (response.code === exports.ErrorCode.ACCOUNT_EXISTS) {
2476
+ // Handle account already exists error
2477
+ this.showMessage('Account Already Exists', 'This email is already registered. Please login instead.');
2478
+ }
2447
2479
  else {
2448
- throw new Error('Registration failed');
2480
+ throw new Error(response.error || 'Registration failed');
2449
2481
  }
2450
2482
  }
2451
2483
  catch (error) {
2452
- // Handle error
2453
- const errorMessage = error instanceof Error ? error.message : 'Signup failed';
2484
+ // Handle HTTP errors
2485
+ if (error.response?.data?.code === exports.ErrorCode.ACCOUNT_EXISTS) {
2486
+ this.showMessage('Account Already Exists', 'This email is already registered. Please login instead.');
2487
+ return;
2488
+ }
2489
+ // Handle other errors
2490
+ const errorMessage = error.response?.data?.error || error.message || 'Signup failed';
2454
2491
  this.showError(errorMessage);
2455
2492
  if (this.options.onError) {
2456
2493
  this.options.onError(error);
@@ -2473,8 +2510,8 @@ class AuthModal {
2473
2510
  try {
2474
2511
  // Show loading state
2475
2512
  submitBtn.disabled = true;
2476
- // TODO: Call forgot password API when available
2477
- // await this.client.postapiauthforgotpassword({ email });
2513
+ // Call forgot password API
2514
+ await this.client.forgotPassword({ email });
2478
2515
  // Show success message
2479
2516
  this.showMessage('Reset Link Sent', `We've sent a password reset link to ${email}`);
2480
2517
  }