@seaverse/auth-sdk 0.4.0 → 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,328 +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('提示', '邮件已发送');
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');
573
573
  ```
574
574
 
575
- #### 重置密码流程
575
+ #### Password Reset Flow
576
576
 
577
- AuthModal 支持完整的密码重置流程:
577
+ AuthModal supports complete password reset flow:
578
578
 
579
- 1. **用户触发忘记密码**:在登录界面点击 "Forgot Password?" 链接
580
- 2. **发送重置邮件**:输入邮箱后,系统发送带有 `reset_token` 的重置链接
581
- 3. **自动唤起重置弹窗**:用户点击邮件中的链接返回网站时,AuthModal 会自动检测 URL 中的 `reset_token` 参数并显示重置密码表单
582
- 4. **设置新密码**:用户输入并确认新密码后提交
583
- 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
584
584
 
585
- 整个流程无需额外代码,AuthModal 会自动处理:
585
+ The entire process requires no extra code, AuthModal handles it automatically:
586
586
 
587
587
  ```typescript
588
- // 1. 初始化 AuthModal(只需一次)
588
+ // 1. Initialize AuthModal (only once)
589
589
  const authModal = new AuthModal({
590
590
  client,
591
- // ... 其他配置
591
+ // ... other configuration
592
592
  });
593
593
 
594
- // 2. 用户点击邮件中的重置链接后,AuthModal 会自动:
595
- // - 检测 URL 中的 ?reset_token=xxx 参数
596
- // - 显示重置密码表单
597
- // - 用户提交新密码
598
- // - 调用 client.resetPassword() API
599
- // - 清理 URL 中的 reset_token 参数
600
- // - 显示成功消息
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
601
601
  ```
602
602
 
603
- #### OAuth 配置说明
603
+ #### OAuth Configuration Instructions
604
604
 
605
- `enableOAuth` 参数是**完全可选的**:
605
+ The `enableOAuth` parameter is **completely optional**:
606
606
 
607
- - 如果**不提供** `enableOAuth`,则不会显示任何第三方登录按钮
608
- - 如果**部分配置**(如只启用 Google),则只显示已启用的按钮
609
- - 如果**完整配置**所有平台,则显示所有第三方登录按钮
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
610
610
 
611
- **配置字段说明**:
612
- - `returnUrl`:**可选** - OAuth 登录后返回的 URL,不填则默认为 `window.location.href`
613
- - `enableOAuth.google`:是否启用 Google 登录
614
- - `enableOAuth.discord`:是否启用 Discord 登录
615
- - `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
616
616
 
617
617
  ```typescript
618
- // 示例1:无OAuth按钮
618
+ // Example 1: No OAuth buttons
619
619
  const authModal1 = new AuthModal({
620
620
  client,
621
621
  theme: 'dark',
622
- // 不传 enableOAuth,不显示任何OAuth按钮
622
+ // No enableOAuth, no OAuth buttons shown
623
623
  });
624
624
 
625
- // 示例2:只显示Google登录
625
+ // Example 2: Only show Google login
626
626
  const authModal2 = new AuthModal({
627
627
  client,
628
628
  theme: 'light',
629
629
  returnUrl: 'https://mygame.com/dashboard',
630
630
  enableOAuth: {
631
631
  google: true,
632
- // Discord GitHub 未启用,不会显示这些按钮
632
+ // Discord and GitHub not enabled, won't show these buttons
633
633
  },
634
634
  });
635
635
 
636
- // 示例3:显示所有OAuth按钮
636
+ // Example 3: Show all OAuth buttons
637
637
  const authModal3 = new AuthModal({
638
638
  client,
639
639
  theme: 'dark',
@@ -645,58 +645,58 @@ const authModal3 = new AuthModal({
645
645
  });
646
646
  ```
647
647
 
648
- #### 处理 OAuth 回调
648
+ #### Handling OAuth Callback
649
649
 
650
- 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:
651
651
 
652
652
  ```typescript
653
- // 在页面加载时自动处理 OAuth 回调
653
+ // Automatically handle OAuth callback on page load
654
654
  const result = AuthModal.handleOAuthCallback({
655
655
  client,
656
656
  onLoginSuccess: (token) => {
657
657
  localStorage.setItem('token', token);
658
- console.log('OAuth 登录成功');
658
+ console.log('OAuth login successful');
659
659
 
660
- // 现在可以直接调用需要认证的接口
661
- // handleOAuthCallback 已自动调用 client.setToken()
660
+ // Can now call authenticated APIs directly
661
+ // handleOAuthCallback has automatically called client.setToken()
662
662
  client.getCurrentUser()
663
- .then(user => console.log('用户信息:', user));
663
+ .then(user => console.log('User info:', user));
664
664
  },
665
665
  });
666
666
 
667
667
  if (result) {
668
- console.log('处理了 OAuth 回调,token:', result.token);
668
+ console.log('Handled OAuth callback, token:', result.token);
669
669
  }
670
670
  ```
671
671
 
672
- **重要说明**:
673
- - `handleOAuthCallback()` 会自动调用 `client.setToken(token)` 来更新 client 的认证配置
674
- - 这意味着在 `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
675
675
 
676
- #### 手动设置 Token
676
+ #### Manual Token Setting
677
677
 
678
- 如果你不使用 `AuthModal.handleOAuthCallback()`,也可以手动设置 token
678
+ If you don't use `AuthModal.handleOAuthCallback()`, you can also set the token manually:
679
679
 
680
680
  ```typescript
681
- // URL 提取 token
681
+ // Extract token from URL
682
682
  const token = new URLSearchParams(window.location.search).get('token');
683
683
  if (token) {
684
- // 手动设置 token
684
+ // Manually set token
685
685
  client.setToken(token);
686
686
  localStorage.setItem('token', token);
687
687
 
688
- // 现在可以调用需要认证的接口
688
+ // Now can call authenticated APIs
689
689
  const user = await client.getCurrentUser();
690
690
  }
691
691
  ```
692
692
 
693
- ### 6. 容器管理
693
+ ### 6. Container Management
694
694
 
695
695
  ```typescript
696
- // 列出所有容器
696
+ // List all containers
697
697
  const containers = await client.listContainers();
698
698
 
699
- // 注册新容器
699
+ // Register new container
700
700
  const result = await client.registerContainer({
701
701
  containerId: 'container-123',
702
702
  metadata: {
@@ -705,226 +705,226 @@ const result = await client.registerContainer({
705
705
  },
706
706
  });
707
707
 
708
- // 获取容器信息
708
+ // Get container info
709
709
  const container = await client.getContainer({
710
710
  containerId: 'container-123',
711
711
  });
712
712
 
713
- // 容器心跳
713
+ // Container heartbeat
714
714
  await client.containerHeartbeat({
715
715
  containerId: 'container-123',
716
716
  status: 'healthy',
717
717
  });
718
718
 
719
- // 注销容器
719
+ // Unregister container
720
720
  await client.unregisterContainer({
721
721
  containerId: 'container-123',
722
722
  });
723
723
 
724
- // 获取容器统计
724
+ // Get container stats
725
725
  const stats = await client.getContainerStats();
726
726
  ```
727
727
 
728
- ### 7. 技能市场
728
+ ### 7. Skill Marketplace
729
729
 
730
730
  ```typescript
731
- // 列出市场技能
731
+ // List marketplace skills
732
732
  const skills = await client.listMarketplaceSkills({
733
733
  category: 'productivity',
734
734
  page: 1,
735
735
  pageSize: 20,
736
736
  });
737
737
 
738
- // 获取技能详情
738
+ // Get skill details
739
739
  const skill = await client.getMarketplaceSkill({
740
740
  skillId: 'skill-123',
741
741
  });
742
742
 
743
- // 安装技能
743
+ // Install skill
744
744
  await client.installSkill({
745
745
  skillId: 'skill-123',
746
746
  });
747
747
 
748
- // 列出已安装的技能
748
+ // List installed skills
749
749
  const userSkills = await client.listUserSkills();
750
750
 
751
- // 卸载技能
751
+ // Uninstall skill
752
752
  await client.uninstallSkill({
753
753
  skillId: 'skill-123',
754
754
  });
755
755
  ```
756
756
 
757
- ### 8. 邀请码管理
757
+ ### 8. Invitation Code Management
758
758
 
759
759
  ```typescript
760
- // 申请邀请码(当用户没有邀请码时)
760
+ // Apply for invitation code (when user doesn't have one)
761
761
  const application = await client.applyInvite({
762
762
  email: 'player@example.com',
763
763
  reason: 'I want to join this amazing platform to build innovative applications and connect with the community.'
764
764
  });
765
765
 
766
766
  if (application.success) {
767
- console.log('申请已提交:', application.data);
768
- console.log('申请ID:', application.data.id);
769
- 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'
770
770
  } else {
771
- // 处理错误
771
+ // Handle error
772
772
  if (application.code === 'APPLICATION_DUPLICATE') {
773
- console.log('您在过去24小时内已提交过申请');
773
+ console.log('You have already submitted an application in the past 24 hours');
774
774
  } else {
775
- console.error('申请失败:', application.error);
775
+ console.error('Application failed:', application.error);
776
776
  }
777
777
  }
778
778
 
779
- // 列出我的邀请码
779
+ // List my invitation codes
780
780
  const invites = await client.listInvites({
781
781
  status: 'active',
782
782
  page: 1,
783
783
  page_size: 20,
784
784
  });
785
- console.log('我的邀请码:', invites.data.invites);
785
+ console.log('My invitation codes:', invites.data.invites);
786
786
 
787
- // 获取邀请码统计
787
+ // Get invitation code stats
788
788
  const stats = await client.getInviteStats();
789
- console.log('总邀请码数:', stats.data.total_codes);
790
- console.log('活跃邀请码:', stats.data.active_codes);
791
- 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);
792
792
 
793
- // 获取邀请码详情
793
+ // Get invitation code details
794
794
  const invite = await client.getInvite('inv_abc123');
795
- console.log('邀请码:', invite.data.code);
796
- console.log('已使用:', invite.data.used_count);
797
- 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);
798
798
 
