@amaster.ai/auth-client 1.0.0-beta.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amaster Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,472 @@
1
+ # @amaster.ai/auth-client
2
+
3
+ Authentication SDK for Amaster Platform - Complete client-side authentication solution with OAuth, session management, and permission checks.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **Multiple Authentication Methods**: Username/Email/Phone + Password, Verification Code, OAuth
8
+ - 🔄 **Automatic Token Refresh**: JWT token auto-refresh before expiration
9
+ - 📦 **Token Storage**: localStorage or sessionStorage with SSR support
10
+ - 🎯 **Permission System**: Role-based and permission-based access control
11
+ - 🔗 **OAuth Integration**: Google, GitHub, WeChat, and custom OAuth providers
12
+ - 📡 **Event System**: Listen to login, logout, and token events
13
+ - 💾 **Session Management**: View and revoke active sessions
14
+ - 🔒 **Type-Safe**: Full TypeScript support
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add @amaster.ai/auth-client
20
+ # or
21
+ npm install @amaster.ai/auth-client
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { createAuthClient } from "@amaster.ai/auth-client";
28
+
29
+ // Initialize the client (with optional callbacks)
30
+ const authClient = createAuthClient({
31
+ onTokenExpired: () => {
32
+ window.location.href = "/login";
33
+ },
34
+ onUnauthorized: () => {
35
+ window.location.href = "/login";
36
+ },
37
+ });
38
+
39
+ // Register a new user
40
+ await authClient.register({
41
+ email: "user@example.com",
42
+ password: "Password@123",
43
+ displayName: "John Doe",
44
+ });
45
+
46
+ // Login
47
+ const result = await authClient.login({
48
+ loginType: "email",
49
+ email: "user@example.com",
50
+ password: "Password@123",
51
+ });
52
+
53
+ if (result.data) {
54
+ console.log("Logged in:", result.data.user);
55
+ }
56
+
57
+ // Get current user
58
+ const user = await authClient.getMe();
59
+
60
+ // Check permissions
61
+ if (authClient.hasPermission("user.read")) {
62
+ // Show user list
63
+ }
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ ```typescript
69
+ interface AuthClientOptions {
70
+ baseURL?: string; // API base URL, defaults to window.location.origin
71
+ storage?: "localStorage" | "sessionStorage"; // Token storage type, defaults to localStorage
72
+ onTokenExpired?: () => void; // Token expiration callback
73
+ onUnauthorized?: () => void; // Unauthorized (401) callback
74
+ }
75
+ ```
76
+
77
+ **Built-in Features (Zero Config):**
78
+
79
+ - ✅ **Auto Token Refresh**: Refreshes 5 minutes before expiry
80
+ - ✅ **Auto Permission Sync**: Syncs on page load and every token refresh
81
+ - ✅ **Lightweight Data**: Only permission names cached, not full objects
82
+ - ✅ **On-Demand DataScope**: Loads only when needed
83
+ - ✅ **SSR Compatible**: Works in both browser and server environments
84
+
85
+ ## Authentication
86
+
87
+ ### Register
88
+
89
+ ```typescript
90
+ await authClient.register({
91
+ email: "user@example.com",
92
+ password: "Password@123",
93
+ displayName: "John Doe",
94
+ });
95
+ ```
96
+
97
+ **With Captcha:**
98
+
99
+ ```typescript
100
+ // 1. Get captcha
101
+ const captchaData = await authClient.getCaptcha();
102
+ document.getElementById("captcha-img").src = captchaData.data.captchaImage;
103
+
104
+ // 2. Register with captcha
105
+ const userInputCode = "AB12";
106
+ await authClient.register({
107
+ email: "user@example.com",
108
+ password: "Password@123",
109
+ captcha: `${captchaData.data.captchaId}:${userInputCode}`,
110
+ });
111
+ ```
112
+
113
+ ### Login
114
+
115
+ **Password Login:**
116
+
117
+ ```typescript
118
+ await authClient.login({
119
+ loginType: "email",
120
+ email: "user@example.com",
121
+ password: "Password@123",
122
+ });
123
+ ```
124
+
125
+ **Verification Code Login:**
126
+
127
+ ```typescript
128
+ // 1. Send code
129
+ await authClient.sendCode({
130
+ type: "email",
131
+ email: "user@example.com",
132
+ });
133
+
134
+ // 2. Login with code
135
+ await authClient.loginWithCode({
136
+ loginType: "email",
137
+ email: "user@example.com",
138
+ code: "123456",
139
+ });
140
+ ```
141
+
142
+ ### OAuth Login
143
+
144
+ **Full-page redirect (recommended):**
145
+
146
+ ```typescript
147
+ // Login page
148
+ sessionStorage.setItem("oauth_redirect", "/dashboard");
149
+ authClient.loginWithOAuth("google");
150
+
151
+ // Callback page (/auth/callback)
152
+ const { user } = await authClient.handleOAuthCallback();
153
+ const redirectUrl = sessionStorage.getItem("oauth_redirect") || "/";
154
+ window.location.href = redirectUrl;
155
+ ```
156
+
157
+ **Popup window:**
158
+
159
+ ```typescript
160
+ // Main page
161
+ const popup = window.open(
162
+ "/api/auth/oauth/google",
163
+ "oauth-login",
164
+ "width=600,height=700"
165
+ );
166
+
167
+ window.addEventListener("message", (event) => {
168
+ if (event.data.type === "oauth-success") {
169
+ authClient.setAccessToken(event.data.accessToken);
170
+ popup?.close();
171
+ }
172
+ });
173
+
174
+ // Callback page
175
+ if (window.opener) {
176
+ const { accessToken } = await authClient.handleOAuthCallback();
177
+ window.opener.postMessage({ type: "oauth-success", accessToken }, origin);
178
+ }
179
+ ```
180
+
181
+ ### Logout
182
+
183
+ ```typescript
184
+ await authClient.logout();
185
+ ```
186
+
187
+ ## User Management
188
+
189
+ ### Get Current User
190
+
191
+ ```typescript
192
+ const result = await authClient.getMe();
193
+ if (result.data) {
194
+ console.log(result.data); // User object
195
+ }
196
+ ```
197
+
198
+ ### Update Profile
199
+
200
+ ```typescript
201
+ await authClient.updateMe({
202
+ displayName: "New Name",
203
+ avatarUrl: "https://example.com/avatar.jpg",
204
+ });
205
+ ```
206
+
207
+ ### Change Password
208
+
209
+ ```typescript
210
+ await authClient.changePassword({
211
+ oldPassword: "OldPassword@123",
212
+ newPassword: "NewPassword@123",
213
+ });
214
+ ```
215
+
216
+ ## Permission Checks
217
+
218
+ ### Local Permission Checks (Fast)
219
+
220
+ Permissions are cached locally as string arrays for fast UI checks:
221
+
222
+ ```typescript
223
+ // Check single role
224
+ if (authClient.hasRole("admin")) {
225
+ // Admin only
226
+ }
227
+
228
+ // Check single permission
229
+ if (authClient.hasPermission("user.read")) {
230
+ // Can read users
231
+ }
232
+
233
+ // Check any permission
234
+ if (authClient.hasAnyPermission(["user.read", "user.manage"])) {
235
+ // Has at least one permission
236
+ }
237
+
238
+ // Check all permissions
239
+ if (authClient.hasAllPermissions(["user.read", "user.write"])) {
240
+ // Has all permissions
241
+ }
242
+ ```
243
+
244
+ ### On-Demand Data Scope Loading
245
+
246
+ Data scopes are loaded only when needed to reduce data transfer:
247
+
248
+ ```typescript
249
+ // Get data scope for a specific permission
250
+ const result = await authClient.getPermissionScope("user.read");
251
+ if (result.data) {
252
+ const { dataScope } = result.data;
253
+
254
+ if (dataScope.scopeType === "department") {
255
+ // Filter users by department
256
+ const users = await api.getUsers({
257
+ departmentId: dataScope.scopeFilter.departmentId
258
+ });
259
+ } else if (dataScope.scopeType === "all") {
260
+ // Show all users
261
+ const users = await api.getUsers();
262
+ }
263
+ }
264
+ ```
265
+
266
+ **Optimized Data Structure:**
267
+
268
+ ```typescript
269
+ // User object (lightweight)
270
+ {
271
+ uid: "xxx",
272
+ email: "user@example.com",
273
+ roles: ["admin", "user"], // Only role codes
274
+ permissions: ["user.read", "user.write", "order.read"], // Only permission names
275
+ // NO dataScopes - loaded on demand
276
+ }
277
+ ```
278
+
279
+ ## OAuth Bindings
280
+
281
+ ### Get Bindings
282
+
283
+ ```typescript
284
+ const result = await authClient.getOAuthBindings();
285
+ if (result.data) {
286
+ console.log(result.data); // Array of OAuthBinding
287
+ }
288
+ ```
289
+
290
+ ### Bind OAuth Account
291
+
292
+ ```typescript
293
+ authClient.bindOAuth("google"); // Redirects to OAuth flow
294
+ ```
295
+
296
+ ### Unbind OAuth Account
297
+
298
+ ```typescript
299
+ await authClient.unbindOAuth("google");
300
+ ```
301
+
302
+ ## Session Management
303
+
304
+ ### Get Sessions
305
+
306
+ ```typescript
307
+ const result = await authClient.getSessions();
308
+ if (result.data) {
309
+ result.data.forEach((session) => {
310
+ console.log(session.ip, session.userAgent, session.isCurrent);
311
+ });
312
+ }
313
+ ```
314
+
315
+ ### Revoke Session
316
+
317
+ ```typescript
318
+ await authClient.revokeSession("session-id");
319
+ ```
320
+
321
+ ### Revoke All Sessions
322
+
323
+ ```typescript
324
+ const result = await authClient.revokeAllSessions();
325
+ if (result.data) {
326
+ console.log(`Revoked ${result.data.revokedCount} sessions`);
327
+ }
328
+ ```
329
+
330
+ ## Event System
331
+
332
+ ### Available Events
333
+
334
+ - `login` - User logged in, callback: `(user: User) => void`
335
+ - `logout` - User logged out, callback: `() => void`
336
+ - `tokenExpired` - Token expired, callback: `() => void`
337
+ - `tokenRefreshed` - Token refreshed, callback: `(token: string) => void`
338
+ - `unauthorized` - Unauthorized (401), callback: `() => void`
339
+
340
+ ### Usage
341
+
342
+ ```typescript
343
+ // Subscribe to events
344
+ authClient.on("unauthorized", () => {
345
+ authClient.clearAuth();
346
+ window.location.href = "/login";
347
+ });
348
+
349
+ authClient.on("login", (user) => {
350
+ console.log("User logged in:", user.displayName);
351
+ });
352
+
353
+ authClient.on("tokenRefreshed", (token) => {
354
+ console.log("Token refreshed");
355
+ });
356
+
357
+ // Unsubscribe
358
+ const handler = () => console.log("Logged out");
359
+ authClient.on("logout", handler);
360
+ authClient.off("logout", handler);
361
+ ```
362
+
363
+ ## Utility Methods
364
+
365
+ ### Check Authentication Status
366
+
367
+ ```typescript
368
+ if (authClient.isAuthenticated()) {
369
+ // User is logged in
370
+ }
371
+ ```
372
+
373
+ ### Get Access Token
374
+
375
+ ```typescript
376
+ const token = authClient.getAccessToken();
377
+ ```
378
+
379
+ ### Set Access Token
380
+
381
+ ```typescript
382
+ authClient.setAccessToken("your-token-here");
383
+ ```
384
+
385
+ ### Clear Auth Data
386
+
387
+ ```typescript
388
+ authClient.clearAuth(); // Clears token and user data
389
+ ```
390
+
391
+ ## Error Handling
392
+
393
+ ```typescript
394
+ try {
395
+ await authClient.login({ ... });
396
+ } catch (error) {
397
+ // Network error or exception
398
+ console.error("Login failed:", error);
399
+ }
400
+
401
+ // Or use result pattern
402
+ const result = await authClient.login({ ... });
403
+ if (result.error) {
404
+ // API error response
405
+ if (result.error.status === 401) {
406
+ alert("Invalid email or password");
407
+ } else if (result.error.status === 403) {
408
+ alert("Account is disabled");
409
+ } else {
410
+ alert(`Login failed: ${result.error.message}`);
411
+ }
412
+ }
413
+ ```
414
+
415
+ ## Best Practices
416
+
417
+ ### Token Management
418
+
419
+ - SDK automatically manages Access Token and Refresh Token
420
+ - Access Token is stored in localStorage/sessionStorage
421
+ - Refresh Token is managed by backend via HttpOnly Cookie
422
+ - Token is automatically refreshed 5 minutes before expiration (configurable)
423
+
424
+ ### Permission Sync
425
+
426
+ - **On Page Load**: User info and permissions automatically sync from backend
427
+ - **On Token Refresh**: Permissions re-sync every 5 minutes when token refreshes
428
+ - **Manual Sync**: Call `await authClient.getMe()` to force sync anytime
429
+
430
+ **Behavior:**
431
+ - Permissions always stay fresh without any configuration
432
+ - Page refresh loads latest permissions from backend
433
+ - Background sync happens automatically every 5 minutes
434
+
435
+ ### Permission Checks
436
+
437
+ - **Frontend permission checks are for UI control only** (show/hide buttons, menus)
438
+ - **Backend must verify permissions again** - frontend checks are NOT security measures
439
+ - Use permission checks to improve UX, not as security enforcement
440
+
441
+ ### SSR Support
442
+
443
+ The SDK detects SSR environments and uses a no-op storage adapter:
444
+
445
+ ```typescript
446
+ // Safe in both browser and SSR
447
+ const authClient = createAuthClient();
448
+ ```
449
+
450
+ ## TypeScript
451
+
452
+ Full TypeScript support with comprehensive type definitions:
453
+
454
+ ```typescript
455
+ import type {
456
+ User,
457
+ LoginResponse,
458
+ Permission,
459
+ Role,
460
+ DataScope,
461
+ Session,
462
+ OAuthBinding,
463
+ } from "@amaster.ai/auth-client";
464
+ ```
465
+
466
+ ## License
467
+
468
+ MIT
469
+
470
+ ## Contributing
471
+
472
+ Contributions are welcome! Please read our contributing guidelines before submitting PRs.
@@ -0,0 +1,138 @@
1
+ /**
2
+ * ============================================================================
3
+ * @amaster.ai/auth-client - Type Definitions
4
+ * ============================================================================
5
+ *
6
+ * 🤖 AI NAVIGATION - Read these files based on your task:
7
+ *
8
+ * 1. Need LOGIN/REGISTER/LOGOUT? → Read: ./auth.d.ts
9
+ * 2. Need PERMISSION checks? → Read: ./permissions.d.ts
10
+ * 3. Need USER profile management? → Read: ./user.d.ts
11
+ * 4. Need OAUTH binding? → Read: ./oauth.d.ts
12
+ * 5. Need SESSION management? → Read: ./sessions.d.ts
13
+ *
14
+ * ============================================================================
15
+ */
16
+ import { HttpClient, ClientResult } from '@amaster.ai/http-client';
17
+ import { s as User, k as RegisterParams, f as LoginResponse, L as LoginParams, d as CodeLoginParams, S as SendCodeParams, r as SuccessResponse, b as CaptchaResponse, h as OAuthProvider, R as RefreshTokenResponse } from './types-4MBObpYA.cjs';
18
+
19
+ /**
20
+ * Authentication Module
21
+ *
22
+ * @module auth
23
+ * @category Authentication
24
+ *
25
+ * Handles user authentication including:
26
+ * - Registration
27
+ * - Login (email/username/phone + password)
28
+ * - Verification code login
29
+ * - OAuth social login
30
+ * - Logout and token refresh
31
+ */
32
+
33
+ interface AuthModuleDeps {
34
+ http: HttpClient;
35
+ onLoginSuccess: (user: User, accessToken: string) => void;
36
+ storage: {
37
+ getItem: (key: string) => string | null;
38
+ };
39
+ clearAuth: () => void;
40
+ }
41
+ declare function createAuthModule(deps: AuthModuleDeps): {
42
+ /**
43
+ * Register a new user account
44
+ *
45
+ * @category Authentication
46
+ * @example
47
+ * ```typescript
48
+ * const result = await auth.register({
49
+ * email: "user@example.com",
50
+ * password: "Password@123",
51
+ * displayName: "John Doe",
52
+ * });
53
+ * ```
54
+ */
55
+ register(params: RegisterParams): Promise<ClientResult<LoginResponse>>;
56
+ /**
57
+ * Login with username/email/phone and password
58
+ *
59
+ * @category Authentication
60
+ * @example
61
+ * ```typescript
62
+ * await auth.login({
63
+ * loginType: "email",
64
+ * email: "user@example.com",
65
+ * password: "Password@123",
66
+ * });
67
+ * ```
68
+ */
69
+ login(params: LoginParams): Promise<ClientResult<LoginResponse>>;
70
+ /**
71
+ * Login with verification code
72
+ *
73
+ * @category Authentication
74
+ * @example
75
+ * ```typescript
76
+ * await auth.loginWithCode({
77
+ * loginType: "email",
78
+ * email: "user@example.com",
79
+ * code: "123456",
80
+ * });
81
+ * ```
82
+ */
83
+ loginWithCode(params: CodeLoginParams): Promise<ClientResult<LoginResponse>>;
84
+ /**
85
+ * Send verification code to email or phone
86
+ *
87
+ * @category Authentication
88
+ * @example
89
+ * ```typescript
90
+ * await auth.sendCode({
91
+ * type: "email",
92
+ * email: "user@example.com",
93
+ * });
94
+ * ```
95
+ */
96
+ sendCode(params: SendCodeParams): Promise<ClientResult<SuccessResponse>>;
97
+ /**
98
+ * Get captcha image
99
+ *
100
+ * @category Authentication
101
+ */
102
+ getCaptcha(): Promise<ClientResult<CaptchaResponse>>;
103
+ /**
104
+ * Redirect to OAuth provider for authentication
105
+ *
106
+ * @category Authentication
107
+ * @example
108
+ * ```typescript
109
+ * auth.loginWithOAuth("google");
110
+ * ```
111
+ */
112
+ loginWithOAuth(provider: OAuthProvider, redirectUrl?: string): void;
113
+ /**
114
+ * Handle OAuth callback
115
+ *
116
+ * @category Authentication
117
+ */
118
+ handleOAuthCallback(): Promise<ClientResult<LoginResponse>>;
119
+ /**
120
+ * Logout current user
121
+ *
122
+ * @category Authentication
123
+ * @example
124
+ * ```typescript
125
+ * await auth.logout();
126
+ * ```
127
+ */
128
+ logout(): Promise<ClientResult<SuccessResponse>>;
129
+ /**
130
+ * Refresh access token
131
+ *
132
+ * @category Authentication
133
+ */
134
+ refreshToken(): Promise<ClientResult<RefreshTokenResponse>>;
135
+ };
136
+ type AuthModule = ReturnType<typeof createAuthModule>;
137
+
138
+ export { type AuthModule, type AuthModuleDeps, createAuthModule };