@seaverse/auth-sdk 0.4.1 → 0.4.2

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
@@ -1,129 +1,129 @@
1
1
  # @seaverse/auth-sdk
2
2
 
3
- SeaVerse Backend API 客户端 SDK - 提供完整的认证、容器管理、技能市场等功能
3
+ SeaVerse Backend API Client SDK - Provides complete authentication, container management, skill marketplace, and more
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@seaverse/auth-sdk.svg)](https://www.npmjs.com/package/@seaverse/auth-sdk)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- ## 功能特性
8
+ ## Features
9
9
 
10
- - 🔐 **用户认证** - 注册、登录、登出、密码重置
11
- - 🌐 **OAuth登录** - GoogleDiscordGitHub 第三方登录
12
- - 🎨 **登录UI组件** - 开箱即用的精美登录弹窗
13
- - ✨ **Toast 通知** - 现代化玻璃态提示,CSS 自动注入
14
- - 🌍 **多环境支持** - ProductionStagingDevelopmentLocal
15
- - ⚡ **TypeScript** - 完整的类型定义
16
- - 🔧 **认证集成** - 内置AuthHooks系统支持
17
- - 🔄 **响应格式兼容** - 自动兼容多种API响应格式
10
+ - 🔐 **User Authentication** - Registration, login, logout, password reset
11
+ - 🌐 **OAuth Login** - Google, Discord, GitHub third-party login
12
+ - 🎨 **Login UI Components** - Out-of-the-box beautiful login modal
13
+ - ✨ **Toast Notifications** - Modern glassmorphism alerts with auto-injected CSS
14
+ - 🌍 **Multi-Environment Support** - Production, Staging, Development, Local
15
+ - ⚡ **TypeScript** - Full type definitions
16
+ - 🔧 **Auth Integration** - Built-in Auth and Hooks system support
17
+ - 🔄 **Response Format Compatibility** - Automatic compatibility with multiple API response formats
18
18
 
19
- ## 安装
19
+ ## Installation
20
20
 
21
21
  ```bash
22
22
  npm install @seaverse/auth-sdk
23
- #
23
+ # or
24
24
  pnpm add @seaverse/auth-sdk
25
25
  ```
26
26
 
27
- ## 核心概念
27
+ ## Core Concepts
28
28
 
29
- ### App ID 和多租户架构
29
+ ### App ID and Multi-Tenant Architecture
30
30
 
31
- **重要**: v0.2.0 开始,`appId` 是初始化 SDK 时的**必需参数**。
31
+ **Important**: Starting from v0.2.0, `appId` is a **required parameter** when initializing the SDK.
32
32
 
33
- #### 什么是 App ID
33
+ #### What is App ID?
34
34
 
35
- 每个应用都有唯一的 `app_id`:
35
+ Each application has a unique `app_id`:
36
36
  - `app_id = "your app id"`
37
37
 
38
- #### 多租户隔离
38
+ #### Multi-Tenant Isolation
39
39
 
40
- - 用户数据按 `app_id` 隔离
41
- - 同一邮箱可在不同应用中注册,使用不同密码
42
- - 每个应用拥有独立的用户池
40
+ - User data is isolated by `app_id`
41
+ - The same email can be registered in different applications with different passwords
42
+ - Each application has its own independent user pool
43
43
 
44
- #### X-App-ID 请求头
44
+ #### X-App-ID Request Header
45
45
 
46
- SDK 会自动在**每个请求**的请求头中添加 `X-App-ID`,无需手动设置:
46
+ The SDK automatically adds `X-App-ID` to **every request** header, no manual configuration needed:
47
47
 
48
48
  ```typescript
49
49
  const client = new SeaVerseBackendAPIClient({
50
- appId: 'game-abc123', // SDK 自动将此值添加到所有请求的 X-App-ID header
50
+ appId: 'game-abc123', // SDK automatically adds this value to all requests' X-App-ID header
51
51
  });
52
52
 
53
- // 所有 API 调用都会自动携带 X-App-ID: game-abc123
53
+ // All API calls will automatically carry X-App-ID: game-abc123
54
54
  await client.login({ email, password });
55
55
  await client.getCurrentUser();
56
56
  ```
57
57
 
58
- ## 快速开始
58
+ ## Quick Start
59
59
 
60
- ### 1. 基本使用
60
+ ### 1. Basic Usage
61
61
 
62
62
  ```typescript
63
63
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
64
64
 
65
- // 方式1: SeaVerse 平台应用(自动检测环境)
65
+ // Method 1: SeaVerse platform application (auto-detect environment)
66
66
  const client = new SeaVerseBackendAPIClient({
67
- appId: 'your app id', // 必需:应用ID
67
+ appId: 'your app id', // Required: Application ID
68
68
  });
69
69
 
70
- // 方式2: 第三方应用(指定环境)
70
+ // Method 2: Third-party application (specify environment)
71
71
  const client = new SeaVerseBackendAPIClient({
72
- appId: 'your app id', // 必需:您的应用ID
72
+ appId: 'your app id', // Required: Your application ID
73
73
  environment: 'production', // 'production' | 'staging' | 'development' | 'local'
74
74
  });
75
75
 
76
- // 方式3: 自定义URL
76
+ // Method 3: Custom URL
77
77
  const client = new SeaVerseBackendAPIClient({
78
- appId: 'your app id', // 必需:您的应用ID
78
+ appId: 'your app id', // Required: Your application ID
79
79
  baseURL: 'https://custom-api.example.com',
80
80
  });
81
81
 
82
- // 方式4: 启用请求重试(默认禁用)
82
+ // Method 4: Enable request retry (disabled by default)
83
83
  const client = new SeaVerseBackendAPIClient({
84
84
  appId: 'your app id',
85
85
  retryOptions: {
86
- maxRetries: 3, // 最多重试 3
87
- retryDelay: 1000, // 初始延迟 1000ms,每次重试延迟加倍
88
- retryStatusCodes: [408, 429, 500, 502, 503, 504], // 这些状态码会触发重试
86
+ maxRetries: 3, // Retry up to 3 times
87
+ retryDelay: 1000, // Initial delay 1000ms, doubles each retry
88
+ retryStatusCodes: [408, 429, 500, 502, 503, 504], // Retry on these status codes
89
89
  },
90
90
  });
91
91
 
92
- // 健康检查
92
+ // Health check
93
93
  const health = await client.getHealth();
94
94
  console.log('Health:', health);
95
95
  ```
96
96
 
97
- ### 2. Iframe 场景下的 Token 获取
97
+ ### 2. Token Retrieval in Iframe Scenarios
98
98
 
99
- 当你的应用被嵌入到 iframe 中时,可以使用 `getIframeToken()` 方法从父页面获取认证 token。这对于第三方登录重定向场景特别有用。
99
+ When your application is embedded in an iframe, you can use the `getIframeToken()` method to retrieve the authentication token from the parent page. This is particularly useful for third-party login redirect scenarios.
100
100
 
101
- #### 检查是否在 iframe 中运行
101
+ #### Check if Running in Iframe
102
102
 
103
- 在调用 iframe 相关方法前,建议先检查应用是否在 iframe 中运行:
103
+ Before calling iframe-related methods, it's recommended to check if the application is running in an iframe:
104
104
 
105
105
  ```typescript
106
106
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
107
107
 
108
- // 方式 1: 使用静态方法(无需 client 实例)
108
+ // Method 1: Use static method (no client instance needed)
109
109
  if (SeaVerseBackendAPIClient.isInIframe()) {
110
- console.log('应用正在 iframe 中运行');
110
+ console.log('Application is running in iframe');
111
111
  } else {
112
- console.log('应用不在 iframe 中运行');
112
+ console.log('Application is not running in iframe');
113
113
  }
114
114
 
115
- // 方式 2: 使用实例方法
115
+ // Method 2: Use instance method
116
116
  const client = new SeaVerseBackendAPIClient({
117
117
  appId: 'your app id',
118
118
  });
119
119
 
120
120
  if (client.isInIframe()) {
121
- console.log('应用正在 iframe 中运行');
122
- // 可以安全地调用 getIframeToken()
121
+ console.log('Application is running in iframe');
122
+ // Safe to call getIframeToken()
123
123
  }
124
124
  ```
125
125
 
126
- #### 子页面 (iframe ) 使用方式
126
+ #### Child Page (Inside Iframe) Usage
127
127
 
128
128
  ```typescript
129
129
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
@@ -132,46 +132,46 @@ const client = new SeaVerseBackendAPIClient({
132
132
  appId: 'your app id',
133
133
  });
134
134
 
135
- // 先检查是否在 iframe
135
+ // First check if running in iframe
136
136
  if (!client.isInIframe()) {
137
- console.log('应用不在 iframe 中,跳过 token 获取');
138
- // 可以使用其他登录方式
137
+ console.log('Not in iframe, skip token retrieval');
138
+ // Can use other login methods
139
139
  } else {
140
- // iframe 中请求父页面的 token
140
+ // Request token from parent page while in iframe
141
141
  try {
142
142
  const token = await client.getIframeToken({
143
- timeout: 10000 // 可选,默认 30
143
+ timeout: 10000 // Optional, default 30 seconds
144
144
  });
145
145
 
146
- // 设置 token client
146
+ // Set token to client
147
147
  client.setToken(token);
148
148
  localStorage.setItem('token', token);
149
149
 
150
- console.log('成功从父页面获取 token');
150
+ console.log('Successfully retrieved token from parent page');
151
151
 
152
- // 现在可以使用需要认证的 API
152
+ // Now can use authenticated APIs
153
153
  const user = await client.getCurrentUser();
154
- console.log('当前用户:', user);
154
+ console.log('Current user:', user);
155
155
  } catch (error) {
156
- console.error('获取 token 失败:', error);
156
+ console.error('Failed to retrieve token:', error);
157
157
  }
158
158
  }
159
159
  ```
160
160
 
161
- #### 父页面监听并响应 token 请求
161
+ #### Parent Page Listens and Responds to Token Requests
162
162
 
163
163
  ```typescript
164
- // 父页面需要监听来自 iframe token 请求
164
+ // Parent page needs to listen for token requests from iframe
165
165
  window.addEventListener('message', (event) => {
166
- // 检查消息类型
166
+ // Check message type
167
167
  if (event.data.type === 'seaverse:get_token') {
168
168
  const requestId = event.data.requestId;
169
169
 
170
- // 获取你的 token ( localStorageAPI )
170
+ // Get your token (from localStorage, API, etc)
171
171
  const token = localStorage.getItem('token');
172
172
 
173
173
  if (token) {
174
- // 发送 token iframe
174
+ // Send token to iframe
175
175
  event.source.postMessage({
176
176
  type: 'seaverse:token',
177
177
  requestId: requestId,
@@ -181,7 +181,7 @@ window.addEventListener('message', (event) => {
181
181
  },
182
182
  }, '*');
183
183
  } else {
184
- // 发送错误消息
184
+ // Send error message
185
185
  event.source.postMessage({
186
186
  type: 'seaverse:token_error',
187
187
  requestId: requestId,
@@ -192,10 +192,10 @@ window.addEventListener('message', (event) => {
192
192
  });
193
193
  ```
194
194
 
195
- #### 完整的 iframe 登录流程示例
195
+ #### Complete Iframe Login Flow Example
196
196
 
197
197
  ```typescript
198
- // 子页面 (iframe)
198
+ // Child page (iframe)
199
199
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
200
200
 
201
201
  const client = new SeaVerseBackendAPIClient({
@@ -203,28 +203,28 @@ const client = new SeaVerseBackendAPIClient({
203
203
  });
204
204
 
205
205
  async function initIframeApp() {
206
- // 0. 检查是否在 iframe
206
+ // 0. Check if running in iframe
207
207
  if (!client.isInIframe()) {
208
- console.log('应用不在 iframe 中,使用常规登录流程');
209
- // 使用常规登录流程
208
+ console.log('Not in iframe, use regular login flow');
209
+ // Use regular login flow
210
210
  showLoginForm();
211
211
  return;
212
212
  }
213
213
 
214
214
  try {
215
- // 1. 尝试从父页面获取 token
215
+ // 1. Try to get token from parent page
216
216
  const token = await client.getIframeToken();
217
217
  client.setToken(token);
218
218
  localStorage.setItem('token', token);
219
219
 
220
- // 2. 验证 token 并获取用户信息
220
+ // 2. Validate token and get user info
221
221
  const user = await client.getCurrentUser();
222
- console.log('已登录:', user);
222
+ console.log('Logged in:', user);
223
223
 
224
- // 3. 继续应用逻辑
224
+ // 3. Continue app logic
225
225
  startApp(user);
226
226
  } catch (error) {
227
- // 4. 如果获取失败,通知父页面需要登录
227
+ // 4. If failed, notify parent page that login is needed
228
228
  window.parent.postMessage({
229
229
  type: 'seaverse:need_login',
230
230
  }, '*');
@@ -235,9 +235,9 @@ initIframeApp();
235
235
  ```
236
236
 
237
237
  ```typescript
238
- // 父页面
238
+ // Parent page
239
239
  window.addEventListener('message', (event) => {
240
- // 处理 token 请求
240
+ // Handle token request
241
241
  if (event.data.type === 'seaverse:get_token') {
242
242
  const requestId = event.data.requestId;
243
243
  const token = localStorage.getItem('token');
@@ -252,23 +252,23 @@ window.addEventListener('message', (event) => {
252
252
  },
253
253
  }, '*');
254
254
  } else {
255
- // 如果没有 token,唤起登录
255
+ // If no token, trigger login
256
256
  showLoginModal();
257
257
  }
258
258
  }
259
259
 
260
- // 处理需要登录的消息
260
+ // Handle need login message
261
261
  if (event.data.type === 'seaverse:need_login') {
262
262
  showLoginModal();
263
263
  }
264
264
  });
265
265
 
266
- // 登录成功后,通知 iframe
266
+ // After successful login, notify iframe
267
267
  function onLoginSuccess(newToken) {
268
268
  const iframe = document.querySelector('iframe');
269
269
  iframe.contentWindow.postMessage({
270
270
  type: 'seaverse:token',
271
- requestId: 'auto', // 自动登录时可以使用固定 ID
271
+ requestId: 'auto', // Can use fixed ID for auto-login
272
272
  payload: {
273
273
  accessToken: newToken,
274
274
  expiresIn: 3600,
@@ -277,9 +277,9 @@ function onLoginSuccess(newToken) {
277
277
  }
278
278
  ```
279
279
 
280
- #### TypeScript 类型定义
280
+ #### TypeScript Type Definitions
281
281
 
282
- SDK 提供了完整的 TypeScript 类型支持:
282
+ The SDK provides complete TypeScript type support:
283
283
 
284
284
  ```typescript
285
285
  import type {
@@ -288,13 +288,13 @@ import type {
288
288
  IframeTokenErrorMessage,
289
289
  } from '@seaverse/auth-sdk';
290
290
 
291
- // Token 请求消息
291
+ // Token request message
292
292
  const request: IframeTokenRequestMessage = {
293
293
  type: 'seaverse:get_token',
294
294
  requestId: 'unique-id',
295
295
  };
296
296
 
297
- // Token 响应消息
297
+ // Token response message
298
298
  const response: IframeTokenResponseMessage = {
299
299
  type: 'seaverse:token',
300
300
  requestId: 'unique-id',
@@ -304,7 +304,7 @@ const response: IframeTokenResponseMessage = {
304
304
  },
305
305
  };
306
306
 
307
- // 错误消息
307
+ // Error message
308
308
  const error: IframeTokenErrorMessage = {
309
309
  type: 'seaverse:token_error',
310
310
  requestId: 'unique-id',
@@ -312,342 +312,328 @@ const error: IframeTokenErrorMessage = {
312
312
  };
313
313
  ```
314
314
 
315
- #### 安全注意事项
315
+ #### Security Considerations
316
316
 
317
- 1. **使用特定 origin**: 在生产环境中,建议使用特定的 origin 而不是 `'*'`:
317
+ 1. **Use specific origin**: In production, use specific origin instead of `'*'`:
318
318
  ```typescript
319
- // 父页面
319
+ // Parent page
320
320
  const ALLOWED_ORIGIN = 'https://your-iframe-domain.com';
321
321
  event.source.postMessage(message, ALLOWED_ORIGIN);
322
322
 
323
- // 子页面发送时也可以指定
323
+ // Child page can also specify when sending
324
324
  window.parent.postMessage(message, 'https://parent-domain.com');
325
325
  ```
326
326
 
327
- 2. **验证消息来源**: 在处理 postMessage 时验证 origin:
327
+ 2. **Verify message origin**: Validate origin when handling postMessage:
328
328
  ```typescript
329
329
  window.addEventListener('message', (event) => {
330
- // 验证来源
330
+ // Verify origin
331
331
  if (event.origin !== 'https://trusted-domain.com') {
332
332
  return;
333
333
  }
334
- // 处理消息...
334
+ // Handle message...
335
335
  });
336
336
  ```
337
337
 
338
- 3. **Token 过期处理**: 记得处理 token 过期的情况:
338
+ 3. **Handle token expiration**: Remember to handle token expiration:
339
339
  ```typescript
340
340
  try {
341
341
  const user = await client.getCurrentUser();
342
342
  } catch (error) {
343
343
  if (error.response?.status === 401) {
344
- // Token 过期,重新获取
344
+ // Token expired, re-retrieve
345
345
  const newToken = await client.getIframeToken();
346
346
  client.setToken(newToken);
347
347
  }
348
348
  }
349
349
  ```
350
350
 
351
- ### 3. 用户认证
351
+ ### 3. User Authentication
352
352
 
353
353
  ```typescript
354
- // 注册新用户
354
+ // Register new user
355
355
  const registerResult = await client.register({
356
356
  email: 'user@example.com',
357
357
  password: 'SecurePassword123',
358
- username: 'johndoe', // 可选,未提供则从邮箱自动生成
359
- invitation_code: 'INVITE123', // 可选
360
- frontend_url: 'https://mygame.com/verify', // 可选,邮箱验证链接的前端URL,默认为 window.location.href
358
+ username: 'johndoe', // Optional, auto-generated from email if not provided
359
+ invitation_code: 'INVITE123', // Optional
360
+ frontend_url: 'https://mygame.com/verify', // Optional, frontend URL for email verification link, defaults to window.location.href
361
361
  });
362
362
 
363
- // 检查注册结果
363
+ // Check registration result
364
364
  if (registerResult.success) {
365
- console.log('注册成功:', registerResult);
365
+ console.log('Registration successful:', registerResult);
366
366
  } else if (registerResult.code === 'ACCOUNT_EXISTS') {
367
- console.log('账户已存在,请直接登录');
368
- console.log('错误详情:', registerResult.details);
367
+ console.log('Account exists, please login directly');
368
+ console.log('Error details:', registerResult.details);
369
369
  }
370
370
 
371
- // 登录
371
+ // Login
372
372
  const loginResult = await client.login({
373
373
  email: 'user@example.com',
374
374
  password: 'SecurePassword123',
375
375
  });
376
376
 
377
- // 保存token
377
+ // Save token
378
378
  localStorage.setItem('token', loginResult.token);
379
379
 
380
- // ⚠️ 注意:邀请码自动跳转
381
- // 如果服务器返回 INVITE_CODE_REQUIRED 错误且包含 redirectUrl
382
- // SDK 会自动将用户重定向到该 URL(通常是邀请码输入页面)
383
- // 无需额外处理,页面会自动跳转
380
+ // ⚠️ Note: Automatic invitation code redirect
381
+ // If server returns INVITE_CODE_REQUIRED error and includes redirectUrl,
382
+ // SDK will automatically redirect user to that URL (usually invitation code input page)
383
+ // No extra handling needed, page will redirect automatically
384
384
 
385
- // 获取当前用户信息
385
+ // Get current user info
386
386
  const user = await client.getCurrentUser();
387
387
  console.log('User:', user);
388
- console.log('App ID:', user.app_id); // 多租户应用ID
388
+ console.log('App ID:', user.app_id); // Multi-tenant application ID
389
389
  console.log('Email verified:', user.email_verified);
390
390
 
391
- // 登出
391
+ // Logout
392
392
  await client.logout();
393
393
 
394
- // 忘记密码
394
+ // Forgot password
395
395
  await client.forgotPassword({
396
396
  email: 'user@example.com',
397
- frontend_url: 'https://mygame.com/', // 可选,默认为 window.location.href
397
+ frontend_url: 'https://mygame.com/', // Optional, defaults to window.location.href
398
398
  });
399
399
 
400
- // 重置密码
400
+ // Reset password
401
401
  await client.resetPassword({
402
402
  token: 'reset-token-from-email',
403
403
  new_password: 'NewSecurePassword123',
404
404
  });
405
405
  ```
406
406
 
407
- ### 4. OAuth 第三方登录 (Backend Proxy Mode)
407
+ ### 4. OAuth Third-Party Login (Backend Proxy Mode)
408
408
 
409
- SDK 使用 Backend Proxy ModeClient Secret 永不暴露给前端,安全性更高。
409
+ The SDK uses Backend Proxy Mode where Client Secret is never exposed to the frontend, providing higher security.
410
410
 
411
- **优势**:
412
- - ✅ Client Secret 从不暴露给前端
413
- - ✅ 支持任意开发者域名(无需在 OAuth 平台配置)
414
- - ✅ 内置 CSRF 防护
415
- - ✅ 零配置,开箱即用
411
+ **Advantages**:
412
+ - ✅ Client Secret is never exposed to frontend
413
+ - ✅ Supports any developer domain (no need to configure in OAuth platform)
414
+ - ✅ Built-in CSRF protection
415
+ - ✅ Zero configuration, works out of the box
416
416
 
417
- **工作流程**:
418
- 1. 前端调用 `{provider}Authorize()` 获取 OAuth URL
419
- 2. 前端重定向用户到 OAuth 提供商
420
- 3. 用户授权后,OAuth 提供商回调到固定的 account-hub URL
421
- 4. account-hub 处理 OAuth,创建 JWT token
422
- 5. account-hub 302 重定向到 `return_url?token=xxx`
423
- 6. 前端从 URL 提取 token 并存储
417
+ **Workflow**:
418
+ 1. Frontend calls `{provider}Authorize()` to get OAuth URL
419
+ 2. Frontend redirects user to OAuth provider
420
+ 3. After user authorization, OAuth provider callbacks to fixed account-hub URL
421
+ 4. account-hub handles OAuth, creates JWT token
422
+ 5. account-hub 302 redirects to `return_url?token=xxx`
423
+ 6. Frontend extracts token from URL and stores it
424
424
 
425
- #### 使用示例
425
+ #### Usage Examples
426
426
 
427
- **方式1:使用默认 return_url(当前页面)**
427
+ **Method 1: Use default return_url (current page)**
428
428
 
429
429
  ```typescript
430
- // Google 登录
430
+ // Google login
431
431
  const { authorize_url } = await client.googleAuthorize();
432
432
  window.location.href = authorize_url;
433
433
 
434
- // Discord 登录
434
+ // Discord login
435
435
  const { authorize_url } = await client.discordAuthorize();
436
436
  window.location.href = authorize_url;
437
437
 
438
- // GitHub 登录
438
+ // GitHub login
439
439
  const { authorize_url } = await client.githubAuthorize();
440
440
  window.location.href = authorize_url;
441
441
  ```
442
442
 
443
- **方式2:自定义 return_url**
443
+ **Method 2: Custom return_url**
444
444
 
445
445
  ```typescript
446
- // 登录后跳转到 dashboard
446
+ // Redirect to dashboard after login
447
447
  const { authorize_url } = await client.googleAuthorize({
448
448
  return_url: 'https://mygame.com/dashboard'
449
449
  });
450
450
  window.location.href = authorize_url;
451
451
  ```
452
452
 
453
- **在回调页面提取 token**:
453
+ **Extract token in callback page**:
454
454
 
455
455
  ```typescript
456
456
  // URL: https://mygame.com/?token=eyJhbGc...
457
457
  const token = new URLSearchParams(window.location.search).get('token');
458
458
  if (token) {
459
459
  localStorage.setItem('token', token);
460
- // 登录成功,跳转或更新 UI
460
+ // Login successful, redirect or update UI
461
461
  }
462
462
  ```
463
463
 
464
- #### OAuth 账号解绑
464
+ #### OAuth Account Unlinking
465
465
 
466
466
  ```typescript
467
- // 解绑 Google 账号
467
+ // Unlink Google account
468
468
  await client.unlinkGoogle();
469
469
 
470
- // 解绑 Discord 账号
470
+ // Unlink Discord account
471
471
  await client.unlinkDiscord();
472
472
 
473
- // 解绑 GitHub 账号
473
+ // Unlink GitHub account
474
474
  await client.unlinkGithub();
475
475
  ```
476
476
 
477
- ### 5. 使用登录UI组件
477
+ ### 5. Using Login UI Components
478
478
 
479
- SDK 提供精美的登录弹窗组件,支持深色和浅色两种主题:
479
+ The SDK provides beautiful login modal components with dark and light themes:
480
480
 
481
- #### 主题对比
481
+ #### Theme Comparison
482
482
 
483
- | 主题 | 设计风格 | 适用场景 |
483
+ | Theme | Design Style | Use Cases |
484
484
  |------|---------|---------|
485
- | **Dark** 🌙 | 动态网格渐变 + 玻璃态效果 | 科技感产品、游戏平台、深色界面应用 |
486
- | **Light** ☀️ | 提升的卡片设计 + 柔和阴影 | 商务应用、内容平台、浅色界面应用 |
485
+ | **Dark** 🌙 | Dynamic grid gradient + glassmorphism | Tech products, gaming platforms, dark interface apps |
486
+ | **Light** ☀️ | Elevated card design + soft shadows | Business apps, content platforms, light interface apps |
487
487
 
488
- #### 基础用法
488
+ #### Basic Usage
489
489
 
490
490
  ```typescript
491
491
  import { SeaVerseBackendAPIClient, AuthModal } from '@seaverse/auth-sdk';
492
- import '@seaverse/auth-sdk/auth-modal.css'; // 导入样式
492
+ import '@seaverse/auth-sdk/auth-modal.css'; // Import styles
493
493
 
494
494
  const client = new SeaVerseBackendAPIClient({
495
- appId: 'your app id', // 必需:您的应用ID
495
+ appId: 'your app id', // Required: Your application ID
496
496
  environment: 'production',
497
497
  });
498
498
 
499
- // 创建登录弹窗
499
+ // Create login modal
500
500
  const authModal = new AuthModal({
501
501
  client,
502
- theme: 'dark', // 'dark' | 'light' - 默认为 'dark'
502
+ theme: 'dark', // 'dark' | 'light' - defaults to 'dark'
503
503
 
504
- // 登录成功回调
504
+ // Login success callback
505
505
  onLoginSuccess: (token, user) => {
506
506
  localStorage.setItem('token', token);
507
- console.log('登录成功:', user);
507
+ console.log('Login successful:', user);
508
508
  },
509
509
 
510
- // 注册成功回调
510
+ // Signup success callback
511
511
  onSignupSuccess: (token, user) => {
512
512
  localStorage.setItem('token', token);
513
- console.log('注册成功:', user);
513
+ console.log('Signup successful:', user);
514
514
  },
515
515
 
516
- // 邀请码需求回调(可选)
516
+ // Invitation code required callback (optional)
517
517
  onInviteCodeRequired: (userId, email) => {
518
- console.log('需要邀请码激活账户:', userId, email);
519
- // AuthModal 会自动显示邀请码输入界面
518
+ console.log('Need invitation code to activate account:', userId, email);
519
+ // AuthModal will automatically show invitation code input interface
520
520
  },
521
521
 
522
- // 申请邀请码成功回调(可选)
522
+ // Apply invite success callback (optional)
523
523
  onApplyInviteSuccess: (applicationId, email) => {
524
- console.log('邀请码申请已提交:', applicationId, email);
525
- // 可以在这里添加自定义逻辑,如显示提示信息
524
+ console.log('Invitation code application submitted:', applicationId, email);
525
+ // Can add custom logic here, such as showing notifications
526
526
  },
527
527
 
528
- // 错误回调
528
+ // Error callback
529
529
  onError: (error) => {
530
- console.error('认证错误:', error.message);
530
+ console.error('Authentication error:', error.message);
531
531
  },
532
532
 
533
- // OAuth 配置(可选)
534
- returnUrl: 'https://mygame.com/', // OAuth 登录后返回的 URL,可选,默认为 window.location.href
533
+ // OAuth configuration (optional)
534
+ returnUrl: 'https://mygame.com/', // URL to return after OAuth login, optional, defaults to window.location.href
535
535
  enableOAuth: {
536
- google: true, // 启用 Google 登录
537
- discord: true, // 启用 Discord 登录
538
- github: true, // 启用 GitHub 登录
536
+ google: true, // Enable Google login
537
+ discord: true, // Enable Discord login
538
+ github: true, // Enable GitHub login
539
539
  },
540
540
  });
541
541
 
542
- // 显示登录界面
542
+ // Show login interface
543
543
  authModal.show('login');
544
544
 
545
- // 显示注册界面
545
+ // Show signup interface
546
546
  authModal.show('signup');
547
547
 
548
- // 隐藏弹窗
548
+ // Hide modal
549
549
  authModal.hide();
550
550
 
551
- // 销毁弹窗
551
+ // Destroy modal
552
552
  authModal.destroy();
553
553
  ```
554
554
 
555
- **✨ 新特性:自动 Toast 通知**
555
+ **✨ New Feature: Auto Toast Notifications**
556
556
 
557
- AuthModal 内置了现代化的 Toast 通知系统,无需额外配置:
557
+ AuthModal has built-in modern Toast notification system, no extra configuration needed:
558
558
 
559
559
  ```typescript
560
- // Toast 会自动显示,CSS 自动注入
561
- // - 注册成功绿色成功提示
562
- // - 账号已存在黄色警告提示
563
- // - 登录失败红色错误提示
564
- // - 重置密码蓝色信息提示
560
+ // Toast displays automatically, CSS auto-injected
561
+ // - Registration success Green success notification
562
+ // - Account exists Yellow warning notification
563
+ // - Login failure Red error notification
564
+ // - Reset password Blue info notification
565
565
 
566
- // 你也可以单独使用 ToastCSS 自动注入)
566
+ // You can also use Toast independently (CSS auto-injected)
567
567
  import { Toast } from '@seaverse/auth-sdk';
568
568
 
569
- Toast.success('操作成功', '数据已保存');
570
- Toast.error('操作失败', '请稍后重试');
571
- Toast.warning('注意', '账号已存在');
572
- Toast.info('提示', '邮件已发送');
573
-
574
- // 自定义显示时长(默认 3000ms)
575
- Toast.success('操作成功', '数据已保存', 5000);
569
+ Toast.success('Success', 'Data saved');
570
+ Toast.error('Failed', 'Please try again later');
571
+ Toast.warning('Notice', 'Account already exists');
572
+ Toast.info('Info', 'Email sent');
576
573
  ```
577
574
 
578
- **🎯 智能交互特性**
579
-
580
- Toast 提供了智能的用户交互体验:
581
-
582
- - **Hover 暂停**:当鼠标悬停在 Toast 上时,自动暂停倒计时,让用户有足够时间阅读消息
583
- - **离开继续**:鼠标移开后,继续倒计时并自动消失
584
- - **手动关闭**:点击右上角的关闭按钮可立即关闭通知
585
- - **自动消失**:默认 3 秒后自动消失(可自定义时长)
586
-
587
- 这些特性确保用户不会错过重要提示信息。
588
-
589
- #### 重置密码流程
575
+ #### Password Reset Flow
590
576
 
591
- AuthModal 支持完整的密码重置流程:
577
+ AuthModal supports complete password reset flow:
592
578
 
593
- 1. **用户触发忘记密码**:在登录界面点击 "Forgot Password?" 链接
594
- 2. **发送重置邮件**:输入邮箱后,系统发送带有 `reset_token` 的重置链接
595
- 3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `reset_token` 参数并显示重置密码表单
596
- 4. **设置新密码**:用户输入并确认新密码后提交
597
- 5. **自动清理 URL**:重置成功后自动清除 URL 中的 `reset_token` 参数
579
+ 1. **User triggers forgot password**: Click "Forgot Password?" link in login interface
580
+ 2. **Send reset email**: After entering email, system sends reset link with `reset_token`
581
+ 3. **Auto trigger reset modal**: When user clicks link in email and returns to website, AuthModal automatically detects `reset_token` parameter in URL and shows reset password form
582
+ 4. **Set new password**: User enters and confirms new password then submits
583
+ 5. **Auto cleanup URL**: After successful reset, automatically clears `reset_token` parameter from URL
598
584
 
599
- 整个流程无需额外代码,AuthModal 会自动处理:
585
+ The entire process requires no extra code, AuthModal handles it automatically:
600
586
 
601
587
  ```typescript
602
- // 1. 初始化 AuthModal(只需一次)
588
+ // 1. Initialize AuthModal (only once)
603
589
  const authModal = new AuthModal({
604
590
  client,
605
- // ... 其他配置
591
+ // ... other configuration
606
592
  });
607
593
 
608
- // 2. 用户点击邮件中的重置链接后,AuthModal 会自动:
609
- // - 检测 URL 中的 ?reset_token=xxx 参数
610
- // - 显示重置密码表单
611
- // - 用户提交新密码
612
- // - 调用 client.resetPassword() API
613
- // - 清理 URL 中的 reset_token 参数
614
- // - 显示成功消息
594
+ // 2. After user clicks reset link in email, AuthModal automatically:
595
+ // - Detects ?reset_token=xxx parameter in URL
596
+ // - Shows reset password form
597
+ // - User submits new password
598
+ // - Calls client.resetPassword() API
599
+ // - Cleans reset_token parameter from URL
600
+ // - Shows success message
615
601
  ```
616
602
 
617
- #### OAuth 配置说明
603
+ #### OAuth Configuration Instructions
618
604
 
619
- `enableOAuth` 参数是**完全可选的**:
605
+ The `enableOAuth` parameter is **completely optional**:
620
606
 
621
- - 如果**不提供** `enableOAuth`,则不会显示任何第三方登录按钮
622
- - 如果**部分配置**(如只启用 Google),则只显示已启用的按钮
623
- - 如果**完整配置**所有平台,则显示所有第三方登录按钮
607
+ - If **not provided**, no third-party login buttons will be shown
608
+ - If **partially configured** (e.g., only enable Google), only enabled buttons will be shown
609
+ - If **fully configured** for all platforms, all third-party login buttons will be shown
624
610
 
625
- **配置字段说明**:
626
- - `returnUrl`:**可选** - OAuth 登录后返回的 URL,不填则默认为 `window.location.href`
627
- - `enableOAuth.google`:是否启用 Google 登录
628
- - `enableOAuth.discord`:是否启用 Discord 登录
629
- - `enableOAuth.github`:是否启用 GitHub 登录
611
+ **Configuration field descriptions**:
612
+ - `returnUrl`: **Optional** - URL to return after OAuth login, defaults to `window.location.href` if not provided
613
+ - `enableOAuth.google`: Whether to enable Google login
614
+ - `enableOAuth.discord`: Whether to enable Discord login
615
+ - `enableOAuth.github`: Whether to enable GitHub login
630
616
 
631
617
  ```typescript
632
- // 示例1:无OAuth按钮
618
+ // Example 1: No OAuth buttons
633
619
  const authModal1 = new AuthModal({
634
620
  client,
635
621
  theme: 'dark',
636
- // 不传 enableOAuth,不显示任何OAuth按钮
622
+ // No enableOAuth, no OAuth buttons shown
637
623
  });
638
624
 
639
- // 示例2:只显示Google登录
625
+ // Example 2: Only show Google login
640
626
  const authModal2 = new AuthModal({
641
627
  client,
642
628
  theme: 'light',
643
629
  returnUrl: 'https://mygame.com/dashboard',
644
630
  enableOAuth: {
645
631
  google: true,
646
- // Discord GitHub 未启用,不会显示这些按钮
632
+ // Discord and GitHub not enabled, won't show these buttons
647
633
  },
648
634
  });
649
635
 
650
- // 示例3:显示所有OAuth按钮
636
+ // Example 3: Show all OAuth buttons
651
637
  const authModal3 = new AuthModal({
652
638
  client,
653
639
  theme: 'dark',
@@ -659,58 +645,58 @@ const authModal3 = new AuthModal({
659
645
  });
660
646
  ```
661
647
 
662
- #### 处理 OAuth 回调
648
+ #### Handling OAuth Callback
663
649
 
664
- Backend Proxy Mode 下,OAuth 登录后会重定向到 `returnUrl?token=xxx`。在页面加载时检查并处理token:
650
+ In Backend Proxy Mode, after OAuth login it redirects to `returnUrl?token=xxx`. Check and handle token on page load:
665
651
 
666
652
  ```typescript
667
- // 在页面加载时自动处理 OAuth 回调
653
+ // Automatically handle OAuth callback on page load
668
654
  const result = AuthModal.handleOAuthCallback({
669
655
  client,
670
656
  onLoginSuccess: (token) => {
671
657
  localStorage.setItem('token', token);
672
- console.log('OAuth 登录成功');
658
+ console.log('OAuth login successful');
673
659
 
674
- // 现在可以直接调用需要认证的接口
675
- // handleOAuthCallback 已自动调用 client.setToken()
660
+ // Can now call authenticated APIs directly
661
+ // handleOAuthCallback has automatically called client.setToken()
676
662
  client.getCurrentUser()
677
- .then(user => console.log('用户信息:', user));
663
+ .then(user => console.log('User info:', user));
678
664
  },
679
665
  });
680
666
 
681
667
  if (result) {
682
- console.log('处理了 OAuth 回调,token:', result.token);
668
+ console.log('Handled OAuth callback, token:', result.token);
683
669
  }
684
670
  ```
685
671
 
686
- **重要说明**:
687
- - `handleOAuthCallback()` 会自动调用 `client.setToken(token)` 来更新 client 的认证配置
688
- - 这意味着在 `onLoginSuccess` 回调之后,所有需要认证的 API(如 `getCurrentUser()`、`logout()` 等)都会自动带上 `Authorization` header
672
+ **Important Note**:
673
+ - `handleOAuthCallback()` automatically calls `client.setToken(token)` to update client authentication configuration
674
+ - This means after the `onLoginSuccess` callback, all authenticated APIs (such as `getCurrentUser()`, `logout()`, etc.) will automatically include the `Authorization` header
689
675
 
690
- #### 手动设置 Token
676
+ #### Manual Token Setting
691
677
 
692
- 如果你不使用 `AuthModal.handleOAuthCallback()`,也可以手动设置 token
678
+ If you don't use `AuthModal.handleOAuthCallback()`, you can also set the token manually:
693
679
 
694
680
  ```typescript
695
- // URL 提取 token
681
+ // Extract token from URL
696
682
  const token = new URLSearchParams(window.location.search).get('token');
697
683
  if (token) {
698
- // 手动设置 token
684
+ // Manually set token
699
685
  client.setToken(token);
700
686
  localStorage.setItem('token', token);
701
687
 
702
- // 现在可以调用需要认证的接口
688
+ // Now can call authenticated APIs
703
689
  const user = await client.getCurrentUser();
704
690
  }
705
691
  ```
706
692
 
707
- ### 6. 容器管理
693
+ ### 6. Container Management
708
694
 
709
695
  ```typescript
710
- // 列出所有容器
696
+ // List all containers
711
697
  const containers = await client.listContainers();
712
698
 
713
- // 注册新容器
699
+ // Register new container
714
700
  const result = await client.registerContainer({
715
701
  containerId: 'container-123',
716
702
  metadata: {
@@ -719,226 +705,226 @@ const result = await client.registerContainer({
719
705
  },
720
706
  });
721
707
 
722
- // 获取容器信息
708
+ // Get container info
723
709
  const container = await client.getContainer({
724
710
  containerId: 'container-123',
725
711
  });
726
712
 
727
- // 容器心跳
713
+ // Container heartbeat
728
714
  await client.containerHeartbeat({
729
715
  containerId: 'container-123',
730
716
  status: 'healthy',
731
717
  });
732
718
 
733
- // 注销容器
719
+ // Unregister container
734
720
  await client.unregisterContainer({
735
721
  containerId: 'container-123',
736
722
  });
737
723
 
738
- // 获取容器统计
724
+ // Get container stats
739
725
  const stats = await client.getContainerStats();
740
726
  ```
741
727
 
742
- ### 7. 技能市场
728
+ ### 7. Skill Marketplace
743
729
 
744
730
  ```typescript
745
- // 列出市场技能
731
+ // List marketplace skills
746
732
  const skills = await client.listMarketplaceSkills({
747
733
  category: 'productivity',
748
734
  page: 1,
749
735
  pageSize: 20,
750
736
  });
751
737
 
752
- // 获取技能详情
738
+ // Get skill details
753
739
  const skill = await client.getMarketplaceSkill({
754
740
  skillId: 'skill-123',
755
741
  });
756
742
 
757
- // 安装技能
743
+ // Install skill
758
744
  await client.installSkill({
759
745
  skillId: 'skill-123',
760
746
  });
761
747
 
762
- // 列出已安装的技能
748
+ // List installed skills
763
749
  const userSkills = await client.listUserSkills();
764
750
 
765
- // 卸载技能
751
+ // Uninstall skill
766
752
  await client.uninstallSkill({
767
753
  skillId: 'skill-123',
768
754
  });
769
755
  ```
770
756
 
771
- ### 8. 邀请码管理
757
+ ### 8. Invitation Code Management
772
758
 
773
759
  ```typescript
774
- // 申请邀请码(当用户没有邀请码时)
760
+ // Apply for invitation code (when user doesn't have one)
775
761
  const application = await client.applyInvite({
776
762
  email: 'player@example.com',
777
763
  reason: 'I want to join this amazing platform to build innovative applications and connect with the community.'
778
764
  });
779
765
 
780
766
  if (application.success) {
781
- console.log('申请已提交:', application.data);
782
- console.log('申请ID:', application.data.id);
783
- console.log('状态:', application.data.status); // 'pending'
767
+ console.log('Application submitted:', application.data);
768
+ console.log('Application ID:', application.data.id);
769
+ console.log('Status:', application.data.status); // 'pending'
784
770
  } else {
785
- // 处理错误
771
+ // Handle error
786
772
  if (application.code === 'APPLICATION_DUPLICATE') {
787
- console.log('您在过去24小时内已提交过申请');
773
+ console.log('You have already submitted an application in the past 24 hours');
788
774
  } else {
789
- console.error('申请失败:', application.error);
775
+ console.error('Application failed:', application.error);
790
776
  }
791
777
  }
792
778
 
793
- // 列出我的邀请码
779
+ // List my invitation codes
794
780
  const invites = await client.listInvites({
795
781
  status: 'active',
796
782
  page: 1,
797
783
  page_size: 20,
798
784
  });
799
- console.log('我的邀请码:', invites.data.invites);
785
+ console.log('My invitation codes:', invites.data.invites);
800
786
 
801
- // 获取邀请码统计
787
+ // Get invitation code stats
802
788
  const stats = await client.getInviteStats();
803
- console.log('总邀请码数:', stats.data.total_codes);
804
- console.log('活跃邀请码:', stats.data.active_codes);
805
- console.log('总使用次数:', stats.data.total_uses);
789
+ console.log('Total invitation codes:', stats.data.total_codes);
790
+ console.log('Active invitation codes:', stats.data.active_codes);
791
+ console.log('Total usage count:', stats.data.total_uses);
806
792
 
807
- // 获取邀请码详情
793
+ // Get invitation code details
808
794
  const invite = await client.getInvite('inv_abc123');
809
- console.log('邀请码:', invite.data.code);
810
- console.log('已使用:', invite.data.used_count);
811
- console.log('最大使用次数:', invite.data.max_uses);
795
+ console.log('Invitation code:', invite.data.code);
796
+ console.log('Used count:', invite.data.used_count);
797
+ console.log('Max uses:', invite.data.max_uses);
812
798
 
813
- // 获取邀请码使用记录
799
+ // Get invitation code usage records
814
800
  const usages = await client.getInviteUsages('inv_abc123', {
815
801
  page: 1,
816
802
  page_size: 20,
817
803
  });
818
- console.log('使用记录:', usages.data.usages);
804
+ console.log('Usage records:', usages.data.usages);
819
805
  ```
820
806
 
821
- ### 9. 邮箱验证与邀请码绑定
807
+ ### 9. Email Verification and Invitation Code Binding
822
808
 
823
- #### 邮箱验证(自动登录)
809
+ #### Email Verification (Auto Login)
824
810
 
825
- 用户注册后会收到验证邮件,邮件中包含验证链接,格式为:`frontend_url?verify_token=xxx`
811
+ After registration, users receive a verification email containing a verification link in the format: `frontend_url?verify_token=xxx`
826
812
 
827
- **方式一:使用 AuthModal 自动处理(推荐)**
813
+ **Method 1: Use AuthModal Auto-Handling (Recommended)**
828
814
 
829
815
  ```typescript
830
816
  import { AuthModal } from '@seaverse/auth-sdk';
831
817
 
832
- // 创建 AuthModal 实例
818
+ // Create AuthModal instance
833
819
  const modal = new AuthModal({
834
820
  client,
835
821
  onLoginSuccess: (token, user) => {
836
822
  localStorage.setItem('token', token);
837
- console.log('邮箱验证并登录成功:', user);
823
+ console.log('Email verified and logged in successfully:', user);
838
824
  },
839
825
  onError: (error) => {
840
- console.error('邮箱验证失败:', error);
826
+ console.error('Email verification failed:', error);
841
827
  }
842
828
  });
843
829
 
844
- // AuthModal 会自动检测 URL 中的 verify_token 参数
845
- // 检测到后会自动:
846
- // 1. 调用 verifyEmail() API 验证邮箱
847
- // 2. 获取返回的 JWT token 并自动登录
848
- // 3. 触发 onLoginSuccess 回调
849
- // 4. 清理 URL 中的 verify_token 参数
850
- // 5. 显示成功消息
830
+ // AuthModal will automatically detect verify_token parameter in URL
831
+ // After detection, it will automatically:
832
+ // 1. Call verifyEmail() API to verify email
833
+ // 2. Get returned JWT token and auto-login
834
+ // 3. Trigger onLoginSuccess callback
835
+ // 4. Clean verify_token parameter from URL
836
+ // 5. Show success message
851
837
  ```
852
838
 
853
- **调试提示**:
839
+ **Debugging Tips**:
854
840
 
855
- 如果邮箱验证出现问题,请检查浏览器控制台日志:
841
+ If email verification has issues, check browser console logs:
856
842
 
857
843
  ```javascript
858
- // 正常情况应该看到:
844
+ // Normal case should show:
859
845
  [AuthModal] Detected verify_token, starting email verification...
860
846
  [AuthModal] Email verification successful: { id: "xxx", email: "user@example.com", ... }
861
847
 
862
- // 如果验证失败,会看到:
848
+ // If verification fails, will show:
863
849
  [AuthModal] Email verification failed: Error: ...
864
850
  ```
865
851
 
866
- **方式二:手动处理邮箱验证**
852
+ **Method 2: Manual Email Verification Handling**
867
853
 
868
854
  ```typescript
869
- // 验证邮箱(从邮件链接中获取 verify_token
855
+ // Verify email (get verify_token from email link)
870
856
  const urlParams = new URLSearchParams(window.location.search);
871
857
  const verifyToken = urlParams.get('verify_token');
872
858
 
873
859
  if (verifyToken) {
874
860
  const result = await client.verifyEmail(verifyToken);
875
861
 
876
- // 自动登录:保存返回的 token
862
+ // Auto-login: save returned token
877
863
  localStorage.setItem('token', result.data.token);
878
864
  localStorage.setItem('refreshToken', result.data.refreshToken);
879
865
 
880
- console.log('邮箱验证成功,已自动登录:', result.data.user);
866
+ console.log('Email verified successfully, auto-logged in:', result.data.user);
881
867
 
882
- // 重定向到主页
868
+ // Redirect to homepage
883
869
  window.location.href = '/';
884
870
  }
885
871
  ```
886
872
 
887
- #### 邀请码绑定(账户激活)
873
+ #### Invitation Code Binding (Account Activation)
888
874
 
889
- 当使用外部邮箱注册或 OAuth 登录但未提供邀请码时,会创建临时账户并需要后续绑定邀请码激活。
875
+ When registering with external email or OAuth login without providing invitation code, a temporary account is created and requires subsequent invitation code binding for activation.
890
876
 
891
- **申请邀请码功能**:
877
+ **Apply for Invitation Code Feature**:
892
878
 
893
- 如果用户没有邀请码,AuthModal 提供了内置的申请功能:
894
- 1. 在邀请码输入界面,用户可以点击 "Don't have an invitation code? Apply for one" 链接
895
- 2. 自动跳转到申请邀请码表单
896
- 3. 用户填写邮箱和申请原因(10-500字符)
897
- 4. 提交后会调用 `applyInvite()` API,后台审核通过后会通过邮件发送邀请码
879
+ If user doesn't have an invitation code, AuthModal provides built-in application feature:
880
+ 1. In invitation code input interface, user can click "Don't have an invitation code? Apply for one" link
881
+ 2. Automatically jumps to apply for invitation code form
882
+ 3. User fills in email and application reason (10-500 characters)
883
+ 4. After submission, calls `applyInvite()` API, after backend approval, invitation code will be sent via email
898
884
 
899
- **自动跳转机制**:
900
- - `login()` 返回 `INVITE_CODE_REQUIRED` 错误且包含 `redirectUrl` 时,SDK 会自动将页面重定向到该 URL
901
- - redirectUrl 通常包含 `error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx` 参数
902
- - 无需手动处理跳转逻辑,SDK 会自动完成
885
+ **Auto Redirect Mechanism**:
886
+ - When `login()` returns `INVITE_CODE_REQUIRED` error and includes `redirectUrl`, SDK automatically redirects page to that URL
887
+ - redirectUrl usually contains `error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx` parameters
888
+ - No need to manually handle redirect logic, SDK completes automatically
903
889
 
904
- 对于其他场景( OAuth 登录后的重定向),后端会直接重定向到 `frontend_url?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx`。
890
+ For other scenarios (such as redirects after OAuth login), backend directly redirects to `frontend_url?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx`.
905
891
 
906
- **方式一:使用 AuthModal 自动处理(推荐)**
892
+ **Method 1: Use AuthModal Auto-Handling (Recommended)**
907
893
 
908
894
  ```typescript
909
895
  import { AuthModal } from '@seaverse/auth-sdk';
910
896
 
911
- // 创建 AuthModal 实例
897
+ // Create AuthModal instance
912
898
  const modal = new AuthModal({
913
899
  client,
914
900
  onLoginSuccess: (token, user) => {
915
901
  localStorage.setItem('token', token);
916
- console.log('登录成功:', user);
902
+ console.log('Login successful:', user);
917
903
  },
918
904
  onInviteCodeRequired: (userId, email) => {
919
- // 可选:当需要邀请码时的自定义处理
920
- console.log('需要邀请码激活账户:', userId, email);
905
+ // Optional: custom handling when invitation code is needed
906
+ console.log('Need invitation code to activate account:', userId, email);
921
907
  }
922
908
  });
923
909
 
924
- // AuthModal 会自动检测 URL 中的以下参数组合:
910
+ // AuthModal will automatically detect the following parameter combinations in URL:
925
911
  // - error_code=INVITE_CODE_REQUIRED
926
- // - user_id temp_user_id(用户ID
927
- // - email(可选,用户邮箱)
912
+ // - user_id or temp_user_id (user ID)
913
+ // - email (optional, user email)
928
914
  //
929
- // 检测到后会自动:
930
- // 1. 显示邀请码输入界面
931
- // 2. 用户输入邀请码后调用 bindInviteCode() API
932
- // 3. 激活成功后自动登录(保存 token
933
- // 4. 清理 URL 中的参数
915
+ // After detection, it will automatically:
916
+ // 1. Show invitation code input interface
917
+ // 2. After user inputs invitation code, call bindInviteCode() API
918
+ // 3. After successful activation, auto-login (save token)
919
+ // 4. Clean parameters from URL
934
920
  ```
935
921
 
936
- **调试提示**:
922
+ **Debugging Tips**:
937
923
 
938
- 如果邀请码弹窗没有出现,请检查浏览器控制台是否有以下日志:
924
+ If invitation code modal doesn't appear, check browser console for the following logs:
939
925
 
940
926
  ```javascript
941
- // 正常情况应该看到:
927
+ // Normal case should show:
942
928
  [AuthModal] Detected INVITE_CODE_REQUIRED: {
943
929
  errorCode: "INVITE_CODE_REQUIRED",
944
930
  userId: "xxx",
@@ -947,50 +933,50 @@ const modal = new AuthModal({
947
933
  fullURL: "http://localhost:8001/?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx"
948
934
  }
949
935
 
950
- // 如果 user_id 缺失,会看到错误提示:
936
+ // If user_id is missing, will show error:
951
937
  [AuthModal] Missing user_id in URL parameters.
952
- // 并弹出 alert 显示完整 URL,方便排查后端重定向问题
938
+ // And shows alert with full URL for troubleshooting backend redirect issues
953
939
  ```
954
940
 
955
- **方式二:手动处理邀请码绑定**
941
+ **Method 2: Manual Invitation Code Binding Handling**
956
942
 
957
943
  ```typescript
958
- // 1. 检查 URL 中是否需要邀请码
944
+ // 1. Check if invitation code is needed in URL
959
945
  const urlParams = new URLSearchParams(window.location.search);
960
946
  const errorCode = urlParams.get('error_code');
961
947
  const userId = urlParams.get('user_id');
962
948
 
963
949
  if (errorCode === 'INVITE_CODE_REQUIRED' && userId) {
964
- // 2. 显示邀请码输入界面(自定义 UI
965
- const inviteCode = await showInviteCodeInput(); // 你的自定义UI
950
+ // 2. Show invitation code input interface (custom UI)
951
+ const inviteCode = await showInviteCodeInput(); // Your custom UI
966
952
 
967
- // 3. 绑定邀请码
953
+ // 3. Bind invitation code
968
954
  const result = await client.bindInviteCode({
969
955
  user_id: userId,
970
956
  invite_code: inviteCode
971
957
  });
972
958
 
973
- // 4. 激活成功,自动登录
959
+ // 4. Activation successful, auto-login
974
960
  localStorage.setItem('token', result.data.token);
975
961
  localStorage.setItem('refreshToken', result.data.refreshToken);
976
- console.log('账户激活成功:', result.data.user);
962
+ console.log('Account activated successfully:', result.data.user);
977
963
 
978
- // 5. 重定向到主页
964
+ // 5. Redirect to homepage
979
965
  window.location.href = '/';
980
966
  }
981
967
  ```
982
968
 
983
- **方式三:使用静态方法处理**
969
+ **Method 3: Use Static Method Handling**
984
970
 
985
971
  ```typescript
986
972
  import { AuthModal } from '@seaverse/auth-sdk';
987
973
 
988
- // AuthModal 提供静态方法处理邀请码场景
974
+ // AuthModal provides static method to handle invitation code scenario
989
975
  const inviteCodeInfo = AuthModal.handleInviteCodeRequired(
990
976
  { client },
991
977
  (userId, email) => {
992
- // 自定义处理逻辑
993
- const code = prompt(`请输入邀请码激活账户 (${email}):`);
978
+ // Custom handling logic
979
+ const code = prompt(`Please enter invitation code to activate account (${email}):`);
994
980
  if (code) {
995
981
  client.bindInviteCode({ user_id: userId, invite_code: code })
996
982
  .then(res => {
@@ -1002,33 +988,33 @@ const inviteCodeInfo = AuthModal.handleInviteCodeRequired(
1002
988
  );
1003
989
  ```
1004
990
 
1005
- ### 10. 其他功能
991
+ ### 10. Other Features
1006
992
 
1007
993
  ```typescript
1008
- // 获取API Service Token
994
+ // Get API Service Token
1009
995
  const apiToken = await client.getApiServiceToken();
1010
996
 
1011
- // 获取对话状态
997
+ // Get conversation status
1012
998
  const status = await client.getConversationStatus({
1013
999
  conversationId: 'conv-123',
1014
1000
  });
1015
1001
 
1016
- // 获取语音Token
1002
+ // Get speech token
1017
1003
  const speechToken = await client.getSpeechToken();
1018
1004
  ```
1019
1005
 
1020
- ## 高级配置
1006
+ ## Advanced Configuration
1021
1007
 
1022
- ### 自定义认证
1008
+ ### Custom Authentication
1023
1009
 
1024
1010
  ```typescript
1025
1011
  import { AuthFactory } from '@seaverse/auth-sdk';
1026
1012
 
1027
1013
  const client = new SeaVerseBackendAPIClient({
1028
- appId: 'your app id', // 必需:应用ID
1014
+ appId: 'your app id', // Required: Application ID
1029
1015
  environment: 'production',
1030
1016
 
1031
- // 使用JWT认证
1017
+ // Use JWT authentication
1032
1018
  auth: AuthFactory.create({
1033
1019
  type: 'jwt',
1034
1020
  credentials: {
@@ -1039,28 +1025,28 @@ const client = new SeaVerseBackendAPIClient({
1039
1025
  });
1040
1026
  ```
1041
1027
 
1042
- ### 自定义Hooks
1028
+ ### Custom Hooks
1043
1029
 
1044
1030
  ```typescript
1045
1031
  import { BuiltInHooks } from '@seaverse/auth-sdk';
1046
1032
 
1047
1033
  const client = new SeaVerseBackendAPIClient({
1048
- appId: 'your app id', // 必需:应用ID
1034
+ appId: 'your app id', // Required: Application ID
1049
1035
  environment: 'production',
1050
1036
 
1051
1037
  hooks: {
1052
1038
  hooks: [
1053
- // 日志Hook
1039
+ // Logger Hook
1054
1040
  BuiltInHooks.createLoggerHook({
1055
1041
  logLevel: 'debug',
1056
1042
  logRequestBody: true,
1057
1043
  logResponseBody: true,
1058
1044
  }),
1059
1045
 
1060
- // 请求ID Hook
1046
+ // Request ID Hook
1061
1047
  BuiltInHooks.createRequestIdHook(),
1062
1048
 
1063
- // 自定义Hook
1049
+ // Custom Hook
1064
1050
  {
1065
1051
  type: 'beforeRequest',
1066
1052
  name: 'custom-hook',
@@ -1074,22 +1060,22 @@ const client = new SeaVerseBackendAPIClient({
1074
1060
  });
1075
1061
  ```
1076
1062
 
1077
- ### 请求重试配置
1063
+ ### Request Retry Configuration
1078
1064
 
1079
- SDK 支持自定义 HTTP 请求重试策略。**默认情况下重试功能是禁用的(maxRetries: 0)**,以确保请求的可预测性。
1065
+ The SDK supports custom HTTP request retry strategies. **By default, retry functionality is disabled (maxRetries: 0)** to ensure request predictability.
1080
1066
 
1081
- #### 默认行为(禁用重试)
1067
+ #### Default Behavior (Retry Disabled)
1082
1068
 
1083
1069
  ```typescript
1084
1070
  const client = new SeaVerseBackendAPIClient({
1085
1071
  appId: 'your app id',
1086
- // retryOptions 未设置,默认不重试
1072
+ // retryOptions not set, no retry by default
1087
1073
  });
1088
1074
 
1089
- // 如果请求失败,会立即返回错误,不会重试
1075
+ // If request fails, will return error immediately, no retry
1090
1076
  ```
1091
1077
 
1092
- #### 启用基础重试
1078
+ #### Enable Basic Retry
1093
1079
 
1094
1080
  ```typescript
1095
1081
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
@@ -1097,25 +1083,25 @@ import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
1097
1083
  const client = new SeaVerseBackendAPIClient({
1098
1084
  appId: 'your app id',
1099
1085
  retryOptions: {
1100
- maxRetries: 3, // 最多重试 3
1101
- retryDelay: 1000, // 初始延迟 1000ms (1)
1102
- // 默认会对以下状态码重试:[408, 429, 500, 502, 503, 504]
1086
+ maxRetries: 3, // Retry up to 3 times
1087
+ retryDelay: 1000, // Initial delay 1000ms (1 second)
1088
+ // Defaults to retry on these status codes: [408, 429, 500, 502, 503, 504]
1103
1089
  },
1104
1090
  });
1105
1091
  ```
1106
1092
 
1107
- **重试策略说明**:
1108
- - 采用**指数退避**算法:第1次等待1秒,第2次等待2秒,第3次等待4
1109
- - 自动重试的 HTTP 状态码:
1110
- - `408` - Request Timeout(请求超时)
1111
- - `429` - Too Many Requests(限流)
1112
- - `500` - Internal Server Error(服务器内部错误)
1113
- - `502` - Bad Gateway(网关错误)
1114
- - `503` - Service Unavailable(服务不可用)
1115
- - `504` - Gateway Timeout(网关超时)
1116
- - 网络错误(无响应)也会触发重试
1093
+ **Retry Strategy Explanation**:
1094
+ - Uses **exponential backoff** algorithm: 1st retry waits 1 second, 2nd waits 2 seconds, 3rd waits 4 seconds
1095
+ - HTTP status codes that trigger auto-retry:
1096
+ - `408` - Request Timeout
1097
+ - `429` - Too Many Requests (rate limiting)
1098
+ - `500` - Internal Server Error
1099
+ - `502` - Bad Gateway
1100
+ - `503` - Service Unavailable
1101
+ - `504` - Gateway Timeout
1102
+ - Network errors (no response) will also trigger retry
1117
1103
 
1118
- #### 自定义重试状态码
1104
+ #### Custom Retry Status Codes
1119
1105
 
1120
1106
  ```typescript
1121
1107
  const client = new SeaVerseBackendAPIClient({
@@ -1123,12 +1109,12 @@ const client = new SeaVerseBackendAPIClient({
1123
1109
  retryOptions: {
1124
1110
  maxRetries: 5,
1125
1111
  retryDelay: 2000,
1126
- retryStatusCodes: [503, 504], // 只对 503 504 重试
1112
+ retryStatusCodes: [503, 504], // Only retry on 503 and 504
1127
1113
  },
1128
1114
  });
1129
1115
  ```
1130
1116
 
1131
- #### 自定义重试逻辑
1117
+ #### Custom Retry Logic
1132
1118
 
1133
1119
  ```typescript
1134
1120
  import type { RetryOptions } from '@seaverse/auth-sdk';
@@ -1136,13 +1122,13 @@ import type { RetryOptions } from '@seaverse/auth-sdk';
1136
1122
  const retryOptions: RetryOptions = {
1137
1123
  maxRetries: 3,
1138
1124
  retryDelay: 1000,
1139
- // 自定义判断逻辑:只对特定错误重试
1125
+ // Custom judgment logic: only retry on specific errors
1140
1126
  shouldRetry: (error) => {
1141
- // 只对服务不可用错误重试
1127
+ // Only retry on service unavailable errors
1142
1128
  if (error.response?.status === 503) {
1143
1129
  return true;
1144
1130
  }
1145
- // 对没有响应的网络错误重试
1131
+ // Retry on network errors with no response
1146
1132
  if (!error.response) {
1147
1133
  return true;
1148
1134
  }
@@ -1156,153 +1142,153 @@ const client = new SeaVerseBackendAPIClient({
1156
1142
  });
1157
1143
  ```
1158
1144
 
1159
- #### RetryOptions 类型定义
1145
+ #### RetryOptions Type Definition
1160
1146
 
1161
1147
  ```typescript
1162
1148
  interface RetryOptions {
1163
- maxRetries?: number; // 最大重试次数,默认 0(禁用)
1164
- retryDelay?: number; // 初始重试延迟(毫秒),默认 1000
1165
- retryStatusCodes?: number[]; // 触发重试的状态码列表
1166
- shouldRetry?: (error: AxiosError) => boolean; // 自定义重试判断函数
1149
+ maxRetries?: number; // Maximum retry count, default 0 (disabled)
1150
+ retryDelay?: number; // Initial retry delay (milliseconds), default 1000
1151
+ retryStatusCodes?: number[]; // List of status codes that trigger retry
1152
+ shouldRetry?: (error: AxiosError) => boolean; // Custom retry judgment function
1167
1153
  }
1168
1154
  ```
1169
1155
 
1170
- **使用建议**:
1171
- - ⚠️ **生产环境建议禁用重试**(默认行为),避免在业务逻辑错误时产生重复请求
1172
- - ✅ 仅在网络不稳定的场景启用重试,如移动端应用、弱网环境
1173
- - ✅ 确保后端 API 支持幂等性操作,避免重试导致的副作用
1174
- - ✅ 对于关键业务(如支付),建议使用自定义 `shouldRetry` 仔细控制重试逻辑
1156
+ **Usage Recommendations**:
1157
+ - ⚠️ **Recommended to disable retry in production** (default behavior), avoid duplicate requests on business logic errors
1158
+ - ✅ Only enable retry in unstable network scenarios, such as mobile apps, weak network environments
1159
+ - ✅ Ensure backend APIs support idempotent operations, avoid side effects from retries
1160
+ - ✅ For critical business (such as payments), recommended to use custom `shouldRetry` to carefully control retry logic
1175
1161
 
1176
- ### 环境配置
1162
+ ### Environment Configuration
1177
1163
 
1178
- SDK支持以下环境:
1164
+ The SDK supports the following environments:
1179
1165
 
1180
- | 环境 | 描述 | BaseURL |
1166
+ | Environment | Description | BaseURL |
1181
1167
  |------|------|---------|
1182
- | `production` | 生产环境 | `https://account-hub.seaverse.ai` |
1183
- | `staging` | 测试环境 | `https://api.staging.seaverse.dev` |
1184
- | `development` | 开发环境 | `https://api.dev.seaverse.dev` |
1185
- | `local` | 本地环境 | `http://localhost:3000` |
1168
+ | `production` | Production environment | `https://account-hub.seaverse.ai` |
1169
+ | `staging` | Staging environment | `https://api.staging.seaverse.dev` |
1170
+ | `development` | Development environment | `https://api.dev.seaverse.dev` |
1171
+ | `local` | Local environment | `http://localhost:3000` |
1186
1172
 
1187
- 自动检测规则:
1173
+ Auto-detection rules:
1188
1174
  - `*.seaverse.com` → production
1189
1175
  - `*.staging.seaverse.dev` → staging
1190
1176
  - `*.dev.seaverse.dev` → development
1191
1177
  - `localhost` → local
1192
1178
 
1193
- ## API 参考
1179
+ ## API Reference
1194
1180
 
1195
- ### 认证相关
1181
+ ### Authentication Related
1196
1182
 
1197
- | 方法 | 参数 | 返回值 | 说明 |
1183
+ | Method | Parameters | Return Value | Description |
1198
1184
  |------|------|--------|------|
1199
- | `register()` | `{ email, password, username?, invitation_code?, frontend_url? }` | `RegisterResponse` | 注册新用户,frontend_url 为邮箱验证链接的前端URL,默认为 window.location.href |
1200
- | `login()` | `{ email, password, frontend_url? }` | `LoginResponse` | 用户登录,frontend_url 用于未验证邮箱时发送验证邮件,默认为 https://seaverse.ai/。⚠️ 如果返回 INVITE_CODE_REQUIRED 且包含 redirectUrl,会自动跳转 |
1201
- | `getCurrentUser()` | - | `User` | 获取当前用户 |
1202
- | `logout()` | - | `SuccessResponse` | 登出 |
1203
- | `verifyEmail()` | `verifyToken: string` | `EmailVerificationResponse` | 验证邮箱并返回自动登录 token |
1204
- | `bindInviteCode()` | `{ user_id, invite_code }` | `BindInviteCodeResponse` | 绑定邀请码激活临时账户并自动登录 |
1205
- | `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | 忘记密码,frontend_url 默认为 window.location.href |
1206
- | `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
1207
- | `setToken()` | `token: string` | `void` | 设置认证 tokenOAuth 登录后使用) |
1208
- | `isInIframe()` | - | `boolean` | 检查应用是否在 iframe 中运行(支持静态方法和实例方法) |
1209
- | `getIframeToken()` | `{ timeout? }` | `Promise<string>` | 从父页面获取 token(仅 iframe 场景),timeout 默认 30000ms |
1210
- | `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
1211
-
1212
- #### 注册流程说明
1213
-
1214
- `register()` 方法支持三种注册流程,SDK 会根据后端响应自动处理:
1215
-
1216
- **流程 1: 立即激活(默认)**
1185
+ | `register()` | `{ email, password, username?, invitation_code?, frontend_url? }` | `RegisterResponse` | Register new user, frontend_url is frontend URL for email verification link, defaults to window.location.href |
1186
+ | `login()` | `{ email, password, frontend_url? }` | `LoginResponse` | User login, frontend_url used for sending verification email when email not verified, defaults to https://seaverse.ai/. ⚠️ If returns INVITE_CODE_REQUIRED with redirectUrl, will automatically redirect |
1187
+ | `getCurrentUser()` | - | `User` | Get current user |
1188
+ | `logout()` | - | `SuccessResponse` | Logout |
1189
+ | `verifyEmail()` | `verifyToken: string` | `EmailVerificationResponse` | Verify email and return auto-login token |
1190
+ | `bindInviteCode()` | `{ user_id, invite_code }` | `BindInviteCodeResponse` | Bind invitation code to activate temporary account and auto-login |
1191
+ | `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | Forgot password, frontend_url defaults to window.location.href |
1192
+ | `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | Reset password |
1193
+ | `setToken()` | `token: string` | `void` | Set authentication token (used after OAuth login) |
1194
+ | `isInIframe()` | - | `boolean` | Check if application is running in iframe (supports static method and instance method) |
1195
+ | `getIframeToken()` | `{ timeout? }` | `Promise<string>` | Get token from parent page (iframe scenario only), timeout defaults to 30000ms |
1196
+ | `getApiServiceToken()` | - | `ApiServiceTokenResponse` | Get API Token |
1197
+
1198
+ #### Registration Flow Description
1199
+
1200
+ The `register()` method supports three registration flows, SDK automatically handles based on backend response:
1201
+
1202
+ **Flow 1: Immediate Activation (Default)**
1217
1203
  ```typescript