799
- // 获取邀请码使用记录
799
+ // Get invitation code usage records
800
800
  const usages = await client.getInviteUsages('inv_abc123', {
801
801
  page: 1,
802
802
  page_size: 20,
803
803
  });
804
- console.log('使用记录:', usages.data.usages);
804
+ console.log('Usage records:', usages.data.usages);
805
805
  ```
806
806
 
807
- ### 9. 邮箱验证与邀请码绑定
807
+ ### 9. Email Verification and Invitation Code Binding
808
808
 
809
- #### 邮箱验证(自动登录)
809
+ #### Email Verification (Auto Login)
810
810
 
811
- 用户注册后会收到验证邮件,邮件中包含验证链接,格式为:`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`
812
812
 
813
- **方式一:使用 AuthModal 自动处理(推荐)**
813
+ **Method 1: Use AuthModal Auto-Handling (Recommended)**
814
814
 
815
815
  ```typescript
816
816
  import { AuthModal } from '@seaverse/auth-sdk';
817
817
 
818
- // 创建 AuthModal 实例
818
+ // Create AuthModal instance
819
819
  const modal = new AuthModal({
820
820
  client,
821
821
  onLoginSuccess: (token, user) => {
822
822
  localStorage.setItem('token', token);
823
- console.log('邮箱验证并登录成功:', user);
823
+ console.log('Email verified and logged in successfully:', user);
824
824
  },
825
825
  onError: (error) => {
826
- console.error('邮箱验证失败:', error);
826
+ console.error('Email verification failed:', error);
827
827
  }
828
828
  });
829
829
 
830
- // AuthModal 会自动检测 URL 中的 verify_token 参数
831
- // 检测到后会自动:
832
- // 1. 调用 verifyEmail() API 验证邮箱
833
- // 2. 获取返回的 JWT token 并自动登录
834
- // 3. 触发 onLoginSuccess 回调
835
- // 4. 清理 URL 中的 verify_token 参数
836
- // 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
837
837
  ```
838
838
 
839
- **调试提示**:
839
+ **Debugging Tips**:
840
840
 
841
- 如果邮箱验证出现问题,请检查浏览器控制台日志:
841
+ If email verification has issues, check browser console logs:
842
842
 
843
843
  ```javascript
844
- // 正常情况应该看到:
844
+ // Normal case should show:
845
845
  [AuthModal] Detected verify_token, starting email verification...
846
846
  [AuthModal] Email verification successful: { id: "xxx", email: "user@example.com", ... }
847
847
 
848
- // 如果验证失败,会看到:
848
+ // If verification fails, will show:
849
849
  [AuthModal] Email verification failed: Error: ...
850
850
  ```
851
851
 
852
- **方式二:手动处理邮箱验证**
852
+ **Method 2: Manual Email Verification Handling**
853
853
 
854
854
  ```typescript
855
- // 验证邮箱(从邮件链接中获取 verify_token
855
+ // Verify email (get verify_token from email link)
856
856
  const urlParams = new URLSearchParams(window.location.search);
857
857
  const verifyToken = urlParams.get('verify_token');
858
858
 
859
859
  if (verifyToken) {
860
860
  const result = await client.verifyEmail(verifyToken);
861
861
 
862
- // 自动登录:保存返回的 token
862
+ // Auto-login: save returned token
863
863
  localStorage.setItem('token', result.data.token);
864
864
  localStorage.setItem('refreshToken', result.data.refreshToken);
865
865
 
866
- console.log('邮箱验证成功,已自动登录:', result.data.user);
866
+ console.log('Email verified successfully, auto-logged in:', result.data.user);
867
867
 
868
- // 重定向到主页
868
+ // Redirect to homepage
869
869
  window.location.href = '/';
870
870
  }
871
871
  ```
872
872
 
873
- #### 邀请码绑定(账户激活)
873
+ #### Invitation Code Binding (Account Activation)
874
874
 
875
- 当使用外部邮箱注册或 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.
876
876
 
877
- **申请邀请码功能**:
877
+ **Apply for Invitation Code Feature**:
878
878
 
879
- 如果用户没有邀请码,AuthModal 提供了内置的申请功能:
880
- 1. 在邀请码输入界面,用户可以点击 "Don't have an invitation code? Apply for one" 链接
881
- 2. 自动跳转到申请邀请码表单
882
- 3. 用户填写邮箱和申请原因(10-500字符)
883
- 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
884
884
 
885
- **自动跳转机制**:
886
- - `login()` 返回 `INVITE_CODE_REQUIRED` 错误且包含 `redirectUrl` 时,SDK 会自动将页面重定向到该 URL
887
- - redirectUrl 通常包含 `error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx` 参数
888
- - 无需手动处理跳转逻辑,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
889
889
 
890
- 对于其他场景( 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`.
891
891
 
892
- **方式一:使用 AuthModal 自动处理(推荐)**
892
+ **Method 1: Use AuthModal Auto-Handling (Recommended)**
893
893
 
894
894
  ```typescript
895
895
  import { AuthModal } from '@seaverse/auth-sdk';
896
896
 
897
- // 创建 AuthModal 实例
897
+ // Create AuthModal instance
898
898
  const modal = new AuthModal({
899
899
  client,
900
900
  onLoginSuccess: (token, user) => {
901
901
  localStorage.setItem('token', token);
902
- console.log('登录成功:', user);
902
+ console.log('Login successful:', user);
903
903
  },
904
904
  onInviteCodeRequired: (userId, email) => {
905
- // 可选:当需要邀请码时的自定义处理
906
- console.log('需要邀请码激活账户:', userId, email);
905
+ // Optional: custom handling when invitation code is needed
906
+ console.log('Need invitation code to activate account:', userId, email);
907
907
  }
908
908
  });
909
909
 
910
- // AuthModal 会自动检测 URL 中的以下参数组合:
910
+ // AuthModal will automatically detect the following parameter combinations in URL:
911
911
  // - error_code=INVITE_CODE_REQUIRED
912
- // - user_id temp_user_id(用户ID
913
- // - email(可选,用户邮箱)
912
+ // - user_id or temp_user_id (user ID)
913
+ // - email (optional, user email)
914
914
  //
915
- // 检测到后会自动:
916
- // 1. 显示邀请码输入界面
917
- // 2. 用户输入邀请码后调用 bindInviteCode() API
918
- // 3. 激活成功后自动登录(保存 token
919
- // 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
920
920
  ```
921
921
 
922
- **调试提示**:
922
+ **Debugging Tips**:
923
923
 
