win-portal-auth-sdk 1.3.0 → 1.3.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/README.md +74 -0
- package/dist/client/auth-client.d.ts +97 -2
- package/dist/client/auth-client.d.ts.map +1 -1
- package/dist/client/auth-client.js +276 -30
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +23 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +49 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -305,9 +305,27 @@ const client = new AuthClient({
|
|
|
305
305
|
baseURL?: string; // Optional: Base URL for requests
|
|
306
306
|
apiKeyHeader?: string; // Optional: Custom header name (default: 'X-API-Key')
|
|
307
307
|
timeout?: number; // Optional: Request timeout (default: 30000ms)
|
|
308
|
+
advanced?: { // Optional: Advanced configuration
|
|
309
|
+
activityThrottleMs?: number; // Activity handler throttle (default: 1000ms)
|
|
310
|
+
refreshTimeoutMs?: number; // Refresh token timeout (default: 5000ms)
|
|
311
|
+
}
|
|
308
312
|
})
|
|
309
313
|
```
|
|
310
314
|
|
|
315
|
+
**Advanced Configuration:**
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// ปรับแต่ง performance และ timeout settings
|
|
319
|
+
const client = new AuthClient({
|
|
320
|
+
apiKey: 'your-api-key',
|
|
321
|
+
baseURL: 'https://api.example.com',
|
|
322
|
+
advanced: {
|
|
323
|
+
activityThrottleMs: 500, // ลด throttle time สำหรับ responsive มากขึ้น (แต่ใช้ CPU มากขึ้น)
|
|
324
|
+
refreshTimeoutMs: 10000, // เพิ่ม timeout สำหรับ slow network
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
311
329
|
#### HTTP Methods
|
|
312
330
|
|
|
313
331
|
- `get<T>(url, config?)` - GET request
|
|
@@ -369,6 +387,62 @@ const client = new AuthClient({
|
|
|
369
387
|
- `getApiKeyMasked()` - Get masked API key for display
|
|
370
388
|
- `getAxiosInstance()` - Get underlying axios instance
|
|
371
389
|
|
|
390
|
+
#### Session Management
|
|
391
|
+
|
|
392
|
+
**Inactivity Detection:**
|
|
393
|
+
|
|
394
|
+
- `enableInactivityDetection(options)` - Enable inactivity detection ที่จับ user activity (mouse/keyboard/touch/scroll)
|
|
395
|
+
- จับ user activity และ trigger callback เมื่อ inactivity timeout
|
|
396
|
+
- ใช้ timeout และ warning time จาก session management config เป็น default
|
|
397
|
+
- Support SSR (Next.js) โดยไม่ error
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
// Enable inactivity detection
|
|
401
|
+
await authClient.enableInactivityDetection({
|
|
402
|
+
callbacks: {
|
|
403
|
+
onInactivityWarning: (remainingSeconds) => {
|
|
404
|
+
console.log(`Inactivity warning: ${remainingSeconds} seconds remaining`);
|
|
405
|
+
// แสดง notification หรือ dialog
|
|
406
|
+
alert(`Session will expire in ${remainingSeconds} seconds due to inactivity`);
|
|
407
|
+
},
|
|
408
|
+
onInactivityTimeout: () => {
|
|
409
|
+
console.log('Inactivity timeout');
|
|
410
|
+
// Redirect to login หรือ logout
|
|
411
|
+
authClient.clearToken();
|
|
412
|
+
window.location.href = '/login';
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
timeoutSeconds: 1800, // 30 minutes (optional, default: จาก session management config)
|
|
416
|
+
warningSeconds: 300, // 5 minutes warning (optional, default: จาก session management config)
|
|
417
|
+
events: ['mousemove', 'keydown', 'touchstart', 'scroll'] // (optional, default: ทั้งหมด)
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// Disable inactivity detection
|
|
421
|
+
authClient.disableInactivityDetection();
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
**Session Expiration Monitoring:**
|
|
425
|
+
|
|
426
|
+
- `enableSessionExpirationMonitoring(options)` - Enable session expiration monitoring
|
|
427
|
+
- ตรวจสอบ session expiration ตาม config จาก settings/sessions
|
|
428
|
+
- เรียก callback เมื่อใกล้หมดอายุ
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
await authClient.enableSessionExpirationMonitoring({
|
|
432
|
+
callbacks: {
|
|
433
|
+
onSessionExpiring: (remainingMinutes, expirationType) => {
|
|
434
|
+
console.log(`Session will expire in ${remainingMinutes} minutes (${expirationType})`);
|
|
435
|
+
// แสดง notification หรือ dialog
|
|
436
|
+
},
|
|
437
|
+
onSessionExpired: () => {
|
|
438
|
+
console.log('Session expired');
|
|
439
|
+
// Redirect to login
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
checkIntervalSeconds: 30 // ตรวจสอบทุก 30 วินาที
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
372
446
|
## Authentication Types
|
|
373
447
|
|
|
374
448
|
The SDK supports three authentication types through the `X-Auth-Type` header:
|
|
@@ -65,6 +65,35 @@ export interface AutomaticRefreshOptions {
|
|
|
65
65
|
*/
|
|
66
66
|
onRefreshFailure?: () => void | Promise<void>;
|
|
67
67
|
}
|
|
68
|
+
export interface InactivityCallbacks {
|
|
69
|
+
/**
|
|
70
|
+
* Callback เมื่อ inactivity ใกล้หมดเวลา (ตาม warningSeconds)
|
|
71
|
+
* @param remainingSeconds - จำนวนวินาทีที่เหลือก่อน inactivity timeout
|
|
72
|
+
*/
|
|
73
|
+
onInactivityWarning?: (remainingSeconds: number) => void | Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Callback เมื่อ inactivity timeout แล้ว
|
|
76
|
+
*/
|
|
77
|
+
onInactivityTimeout?: () => void | Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
export interface InactivityDetectionOptions {
|
|
80
|
+
/**
|
|
81
|
+
* Callbacks สำหรับ inactivity events
|
|
82
|
+
*/
|
|
83
|
+
callbacks: InactivityCallbacks;
|
|
84
|
+
/**
|
|
85
|
+
* Optional: ระยะเวลา inactivity timeout เป็นวินาที (default: ใช้จาก session management config)
|
|
86
|
+
*/
|
|
87
|
+
timeoutSeconds?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Optional: ระยะเวลา warning ก่อน timeout เป็นวินาที (default: ใช้จาก session management config)
|
|
90
|
+
*/
|
|
91
|
+
warningSeconds?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Optional: Events ที่ต้องการจับ (default: ทั้งหมด ['mousemove', 'keydown', 'touchstart', 'scroll'])
|
|
94
|
+
*/
|
|
95
|
+
events?: ('mousemove' | 'keydown' | 'touchstart' | 'scroll')[];
|
|
96
|
+
}
|
|
68
97
|
export declare class AuthClient {
|
|
69
98
|
private client;
|
|
70
99
|
private apiKey;
|
|
@@ -77,14 +106,24 @@ export declare class AuthClient {
|
|
|
77
106
|
private automaticRefreshEnabled;
|
|
78
107
|
private lastRefreshAttempt;
|
|
79
108
|
private refreshPromise;
|
|
80
|
-
private readonly REFRESH_COOLDOWN_MS;
|
|
81
109
|
private sessionExpirationCallbacks;
|
|
82
110
|
private sessionManagementConfig;
|
|
83
111
|
private sessionManagementConfigPromise;
|
|
84
112
|
private sessionExpirationCheckInterval;
|
|
85
113
|
private sessionExpirationCheckIntervalSeconds;
|
|
86
114
|
private lastWarningTime;
|
|
87
|
-
private
|
|
115
|
+
private inactivityCallbacks;
|
|
116
|
+
private inactivityTimeout;
|
|
117
|
+
private inactivityWarningTimeout;
|
|
118
|
+
private lastActivityTime;
|
|
119
|
+
private inactivityDetectionEnabled;
|
|
120
|
+
private inactivityTimeoutSeconds;
|
|
121
|
+
private inactivityWarningSeconds;
|
|
122
|
+
private activityEvents;
|
|
123
|
+
private activityHandler;
|
|
124
|
+
private activityThrottleTimeout;
|
|
125
|
+
private activityThrottleMs;
|
|
126
|
+
private refreshTimeoutMs;
|
|
88
127
|
readonly auth: AuthAPI;
|
|
89
128
|
readonly health: HealthAPI;
|
|
90
129
|
readonly systemConfig: SystemConfigAPI;
|
|
@@ -286,5 +325,61 @@ export declare class AuthClient {
|
|
|
286
325
|
* Reload session management config (for when config changes)
|
|
287
326
|
*/
|
|
288
327
|
reloadSessionManagementConfig(): Promise<void>;
|
|
328
|
+
/**
|
|
329
|
+
* Enable inactivity detection
|
|
330
|
+
* จับ user activity (mouse/keyboard/touch/scroll) และ trigger callback เมื่อ inactivity timeout
|
|
331
|
+
*
|
|
332
|
+
* @param options - Options for inactivity detection
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```typescript
|
|
336
|
+
* await authClient.enableInactivityDetection({
|
|
337
|
+
* callbacks: {
|
|
338
|
+
* onInactivityWarning: (remainingSeconds) => {
|
|
339
|
+
* console.log(`Inactivity warning: ${remainingSeconds} seconds remaining`);
|
|
340
|
+
* // แสดง notification หรือ dialog
|
|
341
|
+
* },
|
|
342
|
+
* onInactivityTimeout: () => {
|
|
343
|
+
* console.log('Inactivity timeout');
|
|
344
|
+
* // Redirect to login หรือ logout
|
|
345
|
+
* authClient.clearToken();
|
|
346
|
+
* window.location.href = '/login';
|
|
347
|
+
* }
|
|
348
|
+
* },
|
|
349
|
+
* timeoutSeconds: 1800, // 30 minutes (optional, default: จาก session management config)
|
|
350
|
+
* warningSeconds: 300, // 5 minutes warning (optional, default: จาก session management config)
|
|
351
|
+
* events: ['mousemove', 'keydown', 'touchstart', 'scroll'] // (optional, default: ทั้งหมด)
|
|
352
|
+
* });
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
enableInactivityDetection(options: InactivityDetectionOptions): Promise<void>;
|
|
356
|
+
/**
|
|
357
|
+
* Disable inactivity detection
|
|
358
|
+
*/
|
|
359
|
+
disableInactivityDetection(): void;
|
|
360
|
+
/**
|
|
361
|
+
* Handle user activity - reset inactivity timer with throttle
|
|
362
|
+
*/
|
|
363
|
+
private handleUserActivity;
|
|
364
|
+
/**
|
|
365
|
+
* Setup activity event listeners
|
|
366
|
+
*/
|
|
367
|
+
private setupActivityListeners;
|
|
368
|
+
/**
|
|
369
|
+
* Remove activity event listeners
|
|
370
|
+
*/
|
|
371
|
+
private removeActivityListeners;
|
|
372
|
+
/**
|
|
373
|
+
* Clear inactivity timeouts (helper method)
|
|
374
|
+
*/
|
|
375
|
+
private clearInactivityTimeouts;
|
|
376
|
+
/**
|
|
377
|
+
* Reset inactivity timer
|
|
378
|
+
*/
|
|
379
|
+
private resetInactivityTimer;
|
|
380
|
+
/**
|
|
381
|
+
* Check inactivity timeout and trigger callbacks if needed
|
|
382
|
+
*/
|
|
383
|
+
private checkInactivityTimeout;
|
|
289
384
|
}
|
|
290
385
|
//# sourceMappingURL=auth-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/client/auth-client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAA8B,MAAM,OAAO,CAAC;AAC5G,OAAO,EAAE,aAAa,EAA8C,MAAM,UAAU,CAAC;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/client/auth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,17 @@ exports.AuthClient = void 0;
|
|
|
14
14
|
const axios_1 = __importDefault(require("axios"));
|
|
15
15
|
const api_1 = require("./api");
|
|
16
16
|
const token_utils_1 = require("../utils/token-utils");
|
|
17
|
+
const logger_1 = require("../utils/logger");
|
|
18
|
+
// Constants - Default values
|
|
19
|
+
const DEFAULT_INACTIVITY_TIMEOUT_SECONDS = 30 * 60; // 30 minutes
|
|
20
|
+
const DEFAULT_WARNING_SECONDS = 5 * 60; // 5 minutes
|
|
21
|
+
const DEFAULT_SESSION_CHECK_INTERVAL_SECONDS = 30; // 30 seconds
|
|
22
|
+
// Internal constants - Rate limiting (ไม่ควรให้ customize)
|
|
23
|
+
const REFRESH_COOLDOWN_MS = 30 * 1000; // 30 seconds - rate limiting for refresh
|
|
24
|
+
const WARNING_COOLDOWN_MS = 60 * 1000; // 1 minute - rate limiting for warnings
|
|
25
|
+
// Internal constants - Performance tuning (สามารถ customize ได้ผ่าน advanced config)
|
|
26
|
+
const DEFAULT_ACTIVITY_THROTTLE_MS = 1000; // 1 second - throttle activity handler
|
|
27
|
+
const DEFAULT_REFRESH_TIMEOUT_MS = 5000; // 5 seconds - refresh timeout
|
|
17
28
|
class AuthClient {
|
|
18
29
|
constructor(config) {
|
|
19
30
|
this.token = null;
|
|
@@ -25,21 +36,38 @@ class AuthClient {
|
|
|
25
36
|
this.automaticRefreshEnabled = null;
|
|
26
37
|
this.lastRefreshAttempt = 0;
|
|
27
38
|
this.refreshPromise = null;
|
|
28
|
-
this.REFRESH_COOLDOWN_MS = 30 * 1000; // 30 seconds cooldown
|
|
29
39
|
// Session expiration monitoring
|
|
30
40
|
this.sessionExpirationCallbacks = null;
|
|
31
41
|
this.sessionManagementConfig = null;
|
|
32
42
|
this.sessionManagementConfigPromise = null;
|
|
33
43
|
this.sessionExpirationCheckInterval = null;
|
|
34
|
-
this.sessionExpirationCheckIntervalSeconds =
|
|
44
|
+
this.sessionExpirationCheckIntervalSeconds = DEFAULT_SESSION_CHECK_INTERVAL_SECONDS;
|
|
35
45
|
this.lastWarningTime = 0;
|
|
36
|
-
|
|
46
|
+
// Inactivity detection
|
|
47
|
+
this.inactivityCallbacks = null;
|
|
48
|
+
this.inactivityTimeout = null;
|
|
49
|
+
this.inactivityWarningTimeout = null;
|
|
50
|
+
this.lastActivityTime = 0;
|
|
51
|
+
this.inactivityDetectionEnabled = false;
|
|
52
|
+
this.inactivityTimeoutSeconds = 0;
|
|
53
|
+
this.inactivityWarningSeconds = 0;
|
|
54
|
+
this.activityEvents = [];
|
|
55
|
+
this.activityHandler = null;
|
|
56
|
+
this.activityThrottleTimeout = null;
|
|
57
|
+
this.activityThrottleMs = DEFAULT_ACTIVITY_THROTTLE_MS;
|
|
58
|
+
this.refreshTimeoutMs = DEFAULT_REFRESH_TIMEOUT_MS;
|
|
37
59
|
this.apiKey = config.apiKey;
|
|
38
60
|
this.apiKeyHeader = config.apiKeyHeader || 'X-API-Key';
|
|
39
|
-
|
|
61
|
+
// Apply advanced config if provided
|
|
62
|
+
if (config.advanced) {
|
|
63
|
+
this.activityThrottleMs = config.advanced.activityThrottleMs ?? DEFAULT_ACTIVITY_THROTTLE_MS;
|
|
64
|
+
this.refreshTimeoutMs = config.advanced.refreshTimeoutMs ?? DEFAULT_REFRESH_TIMEOUT_MS;
|
|
65
|
+
}
|
|
66
|
+
logger_1.logger.debug('Initializing with config:', {
|
|
40
67
|
baseURL: config.baseURL,
|
|
41
68
|
timeout: config.timeout,
|
|
42
69
|
apiKeyHeader: this.apiKeyHeader,
|
|
70
|
+
advanced: config.advanced,
|
|
43
71
|
});
|
|
44
72
|
this.client = axios_1.default.create({
|
|
45
73
|
baseURL: config.baseURL,
|
|
@@ -67,29 +95,28 @@ class AuthClient {
|
|
|
67
95
|
const isCritical = remainingMinutes !== null && remainingMinutes <= 1;
|
|
68
96
|
const now = Date.now();
|
|
69
97
|
const timeSinceLastRefresh = now - this.lastRefreshAttempt;
|
|
70
|
-
if (timeSinceLastRefresh >= this.
|
|
71
|
-
|
|
72
|
-
console.log(`[AuthClient] Token near expiration (${remainingMinutes} min remaining), refreshing...`);
|
|
98
|
+
if (timeSinceLastRefresh >= REFRESH_COOLDOWN_MS && !this.refreshPromise) {
|
|
99
|
+
logger_1.logger.debug(`Token near expiration (${remainingMinutes} min remaining), refreshing...`);
|
|
73
100
|
this.lastRefreshAttempt = now;
|
|
74
101
|
if (isCritical) {
|
|
75
102
|
// Critical: await refresh
|
|
76
103
|
try {
|
|
77
104
|
const newToken = await Promise.race([
|
|
78
105
|
this.performRefresh(),
|
|
79
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Refresh timeout')),
|
|
106
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Refresh timeout')), this.refreshTimeoutMs)),
|
|
80
107
|
]);
|
|
81
108
|
this.token = newToken;
|
|
82
109
|
requestConfig.headers['Authorization'] = `Bearer ${newToken}`;
|
|
83
|
-
|
|
110
|
+
logger_1.logger.info('Token refreshed successfully (critical)');
|
|
84
111
|
}
|
|
85
112
|
catch (error) {
|
|
86
|
-
|
|
113
|
+
logger_1.logger.error('Critical token refresh failed:', error);
|
|
87
114
|
}
|
|
88
115
|
}
|
|
89
116
|
else {
|
|
90
117
|
// Background refresh
|
|
91
118
|
this.performRefresh().catch((error) => {
|
|
92
|
-
|
|
119
|
+
logger_1.logger.error('Background token refresh failed:', error);
|
|
93
120
|
});
|
|
94
121
|
}
|
|
95
122
|
}
|
|
@@ -107,7 +134,7 @@ class AuthClient {
|
|
|
107
134
|
// Handle 401 errors - try refresh token before failing
|
|
108
135
|
if (error.response?.status === 401 && originalRequest && this.refreshTokenCallbacks) {
|
|
109
136
|
if (originalRequest._retry) {
|
|
110
|
-
|
|
137
|
+
logger_1.logger.warn('401 Unauthorized after retry - refresh failed');
|
|
111
138
|
if (this.refreshTokenCallbacks.onRefreshFailure) {
|
|
112
139
|
await this.refreshTokenCallbacks.onRefreshFailure();
|
|
113
140
|
}
|
|
@@ -115,7 +142,7 @@ class AuthClient {
|
|
|
115
142
|
}
|
|
116
143
|
// Skip refresh for refresh endpoint itself
|
|
117
144
|
if (originalRequest.url?.includes('/auth/refresh') || originalRequest.url?.includes('/auth/refresh-token')) {
|
|
118
|
-
|
|
145
|
+
logger_1.logger.error('Refresh endpoint failed - session expired');
|
|
119
146
|
if (this.refreshTokenCallbacks.onRefreshFailure) {
|
|
120
147
|
await this.refreshTokenCallbacks.onRefreshFailure();
|
|
121
148
|
}
|
|
@@ -124,15 +151,15 @@ class AuthClient {
|
|
|
124
151
|
// Try to refresh token
|
|
125
152
|
try {
|
|
126
153
|
originalRequest._retry = true;
|
|
127
|
-
|
|
154
|
+
logger_1.logger.debug('401 detected, attempting token refresh...');
|
|
128
155
|
const newToken = await this.performRefresh();
|
|
129
156
|
originalRequest.headers = originalRequest.headers || {};
|
|
130
157
|
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
|
131
|
-
|
|
158
|
+
logger_1.logger.debug('Token refreshed, retrying original request...');
|
|
132
159
|
return this.client(originalRequest);
|
|
133
160
|
}
|
|
134
161
|
catch (refreshError) {
|
|
135
|
-
|
|
162
|
+
logger_1.logger.error('Token refresh failed:', refreshError);
|
|
136
163
|
if (this.refreshTokenCallbacks.onRefreshFailure) {
|
|
137
164
|
await this.refreshTokenCallbacks.onRefreshFailure();
|
|
138
165
|
}
|
|
@@ -141,10 +168,10 @@ class AuthClient {
|
|
|
141
168
|
}
|
|
142
169
|
// Handle other errors
|
|
143
170
|
if (error.response?.status === 401) {
|
|
144
|
-
|
|
171
|
+
logger_1.logger.error('API Key authentication failed');
|
|
145
172
|
}
|
|
146
173
|
else if (error.response?.status === 429) {
|
|
147
|
-
|
|
174
|
+
logger_1.logger.error('Rate limit exceeded');
|
|
148
175
|
}
|
|
149
176
|
return Promise.reject(error);
|
|
150
177
|
});
|
|
@@ -170,7 +197,7 @@ class AuthClient {
|
|
|
170
197
|
* ```
|
|
171
198
|
*/
|
|
172
199
|
initializeOAuth(config) {
|
|
173
|
-
|
|
200
|
+
logger_1.logger.debug('Initializing OAuth with:', {
|
|
174
201
|
clientId: config.clientId,
|
|
175
202
|
redirectUri: config.redirectUri,
|
|
176
203
|
scope: config.scope,
|
|
@@ -244,7 +271,7 @@ class AuthClient {
|
|
|
244
271
|
setToken(token, type = 'jwt') {
|
|
245
272
|
this.token = token;
|
|
246
273
|
this.authType = type;
|
|
247
|
-
|
|
274
|
+
logger_1.logger.debug(`Token set with type: ${type}`);
|
|
248
275
|
// Reset warning time when token changes
|
|
249
276
|
this.lastWarningTime = 0;
|
|
250
277
|
// If session expiration monitoring is enabled, check immediately
|
|
@@ -265,7 +292,7 @@ class AuthClient {
|
|
|
265
292
|
*/
|
|
266
293
|
setAuthType(type) {
|
|
267
294
|
this.authType = type;
|
|
268
|
-
|
|
295
|
+
logger_1.logger.debug(`Auth type changed to: ${type}`);
|
|
269
296
|
}
|
|
270
297
|
/**
|
|
271
298
|
* Get current token (masked)
|
|
@@ -379,10 +406,10 @@ class AuthClient {
|
|
|
379
406
|
const config = await this.systemConfig.getSecurityJwtConfig();
|
|
380
407
|
this.refreshThresholdMinutes = config.refresh_threshold_minutes;
|
|
381
408
|
this.automaticRefreshEnabled = config.automatic_refresh ?? true;
|
|
382
|
-
|
|
409
|
+
logger_1.logger.debug(`JWT config loaded: refresh_threshold_minutes=${this.refreshThresholdMinutes} minutes, automatic_refresh=${this.automaticRefreshEnabled}`);
|
|
383
410
|
}
|
|
384
411
|
catch (error) {
|
|
385
|
-
|
|
412
|
+
logger_1.logger.error('Failed to load JWT config:', error);
|
|
386
413
|
// Reset to allow retry
|
|
387
414
|
this.jwtConfigPromise = null;
|
|
388
415
|
throw error;
|
|
@@ -429,7 +456,7 @@ class AuthClient {
|
|
|
429
456
|
if (session.refresh_token) {
|
|
430
457
|
await this.refreshTokenCallbacks.setRefreshToken(session.refresh_token);
|
|
431
458
|
}
|
|
432
|
-
|
|
459
|
+
logger_1.logger.debug('Token refreshed successfully');
|
|
433
460
|
return newAccessToken;
|
|
434
461
|
}
|
|
435
462
|
catch (error) {
|
|
@@ -442,11 +469,11 @@ class AuthClient {
|
|
|
442
469
|
if (tokens.refresh_token) {
|
|
443
470
|
await this.refreshTokenCallbacks.setRefreshToken(tokens.refresh_token);
|
|
444
471
|
}
|
|
445
|
-
|
|
472
|
+
logger_1.logger.debug('Token refreshed successfully (fallback)');
|
|
446
473
|
return newAccessToken;
|
|
447
474
|
}
|
|
448
475
|
catch (fallbackError) {
|
|
449
|
-
|
|
476
|
+
logger_1.logger.error('Fallback refresh also failed:', fallbackError);
|
|
450
477
|
throw fallbackError;
|
|
451
478
|
}
|
|
452
479
|
}
|
|
@@ -487,7 +514,7 @@ class AuthClient {
|
|
|
487
514
|
*/
|
|
488
515
|
async enableSessionExpirationMonitoring(options) {
|
|
489
516
|
this.sessionExpirationCallbacks = options.callbacks;
|
|
490
|
-
this.sessionExpirationCheckIntervalSeconds = options.checkIntervalSeconds ??
|
|
517
|
+
this.sessionExpirationCheckIntervalSeconds = options.checkIntervalSeconds ?? DEFAULT_SESSION_CHECK_INTERVAL_SECONDS;
|
|
491
518
|
// Load session management config
|
|
492
519
|
await this.loadSessionManagementConfig();
|
|
493
520
|
// Start monitoring
|
|
@@ -519,7 +546,7 @@ class AuthClient {
|
|
|
519
546
|
try {
|
|
520
547
|
const config = await this.systemConfig.getSessionManagement();
|
|
521
548
|
this.sessionManagementConfig = config;
|
|
522
|
-
|
|
549
|
+
logger_1.logger.debug('Session management config loaded:', {
|
|
523
550
|
inactivityEnabled: config.inactivity.enabled,
|
|
524
551
|
inactivityTimeout: `${config.inactivity.timeout_duration} ${config.inactivity.timeout_unit}`,
|
|
525
552
|
inactivityWarningMinutes: config.inactivity.warning_minutes,
|
|
@@ -528,7 +555,7 @@ class AuthClient {
|
|
|
528
555
|
});
|
|
529
556
|
}
|
|
530
557
|
catch (error) {
|
|
531
|
-
|
|
558
|
+
logger_1.logger.error('Failed to load session management config:', error);
|
|
532
559
|
// Reset to allow retry
|
|
533
560
|
this.sessionManagementConfigPromise = null;
|
|
534
561
|
throw error;
|
|
@@ -628,7 +655,7 @@ class AuthClient {
|
|
|
628
655
|
// Check cooldown to avoid spam
|
|
629
656
|
const now = Date.now();
|
|
630
657
|
const timeSinceLastWarning = now - this.lastWarningTime;
|
|
631
|
-
if (timeSinceLastWarning >=
|
|
658
|
+
if (timeSinceLastWarning >= WARNING_COOLDOWN_MS) {
|
|
632
659
|
this.lastWarningTime = now;
|
|
633
660
|
this.sessionExpirationCallbacks.onSessionExpiring(remainingMinutes, expirationType);
|
|
634
661
|
}
|
|
@@ -641,5 +668,224 @@ class AuthClient {
|
|
|
641
668
|
this.sessionManagementConfig = null;
|
|
642
669
|
await this.loadSessionManagementConfig();
|
|
643
670
|
}
|
|
671
|
+
/**
|
|
672
|
+
* Enable inactivity detection
|
|
673
|
+
* จับ user activity (mouse/keyboard/touch/scroll) และ trigger callback เมื่อ inactivity timeout
|
|
674
|
+
*
|
|
675
|
+
* @param options - Options for inactivity detection
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```typescript
|
|
679
|
+
* await authClient.enableInactivityDetection({
|
|
680
|
+
* callbacks: {
|
|
681
|
+
* onInactivityWarning: (remainingSeconds) => {
|
|
682
|
+
* console.log(`Inactivity warning: ${remainingSeconds} seconds remaining`);
|
|
683
|
+
* // แสดง notification หรือ dialog
|
|
684
|
+
* },
|
|
685
|
+
* onInactivityTimeout: () => {
|
|
686
|
+
* console.log('Inactivity timeout');
|
|
687
|
+
* // Redirect to login หรือ logout
|
|
688
|
+
* authClient.clearToken();
|
|
689
|
+
* window.location.href = '/login';
|
|
690
|
+
* }
|
|
691
|
+
* },
|
|
692
|
+
* timeoutSeconds: 1800, // 30 minutes (optional, default: จาก session management config)
|
|
693
|
+
* warningSeconds: 300, // 5 minutes warning (optional, default: จาก session management config)
|
|
694
|
+
* events: ['mousemove', 'keydown', 'touchstart', 'scroll'] // (optional, default: ทั้งหมด)
|
|
695
|
+
* });
|
|
696
|
+
* ```
|
|
697
|
+
*/
|
|
698
|
+
async enableInactivityDetection(options) {
|
|
699
|
+
// Disable existing detection if any
|
|
700
|
+
this.disableInactivityDetection();
|
|
701
|
+
this.inactivityCallbacks = options.callbacks;
|
|
702
|
+
// Load session management config if not loaded
|
|
703
|
+
if (!this.sessionManagementConfig) {
|
|
704
|
+
await this.loadSessionManagementConfig();
|
|
705
|
+
}
|
|
706
|
+
// Determine timeout and warning seconds
|
|
707
|
+
if (options.timeoutSeconds !== undefined) {
|
|
708
|
+
this.inactivityTimeoutSeconds = options.timeoutSeconds;
|
|
709
|
+
}
|
|
710
|
+
else if (this.sessionManagementConfig?.inactivity.enabled) {
|
|
711
|
+
// Use session management config
|
|
712
|
+
this.inactivityTimeoutSeconds =
|
|
713
|
+
(0, token_utils_1.convertDurationToMinutes)(this.sessionManagementConfig.inactivity.timeout_duration, this.sessionManagementConfig.inactivity.timeout_unit) * 60; // Convert to seconds
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
// Default: 30 minutes
|
|
717
|
+
this.inactivityTimeoutSeconds = DEFAULT_INACTIVITY_TIMEOUT_SECONDS;
|
|
718
|
+
}
|
|
719
|
+
if (options.warningSeconds !== undefined) {
|
|
720
|
+
this.inactivityWarningSeconds = options.warningSeconds;
|
|
721
|
+
}
|
|
722
|
+
else if (this.sessionManagementConfig?.inactivity.warning_minutes) {
|
|
723
|
+
// Use session management config (convert minutes to seconds)
|
|
724
|
+
this.inactivityWarningSeconds = this.sessionManagementConfig.inactivity.warning_minutes * 60;
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
// Default: 5 minutes
|
|
728
|
+
this.inactivityWarningSeconds = DEFAULT_WARNING_SECONDS;
|
|
729
|
+
}
|
|
730
|
+
// Determine events to listen
|
|
731
|
+
this.activityEvents = options.events || ['mousemove', 'keydown', 'touchstart', 'scroll'];
|
|
732
|
+
// Initialize last activity time
|
|
733
|
+
this.lastActivityTime = Date.now();
|
|
734
|
+
// Enable detection
|
|
735
|
+
this.inactivityDetectionEnabled = true;
|
|
736
|
+
// Setup event listeners
|
|
737
|
+
this.setupActivityListeners();
|
|
738
|
+
// Start timer
|
|
739
|
+
this.resetInactivityTimer();
|
|
740
|
+
logger_1.logger.debug('Inactivity detection enabled:', {
|
|
741
|
+
timeoutSeconds: this.inactivityTimeoutSeconds,
|
|
742
|
+
warningSeconds: this.inactivityWarningSeconds,
|
|
743
|
+
events: this.activityEvents,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Disable inactivity detection
|
|
748
|
+
*/
|
|
749
|
+
disableInactivityDetection() {
|
|
750
|
+
this.inactivityDetectionEnabled = false;
|
|
751
|
+
// Clear throttle timeout
|
|
752
|
+
if (this.activityThrottleTimeout) {
|
|
753
|
+
clearTimeout(this.activityThrottleTimeout);
|
|
754
|
+
this.activityThrottleTimeout = null;
|
|
755
|
+
}
|
|
756
|
+
// Clear timeouts
|
|
757
|
+
this.clearInactivityTimeouts();
|
|
758
|
+
// Remove event listeners
|
|
759
|
+
this.removeActivityListeners();
|
|
760
|
+
// Reset state
|
|
761
|
+
this.inactivityCallbacks = null;
|
|
762
|
+
this.lastActivityTime = 0;
|
|
763
|
+
this.inactivityTimeoutSeconds = 0;
|
|
764
|
+
this.inactivityWarningSeconds = 0;
|
|
765
|
+
this.activityEvents = [];
|
|
766
|
+
logger_1.logger.debug('Inactivity detection disabled');
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Handle user activity - reset inactivity timer with throttle
|
|
770
|
+
*/
|
|
771
|
+
handleUserActivity() {
|
|
772
|
+
if (!this.inactivityDetectionEnabled) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
// Throttle: reset timer สูงสุดทุก 1 วินาที เพื่อลด CPU usage
|
|
776
|
+
if (this.activityThrottleTimeout) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
this.lastActivityTime = Date.now();
|
|
780
|
+
this.resetInactivityTimer();
|
|
781
|
+
this.activityThrottleTimeout = setTimeout(() => {
|
|
782
|
+
this.activityThrottleTimeout = null;
|
|
783
|
+
}, this.activityThrottleMs);
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Setup activity event listeners
|
|
787
|
+
*/
|
|
788
|
+
setupActivityListeners() {
|
|
789
|
+
if (typeof window === 'undefined') {
|
|
790
|
+
logger_1.logger.warn('Cannot setup activity listeners: window is undefined (SSR)');
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
// Remove existing listeners if any
|
|
794
|
+
this.removeActivityListeners();
|
|
795
|
+
// Create handler
|
|
796
|
+
const handler = () => {
|
|
797
|
+
this.handleUserActivity();
|
|
798
|
+
};
|
|
799
|
+
this.activityHandler = handler;
|
|
800
|
+
// Setup listeners for each event type
|
|
801
|
+
this.activityEvents.forEach((eventType) => {
|
|
802
|
+
window.addEventListener(eventType, handler, { passive: true });
|
|
803
|
+
});
|
|
804
|
+
logger_1.logger.debug('Activity listeners setup:', this.activityEvents);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Remove activity event listeners
|
|
808
|
+
*/
|
|
809
|
+
removeActivityListeners() {
|
|
810
|
+
if (typeof window === 'undefined' || !this.activityHandler) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
const handler = this.activityHandler;
|
|
814
|
+
this.activityEvents.forEach((eventType) => {
|
|
815
|
+
window.removeEventListener(eventType, handler);
|
|
816
|
+
});
|
|
817
|
+
this.activityHandler = null;
|
|
818
|
+
logger_1.logger.debug('Activity listeners removed');
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Clear inactivity timeouts (helper method)
|
|
822
|
+
*/
|
|
823
|
+
clearInactivityTimeouts() {
|
|
824
|
+
if (this.inactivityWarningTimeout) {
|
|
825
|
+
clearTimeout(this.inactivityWarningTimeout);
|
|
826
|
+
this.inactivityWarningTimeout = null;
|
|
827
|
+
}
|
|
828
|
+
if (this.inactivityTimeout) {
|
|
829
|
+
clearTimeout(this.inactivityTimeout);
|
|
830
|
+
this.inactivityTimeout = null;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Reset inactivity timer
|
|
835
|
+
*/
|
|
836
|
+
resetInactivityTimer() {
|
|
837
|
+
// Clear existing timeouts
|
|
838
|
+
this.clearInactivityTimeouts();
|
|
839
|
+
if (!this.inactivityDetectionEnabled || !this.inactivityCallbacks) {
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
const now = Date.now();
|
|
843
|
+
this.lastActivityTime = now;
|
|
844
|
+
// Setup warning timeout
|
|
845
|
+
if (this.inactivityWarningSeconds > 0 && this.inactivityCallbacks.onInactivityWarning) {
|
|
846
|
+
const warningTime = this.inactivityTimeoutSeconds - this.inactivityWarningSeconds;
|
|
847
|
+
if (warningTime > 0) {
|
|
848
|
+
const timerStartTime = now; // Capture start time for this timer
|
|
849
|
+
this.inactivityWarningTimeout = setTimeout(() => {
|
|
850
|
+
// Calculate remaining seconds based on when timer was set
|
|
851
|
+
const elapsedSeconds = (Date.now() - timerStartTime) / 1000;
|
|
852
|
+
const remainingSeconds = this.inactivityTimeoutSeconds - elapsedSeconds;
|
|
853
|
+
if (this.inactivityCallbacks?.onInactivityWarning && remainingSeconds > 0) {
|
|
854
|
+
this.inactivityCallbacks.onInactivityWarning(Math.floor(remainingSeconds));
|
|
855
|
+
}
|
|
856
|
+
}, warningTime * 1000);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
// Setup timeout
|
|
860
|
+
this.inactivityTimeout = setTimeout(() => {
|
|
861
|
+
if (this.inactivityCallbacks?.onInactivityTimeout) {
|
|
862
|
+
this.inactivityCallbacks.onInactivityTimeout();
|
|
863
|
+
}
|
|
864
|
+
}, this.inactivityTimeoutSeconds * 1000);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Check inactivity timeout and trigger callbacks if needed
|
|
868
|
+
*/
|
|
869
|
+
checkInactivityTimeout() {
|
|
870
|
+
if (!this.inactivityDetectionEnabled || !this.inactivityCallbacks) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
const now = Date.now();
|
|
874
|
+
const inactiveSeconds = (now - this.lastActivityTime) / 1000;
|
|
875
|
+
// Check if timeout reached
|
|
876
|
+
if (inactiveSeconds >= this.inactivityTimeoutSeconds) {
|
|
877
|
+
if (this.inactivityCallbacks.onInactivityTimeout) {
|
|
878
|
+
this.inactivityCallbacks.onInactivityTimeout();
|
|
879
|
+
}
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
// Check if warning should be triggered
|
|
883
|
+
const remainingSeconds = this.inactivityTimeoutSeconds - inactiveSeconds;
|
|
884
|
+
if (remainingSeconds <= this.inactivityWarningSeconds &&
|
|
885
|
+
remainingSeconds > 0 &&
|
|
886
|
+
this.inactivityCallbacks.onInactivityWarning) {
|
|
887
|
+
this.inactivityCallbacks.onInactivityWarning(Math.floor(remainingSeconds));
|
|
888
|
+
}
|
|
889
|
+
}
|
|
644
890
|
}
|
|
645
891
|
exports.AuthClient = AuthClient;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Client exports for frontend applications
|
|
3
3
|
*/
|
|
4
4
|
export { AuthClient } from './auth-client';
|
|
5
|
-
export type { RefreshTokenCallbacks, AutomaticRefreshOptions, SessionExpirationCallbacks, SessionExpirationOptions, } from './auth-client';
|
|
5
|
+
export type { RefreshTokenCallbacks, AutomaticRefreshOptions, SessionExpirationCallbacks, SessionExpirationOptions, InactivityCallbacks, InactivityDetectionOptions, } from './auth-client';
|
|
6
6
|
export * from './api';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AACvB,cAAc,OAAO,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,SAAS,CAAC;AAGxB,cAAc,UAAU,CAAC;AAGzB,cAAc,cAAc,CAAC;AAG7B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,SAAS,CAAC;AAGxB,cAAc,UAAU,CAAC;AAGzB,cAAc,cAAc,CAAC;AAG7B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
20
20
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.logger = void 0;
|
|
23
24
|
// Types
|
|
24
25
|
__exportStar(require("./types"), exports);
|
|
25
26
|
// Client (Frontend & Backend)
|
|
@@ -28,3 +29,5 @@ __exportStar(require("./client"), exports);
|
|
|
28
29
|
__exportStar(require("./middleware"), exports);
|
|
29
30
|
// Utils
|
|
30
31
|
__exportStar(require("./utils/token-utils"), exports);
|
|
32
|
+
var logger_1 = require("./utils/logger");
|
|
33
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
|
package/dist/types/index.d.ts
CHANGED
|
@@ -67,6 +67,24 @@ export interface AuthSdkConfig {
|
|
|
67
67
|
baseURL?: string;
|
|
68
68
|
apiKeyHeader?: string;
|
|
69
69
|
timeout?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Advanced configuration options
|
|
72
|
+
* สำหรับปรับแต่ง internal behavior ของ SDK
|
|
73
|
+
*/
|
|
74
|
+
advanced?: {
|
|
75
|
+
/**
|
|
76
|
+
* Activity throttle time (milliseconds)
|
|
77
|
+
* ระยะเวลาที่ throttle activity handler เพื่อลด CPU usage
|
|
78
|
+
* Default: 1000ms (1 second)
|
|
79
|
+
*/
|
|
80
|
+
activityThrottleMs?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Refresh token timeout (milliseconds)
|
|
83
|
+
* ระยะเวลาที่รอ refresh token request ก่อน timeout
|
|
84
|
+
* Default: 5000ms (5 seconds)
|
|
85
|
+
*/
|
|
86
|
+
refreshTimeoutMs?: number;
|
|
87
|
+
};
|
|
70
88
|
}
|
|
71
89
|
/**
|
|
72
90
|
* NestJS Module Configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IAGf,iBAAiB,EAAE,OAAO,CAAC;IAG3B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAGxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC;IAGtD,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,IAAI,CAAC;IAGlB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IAGf,iBAAiB,EAAE,OAAO,CAAC;IAG3B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAGxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC;IAGtD,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,IAAI,CAAC;IAGlB,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT;;;;WAIG;QACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B;;;;WAIG;QACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAGD,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC;AAG7B,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Utility
|
|
3
|
+
*
|
|
4
|
+
* @description Centralized logging utility for Auth SDK
|
|
5
|
+
* Supports different log levels and environment-based filtering
|
|
6
|
+
*/
|
|
7
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
|
+
interface LoggerConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
logLevel: LogLevel;
|
|
11
|
+
}
|
|
12
|
+
declare class Logger {
|
|
13
|
+
private config;
|
|
14
|
+
private shouldLog;
|
|
15
|
+
debug(...args: any[]): void;
|
|
16
|
+
info(...args: any[]): void;
|
|
17
|
+
warn(...args: any[]): void;
|
|
18
|
+
error(...args: any[]): void;
|
|
19
|
+
setConfig(config: Partial<LoggerConfig>): void;
|
|
20
|
+
}
|
|
21
|
+
export declare const logger: Logger;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,cAAM,MAAM;IACV,OAAO,CAAC,MAAM,CAGZ;IAEF,OAAO,CAAC,SAAS;IAUjB,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3B,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM1B,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM1B,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3B,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;CAG/C;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Logger Utility
|
|
4
|
+
*
|
|
5
|
+
* @description Centralized logging utility for Auth SDK
|
|
6
|
+
* Supports different log levels and environment-based filtering
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.logger = void 0;
|
|
10
|
+
class Logger {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.config = {
|
|
13
|
+
enabled: true,
|
|
14
|
+
logLevel: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
shouldLog(level) {
|
|
18
|
+
if (!this.config.enabled)
|
|
19
|
+
return false;
|
|
20
|
+
const levels = ['debug', 'info', 'warn', 'error'];
|
|
21
|
+
const currentLevelIndex = levels.indexOf(this.config.logLevel);
|
|
22
|
+
const messageLevelIndex = levels.indexOf(level);
|
|
23
|
+
return messageLevelIndex >= currentLevelIndex;
|
|
24
|
+
}
|
|
25
|
+
debug(...args) {
|
|
26
|
+
if (this.shouldLog('debug')) {
|
|
27
|
+
console.log('[AuthClient]', ...args);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
info(...args) {
|
|
31
|
+
if (this.shouldLog('info')) {
|
|
32
|
+
console.log('[AuthClient]', ...args);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
warn(...args) {
|
|
36
|
+
if (this.shouldLog('warn')) {
|
|
37
|
+
console.warn('[AuthClient]', ...args);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
error(...args) {
|
|
41
|
+
if (this.shouldLog('error')) {
|
|
42
|
+
console.error('[AuthClient]', ...args);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
setConfig(config) {
|
|
46
|
+
this.config = { ...this.config, ...config };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.logger = new Logger();
|