1218
1204
  const response = await client.register({ email, password });
1219
1205
  // response.success === true
1220
- // response.requiresEmailVerification === undefined ( false)
1221
- // response.requiresInvitationCode === undefined ( false)
1222
- // → SDK 自动调用 login() 并触发 onSignupSuccess 回调
1206
+ // response.requiresEmailVerification === undefined (or false)
1207
+ // response.requiresInvitationCode === undefined (or false)
1208
+ // → SDK automatically calls login() and triggers onSignupSuccess callback
1223
1209
  ```
1224
1210
 
1225
- **流程 2: 需要邮箱验证**
1211
+ **Flow 2: Requires Email Verification**
1226
1212
  ```typescript
1227
1213
  const response = await client.register({ email, password });
1228
1214
  // response.success === true
1229
1215
  // response.requiresEmailVerification === true
1230
- // → SDK 显示 Toast 提示用户检查邮箱
1231
- // → 不会自动调用 login(),用户需要点击邮件中的验证链接
1216
+ // → SDK shows Toast prompting user to check email
1217
+ // → Does not auto-call login(), user needs to click verification link in email
1232
1218
  ```
1233
1219
 
1234
- **流程 3: 需要邀请码激活**
1220
+ **Flow 3: Requires Invitation Code Activation**
1235
1221
  ```typescript