924
- 如果邀请码弹窗没有出现,请检查浏览器控制台是否有以下日志:
924
+ If invitation code modal doesn't appear, check browser console for the following logs:
925
925
 
926
926
  ```javascript
927
- // 正常情况应该看到:
927
+ // Normal case should show:
928
928
  [AuthModal] Detected INVITE_CODE_REQUIRED: {
929
929
  errorCode: "INVITE_CODE_REQUIRED",
930
930
  userId: "xxx",
@@ -933,50 +933,50 @@ const modal = new AuthModal({
933
933
  fullURL: "http://localhost:8001/?error_code=INVITE_CODE_REQUIRED&user_id=xxx&email=xxx"
934
934
  }
935
935
 
936
- // 如果 user_id 缺失,会看到错误提示:
936
+ // If user_id is missing, will show error:
937
937
  [AuthModal] Missing user_id in URL parameters.
938
- // 并弹出 alert 显示完整 URL,方便排查后端重定向问题
938
+ // And shows alert with full URL for troubleshooting backend redirect issues
939
939
  ```
940
940
 
941
- **方式二:手动处理邀请码绑定**
941
+ **Method 2: Manual Invitation Code Binding Handling**
942
942
 
943
943
  ```typescript
944
- // 1. 检查 URL 中是否需要邀请码
944
+ // 1. Check if invitation code is needed in URL
945
945
  const urlParams = new URLSearchParams(window.location.search);
946
946
  const errorCode = urlParams.get('error_code');
947
947
  const userId = urlParams.get('user_id');
948
948
 
949
949
  if (errorCode === 'INVITE_CODE_REQUIRED' && userId) {
950
- // 2. 显示邀请码输入界面(自定义 UI
951
- const inviteCode = await showInviteCodeInput(); // 你的自定义UI
950
+ // 2. Show invitation code input interface (custom UI)
951
+ const inviteCode = await showInviteCodeInput(); // Your custom UI
952
952
 
953
- // 3. 绑定邀请码
953
+ // 3. Bind invitation code
954
954
  const result = await client.bindInviteCode({
955
955
  user_id: userId,
956
956
  invite_code: inviteCode
957
957
  });
958
958
 
959
- // 4. 激活成功,自动登录
959
+ // 4. Activation successful, auto-login
960
960
  localStorage.setItem('token', result.data.token);
961
961
  localStorage.setItem('refreshToken', result.data.refreshToken);
962
- console.log('账户激活成功:', result.data.user);
962
+ console.log('Account activated successfully:', result.data.user);
963
963
 
964
- // 5. 重定向到主页
964
+ // 5. Redirect to homepage
965
965
  window.location.href = '/';
966
966
  }
967
967
  ```
968
968
 
969
- **方式三:使用静态方法处理**
969
+ **Method 3: Use Static Method Handling**
970
970
 
971
971
  ```typescript
972
972
  import { AuthModal } from '@seaverse/auth-sdk';
973
973
 
974
- // AuthModal 提供静态方法处理邀请码场景
974
+ // AuthModal provides static method to handle invitation code scenario
975
975
  const inviteCodeInfo = AuthModal.handleInviteCodeRequired(
976
976
  { client },
977
977
  (userId, email) => {
978
- // 自定义处理逻辑
979
- const code = prompt(`请输入邀请码激活账户 (${email}):`);
978
+ // Custom handling logic
979
+ const code = prompt(`Please enter invitation code to activate account (${email}):`);
980
980
  if (code) {
981
981
  client.bindInviteCode({ user_id: userId, invite_code: code })
982
982
  .then(res => {
@@ -988,33 +988,33 @@ const inviteCodeInfo = AuthModal.handleInviteCodeRequired(
988
988
  );
989
989
  ```
990
990
 
991
- ### 10. 其他功能
991
+ ### 10. Other Features
992
992
 
993
993
  ```typescript
994
- // 获取API Service Token
994
+ // Get API Service Token
995
995
  const apiToken = await client.getApiServiceToken();
996
996
 
997
- // 获取对话状态
997
+ // Get conversation status
998
998
  const status = await client.getConversationStatus({
999
999
  conversationId: 'conv-123',
1000
1000
  });
1001
1001
 
1002
- // 获取语音Token
1002
+ // Get speech token
1003
1003
  const speechToken = await client.getSpeechToken();
1004
1004
  ```
1005
1005
 
1006
- ## 高级配置
1006
+ ## Advanced Configuration
1007
1007
 
1008
- ### 自定义认证
1008
+ ### Custom Authentication
1009
1009
 
1010
1010
  ```typescript
1011
1011
  import { AuthFactory } from '@seaverse/auth-sdk';
1012
1012
 
1013
1013
  const client = new SeaVerseBackendAPIClient({
1014
- appId: 'your app id', // 必需:应用ID
1014
+ appId: 'your app id', // Required: Application ID
1015
1015
  environment: 'production',
1016
1016
 
1017
- // 使用JWT认证
1017
+ // Use JWT authentication
1018
1018
  auth: AuthFactory.create({
1019
1019
  type: 'jwt',
1020
1020
  credentials: {
@@ -1025,28 +1025,28 @@ const client = new SeaVerseBackendAPIClient({
1025
1025
  });
1026
1026
  ```
1027
1027
 
1028
- ### 自定义Hooks
1028
+ ### Custom Hooks
1029
1029
 
1030
1030
  ```typescript
1031
1031
  import { BuiltInHooks } from '@seaverse/auth-sdk';
1032
1032
 
1033
1033
  const client = new SeaVerseBackendAPIClient({
1034
- appId: 'your app id', // 必需:应用ID
1034
+ appId: 'your app id', // Required: Application ID
1035
1035
  environment: 'production',
1036
1036
 
1037
1037
  hooks: {
1038
1038
  hooks: [
1039
- // 日志Hook
1039
+ // Logger Hook
1040
1040
  BuiltInHooks.createLoggerHook({
1041
1041
  logLevel: 'debug',
1042
1042
  logRequestBody: true,
1043
1043
  logResponseBody: true,
1044
1044
  }),
1045
1045
 
1046
- // 请求ID Hook
1046
+ // Request ID Hook
1047
1047
  BuiltInHooks.createRequestIdHook(),
1048
1048
 
1049
- // 自定义Hook
1049
+ // Custom Hook
1050
1050
  {
1051
1051
  type: 'beforeRequest',
1052
1052
  name: 'custom-hook',
@@ -1060,22 +1060,22 @@ const client = new SeaVerseBackendAPIClient({
1060
1060
  });
1061
1061
  ```
1062
1062
 
1063
- ### 请求重试配置
1063
+ ### Request Retry Configuration
1064
1064
 
1065
- 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.
1066
1066
 
1067
- #### 默认行为(禁用重试)
1067
+ #### Default Behavior (Retry Disabled)
1068
1068
 
1069
1069
  ```typescript
1070
1070
  const client = new SeaVerseBackendAPIClient({
1071
1071
  appId: 'your app id',
1072
- // retryOptions 未设置,默认不重试
1072
+ // retryOptions not set, no retry by default
1073
1073
  });
1074
1074
 
1075
- // 如果请求失败,会立即返回错误,不会重试
1075
+ // If request fails, will return error immediately, no retry
1076
1076
  ```
1077
1077
 
1078
- #### 启用基础重试
1078
+ #### Enable Basic Retry
1079
1079
 
1080
1080
  ```typescript
1081
1081
  import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
@@ -1083,25 +1083,25 @@ import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
1083
1083
  const client = new SeaVerseBackendAPIClient({
1084
1084
  appId: 'your app id',
1085
1085
  retryOptions: {
1086
- maxRetries: 3, // 最多重试 3
1087
- retryDelay: 1000, // 初始延迟 1000ms (1)
1088
- // 默认会对以下状态码重试:[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]
1089
1089
  },
1090
1090
  });
1091
1091
  ```
1092
1092
 
1093
- **重试策略说明**:
1094
- - 采用**指数退避**算法:第1次等待1秒,第2次等待2秒,第3次等待4
1095
- - 自动重试的 HTTP 状态码:
1096
- - `408` - Request Timeout(请求超时)
1097
- - `429` - Too Many Requests(限流)
1098
- - `500` - Internal Server Error(服务器内部错误)
1099
- - `502` - Bad Gateway(网关错误)
1100
- - `503` - Service Unavailable(服务不可用)
1101
- - `504` - Gateway Timeout(网关超时)
1102
- - 网络错误(无响应)也会触发重试
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
1103
1103
 
1104
- #### 自定义重试状态码
1104
+ #### Custom Retry Status Codes
1105
1105
 
1106
1106
  ```typescript
1107
1107
  const client = new SeaVerseBackendAPIClient({
@@ -1109,12 +1109,12 @@ const client = new SeaVerseBackendAPIClient({
1109
1109
  retryOptions: {
1110
1110
  maxRetries: 5,
1111
1111
  retryDelay: 2000,
1112
- retryStatusCodes: [503, 504], // 只对 503 504 重试
1112
+ retryStatusCodes: [503, 504], // Only retry on 503 and 504
1113
1113
  },
1114
1114
  });
1115
1115
  ```
1116
1116
 
1117
- #### 自定义重试逻辑
1117
+ #### Custom Retry Logic
1118
1118
 
1119
1119
  ```typescript
1120
1120
  import type { RetryOptions } from '@seaverse/auth-sdk';
@@ -1122,13 +1122,13 @@ import type { RetryOptions } from '@seaverse/auth-sdk';
1122
1122
  const retryOptions: RetryOptions = {
1123
1123
  maxRetries: 3,
1124
1124
  retryDelay: 1000,
1125
- // 自定义判断逻辑:只对特定错误重试
1125
+ // Custom judgment logic: only retry on specific errors
1126
1126
  shouldRetry: (error) => {
1127
- // 只对服务不可用错误重试
1127
+ // Only retry on service unavailable errors
1128
1128
  if (error.response?.status === 503) {
1129
1129
  return true;
1130
1130
  }
1131
- // 对没有响应的网络错误重试
1131
+ // Retry on network errors with no response
1132
1132
  if (!error.response) {
1133
1133
  return true;
1134
1134
  }
@@ -1142,153 +1142,153 @@ const client = new SeaVerseBackendAPIClient({
1142
1142
  });
1143
1143
  ```
1144
1144
 
1145
- #### RetryOptions 类型定义
1145
+ #### RetryOptions Type Definition
1146
1146
 
1147
1147
  ```typescript
1148
1148
  interface RetryOptions {
1149
- maxRetries?: number; // 最大重试次数,默认 0(禁用)
1150
- retryDelay?: number; // 初始重试延迟(毫秒),默认 1000
1151
- retryStatusCodes?: number[]; // 触发重试的状态码列表
1152
- 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
1153
1153
  }
1154
1154
  ```
1155
1155
 
1156
- **使用建议**:
1157
- - ⚠️ **生产环境建议禁用重试**(默认行为),避免在业务逻辑错误时产生重复请求
1158
- - ✅ 仅在网络不稳定的场景启用重试,如移动端应用、弱网环境
1159
- - ✅ 确保后端 API 支持幂等性操作,避免重试导致的副作用
1160
- - ✅ 对于关键业务(如支付),建议使用自定义 `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
1161
1161
 
1162
- ### 环境配置
1162
+ ### Environment Configuration
1163
1163
 
1164
- SDK支持以下环境:
1164
+ The SDK supports the following environments:
1165
1165
 
1166
- | 环境 | 描述 | BaseURL |
1166
+ | Environment | Description | BaseURL |
1167
1167
  |------|------|---------|
1168
- | `production` | 生产环境 | `https://account-hub.seaverse.ai` |
1169
- | `staging` | 测试环境 | `https://api.staging.seaverse.dev` |
1170
- | `development` | 开发环境 | `https://api.dev.seaverse.dev` |
1171
- | `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` |
1172
1172
 
1173
- 自动检测规则:
1173
+ Auto-detection rules:
1174
1174
  - `*.seaverse.com` → production
1175
1175
  - `*.staging.seaverse.dev` → staging
1176
1176
  - `*.dev.seaverse.dev` → development
1177
1177
  - `localhost` → local
1178
1178
 
1179
- ## API 参考
1179
+ ## API Reference
1180
1180
 
1181
- ### 认证相关
1181
+ ### Authentication Related
1182
1182
 
1183
- | 方法 | 参数 | 返回值 | 说明 |
1183
+ | Method | Parameters | Return Value | Description |
1184
1184
  |------|------|--------|------|
1185
- | `register()` | `{ email, password, username?, invitation_code?, frontend_url? }` | `RegisterResponse` | 注册新用户,frontend_url 为邮箱验证链接的前端URL,默认为 window.location.href |
1186
- | `login()` | `{ email, password, frontend_url? }` | `LoginResponse` | 用户登录,frontend_url 用于未验证邮箱时发送验证邮件,默认为 https://seaverse.ai/。⚠️ 如果返回 INVITE_CODE_REQUIRED 且包含 redirectUrl,会自动跳转 |
1187
- | `getCurrentUser()` | - | `User` | 获取当前用户 |
1188
- | `logout()` | - | `SuccessResponse` | 登出 |
1189
- | `verifyEmail()` | `verifyToken: string` | `EmailVerificationResponse` | 验证邮箱并返回自动登录 token |
1190
- | `bindInviteCode()` | `{ user_id, invite_code }` | `BindInviteCodeResponse` | 绑定邀请码激活临时账户并自动登录 |
1191
- | `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | 忘记密码,frontend_url 默认为 window.location.href |
1192
- | `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
1193
- | `setToken()` | `token: string` | `void` | 设置认证 tokenOAuth 登录后使用) |
1194
- | `isInIframe()` | - | `boolean` | 检查应用是否在 iframe 中运行(支持静态方法和实例方法) |
1195
- | `getIframeToken()` | `{ timeout? }` | `Promise<string>` | 从父页面获取 token(仅 iframe 场景),timeout 默认 30000ms |
1196
- | `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
1197
-
1198
- #### 注册流程说明
1199
-
1200
- `register()` 方法支持三种注册流程,SDK 会根据后端响应自动处理:
1201
-
1202
- **流程 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)**
1203
1203
  ```typescript
1204
1204
  const response = await client.register({ email, password });
1205
1205
  // response.success === true
1206
- // response.requiresEmailVerification === undefined ( false)
1207
- // response.requiresInvitationCode === undefined ( false)
1208
- // → SDK 自动调用 login() 并触发 onSignupSuccess 回调
1206
+ // response.requiresEmailVerification === undefined (or false)
1207
+ // response.requiresInvitationCode === undefined (or false)
1208
+ // → SDK automatically calls login() and triggers onSignupSuccess callback
1209
1209
  ```
1210
1210
 
1211
- **流程 2: 需要邮箱验证**
1211
+ **Flow 2: Requires Email Verification**
1212
1212
  ```typescript
1213
1213
  const response = await client.register({ email, password });
1214
1214
  // response.success === true
1215
1215
  // response.requiresEmailVerification === true
1216
- // → SDK 显示 Toast 提示用户检查邮箱
1217
- // → 不会自动调用 login(),用户需要点击邮件中的验证链接
1216
+ // → SDK shows Toast prompting user to check email
1217
+ // → Does not auto-call login(), user needs to click verification link in email
1218
1218
  ```
1219
1219
 
1220
- **流程 3: 需要邀请码激活**
1220
+ **Flow 3: Requires Invitation Code Activation**
1221
1221
  ```typescript
1222
1222
  const response = await client.register({ email, password });
1223
1223
  // response.success === true
1224
1224
  // response.requiresInvitationCode === true
1225
1225
  // response.tempUserId === "temp_xxx"
1226
- // → SDK 显示邀请码输入表单
1227
- // → 不会自动调用 login(),用户需要输入邀请码
1226
+ // → SDK shows invitation code input form
1227
+ // → Does not auto-call login(), user needs to input invitation code
1228
1228
  ```
1229
1229
 
1230
- **重要提示**:
1231
- - AuthModal 会自动处理这三种流程,无需手动判断
1232
- - 只有在无需验证或激活的情况下,才会自动调用 `login()`
1233
- - 这避免了在邮箱未验证或账户未激活时产生不必要的登录请求
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
1234
1234
 
1235
- ### OAuth相关
1235
+ ### OAuth Related
1236
1236
 
1237
- | 方法 | 参数 | 返回值 | 说明 |
1237
+ | Method | Parameters | Return Value | Description |
1238
1238
  |------|------|--------|------|
1239
- | `googleAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Google OAuth 授权 URL |
1240
- | `discordAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | Discord OAuth 授权 URL |
1241
- | `githubAuthorize()` | `{ return_url? }` | `OAuthAuthorizeResponse` | GitHub OAuth 授权 URL |
1242
- | `unlinkGoogle()` | - | `SuccessResponse` | 解绑Google |
1243
- | `unlinkDiscord()` | - | `SuccessResponse` | 解绑Discord |
1244
- | `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 |
1245
1245
 