1236
1222
  const response = await client.register({ email, password });
1237
1223
  // response.success === true
1238
1224
  // response.requiresInvitationCode === true
1239
1225
  // response.tempUserId === "temp_xxx"
1240
- // → SDK 显示邀请码输入表单
1241
- // → 不会自动调用 login(),用户需要输入邀请码
1226
+ // → SDK shows invitation code input form
1227
+ // → Does not auto-call login(), user needs to input invitation code
1242
1228
  ```
1243
1229
 
1244
- **重要提示**:
1245
- - AuthModal 会自动处理这三种流程,无需手动判断
1246
- - 只有在无需验证或激活的情况下,才会自动调用 `login()`
1247
- - 这避免了在邮箱未验证或账户未激活时产生不必要的登录请求
1230
+ **Important Note**:
1231
+ - AuthModal automatically handles these three flows, no manual judgment needed
1232
+ - Only when no verification or activation is needed, will `login()` be automatically called
1233
+ - This avoids unnecessary login requests when email is not verified or account is not activated
1248
1234
 
1249
- ### OAuth相关
1235
+ ### OAuth Related
1250
1236
 
1251
- | 方法 | 参数 | 返回值 | 说明 |
1237
+ | Method | Parameters | Return Value | Description |
1252
1238
  |------|------|--------|------|
1253
- | `googleAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Google OAuth 授权 URL |
1254
- | `discordAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Discord OAuth 授权 URL |
1255
- | `githubAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | GitHub OAuth 授权 URL |
1256
- | `unlinkGoogle()` | - | `SuccessResponse` | 解绑Google |
1257
- | `unlinkDiscord()` | - | `SuccessResponse` | 解绑Discord |
1258
- | `unlinkGithub()` | - | `SuccessResponse` | 解绑GitHub |
1239
+ | `googleAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Google OAuth authorization URL |
1240
+ | `discordAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Discord OAuth authorization URL |
1241
+ | `githubAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | GitHub OAuth authorization URL |
1242
+ | `unlinkGoogle()` | - | `SuccessResponse` | Unlink Google |
1243
+ | `unlinkDiscord()` | - | `SuccessResponse` | Unlink Discord |
1244
+ | `unlinkGithub()` | - | `SuccessResponse` | Unlink GitHub |
1259
1245
 
1260
- ### 容器管理
1246
+ ### Container Management
1261
1247
 
1262
- | 方法 | 参数 | 返回值 | 说明 |
1248
+ | Method | Parameters | Return Value | Description |
1263
1249
  |------|------|--------|------|
1264
- | `listContainers()` | - | `ContainerListResponse` | 列出容器 |
1265
- | `registerContainer()` | `{ containerId, metadata }` | `SuccessResponse` | 注册容器 |
1266
- | `getContainer()` | `{ containerId }` | `Container` | 获取容器信息 |
1267
- | `unregisterContainer()` | `{ containerId }` | `SuccessResponse` | 注销容器 |
1268
- | `containerHeartbeat()` | `{ containerId, status }` | `SuccessResponse` | 容器心跳 |
1269
- | `getContainerStats()` | - | `ContainerStatsResponse` | 容器统计 |
1250
+ | `listContainers()` | - | `ContainerListResponse` | List containers |
1251
+ | `registerContainer()` | `{ containerId, metadata }` | `SuccessResponse` | Register container |
1252
+ | `getContainer()` | `{ containerId }` | `Container` | Get container info |
1253
+ | `unregisterContainer()` | `{ containerId }` | `SuccessResponse` | Unregister container |
1254
+ | `containerHeartbeat()` | `{ containerId, status }` | `SuccessResponse` | Container heartbeat |
1255
+ | `getContainerStats()` | - | `ContainerStatsResponse` | Container stats |
1270
1256
 
1271
- ### 技能市场
1257
+ ### Skill Marketplace
1272
1258
 
1273
- | 方法 | 参数 | 返回值 | 说明 |
1259
+ | Method | Parameters | Return Value | Description |
1274
1260
  |------|------|--------|------|
1275
- | `listMarketplaceSkills()` | `{ category?, page?, pageSize? }` | `MarketplaceSkillsListResponse` | 列出市场技能 |
1276
- | `getMarketplaceSkill()` | `{ skillId }` | `MarketplaceSkill` | 获取技能详情 |
1277
- | `installSkill()` | `{ skillId }` | `SuccessResponse` | 安装技能 |
1278
- | `listUserSkills()` | - | `UserInstalledSkillsListResponse` | 列出已安装技能 |
1279
- | `uninstallSkill()` | `{ skillId }` | `SuccessResponse` | 卸载技能 |
1261
+ | `listMarketplaceSkills()` | `{ category?, page?, pageSize? }` | `MarketplaceSkillsListResponse` | List marketplace skills |
1262
+ | `getMarketplaceSkill()` | `{ skillId }` | `MarketplaceSkill` | Get skill details |
1263
+ | `installSkill()` | `{ skillId }` | `SuccessResponse` | Install skill |
1264
+ | `listUserSkills()` | - | `UserInstalledSkillsListResponse` | List installed skills |
1265
+ | `uninstallSkill()` | `{ skillId }` | `SuccessResponse` | Uninstall skill |
1280
1266
 
1281
- ### 邀请码管理
1267
+ ### Invitation Code Management
1282
1268
 
1283
- | 方法 | 参数 | 返回值 | 说明 |
1269
+ | Method | Parameters | Return Value | Description |
1284
1270
  |------|------|--------|------|
1285
- | `applyInvite()` | `{ email, reason }` | `ApplyInviteResponse` | 申请邀请码(reason 10-500字符)|
1286
- | `listInvites()` | `{ page?, page_size?, status? }` | `ListInvitesResponse` | 列出我的邀请码 |
1287
- | `getInviteStats()` | - | `InviteStatsResponse` | 获取邀请码统计 |
1288
- | `getInvite()` | `inviteId: string` | `InviteCodeDetailResponse` | 获取邀请码详情 |
1289
- | `getInviteUsages()` | `inviteId: string, { page?, page_size? }` | `ListInviteUsagesResponse` | 获取邀请码使用记录 |
1271
+ | `applyInvite()` | `{ email, reason }` | `ApplyInviteResponse` | Apply for invitation code (reason needs 10-500 characters)|
1272
+ | `listInvites()` | `{ page?, page_size?, status? }` | `ListInvitesResponse` | List my invitation codes |
1273
+ | `getInviteStats()` | - | `InviteStatsResponse` | Get invitation code stats |
1274
+ | `getInvite()` | `inviteId: string` | `InviteCodeDetailResponse` | Get invitation code details |
1275
+ | `getInviteUsages()` | `inviteId: string, { page?, page_size? }` | `ListInviteUsagesResponse` | Get invitation code usage records |
1290
1276
 
1291
- ### 其他
1277
+ ### Others
1292
1278
 
1293
- | 方法 | 参数 | 返回值 | 说明 |
1279
+ | Method | Parameters | Return Value | Description |
1294
1280
  |------|------|--------|------|
1295
- | `getHealth()` | - | `HealthResponse` | 健康检查 |
1296
- | `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | 获取对话状态 |
1297
- | `getSpeechToken()` | - | `SpeechTokenResponse` | 获取语音Token |
1281
+ | `getHealth()` | - | `HealthResponse` | Health check |
1282
+ | `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | Get conversation status |
1283
+ | `getSpeechToken()` | - | `SpeechTokenResponse` | Get speech token |
1298
1284
 
1299
- ## 响应格式兼容性
1285
+ ## Response Format Compatibility
1300
1286
 
1301
- ### 自动响应解包
1287
+ ### Auto Response Unwrapping
1302
1288
 
1303
- v0.2.5 开始,SDK 自动兼容两种API响应格式,无需手动处理:
1289
+ Starting from v0.2.5, SDK automatically supports two API response formats, no manual handling needed:
1304
1290
 
1305
- **格式 1: 包装格式**(推荐)
1291
+ **Format 1: Wrapped Format** (Recommended)
1306
1292
  ```json