1246
- ### 容器管理
1246
+ ### Container Management
1247
1247
 
1248
- | 方法 | 参数 | 返回值 | 说明 |
1248
+ | Method | Parameters | Return Value | Description |
1249
1249
  |------|------|--------|------|
1250
- | `listContainers()` | - | `ContainerListResponse` | 列出容器 |
1251
- | `registerContainer()` | `{ containerId, metadata }` | `SuccessResponse` | 注册容器 |
1252
- | `getContainer()` | `{ containerId }` | `Container` | 获取容器信息 |
1253
- | `unregisterContainer()` | `{ containerId }` | `SuccessResponse` | 注销容器 |
1254
- | `containerHeartbeat()` | `{ containerId, status }` | `SuccessResponse` | 容器心跳 |
1255
- | `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 |
1256
1256
 
1257
- ### 技能市场
1257
+ ### Skill Marketplace
1258
1258
 
1259
- | 方法 | 参数 | 返回值 | 说明 |
1259
+ | Method | Parameters | Return Value | Description |
1260
1260
  |------|------|--------|------|
1261
- | `listMarketplaceSkills()` | `{ category?, page?, pageSize? }` | `MarketplaceSkillsListResponse` | 列出市场技能 |
1262
- | `getMarketplaceSkill()` | `{ skillId }` | `MarketplaceSkill` | 获取技能详情 |
1263
- | `installSkill()` | `{ skillId }` | `SuccessResponse` | 安装技能 |
1264
- | `listUserSkills()` | - | `UserInstalledSkillsListResponse` | 列出已安装技能 |
1265
- | `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 |
1266
1266
 
1267
- ### 邀请码管理
1267
+ ### Invitation Code Management
1268
1268
 
1269
- | 方法 | 参数 | 返回值 | 说明 |
1269
+ | Method | Parameters | Return Value | Description |
1270
1270
  |------|------|--------|------|
1271
- | `applyInvite()` | `{ email, reason }` | `ApplyInviteResponse` | 申请邀请码(reason 10-500字符)|
1272
- | `listInvites()` | `{ page?, page_size?, status? }` | `ListInvitesResponse` | 列出我的邀请码 |
1273
- | `getInviteStats()` | - | `InviteStatsResponse` | 获取邀请码统计 |
1274
- | `getInvite()` | `inviteId: string` | `InviteCodeDetailResponse` | 获取邀请码详情 |
1275
- | `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 |
1276
1276
 
1277
- ### 其他
1277
+ ### Others
1278
1278
 
1279
- | 方法 | 参数 | 返回值 | 说明 |
1279
+ | Method | Parameters | Return Value | Description |
1280
1280
  |------|------|--------|------|
1281
- | `getHealth()` | - | `HealthResponse` | 健康检查 |
1282
- | `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | 获取对话状态 |
1283
- | `getSpeechToken()` | - | `SpeechTokenResponse` | 获取语音Token |
1281
+ | `getHealth()` | - | `HealthResponse` | Health check |
1282
+ | `getConversationStatus()` | `{ conversationId }` | `ConversationStatusResponse` | Get conversation status |
1283
+ | `getSpeechToken()` | - | `SpeechTokenResponse` | Get speech token |
1284
1284
 
1285
- ## 响应格式兼容性
1285
+ ## Response Format Compatibility
1286
1286
 
1287
- ### 自动响应解包
1287
+ ### Auto Response Unwrapping
1288
1288
 
1289
- v0.2.5 开始,SDK 自动兼容两种API响应格式,无需手动处理:
1289
+ Starting from v0.2.5, SDK automatically supports two API response formats, no manual handling needed:
1290
1290
 
1291
- **格式 1: 包装格式**(推荐)
1291
+ **Format 1: Wrapped Format** (Recommended)
1292
1292
  ```json
1293
1293
  {
1294
1294
  "data": {
@@ -1299,7 +1299,7 @@ const response = await client.register({ email, password });
1299
1299
  }
1300
1300
  ```
1301
1301
 
1302
- **格式 2: 扁平格式**(向后兼容)
1302
+ **Format 2: Flat Format** (Backward Compatible)
1303
1303
  ```json
1304
1304
  {
1305
1305
  "token": "eyJhbGc...",
@@ -1307,101 +1307,101 @@ const response = await client.register({ email, password });
1307
1307
  }
1308
1308
  ```
1309
1309
 
1310
- SDK 会自动检测响应格式并提取正确的数据:
1310
+ SDK automatically detects response format and extracts correct data:
1311
1311
 
1312
1312
  ```typescript
1313
- // 无论后端返回哪种格式,以下代码都能正常工作
1313
+ // Regardless of which format backend returns, the following code works
1314
1314
  const loginResult = await client.login({
1315
1315
  email: 'user@example.com',
1316
1316
  password: 'password123',
1317
1317
  });
1318
1318
 
1319
- console.log(loginResult.token); // ✅ 始终能正确获取 token
1320
- console.log(loginResult.user); // ✅ 始终能正确获取 user
1319
+ console.log(loginResult.token); // ✅ Always gets token correctly
1320
+ console.log(loginResult.user); // ✅ Always gets user correctly
1321
1321
  ```
1322
1322
 
1323
- ### 受影响的方法
1323
+ ### Affected Methods
1324
1324
 
1325
- 以下方法已实现自动响应解包:
1325
+ The following methods have implemented auto response unwrapping:
1326
1326
 
1327
- - ✅ `login()` - 登录接口
1328
- - ✅ `register()` - 注册接口
1329
- - ✅ `getCurrentUser()` - 获取当前用户
1327
+ - ✅ `login()` - Login API
1328
+ - ✅ `register()` - Registration API
1329
+ - ✅ `getCurrentUser()` - Get current user
1330
1330
 
1331
- ### 实现原理
1331
+ ### Implementation Principle
1332
1332
 
1333
- SDK 内部通过以下逻辑自动处理响应格式:
1333
+ SDK internally handles response format through the following logic:
1334
1334
 
1335
1335
  ```typescript
1336
1336
  const response = await httpClient.request(config);
1337
1337
  const responseData = response.data;
1338
1338
 
1339
- // 检测并解包
1339
+ // Detect and unwrap
1340
1340
  if (responseData.data && typeof responseData.data === 'object') {
1341
- // 包装格式: 提取 data 字段
1341
+ // Wrapped format: extract data field
1342
1342
  return responseData.data;
1343
1343
  }
1344
- // 扁平格式: 直接返回
1344
+ // Flat format: return directly
1345
1345
  return responseData;
1346
1346
  ```
1347
1347
 
1348
- 这意味着:
1349
- - 🔄 **后端格式变更无需前端修改** - 后端可以自由调整响应格式
1350
- - 🔧 **渐进式迁移** - 可以逐步将不同接口迁移到新格式
1351
- - ✅ **向后兼容** - 旧代码无需修改即可继续工作
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
1352
1352
 
1353
- ## 错误处理
1353
+ ## Error Handling
1354
1354
 
1355
- ### 错误响应格式
1355
+ ### Error Response Format
1356
1356
 
1357
- 所有 API 错误都遵循统一的响应格式:
1357
+ All API errors follow a unified response format:
1358
1358
 
1359
1359
  ```typescript
1360
1360
  interface ApiError {
1361
- success: false; // 错误时始终为 false
1362
- error: string; // 人类可读的错误消息
1363
- code?: string; // 机器可读的错误码
1364
- 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
1365
1365
  }
1366
1366
  ```
1367
1367
 
1368
- ### 错误码
1368
+ ### Error Codes
1369
1369
 
1370
- SDK 提供了标准的错误码枚举:
1370
+ SDK provides standard error code enums:
1371
1371
 