1307
1293
  {
1308
1294
  "data": {
@@ -1313,7 +1299,7 @@ const response = await client.register({ email, password });
1313
1299
  }
1314
1300
  ```
1315
1301
 
1316
- **格式 2: 扁平格式**(向后兼容)
1302
+ **Format 2: Flat Format** (Backward Compatible)
1317
1303
  ```json
1318
1304
  {
1319
1305
  "token": "eyJhbGc...",
@@ -1321,101 +1307,101 @@ const response = await client.register({ email, password });
1321
1307
  }
1322
1308
  ```
1323
1309
 
1324
- SDK 会自动检测响应格式并提取正确的数据:
1310
+ SDK automatically detects response format and extracts correct data:
1325
1311
 
1326
1312
  ```typescript
1327
- // 无论后端返回哪种格式,以下代码都能正常工作
1313
+ // Regardless of which format backend returns, the following code works
1328
1314
  const loginResult = await client.login({
1329
1315
  email: 'user@example.com',
1330
1316
  password: 'password123',
1331
1317
  });
1332
1318
 
1333
- console.log(loginResult.token); // ✅ 始终能正确获取 token
1334
- console.log(loginResult.user); // ✅ 始终能正确获取 user
1319
+ console.log(loginResult.token); // ✅ Always gets token correctly
1320
+ console.log(loginResult.user); // ✅ Always gets user correctly
1335
1321
  ```
1336
1322
 
1337
- ### 受影响的方法
1323
+ ### Affected Methods
1338
1324
 
1339
- 以下方法已实现自动响应解包:
1325
+ The following methods have implemented auto response unwrapping:
1340
1326
 
1341
- - ✅ `login()` - 登录接口
1342
- - ✅ `register()` - 注册接口
1343
- - ✅ `getCurrentUser()` - 获取当前用户
1327
+ - ✅ `login()` - Login API
1328
+ - ✅ `register()` - Registration API
1329
+ - ✅ `getCurrentUser()` - Get current user
1344
1330
 
1345
- ### 实现原理
1331
+ ### Implementation Principle
1346
1332
 
1347
- SDK 内部通过以下逻辑自动处理响应格式:
1333
+ SDK internally handles response format through the following logic:
1348
1334
 
1349
1335
  ```typescript
1350
1336
  const response = await httpClient.request(config);
1351
1337
  const responseData = response.data;
1352
1338
 
1353
- // 检测并解包
1339
+ // Detect and unwrap
1354
1340
  if (responseData.data && typeof responseData.data === 'object') {
1355
- // 包装格式: 提取 data 字段
1341
+ // Wrapped format: extract data field
1356
1342
  return responseData.data;
1357
1343
  }
1358
- // 扁平格式: 直接返回
1344
+ // Flat format: return directly
1359
1345
  return responseData;
1360
1346
  ```
1361
1347
 
1362
- 这意味着:
1363
- - 🔄 **后端格式变更无需前端修改** - 后端可以自由调整响应格式
1364
- - 🔧 **渐进式迁移** - 可以逐步将不同接口迁移到新格式
1365
- - ✅ **向后兼容** - 旧代码无需修改即可继续工作
1348
+ This means:
1349
+ - 🔄 **Backend format changes don't require frontend modifications** - Backend can freely adjust response format
1350
+ - 🔧 **Progressive migration** - Different APIs can be migrated to new format gradually
1351
+ - ✅ **Backward compatible** - Old code continues to work without modifications
1366
1352
 
1367
- ## 错误处理
1353
+ ## Error Handling
1368
1354
 
1369
- ### 错误响应格式
1355
+ ### Error Response Format
1370
1356
 
1371
- 所有 API 错误都遵循统一的响应格式:
1357
+ All API errors follow a unified response format:
1372
1358
 
1373
1359
  ```typescript
1374
1360
  interface ApiError {
1375
- success: false; // 错误时始终为 false
1376
- error: string; // 人类可读的错误消息
1377
- code?: string; // 机器可读的错误码
1378
- details?: any; // 额外的错误详情
1361
+ success: false; // Always false on error
1362
+ error: string; // Human-readable error message
1363
+ code?: string; // Machine-readable error code
1364
+ details?: any; // Additional error details
1379
1365
  }
1380
1366
  ```
1381
1367
 
1382
- ### 错误码
1368
+ ### Error Codes
1383
1369
 
1384
- SDK 提供了标准的错误码枚举:
1370
+ SDK provides standard error code enums:
1385
1371
 
1386
1372
  ```typescript
1387
1373
  import { ErrorCode } from '@seaverse/auth-sdk';
1388
1374
 
1389
- // 账户相关错误
1390
- ErrorCode.ACCOUNT_EXISTS // 账户已存在
1391
- ErrorCode.ACCOUNT_NOT_FOUND // 账户不存在
1392
- ErrorCode.ACCOUNT_SUSPENDED // 账户已被暂停
1393
- ErrorCode.INVALID_CREDENTIALS // 登录凭证无效
1394
- ErrorCode.EMAIL_NOT_VERIFIED // 邮箱未验证
1395
-
1396
- // 验证相关错误
1397
- ErrorCode.INVALID_EMAIL // 无效的邮箱地址
1398
- ErrorCode.INVALID_PASSWORD // 无效的密码
1399
- ErrorCode.PASSWORD_TOO_WEAK // 密码强度不够
1400
-
1401
- // 邀请码相关错误
1402
- ErrorCode.INVALID_INVITATION_CODE // 无效的邀请码
1403
- ErrorCode.INVITATION_REQUIRED // 需要邀请码
1404
- ErrorCode.INVITE_CODE_REQUIRED // 需要邀请码(会自动跳转到 redirectUrl
1405
-
1406
- // Token 相关错误
1407
- ErrorCode.INVALID_TOKEN // 无效的 token
1408
- ErrorCode.TOKEN_EXPIRED // Token 已过期
1409
-
1410
- // 内部错误
1411
- ErrorCode.INTERNAL_ERROR // 服务器内部错误
1375
+ // Account-related errors
1376
+ ErrorCode.ACCOUNT_EXISTS // Account already exists
1377
+ ErrorCode.ACCOUNT_NOT_FOUND // Account not found
1378
+ ErrorCode.ACCOUNT_SUSPENDED // Account suspended
1379
+ ErrorCode.INVALID_CREDENTIALS // Invalid login credentials
1380
+ ErrorCode.EMAIL_NOT_VERIFIED // Email not verified
1381
+
1382
+ // Validation-related errors
1383
+ ErrorCode.INVALID_EMAIL // Invalid email address
1384
+ ErrorCode.INVALID_PASSWORD // Invalid password
1385
+ ErrorCode.PASSWORD_TOO_WEAK // Password too weak
1386
+
1387
+ // Invitation code-related errors
1388
+ ErrorCode.INVALID_INVITATION_CODE // Invalid invitation code
1389
+ ErrorCode.INVITATION_REQUIRED // Invitation code required
1390
+ ErrorCode.INVITE_CODE_REQUIRED // Invitation code required (will auto-redirect to redirectUrl)
1391
+
1392
+ // Token-related errors
1393
+ ErrorCode.INVALID_TOKEN // Invalid token
1394
+ ErrorCode.TOKEN_EXPIRED // Token expired
1395
+
1396
+ // Internal errors
1397
+ ErrorCode.INTERNAL_ERROR // Server internal error
1412
1398
  ```
1413
1399
 
1414
- ### 错误处理最佳实践
1400
+ ### Error Handling Best Practices
1415
1401
 
1416
- #### 1. 注册时处理重复用户
1402
+ #### 1. Handle Duplicate Users During Registration
1417
1403
 
1418
- 由于后端在账户已存在时返回 200 OK(成功响应),所以前端不会抛出异常,而是在响应体中包含错误信息。
1404
+ Since backend returns 200 OK when account exists (success response), frontend won't throw exception, but includes error info in response body.
1419
1405
 
1420
1406
  ```typescript
1421
1407
  import { ErrorCode } from '@seaverse/auth-sdk';
@@ -1425,27 +1411,27 @@ const result = await client.register({
1425
1411
  password: 'password123',
1426
1412
  });
1427
1413
 
1428
- // 检查响应中的 success 字段
1414
+ // Check success field in response
1429
1415
  if (result.success) {
1430
- console.log('注册成功:', result);
1431
- // 进行后续操作,如自动登录
1416
+ console.log('Registration successful:', result);
1417
+ // Proceed with follow-up actions, such as auto-login
1432
1418
  } else if (result.code === ErrorCode.ACCOUNT_EXISTS) {
1433
- // 账户已存在,提示用户
1419
+ // Account exists, prompt user
1434
1420
  const { email, app_id } = result.details;
1435
- console.log(`账户 ${email} 已存在于应用 ${app_id} 中`);
1421
+ console.log(`Account ${email} already exists in application ${app_id}`);
1436
1422
 
1437
- // 显示友好的提示信息
1423
+ // Show friendly prompt
1438
1424
  alert('This email is already registered. Please login instead.');
1439
1425
 
1440
- // 或者引导用户去登录
1426
+ // Or guide user to login
1441
1427
  showLoginModal();
1442
1428
  } else {
1443
- // 处理其他错误
1444
- console.error('注册失败:', result.error);
1429
+ // Handle other errors
1430
+ console.error('Registration failed:', result.error);
1445
1431
  }
1446
1432
  ```
1447
1433
 
1448
- #### 2. 登录时处理各种错误
1434
+ #### 2. Handle Various Errors During Login
1449
1435
 
1450
1436
  ```typescript
1451
1437
  try {
@@ -1453,28 +1439,28 @@ try {
1453
1439
  email: 'user@example.com',
1454
1440
  password: 'wrong-password',
1455
1441
  });
1456
- console.log('登录成功:', result);
1442
+ console.log('Login successful:', result);
1457
1443
  } catch (error) {
1458
1444
  const errorCode = error.response?.data?.code;
1459
1445
 
1460
1446
  switch (errorCode) {
1461
1447
  case ErrorCode.INVALID_CREDENTIALS:
1462
- showError('用户名或密码错误');
1448
+ showError('Incorrect username or password');
1463
1449
  break;
1464
1450
  case ErrorCode.EMAIL_NOT_VERIFIED:
1465
- showError('请先验证您的邮箱');
1451
+ showError('Please verify your email first');
1466
1452
  showResendVerificationButton();
1467
1453
  break;
1468
1454
  case ErrorCode.ACCOUNT_SUSPENDED:
1469
- showError('您的账户已被暂停,请联系管理员');
1455
+ showError('Your account has been suspended, please contact administrator');
1470
1456
  break;
1471
1457
  default:
1472
- showError('登录失败,请稍后重试');
1458
+ showError('Login failed, please try again later');
1473
1459
  }
1474
1460
  }
1475
1461
  ```
1476
1462
 
1477
- #### 3. 通用错误处理函数
1463
+ #### 3. Generic Error Handling Function
1478
1464
 
1479
1465
  ```typescript
1480
1466
  import { ErrorCode } from '@seaverse/auth-sdk';
@@ -1483,44 +1469,44 @@ function handleApiError(error: any) {
1483
1469
  const apiError = error.response?.data;
1484
1470
 
1485
1471
  if (!apiError) {
1486
- // 网络错误或其他未知错误
1472
+ // Network error or other unknown error
1487
1473
  return {
1488
- title: '网络错误',
1489
- message: '请检查您的网络连接',
1474
+ title: 'Network Error',
1475
+ message: 'Please check your network connection',
1490
1476
  };
1491
1477
  }
1492
1478
 
1493
- // 根据错误码返回用户友好的消息
1479
+ // Return user-friendly messages based on error code
1494
1480
  const errorMessages: Record<string, { title: string; message: string }> = {
1495
1481
  [ErrorCode.ACCOUNT_EXISTS]: {
1496
- title: '账户已存在',
1497
- message: '该邮箱已注册,请直接登录',
1482
+ title: 'Account Exists',
1483
+ message: 'This email is already registered, please login directly',
1498
1484
  },
1499
1485
  [ErrorCode.INVALID_CREDENTIALS]: {
1500
- title: '登录失败',
1501
- message: '用户名或密码错误',
1486
+ title: 'Login Failed',
1487
+ message: 'Incorrect username or password',
1502
1488
  },
1503
1489
  [ErrorCode.EMAIL_NOT_VERIFIED]: {
1504
- title: '邮箱未验证',
1505
- message: '请先验证您的邮箱地址',
1490
+ title: 'Email Not Verified',
1491
+ message: 'Please verify your email address first',
1506
1492
  },
1507
1493
  [ErrorCode.INVALID_INVITATION_CODE]: {
1508
- title: '邀请码无效',
1509
- message: '请检查您的邀请码是否正确',
1494
+ title: 'Invalid Invitation Code',
1495
+ message: 'Please check if your invitation code is correct',
1510
1496
  },
1511
1497
  [ErrorCode.TOKEN_EXPIRED]: {
1512
- title: '登录已过期',
1513
- message: '请重新登录',
1498
+ title: 'Login Expired',
1499
+ message: 'Please login again',
1514
1500
  },
1515
1501
  };
1516
1502
 
1517
1503
  return errorMessages[apiError.code] || {
1518
- title: '操作失败',
1519
- message: apiError.error || '发生未知错误',
1504
+ title: 'Operation Failed',
1505
+ message: apiError.error || 'Unknown error occurred',
1520
1506
  };
1521
1507
  }