1372
1372
  ```typescript
1373
1373
  import { ErrorCode } from '@seaverse/auth-sdk';
1374
1374
 
1375
- // 账户相关错误
1376
- ErrorCode.ACCOUNT_EXISTS // 账户已存在
1377
- ErrorCode.ACCOUNT_NOT_FOUND // 账户不存在
1378
- ErrorCode.ACCOUNT_SUSPENDED // 账户已被暂停
1379
- ErrorCode.INVALID_CREDENTIALS // 登录凭证无效
1380
- ErrorCode.EMAIL_NOT_VERIFIED // 邮箱未验证
1381
-
1382
- // 验证相关错误
1383
- ErrorCode.INVALID_EMAIL // 无效的邮箱地址
1384
- ErrorCode.INVALID_PASSWORD // 无效的密码
1385
- ErrorCode.PASSWORD_TOO_WEAK // 密码强度不够
1386
-
1387
- // 邀请码相关错误
1388
- ErrorCode.INVALID_INVITATION_CODE // 无效的邀请码
1389
- ErrorCode.INVITATION_REQUIRED // 需要邀请码
1390
- ErrorCode.INVITE_CODE_REQUIRED // 需要邀请码(会自动跳转到 redirectUrl
1391
-
1392
- // Token 相关错误
1393
- ErrorCode.INVALID_TOKEN // 无效的 token
1394
- ErrorCode.TOKEN_EXPIRED // Token 已过期
1395
-
1396
- // 内部错误
1397
- 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
1398
1398
  ```
1399
1399
 
1400
- ### 错误处理最佳实践
1400
+ ### Error Handling Best Practices
1401
1401
 
1402
- #### 1. 注册时处理重复用户
1402
+ #### 1. Handle Duplicate Users During Registration
1403
1403
 
1404
- 由于后端在账户已存在时返回 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.
1405
1405
 
1406
1406
  ```typescript
1407
1407
  import { ErrorCode } from '@seaverse/auth-sdk';
@@ -1411,27 +1411,27 @@ const result = await client.register({
1411
1411
  password: 'password123',
1412
1412
  });
1413
1413
 
1414
- // 检查响应中的 success 字段
1414
+ // Check success field in response
1415
1415
  if (result.success) {
1416
- console.log('注册成功:', result);
1417
- // 进行后续操作,如自动登录
1416
+ console.log('Registration successful:', result);
1417
+ // Proceed with follow-up actions, such as auto-login
1418
1418
  } else if (result.code === ErrorCode.ACCOUNT_EXISTS) {
1419
- // 账户已存在,提示用户
1419
+ // Account exists, prompt user
1420
1420
  const { email, app_id } = result.details;
1421
- console.log(`账户 ${email} 已存在于应用 ${app_id} 中`);
1421
+ console.log(`Account ${email} already exists in application ${app_id}`);
1422
1422
 
1423
- // 显示友好的提示信息
1423
+ // Show friendly prompt
1424
1424
  alert('This email is already registered. Please login instead.');
1425
1425
 
1426
- // 或者引导用户去登录
1426
+ // Or guide user to login
1427
1427
  showLoginModal();
1428
1428
  } else {
1429
- // 处理其他错误
1430
- console.error('注册失败:', result.error);
1429
+ // Handle other errors
1430
+ console.error('Registration failed:', result.error);
1431
1431
  }
1432
1432
  ```
1433
1433
 
1434
- #### 2. 登录时处理各种错误
1434
+ #### 2. Handle Various Errors During Login
1435
1435
 
1436
1436
  ```typescript
1437
1437
  try {
@@ -1439,28 +1439,28 @@ try {
1439
1439
  email: 'user@example.com',
1440
1440
  password: 'wrong-password',
1441
1441
  });
1442
- console.log('登录成功:', result);
1442
+ console.log('Login successful:', result);
1443
1443
  } catch (error) {
1444
1444
  const errorCode = error.response?.data?.code;
1445
1445
 
1446
1446
  switch (errorCode) {
1447
1447
  case ErrorCode.INVALID_CREDENTIALS:
1448
- showError('用户名或密码错误');
1448
+ showError('Incorrect username or password');
1449
1449
  break;
1450
1450
  case ErrorCode.EMAIL_NOT_VERIFIED:
1451
- showError('请先验证您的邮箱');
1451
+ showError('Please verify your email first');
1452
1452
  showResendVerificationButton();
1453
1453
  break;
1454
1454
  case ErrorCode.ACCOUNT_SUSPENDED:
1455
- showError('您的账户已被暂停,请联系管理员');
1455
+ showError('Your account has been suspended, please contact administrator');
1456
1456
  break;
1457
1457
  default:
1458
- showError('登录失败,请稍后重试');
1458
+ showError('Login failed, please try again later');
1459
1459
  }
1460
1460
  }
1461
1461
  ```
1462
1462
 
1463
- #### 3. 通用错误处理函数
1463
+ #### 3. Generic Error Handling Function
1464
1464
 
1465
1465
  ```typescript
1466
1466
  import { ErrorCode } from '@seaverse/auth-sdk';
@@ -1469,44 +1469,44 @@ function handleApiError(error: any) {
1469
1469
  const apiError = error.response?.data;
1470
1470
 
1471
1471
  if (!apiError) {
1472
- // 网络错误或其他未知错误
1472
+ // Network error or other unknown error
1473
1473
  return {
1474
- title: '网络错误',
1475
- message: '请检查您的网络连接',
1474
+ title: 'Network Error',
1475
+ message: 'Please check your network connection',
1476
1476
  };
1477
1477
  }
1478
1478
 
1479
- // 根据错误码返回用户友好的消息
1479
+ // Return user-friendly messages based on error code
1480
1480
  const errorMessages: Record<string, { title: string; message: string }> = {
1481
1481
  [ErrorCode.ACCOUNT_EXISTS]: {
1482
- title: '账户已存在',
1483
- message: '该邮箱已注册,请直接登录',
1482
+ title: 'Account Exists',
1483
+ message: 'This email is already registered, please login directly',
1484
1484
  },
1485
1485
  [ErrorCode.INVALID_CREDENTIALS]: {
1486
- title: '登录失败',
1487
- message: '用户名或密码错误',
1486
+ title: 'Login Failed',
1487
+ message: 'Incorrect username or password',
1488
1488
  },
1489
1489
  [ErrorCode.EMAIL_NOT_VERIFIED]: {
1490
- title: '邮箱未验证',
1491
- message: '请先验证您的邮箱地址',
1490
+ title: 'Email Not Verified',
1491
+ message: 'Please verify your email address first',
1492
1492
  },
1493
1493
  [ErrorCode.INVALID_INVITATION_CODE]: {
1494
- title: '邀请码无效',
1495
- message: '请检查您的邀请码是否正确',
1494
+ title: 'Invalid Invitation Code',
1495
+ message: 'Please check if your invitation code is correct',
1496
1496
  },
1497
1497
  [ErrorCode.TOKEN_EXPIRED]: {
1498
- title: '登录已过期',
1499
- message: '请重新登录',
1498
+ title: 'Login Expired',
1499
+ message: 'Please login again',
1500
1500
  },
1501
1501
  };
1502
1502
 
1503
1503
  return errorMessages[apiError.code] || {
1504
- title: '操作失败',
1505
- message: apiError.error || '发生未知错误',
1504
+ title: 'Operation Failed',
1505
+ message: apiError.error || 'Unknown error occurred',
1506
1506
  };
1507
1507
  }
1508
1508
 
1509
- // 使用示例
1509
+ // Usage example
1510
1510
  try {
1511
1511
  await client.register({ email, password });
1512
1512
  } catch (error) {
@@ -1515,7 +1515,7 @@ try {
1515
1515
  }
1516
1516
  ```
1517
1517
 
1518
- #### 4. TypeScript 类型安全的错误处理
1518
+ #### 4. TypeScript Type-Safe Error Handling
1519
1519
 
1520
1520
  ```typescript
1521
1521
  import { ErrorCode, models } from '@seaverse/auth-sdk';
@@ -1555,164 +1555,164 @@ if (registerResult.success) {
1555
1555
  }
1556
1556
  ```
1557
1557
 
1558
- ### HTTP 状态码对照
1558
+ ### HTTP Status Code Reference
1559
1559
 
1560
- | HTTP状态码 | 错误码示例 | 说明 |
1560
+ | HTTP Status Code | Error Code Example | Description |
1561
1561
  |-----------|----------|------|
1562
- | 200 OK | `ACCOUNT_EXISTS` | 账户已存在(业务错误但返回成功响应) |
1563
- | 400 Bad Request | `INVALID_EMAIL`, `PASSWORD_TOO_WEAK` | 请求参数无效 |
1564
- | 401 Unauthorized | `INVALID_CREDENTIALS`, `TOKEN_EXPIRED` | 认证失败 |
1565
- | 403 Forbidden | `EMAIL_NOT_VERIFIED`, `ACCOUNT_SUSPENDED` | 权限不足 |
1566
- | 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 |
1567
1567
 
1568
- **注意**:对于注册接口,账户已存在的情况会返回 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.
1569
1569
 
1570
- ## 类型定义
1570
+ ## Type Definitions
1571
1571
 
1572
1572
  ```typescript
1573
- // 用户信息
1573
+ // User info
1574
1574
  interface User {
1575
1575
  id?: string;
1576
- app_id?: string | null; // 应用ID(多租户支持)
1576
+ app_id?: string | null; // Application ID (multi-tenant support)
1577
1577
  email?: string;
1578
1578
  username?: string;
1579
- created_at?: number; // Unix时间戳
1580
- email_verified?: boolean; // 邮箱验证状态
1581
- google_id?: string | null; // Google账号ID
1582
- discord_id?: string | null; // Discord账号ID
1583
- github_id?: string | null; // GitHub账号ID
1584
-
1585
- // 已弃用字段(向后兼容)
1586
- createdAt?: number; // @deprecated 使用 created_at
1587
- emailVerified?: boolean; // @deprecated 使用 email_verified
1588
- googleId?: string; // @deprecated 使用 google_id
1589
- discordId?: string; // @deprecated 使用 discord_id
1590
- 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
1591
1591
  }
1592
1592
 
1593
- // 登录响应
1593
+ // Login response
1594
1594
  interface LoginResponse {
1595
1595
  token: string;
1596
1596
  user: User;
1597
1597
  }
1598
1598
 
1599
- // 注册响应
1599
+ // Registration response
1600
1600
  interface RegisterResponse {
1601
1601
  success: boolean;
1602
1602
  message?: string;
1603
1603
  userId?: string;
1604
- // 邮箱验证相关
1605
- requiresEmailVerification?: boolean; // 是否需要邮箱验证
1606
- // 邀请码激活相关
1607
- requiresInvitationCode?: boolean; // 是否需要邀请码激活
1608
- tempUserId?: string; // 临时用户ID(需要激活)
1609
- // 错误信息
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
1610
1610
  error?: string;
1611
- code?: string; // 'ACCOUNT_EXISTS'
1611
+ code?: string; // E.g. 'ACCOUNT_EXISTS'
1612
1612
  details?: Record<string, any>;
1613
1613
  }
1614
1614
 
1615
- // AuthModal选项
1615
+ // AuthModal options
1616
1616
  interface AuthModalOptions {
1617
1617
  client: SeaVerseBackendAPIClient;
1618
1618
  theme?: 'dark' | 'light';
1619
1619
  onLoginSuccess?: (token: string, user: any) => void;
1620
1620
  onSignupSuccess?: (token: string, user: any) => void;
1621
- onInviteCodeRequired?: (userId: string, email: string) => void; // 当需要邀请码激活时的回调
1622
- 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
1623
1623
  onError?: (error: Error) => void;
1624
- returnUrl?: string; // OAuth 登录后返回的 URL,可选,默认为 window.location.href
1624
+ returnUrl?: string; // URL to return after OAuth login, optional, defaults to window.location.href
1625
1625
  enableOAuth?: {
1626
- google?: boolean; // 启用 Google 登录
1627
- discord?: boolean; // 启用 Discord 登录
1628
- github?: boolean; // 启用 GitHub 登录
1626
+ google?: boolean; // Enable Google login
1627
+ discord?: boolean; // Enable Discord login
1628
+ github?: boolean; // Enable GitHub login
1629
1629
  };
1630
1630
  }
1631
1631
  ```
1632
1632
 
1633
- ## 完整示例
1633
+ ## Complete Examples
1634
1634
 
1635
- 查看 [examples/auth-sdk-demo](../../examples/auth-sdk-demo) 目录获取完整的可运行示例。
1635
+ Check [examples/auth-sdk-demo](../../examples/auth-sdk-demo) directory for complete runnable examples.
1636
1636
 
1637
1637
  ```bash
1638
- # 运行示例
1638
+ # Run example
1639
1639
  cd examples/auth-sdk-demo
1640
1640
  pnpm install
1641
1641
  pnpm dev
1642
1642
  ```
1643
1643
 
1644
- ## 从旧版本迁移
1644
+ ## Migration from Old Versions
1645
1645
 
1646
- ### v0.1.x → v0.2.0 升级指南
1646
+ ### v0.1.x → v0.2.0 Upgrade Guide
1647
1647
 
1648
- #### 1. 向后兼容性
1649
- 好消息!v0.2.0 完全向后兼容,现有代码**无需修改**即可继续工作。
1648
+ #### 1. Backward Compatibility
1649
+ Good news! v0.2.0 is fully backward compatible, existing code **works without modifications**.
1650
1650
 
1651
- #### 2. 推荐的迁移步骤
1651
+ #### 2. Recommended Migration Steps
1652
1652
 
1653
- 虽然不是必须的,但我们建议逐步迁移到新的字段命名规范:
1653
+ While not required, we recommend gradually migrating to new field naming conventions:
1654
1654
 
1655
1655
  ```typescript
1656
- // 旧代码(仍然可用)
1656
+ // Old code (still works)
1657
1657
  const user = await client.getCurrentUser();
1658
- console.log(user.emailVerified); // ⚠️ 已弃用但可用
1659
- console.log(user.createdAt); // ⚠️ 已弃用但可用
1658
+ console.log(user.emailVerified); // ⚠️ Deprecated but works
1659
+ console.log(user.createdAt); // ⚠️ Deprecated but works
1660
1660
 
1661
- // 新代码(推荐)
1661
+ // New code (recommended)
1662
1662
  const user = await client.getCurrentUser();
1663
- console.log(user.email_verified); // ✅ 推荐使用
1664
- console.log(user.created_at); // ✅ 推荐使用
1665
- 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
1666
1666
  ```
1667
1667
 
1668
- #### 3. 注册接口更新
1668
+ #### 3. Registration API Update
1669
1669
 
1670
1670
  ```typescript
1671
- // 旧代码(仍然可用)
1671
+ // Old code (still works)
1672
1672
  await client.register({
1673
1673
  email: 'user@example.com',
1674
1674
  password: 'password123',
1675
- invitationCode: 'INVITE123', // ⚠️ 已弃用但可用
1675
+ invitationCode: 'INVITE123', // ⚠️ Deprecated but works
1676
1676
  });
1677
1677
 
1678
- // 新代码(推荐)
1678
+ // New code (recommended)
1679
1679
  await client.register({
1680
1680
  email: 'user@example.com',
1681
1681
  password: 'password123',
1682
- username: 'myusername', // ✨ 新功能
1683
- invitation_code: 'INVITE123', // ✅ 推荐使用
1682
+ username: 'myusername', // ✨ New feature
1683
+ invitation_code: 'INVITE123', // ✅ Recommended
1684
1684
  });
1685
1685
  ```
1686
1686
 
1687
- #### 4. 密码重置接口更新
1687
+ #### 4. Password Reset API Update
1688
1688
 
1689
1689
  ```typescript
1690
- // 旧代码(需要更新)
1690
+ // Old code (needs update)
1691
1691
  await client.resetPassword({
1692
1692
  token: 'reset-token',
1693
- newPassword: 'NewPass123', // ⚠️ 已弃用
1693
+ newPassword: 'NewPass123', // ⚠️ Deprecated
1694
1694
  });
1695
1695
 
1696
- // 新代码(推荐)
1696
+ // New code (recommended)
1697
1697
  await client.resetPassword({
1698
1698
  token: 'reset-token',
1699
- new_password: 'NewPass123', // ✅ 推荐使用
1699
+ new_password: 'NewPass123', // ✅ Recommended
1700
1700
  });
1701
1701
  ```
1702
1702
 