1522
1508
 
1523
- // 使用示例
1509
+ // Usage example
1524
1510
  try {
1525
1511
  await client.register({ email, password });
1526
1512
  } catch (error) {
@@ -1529,7 +1515,7 @@ try {
1529
1515
  }
1530
1516
  ```
1531
1517
 
1532
- #### 4. TypeScript 类型安全的错误处理
1518
+ #### 4. TypeScript Type-Safe Error Handling
1533
1519
 
1534
1520
  ```typescript
1535
1521
  import { ErrorCode, models } from '@seaverse/auth-sdk';
@@ -1569,164 +1555,164 @@ if (registerResult.success) {
1569
1555
  }
1570
1556
  ```
1571
1557
 
1572
- ### HTTP 状态码对照
1558
+ ### HTTP Status Code Reference
1573
1559
 
1574
- | HTTP状态码 | 错误码示例 | 说明 |
1560
+ | HTTP Status Code | Error Code Example | Description |
1575
1561
  |-----------|----------|------|
1576
- | 200 OK | `ACCOUNT_EXISTS` | 账户已存在(业务错误但返回成功响应) |
1577
- | 400 Bad Request | `INVALID_EMAIL`, `PASSWORD_TOO_WEAK` | 请求参数无效 |
1578
- | 401 Unauthorized | `INVALID_CREDENTIALS`, `TOKEN_EXPIRED` | 认证失败 |
1579
- | 403 Forbidden | `EMAIL_NOT_VERIFIED`, `ACCOUNT_SUSPENDED` | 权限不足 |
1580
- | 500 Internal Server Error | `INTERNAL_ERROR` | 服务器内部错误 |
1562
+ | 200 OK | `ACCOUNT_EXISTS` | Account exists (business error but returns success response) |
1563
+ | 400 Bad Request | `INVALID_EMAIL`, `PASSWORD_TOO_WEAK` | Invalid request parameters |
1564
+ | 401 Unauthorized | `INVALID_CREDENTIALS`, `TOKEN_EXPIRED` | Authentication failed |
1565
+ | 403 Forbidden | `EMAIL_NOT_VERIFIED`, `ACCOUNT_SUSPENDED` | Insufficient permissions |
1566
+ | 500 Internal Server Error | `INTERNAL_ERROR` | Server internal error |
1581
1567
 
1582
- **注意**:对于注册接口,账户已存在的情况会返回 200 OK,但在响应体中 `success: false` `code: "ACCOUNT_EXISTS"`。这样设计是为了前端能够更容易地处理这种常见的业务场景。
1568
+ **Note**: For registration API, account exists case returns 200 OK, but in response body `success: false` and `code: "ACCOUNT_EXISTS"`. This design makes it easier for frontend to handle this common business scenario.
1583
1569
 
1584
- ## 类型定义
1570
+ ## Type Definitions
1585
1571
 
1586
1572
  ```typescript
1587
- // 用户信息
1573
+ // User info
1588
1574
  interface User {
1589
1575
  id?: string;
1590
- app_id?: string | null; // 应用ID(多租户支持)
1576
+ app_id?: string | null; // Application ID (multi-tenant support)
1591
1577
  email?: string;
1592
1578
  username?: string;
1593
- created_at?: number; // Unix时间戳
1594
- email_verified?: boolean; // 邮箱验证状态
1595
- google_id?: string | null; // Google账号ID
1596
- discord_id?: string | null; // Discord账号ID
1597
- github_id?: string | null; // GitHub账号ID
1598
-
1599
- // 已弃用字段(向后兼容)
1600
- createdAt?: number; // @deprecated 使用 created_at
1601
- emailVerified?: boolean; // @deprecated 使用 email_verified
1602
- googleId?: string; // @deprecated 使用 google_id
1603
- discordId?: string; // @deprecated 使用 discord_id
1604
- githubId?: string; // @deprecated 使用 github_id
1579
+ created_at?: number; // Unix timestamp
1580
+ email_verified?: boolean; // Email verification status
1581
+ google_id?: string | null; // Google account ID
1582
+ discord_id?: string | null; // Discord account ID
1583
+ github_id?: string | null; // GitHub account ID
1584
+
1585
+ // Deprecated fields (backward compatible)
1586
+ createdAt?: number; // @deprecated Use created_at
1587
+ emailVerified?: boolean; // @deprecated Use email_verified
1588
+ googleId?: string; // @deprecated Use google_id
1589
+ discordId?: string; // @deprecated Use discord_id
1590
+ githubId?: string; // @deprecated Use github_id
1605
1591
  }
1606
1592
 
1607
- // 登录响应
1593
+ // Login response
1608
1594
  interface LoginResponse {
1609
1595
  token: string;
1610
1596
  user: User;
1611
1597
  }
1612
1598
 
1613
- // 注册响应
1599
+ // Registration response
1614
1600
  interface RegisterResponse {
1615
1601
  success: boolean;
1616
1602
  message?: string;
1617
1603
  userId?: string;
1618
- // 邮箱验证相关
1619
- requiresEmailVerification?: boolean; // 是否需要邮箱验证
1620
- // 邀请码激活相关
1621
- requiresInvitationCode?: boolean; // 是否需要邀请码激活
1622
- tempUserId?: string; // 临时用户ID(需要激活)
1623
- // 错误信息
1604
+ // Email verification related
1605
+ requiresEmailVerification?: boolean; // Whether email verification is required
1606
+ // Invitation code activation related
1607
+ requiresInvitationCode?: boolean; // Whether invitation code activation is required
1608
+ tempUserId?: string; // Temporary user ID (needs activation)
1609
+ // Error info
1624
1610
  error?: string;
1625
- code?: string; // 'ACCOUNT_EXISTS'
1611
+ code?: string; // E.g. 'ACCOUNT_EXISTS'
1626
1612
  details?: Record<string, any>;
1627
1613
  }
1628
1614
 
1629
- // AuthModal选项
1615
+ // AuthModal options
1630
1616
  interface AuthModalOptions {
1631
1617
  client: SeaVerseBackendAPIClient;
1632
1618
  theme?: 'dark' | 'light';
1633
1619
  onLoginSuccess?: (token: string, user: any) => void;
1634
1620
  onSignupSuccess?: (token: string, user: any) => void;
1635
- onInviteCodeRequired?: (userId: string, email: string) => void; // 当需要邀请码激活时的回调
1636
- onApplyInviteSuccess?: (applicationId: string, email: string) => void; // 申请邀请码成功的回调
1621
+ onInviteCodeRequired?: (userId: string, email: string) => void; // Callback when invitation code activation is needed
1622
+ onApplyInviteSuccess?: (applicationId: string, email: string) => void; // Callback when invitation code application succeeds
1637
1623
  onError?: (error: Error) => void;
1638
- returnUrl?: string; // OAuth 登录后返回的 URL,可选,默认为 window.location.href
1624
+ returnUrl?: string; // URL to return after OAuth login, optional, defaults to window.location.href
1639
1625
  enableOAuth?: {
1640
- google?: boolean; // 启用 Google 登录
1641
- discord?: boolean; // 启用 Discord 登录
1642
- github?: boolean; // 启用 GitHub 登录
1626
+ google?: boolean; // Enable Google login
1627
+ discord?: boolean; // Enable Discord login
1628
+ github?: boolean; // Enable GitHub login
1643
1629
  };
1644
1630
  }
1645
1631
  ```
1646
1632
 
1647
- ## 完整示例
1633
+ ## Complete Examples
1648
1634
 
1649
- 查看 [examples/auth-sdk-demo](../../examples/auth-sdk-demo) 目录获取完整的可运行示例。
1635
+ Check [examples/auth-sdk-demo](../../examples/auth-sdk-demo) directory for complete runnable examples.
1650
1636
 
1651
1637
  ```bash
1652
- # 运行示例
1638
+ # Run example
1653
1639
  cd examples/auth-sdk-demo
1654
1640
  pnpm install
1655
1641
  pnpm dev
1656
1642
  ```
1657
1643
 
1658
- ## 从旧版本迁移
1644
+ ## Migration from Old Versions
1659
1645
 
1660
- ### v0.1.x → v0.2.0 升级指南
1646
+ ### v0.1.x → v0.2.0 Upgrade Guide
1661
1647
 
1662
- #### 1. 向后兼容性
1663
- 好消息!v0.2.0 完全向后兼容,现有代码**无需修改**即可继续工作。
1648
+ #### 1. Backward Compatibility
1649
+ Good news! v0.2.0 is fully backward compatible, existing code **works without modifications**.
1664
1650
 
1665
- #### 2. 推荐的迁移步骤
1651
+ #### 2. Recommended Migration Steps
1666
1652
 
1667
- 虽然不是必须的,但我们建议逐步迁移到新的字段命名规范:
1653
+ While not required, we recommend gradually migrating to new field naming conventions:
1668
1654
 
1669
1655
  ```typescript
1670
- // 旧代码(仍然可用)
1656
+ // Old code (still works)
1671
1657
  const user = await client.getCurrentUser();
1672
- console.log(user.emailVerified); // ⚠️ 已弃用但可用
1673
- console.log(user.createdAt); // ⚠️ 已弃用但可用
1658
+ console.log(user.emailVerified); // ⚠️ Deprecated but works
1659
+ console.log(user.createdAt); // ⚠️ Deprecated but works
1674
1660
 
1675
- // 新代码(推荐)
1661
+ // New code (recommended)
1676
1662
  const user = await client.getCurrentUser();
1677
- console.log(user.email_verified); // ✅ 推荐使用
1678
- console.log(user.created_at); // ✅ 推荐使用
1679
- console.log(user.app_id); // ✅ 新字段:多租户支持
1663
+ console.log(user.email_verified); // ✅ Recommended
1664
+ console.log(user.created_at); // ✅ Recommended
1665
+ console.log(user.app_id); // ✅ New field: multi-tenant support
1680
1666
  ```
1681
1667
 
1682
- #### 3. 注册接口更新
1668
+ #### 3. Registration API Update
1683
1669
 
1684
1670
  ```typescript
1685
- // 旧代码(仍然可用)
1671
+ // Old code (still works)
1686
1672
  await client.register({
1687
1673
  email: 'user@example.com',
1688
1674
  password: 'password123',
1689
- invitationCode: 'INVITE123', // ⚠️ 已弃用但可用
1675
+ invitationCode: 'INVITE123', // ⚠️ Deprecated but works
1690
1676
  });
1691
1677
 
1692
- // 新代码(推荐)
1678
+ // New code (recommended)
1693
1679
  await client.register({
1694
1680
  email: 'user@example.com',
1695
1681
  password: 'password123',
1696
- username: 'myusername', // ✨ 新功能
1697
- invitation_code: 'INVITE123', // ✅ 推荐使用
1682
+ username: 'myusername', // ✨ New feature
1683
+ invitation_code: 'INVITE123', // ✅ Recommended
1698
1684
  });
1699
1685
  ```
1700
1686
 
1701
- #### 4. 密码重置接口更新
1687
+ #### 4. Password Reset API Update
1702
1688
 
1703
1689
  ```typescript
1704
- // 旧代码(需要更新)
1690
+ // Old code (needs update)
1705
1691
  await client.resetPassword({
1706
1692
  token: 'reset-token',
1707
- newPassword: 'NewPass123', // ⚠️ 已弃用
1693
+ newPassword: 'NewPass123', // ⚠️ Deprecated
1708
1694
  });
1709
1695
 
1710
- // 新代码(推荐)
1696
+ // New code (recommended)
1711
1697
  await client.resetPassword({
1712
1698
  token: 'reset-token',
1713
- new_password: 'NewPass123', // ✅ 推荐使用
1699
+ new_password: 'NewPass123', // ✅ Recommended
1714
1700
  });
1715
1701
  ```
1716
1702
 
1717
- #### 5. TypeScript 类型提示
1703
+ #### 5. TypeScript Type Hints
1718
1704
 
1719
- 如果你使用 TypeScript,编译器会自动提示已弃用的字段:
1705
+ If you use TypeScript, compiler will automatically hint deprecated fields:
1720
1706
 
1721
1707
  ```typescript
1722
1708
  const user = await client.getCurrentUser();
1723
- user.emailVerified; // TypeScript 会显示删除线和弃用警告
1724
- user.email_verified; // ✅ 无警告
1709
+ user.emailVerified; // TypeScript will show strikethrough and deprecation warning
1710
+ user.email_verified; // ✅ No warning
1725
1711
  ```
1726
1712
 
1727
- #### 6. 多租户功能(新增)
1713
+ #### 6. Multi-Tenant Feature (New)
1728
1714
 
1729
- 如果你的应用需要支持多租户架构,可以使用新的 `app_id` 字段:
1715
+ If your application needs multi-tenant architecture support, you can use the new `app_id` field:
1730
1716
 
1731
1717
  ```typescript
1732
1718
  const user = await client.getCurrentUser();
@@ -1734,20 +1720,20 @@ const user = await client.getCurrentUser();
1734
1720
  console.log('your app id:', user.app_id);
1735
1721
  ```
1736
1722
 
1737
- ## 常见问题
1723
+ ## FAQ
1738
1724
 
1739
- ### 如何处理认证token?
1725
+ ### How to Handle Authentication Token?
1740
1726
 
1741
1727
  ```typescript
1742
- // 登录成功后保存token
1728
+ // Save token after successful login
1743
1729
  const loginResult = await client.login({ email, password });
1744
1730
  localStorage.setItem('token', loginResult.token);
1745
1731
 
1746
- // 创建带认证的client
1732
+ // Create authenticated client
1747
1733
  import { AuthFactory } from '@seaverse/auth-sdk';
1748
1734
 
1749
1735
  const authenticatedClient = new SeaVerseBackendAPIClient({
1750
- appId: 'your app id', // 必需:应用ID
1736
+ appId: 'your app id', // Required: Application ID
1751
1737
  environment: 'production',
1752
1738
  auth: AuthFactory.create({
1753
1739
  type: 'jwt',
@@ -1759,49 +1745,49 @@ const authenticatedClient = new SeaVerseBackendAPIClient({
1759
1745
  });
1760
1746
  ```
1761
1747
 
1762
- ### OAuth redirect_uri_mismatch错误?
1748
+ ### OAuth redirect_uri_mismatch Error?
1763
1749
 
1764
- 确保OAuth应用配置中的重定向URI与代码中的`redirectUri`完全一致(包括协议、域名、端口、路径)。
1750
+ Ensure the redirect URI in OAuth application configuration exactly matches the `redirectUri` in code (including protocol, domain, port, path).
1765
1751
 
1766
- ### 如何自定义请求超时?
1752
+ ### How to Customize Request Timeout?
1767
1753
 
1768
1754
  ```typescript
1769
1755
  const client = new SeaVerseBackendAPIClient({
1770
- appId: 'your app id', // 必需:应用ID
1756
+ appId: 'your app id', // Required: Application ID
1771
1757
  environment: 'production',
1772
- timeout: 30000, // 30
1758
+ timeout: 30000, // 30 seconds
1773
1759
  });
1774
1760
  ```
1775
1761
 
1776
- ### 本地开发如何连接到本地API
1762
+ ### How to Connect to Local API in Local Development?
1777
1763
 
1778
1764
  ```typescript
1779
1765
  const client = new SeaVerseBackendAPIClient({
1780
- appId: 'your app id', // 必需:应用ID
1781
- environment: 'local', // 或使用 baseURL: 'http://localhost:3000'
1766
+ appId: 'your app id', // Required: Application ID
1767
+ environment: 'local', // Or use baseURL: 'http://localhost:3000'
1782
1768
  });
1783
1769
  ```
1784
1770
 
1785
- ## 开发
1771
+ ## Development
1786
1772
 
1787
1773
  ```bash
1788
- # 安装依赖
1774
+ # Install dependencies
1789
1775
  pnpm install
1790
1776
 
1791
- # 构建
1777
+ # Build
1792
1778
  pnpm build
1793
1779
 
1794
- # Watch模式
1780
+ # Watch mode
1795
1781
  pnpm dev
1796
1782
 
1797
- # 测试
1783
+ # Test
1798
1784
  pnpm test
1799
1785
  ```
1800
1786
 
1801
- ## 相关链接
1787
+ ## Related Links
1802
1788
 
1803
1789
  - 📦 [NPM Package](https://www.npmjs.com/package/@seaverse/auth-sdk)
1804
- - 📖 [示例项目](../../examples/auth-sdk-demo)
1790
+ - 📖 [Example Project](../../examples/auth-sdk-demo)
1805
1791
  - 🐛 [Issues](https://github.com/seaverseai/sv-sdk/issues)
1806
1792
  - 💬 [Discussions](https://github.com/seaverseai/sv-sdk/discussions)
1807
1793
 
@@ -1809,48 +1795,48 @@ pnpm test
1809
1795
 
1810
1796
  MIT © [SeaVerse Team](mailto:support@seaverse.com)
1811
1797
 
1812
- ## 更新日志
1798
+ ## Changelog
1813
1799
 
1814
- ### v0.3.6 (当前版本)
1815
- - 🧹 **代码清理**: 移除桌面应用OAuth回调相关功能
1816
- - 移除 `oauthDesktopURL` 配置选项
1817
- - 简化OAuth流程,统一使用 `returnUrl` 参数
1818
- - 清理相关文档和代码注释
1800
+ ### v0.3.6 (Current Version)
1801
+ - 🧹 **Code Cleanup**: Remove desktop application OAuth callback related functionality
1802
+ - Remove `oauthDesktopURL` configuration option
1803
+ - Simplify OAuth flow, unified use of `returnUrl` parameter
1804
+ - Clean up related documentation and code comments
1819
1805
 
1820
1806
  ### v0.2.5
1821
- - 🔄 **响应格式兼容**: 自动兼容包装格式和扁平格式的API响应
1822
- - 修复登录时提示 "Invalid response from server" 的问题
1823
- - `login()`, `register()`, `getCurrentUser()` 方法自动解包 `data` 字段
1824
- - 支持两种格式: `{ data: {...}, success: true }` `{ ... }`
1825
- - 📝 **文档更新**: 新增响应格式兼容性章节
1807
+ - 🔄 **Response Format Compatibility**: Automatic compatibility with wrapped and flat API response formats
1808
+ - Fix "Invalid response from server" prompt during login
1809
+ - `login()`, `register()`, `getCurrentUser()` methods auto-unwrap `data` field
1810
+ - Support two formats: `{ data: {...}, success: true }` and `{ ... }`
1811
+ - 📝 **Documentation Update**: Add response format compatibility section
1826
1812
 
1827
1813
  ### v0.2.0
1828
- - 🔄 **API路径更新**: 所有认证API从 `/api/auth/*` 迁移到 `/sdk/v1/auth/*`
1829
- - 🏢 **多租户支持**: User模型新增 `app_id` 字段,支持多应用隔离
1830
- - 🔑 **重要变更**: `appId` 现在是**必需参数**,SDK 自动在所有请求中添加 `X-App-ID` 请求头
1831
- - ✨ **新功能**:
1832
- - 注册时支持自定义 `username`(可选)
1833
- - 所有字段标准化为 snake_case(保留 camelCase 向后兼容)
1834
- - 📝 **字段更新**:
1835
- - `SeaVerseBackendAPIClientOptions`: 新增必需字段 `appId`
1836
- - `User`: 新增 `app_id`, `created_at`, `email_verified`, `google_id`, `discord_id`, `github_id`
1837
- - `RegisterRequest`: 新增 `username`, `invitation_code`
1814
+ - 🔄 **API Path Update**: All authentication APIs migrated from `/api/auth/*` to `/sdk/v1/auth/*`
1815
+ - 🏢 **Multi-Tenant Support**: User model adds `app_id` field, supports multi-application isolation
1816
+ - 🔑 **Important Change**: `appId` is now a **required parameter**, SDK automatically adds `X-App-ID` request header to all requests
1817
+ - ✨ **New Features**:
1818
+ - Registration supports custom `username` (optional)
1819
+ - All fields standardized to snake_case (retains camelCase backward compatibility)
1820
+ - 📝 **Field Updates**:
1821
+ - `SeaVerseBackendAPIClientOptions`: Add required field `appId`
1822
+ - `User`: Add `app_id`, `created_at`, `email_verified`, `google_id`, `discord_id`, `github_id`
1823
+ - `RegisterRequest`: Add `username`, `invitation_code`
1838
1824
  - `ResetPasswordRequest`: `newPassword` → `new_password`
1839
1825
  - ⚠️ **Breaking Changes**:
1840
- - 必须提供 `appId` 参数才能初始化 client
1841
- - API 路径变更需要后端支持
1842
- - ✅ **向后兼容**: `appId` 外,所有旧字段仍然可用
1826
+ - Must provide `appId` parameter to initialize client
1827
+ - API path changes require backend support
1828
+ - ✅ **Backward Compatible**: Except for `appId`, all old fields still work
1843
1829
 
1844
1830
  ### v0.1.5
1845
- - 修复OAuth state管理,从sessionStorage切换到localStorage
1846
- - 增强API响应处理
1831
+ - Fix OAuth state management, switch from sessionStorage to localStorage
1832
+ - Enhance API response handling
1847
1833
 
1848
1834
  ### v0.1.4
1849
- - 增强API响应处理
1850
- - 优化错误处理
1835
+ - Enhance API response handling
1836
+ - Optimize error handling
1851
1837
 
1852
1838
  ### v0.1.2
1853
- - 更新包名为@seaverse/auth-sdk
1854
- - 添加多环境支持
1839
+ - Update package name to @seaverse/auth-sdk
1840
+ - Add multi-environment support
1855
1841
 
1856
- 查看完整更新日志:[CHANGELOG.md](./CHANGELOG.md)
1842
+ View complete changelog: [CHANGELOG.md](./CHANGELOG.md)