1703
- #### 5. TypeScript 类型提示
1703
+ #### 5. TypeScript Type Hints
1704
1704
 
1705
- 如果你使用 TypeScript,编译器会自动提示已弃用的字段:
1705
+ If you use TypeScript, compiler will automatically hint deprecated fields:
1706
1706
 
1707
1707
  ```typescript
1708
1708
  const user = await client.getCurrentUser();
1709
- user.emailVerified; // TypeScript 会显示删除线和弃用警告
1710
- user.email_verified; // ✅ 无警告
1709
+ user.emailVerified; // TypeScript will show strikethrough and deprecation warning
1710
+ user.email_verified; // ✅ No warning
1711
1711
  ```
1712
1712
 
1713
- #### 6. 多租户功能(新增)
1713
+ #### 6. Multi-Tenant Feature (New)
1714
1714
 
1715
- 如果你的应用需要支持多租户架构,可以使用新的 `app_id` 字段:
1715
+ If your application needs multi-tenant architecture support, you can use the new `app_id` field:
1716
1716
 
1717
1717
  ```typescript
1718
1718
  const user = await client.getCurrentUser();
@@ -1720,20 +1720,20 @@ const user = await client.getCurrentUser();
1720
1720
  console.log('your app id:', user.app_id);
1721
1721
  ```
1722
1722
 
1723
- ## 常见问题
1723
+ ## FAQ
1724
1724
 
1725
- ### 如何处理认证token?
1725
+ ### How to Handle Authentication Token?
1726
1726
 
1727
1727
  ```typescript
1728
- // 登录成功后保存token
1728
+ // Save token after successful login
1729
1729
  const loginResult = await client.login({ email, password });
1730
1730
  localStorage.setItem('token', loginResult.token);
1731
1731
 
1732
- // 创建带认证的client
1732
+ // Create authenticated client
1733
1733
  import { AuthFactory } from '@seaverse/auth-sdk';
1734
1734
 
1735
1735
  const authenticatedClient = new SeaVerseBackendAPIClient({
1736
- appId: 'your app id', // 必需:应用ID
1736
+ appId: 'your app id', // Required: Application ID
1737
1737
  environment: 'production',
1738
1738
  auth: AuthFactory.create({
1739
1739
  type: 'jwt',
@@ -1745,49 +1745,49 @@ const authenticatedClient = new SeaVerseBackendAPIClient({
1745
1745
  });
1746
1746
  ```
1747
1747
 
1748
- ### OAuth redirect_uri_mismatch错误?
1748
+ ### OAuth redirect_uri_mismatch Error?
1749
1749
 
1750
- 确保OAuth应用配置中的重定向URI与代码中的`redirectUri`完全一致(包括协议、域名、端口、路径)。
1750
+ Ensure the redirect URI in OAuth application configuration exactly matches the `redirectUri` in code (including protocol, domain, port, path).
1751
1751
 
1752
- ### 如何自定义请求超时?
1752
+ ### How to Customize Request Timeout?
1753
1753
 
1754
1754
  ```typescript
1755
1755
  const client = new SeaVerseBackendAPIClient({
1756
- appId: 'your app id', // 必需:应用ID
1756
+ appId: 'your app id', // Required: Application ID
1757
1757
  environment: 'production',
1758
- timeout: 30000, // 30
1758
+ timeout: 30000, // 30 seconds
1759
1759
  });
1760
1760
  ```
1761
1761
 
1762
- ### 本地开发如何连接到本地API
1762
+ ### How to Connect to Local API in Local Development?
1763
1763
 
1764
1764
  ```typescript
1765
1765
  const client = new SeaVerseBackendAPIClient({
1766
- appId: 'your app id', // 必需:应用ID
1767
- environment: 'local', // 或使用 baseURL: 'http://localhost:3000'
1766
+ appId: 'your app id', // Required: Application ID
1767
+ environment: 'local', // Or use baseURL: 'http://localhost:3000'
1768
1768
  });
1769
1769
  ```
1770
1770
 
1771
- ## 开发
1771
+ ## Development
1772
1772
 
1773
1773
  ```bash
1774
- # 安装依赖
1774
+ # Install dependencies
1775
1775
  pnpm install
1776
1776
 
1777
- # 构建
1777
+ # Build
1778
1778
  pnpm build
1779
1779
 
1780
- # Watch模式
1780
+ # Watch mode
1781
1781
  pnpm dev
1782
1782
 
1783
- # 测试
1783
+ # Test
1784
1784
  pnpm test
1785
1785
  ```
1786
1786
 
1787
- ## 相关链接
1787
+ ## Related Links
1788
1788
 
1789
1789
  - 📦 [NPM Package](https://www.npmjs.com/package/@seaverse/auth-sdk)
1790
- - 📖 [示例项目](../../examples/auth-sdk-demo)
1790
+ - 📖 [Example Project](../../examples/auth-sdk-demo)
1791
1791
  - 🐛 [Issues](https://github.com/seaverseai/sv-sdk/issues)
1792
1792
  - 💬 [Discussions](https://github.com/seaverseai/sv-sdk/discussions)
1793
1793
 
@@ -1795,48 +1795,48 @@ pnpm test
1795
1795
 
1796
1796
  MIT © [SeaVerse Team](mailto:support@seaverse.com)
1797
1797
 
1798
- ## 更新日志
1798
+ ## Changelog
1799
1799
 
1800
- ### v0.3.6 (当前版本)
1801
- - 🧹 **代码清理**: 移除桌面应用OAuth回调相关功能
1802
- - 移除 `oauthDesktopURL` 配置选项
1803
- - 简化OAuth流程,统一使用 `returnUrl` 参数
1804
- - 清理相关文档和代码注释
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
1805
1805
 
1806
1806
  ### v0.2.5
1807
- - 🔄 **响应格式兼容**: 自动兼容包装格式和扁平格式的API响应
1808
- - 修复登录时提示 "Invalid response from server" 的问题
1809
- - `login()`, `register()`, `getCurrentUser()` 方法自动解包 `data` 字段
1810
- - 支持两种格式: `{ data: {...}, success: true }` `{ ... }`
1811
- - 📝 **文档更新**: 新增响应格式兼容性章节
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
1812
1812
 
1813
1813
  ### v0.2.0
1814
- - 🔄 **API路径更新**: 所有认证API从 `/api/auth/*` 迁移到 `/sdk/v1/auth/*`
1815
- - 🏢 **多租户支持**: User模型新增 `app_id` 字段,支持多应用隔离
1816
- - 🔑 **重要变更**: `appId` 现在是**必需参数**,SDK 自动在所有请求中添加 `X-App-ID` 请求头
1817
- - ✨ **新功能**:
1818
- - 注册时支持自定义 `username`(可选)
1819
- - 所有字段标准化为 snake_case(保留 camelCase 向后兼容)
1820
- - 📝 **字段更新**:
1821
- - `SeaVerseBackendAPIClientOptions`: 新增必需字段 `appId`
1822
- - `User`: 新增 `app_id`, `created_at`, `email_verified`, `google_id`, `discord_id`, `github_id`
1823
- - `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`
1824
1824
  - `ResetPasswordRequest`: `newPassword` → `new_password`
1825
1825
  - ⚠️ **Breaking Changes**:
1826
- - 必须提供 `appId` 参数才能初始化 client
1827
- - API 路径变更需要后端支持
1828
- - ✅ **向后兼容**: `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
1829
1829
 
1830
1830
  ### v0.1.5
1831
- - 修复OAuth state管理,从sessionStorage切换到localStorage
1832
- - 增强API响应处理
1831
+ - Fix OAuth state management, switch from sessionStorage to localStorage
1832
+ - Enhance API response handling
1833
1833
 
1834
1834
  ### v0.1.4
1835
- - 增强API响应处理
1836
- - 优化错误处理
1835
+ - Enhance API response handling
1836
+ - Optimize error handling
1837
1837
 
1838
1838
  ### v0.1.2
1839
- - 更新包名为@seaverse/auth-sdk
1840
- - 添加多环境支持
1839
+ - Update package name to @seaverse/auth-sdk
1840
+ - Add multi-environment support
1841
1841
 
1842
- 查看完整更新日志:[CHANGELOG.md](./CHANGELOG.md)
1842
+ View complete changelog: [CHANGELOG.md](./CHANGELOG.md)