win-portal-auth-sdk 1.6.1 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/api/system-config.api.d.ts +4 -13
- package/dist/client/api/system-config.api.d.ts.map +1 -1
- package/dist/client/api/system-config.api.js +7 -21
- package/dist/client/auth-client.d.ts +44 -18
- package/dist/client/auth-client.d.ts.map +1 -1
- package/dist/client/auth-client.js +82 -19
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/session-socket.d.ts +89 -0
- package/dist/client/session-socket.d.ts.map +1 -0
- package/dist/client/session-socket.js +195 -0
- package/dist/middleware/express.middleware.d.ts +18 -5
- package/dist/middleware/express.middleware.d.ts.map +1 -1
- package/dist/middleware/express.middleware.js +18 -5
- package/dist/middleware/nestjs.guard.d.ts +30 -6
- package/dist/middleware/nestjs.guard.d.ts.map +1 -1
- package/dist/middleware/nestjs.guard.js +30 -6
- package/dist/types/webhook.types.d.ts +3 -1
- package/dist/types/webhook.types.d.ts.map +1 -1
- package/package.json +9 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { SessionManagementConfig, SystemConfig, SystemConfigByCategory } from '../../types';
|
|
1
2
|
import { AuthClient } from '../auth-client';
|
|
2
|
-
import { SystemConfig, SystemConfigByCategory, SecurityJwtConfig, SessionManagementConfig } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* System Config API
|
|
5
5
|
* Methods for retrieving system configurations
|
|
@@ -12,22 +12,13 @@ export declare class SystemConfigAPI {
|
|
|
12
12
|
* GET /system-configs/categories/:category
|
|
13
13
|
* ดึง configs ตาม category - ส่ง object ที่รวมทุก key เป็น { key1: value1, key2: value2 }
|
|
14
14
|
*/
|
|
15
|
-
getByCategory
|
|
15
|
+
private getByCategory;
|
|
16
16
|
/**
|
|
17
17
|
* GET /system-configs/categories/:category/:key
|
|
18
18
|
* ดึง config ตาม category และ key - ส่ง full metadata row
|
|
19
19
|
*/
|
|
20
|
-
getByCategoryAndKey
|
|
21
|
-
|
|
22
|
-
* GET /system-configs/categories/security
|
|
23
|
-
* ดึง security configs ทั้งหมด (convenience method)
|
|
24
|
-
*/
|
|
25
|
-
security(): Promise<SystemConfigByCategory>;
|
|
26
|
-
/**
|
|
27
|
-
* GET /system-configs/categories/security/jwt
|
|
28
|
-
* ดึง JWT configuration (convenience method)
|
|
29
|
-
*/
|
|
30
|
-
getSecurityJwtConfig(): Promise<SecurityJwtConfig>;
|
|
20
|
+
private getByCategoryAndKey;
|
|
21
|
+
get(category: string, key?: string): Promise<SystemConfig | SystemConfigByCategory>;
|
|
31
22
|
/**
|
|
32
23
|
* GET /system-configs/categories/security/session-management
|
|
33
24
|
* ดึง Session Management configuration (convenience method)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-config.api.d.ts","sourceRoot":"","sources":["../../../src/client/api/system-config.api.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"system-config.api.d.ts","sourceRoot":"","sources":["../../../src/client/api/system-config.api.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,uBAAuB,EACvB,YAAY,EACZ,sBAAsB,EACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;GAIG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAEtC;;;OAGG;YACW,aAAa;IAO3B;;;OAGG;YACW,mBAAmB;IAK3B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,sBAAsB,CAAC;IAOzF;;;OAGG;IACG,oBAAoB,IAAI,OAAO,CAAC,uBAAuB,CAAC;CAI/D"}
|
|
@@ -26,33 +26,19 @@ class SystemConfigAPI {
|
|
|
26
26
|
const response = await this.client.get(`/system-configs/categories/${category}/${key}`);
|
|
27
27
|
return response.data.data;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return this.getByCategory('security');
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* GET /system-configs/categories/security/jwt
|
|
38
|
-
* ดึง JWT configuration (convenience method)
|
|
39
|
-
*/
|
|
40
|
-
async getSecurityJwtConfig() {
|
|
41
|
-
const config = await this.getByCategoryAndKey('security', 'jwt');
|
|
42
|
-
return config.value;
|
|
29
|
+
async get(category, key) {
|
|
30
|
+
if (key) {
|
|
31
|
+
return await this.getByCategoryAndKey(category, key);
|
|
32
|
+
}
|
|
33
|
+
return await this.getByCategory(category);
|
|
43
34
|
}
|
|
44
35
|
/**
|
|
45
36
|
* GET /system-configs/categories/security/session-management
|
|
46
37
|
* ดึง Session Management configuration (convenience method)
|
|
47
38
|
*/
|
|
48
39
|
async getSessionManagement() {
|
|
49
|
-
const securityConfigs = await this.security
|
|
50
|
-
|
|
51
|
-
const sessionManagement = securityConfigs['session_management'] || securityConfigs['session-management'];
|
|
52
|
-
if (!sessionManagement) {
|
|
53
|
-
throw new Error('Session management configuration not found');
|
|
54
|
-
}
|
|
55
|
-
return sessionManagement;
|
|
40
|
+
const securityConfigs = await this.get('security', 'session_management');
|
|
41
|
+
return securityConfigs.value;
|
|
56
42
|
}
|
|
57
43
|
}
|
|
58
44
|
exports.SystemConfigAPI = SystemConfigAPI;
|
|
@@ -128,6 +128,9 @@ export declare class AuthClient {
|
|
|
128
128
|
private activityThrottleTimeout;
|
|
129
129
|
private activityThrottleMs;
|
|
130
130
|
private refreshTimeoutMs;
|
|
131
|
+
private lastActivityRefreshTime;
|
|
132
|
+
private ACTIVITY_REFRESH_INTERVAL_MS;
|
|
133
|
+
private sessionSocket;
|
|
131
134
|
readonly auth: AuthAPI;
|
|
132
135
|
readonly health: HealthAPI;
|
|
133
136
|
readonly systemConfig: SystemConfigAPI;
|
|
@@ -188,22 +191,32 @@ export declare class AuthClient {
|
|
|
188
191
|
/**
|
|
189
192
|
* Set JWT token for authenticated requests
|
|
190
193
|
*
|
|
194
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
195
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ใช้ `createAuthGuard()` หรือ `authMiddleware()` แทน (ไม่ต้อง setToken)
|
|
196
|
+
*
|
|
191
197
|
* @param token - JWT access token
|
|
192
198
|
* @param type - Token type: 'jwt' (default), 'oauth', or 'hybrid'
|
|
193
199
|
*
|
|
194
200
|
* @example
|
|
195
201
|
* ```typescript
|
|
196
|
-
* // JWT token from /auth/login
|
|
202
|
+
* // Frontend: JWT token from /auth/login
|
|
197
203
|
* authClient.setToken(session.token, 'jwt');
|
|
198
204
|
*
|
|
199
|
-
* // OAuth access token
|
|
205
|
+
* // Frontend: OAuth access token
|
|
200
206
|
* authClient.setToken(oauthToken, 'oauth');
|
|
201
207
|
*
|
|
202
|
-
* //
|
|
203
|
-
*
|
|
208
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
209
|
+
* // @UseGuards(AuthGuard)
|
|
204
210
|
* ```
|
|
205
211
|
*/
|
|
206
212
|
setToken(token: string, type?: 'jwt' | 'oauth' | 'hybrid'): void;
|
|
213
|
+
/**
|
|
214
|
+
* Update session socket token if real-time monitoring is enabled
|
|
215
|
+
*
|
|
216
|
+
* @private
|
|
217
|
+
* @param token - New JWT token to update
|
|
218
|
+
*/
|
|
219
|
+
private updateSessionSocketToken;
|
|
207
220
|
/**
|
|
208
221
|
* Get current token type
|
|
209
222
|
*/
|
|
@@ -228,33 +241,30 @@ export declare class AuthClient {
|
|
|
228
241
|
getAxiosInstance(): AxiosInstance;
|
|
229
242
|
/**
|
|
230
243
|
* Enable automatic token refresh
|
|
231
|
-
*
|
|
244
|
+
*
|
|
245
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
246
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ถือ token, Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป
|
|
247
|
+
*
|
|
248
|
+
* Call this after user is authenticated to enable automatic refresh.
|
|
249
|
+
* SDK จะ refresh token อัตโนมัติก่อนหมดอายุผ่าน axios interceptor.
|
|
232
250
|
*
|
|
233
251
|
* @param options - Options for automatic refresh (optional - SDK will use session-based refresh if not provided)
|
|
234
252
|
*
|
|
235
253
|
* @example
|
|
236
254
|
* ```typescript
|
|
237
|
-
* //
|
|
238
|
-
* // Works when login only returns access_token
|
|
255
|
+
* // Frontend: Session-based refresh (default - no refresh token needed)
|
|
239
256
|
* await authClient.enableAutomaticRefresh({
|
|
240
257
|
* onRefreshFailure: () => window.location.href = '/login'
|
|
241
258
|
* });
|
|
242
259
|
*
|
|
243
|
-
* //
|
|
260
|
+
* // Frontend: With refresh token (if login returns refresh_token)
|
|
244
261
|
* await authClient.enableAutomaticRefresh({
|
|
245
262
|
* refreshTokenKey: 'refresh_token',
|
|
246
263
|
* onRefreshFailure: () => window.location.href = '/login'
|
|
247
264
|
* });
|
|
248
265
|
*
|
|
249
|
-
* //
|
|
250
|
-
*
|
|
251
|
-
* callbacks: {
|
|
252
|
-
* getRefreshToken: () => customStorage.get('refresh_token'),
|
|
253
|
-
* setRefreshToken: (token) => customStorage.set('refresh_token', token),
|
|
254
|
-
* clearRefreshToken: () => customStorage.remove('refresh_token'),
|
|
255
|
-
* onRefreshFailure: () => window.location.href = '/login'
|
|
256
|
-
* }
|
|
257
|
-
* });
|
|
266
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
267
|
+
* // @UseGuards(AuthGuard) // Guard จะ validate token อัตโนมัติ
|
|
258
268
|
* ```
|
|
259
269
|
*/
|
|
260
270
|
enableAutomaticRefresh(options?: AutomaticRefreshOptions): Promise<void>;
|
|
@@ -285,12 +295,17 @@ export declare class AuthClient {
|
|
|
285
295
|
reloadJwtConfig(): Promise<void>;
|
|
286
296
|
/**
|
|
287
297
|
* Enable session expiration monitoring
|
|
298
|
+
*
|
|
299
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
300
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ track session expiration, Frontend เป็นคนจัดการ
|
|
301
|
+
*
|
|
288
302
|
* จะตรวจสอบ session expiration ตาม config จาก settings/sessions และเรียก callback เมื่อใกล้หมดอายุ
|
|
289
303
|
*
|
|
290
304
|
* @param options - Options for session expiration monitoring
|
|
291
305
|
*
|
|
292
306
|
* @example
|
|
293
307
|
* ```typescript
|
|
308
|
+
* // Frontend: Monitor session expiration
|
|
294
309
|
* await authClient.enableSessionExpirationMonitoring({
|
|
295
310
|
* callbacks: {
|
|
296
311
|
* onSessionExpiring: (remainingMinutes, expirationType) => {
|
|
@@ -304,6 +319,8 @@ export declare class AuthClient {
|
|
|
304
319
|
* },
|
|
305
320
|
* checkIntervalSeconds: 30 // ตรวจสอบทุก 30 วินาที
|
|
306
321
|
* });
|
|
322
|
+
*
|
|
323
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
307
324
|
* ```
|
|
308
325
|
*/
|
|
309
326
|
enableSessionExpirationMonitoring(options: SessionExpirationOptions): Promise<void>;
|
|
@@ -345,12 +362,18 @@ export declare class AuthClient {
|
|
|
345
362
|
reloadSessionManagementConfig(): Promise<void>;
|
|
346
363
|
/**
|
|
347
364
|
* Enable inactivity detection
|
|
348
|
-
*
|
|
365
|
+
*
|
|
366
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
367
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ track user activity, Frontend เป็นคนจัดการ
|
|
368
|
+
*
|
|
369
|
+
* จับ user activity (mouse/keyboard/touch/scroll) และ trigger callback เมื่อ inactivity timeout.
|
|
370
|
+
* เมื่อมี activity จะ trigger token refresh เพื่อ update server-side `last_access_at`.
|
|
349
371
|
*
|
|
350
372
|
* @param options - Options for inactivity detection
|
|
351
373
|
*
|
|
352
374
|
* @example
|
|
353
375
|
* ```typescript
|
|
376
|
+
* // Frontend: Track user activity and trigger token refresh
|
|
354
377
|
* await authClient.enableInactivityDetection({
|
|
355
378
|
* callbacks: {
|
|
356
379
|
* onInactivityWarning: (remainingSeconds) => {
|
|
@@ -368,6 +391,8 @@ export declare class AuthClient {
|
|
|
368
391
|
* warningSeconds: 300, // 5 minutes warning (optional, default: จาก session management config)
|
|
369
392
|
* events: ['mousemove', 'keydown', 'touchstart', 'scroll'] // (optional, default: ทั้งหมด)
|
|
370
393
|
* });
|
|
394
|
+
*
|
|
395
|
+
* // Backend: ไม่ต้องใช้ - Server-side inactivity enforcement ทำงานอัตโนมัติ
|
|
371
396
|
* ```
|
|
372
397
|
*/
|
|
373
398
|
enableInactivityDetection(options: InactivityDetectionOptions): Promise<void>;
|
|
@@ -377,6 +402,7 @@ export declare class AuthClient {
|
|
|
377
402
|
disableInactivityDetection(): void;
|
|
378
403
|
/**
|
|
379
404
|
* Handle user activity - reset inactivity timer with throttle
|
|
405
|
+
* Also trigger token refresh to update server-side last_access_at (if auto-refresh enabled)
|
|
380
406
|
*/
|
|
381
407
|
private handleUserActivity;
|
|
382
408
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/client/auth-client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/client/auth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,10 @@ class AuthClient {
|
|
|
56
56
|
this.activityThrottleTimeout = null;
|
|
57
57
|
this.activityThrottleMs = DEFAULT_ACTIVITY_THROTTLE_MS;
|
|
58
58
|
this.refreshTimeoutMs = DEFAULT_REFRESH_TIMEOUT_MS;
|
|
59
|
+
this.lastActivityRefreshTime = 0; // Track last time we refreshed due to activity
|
|
60
|
+
this.ACTIVITY_REFRESH_INTERVAL_MS = 5 * 60 * 1000; // Refresh every 5 minutes when active (keep-alive)
|
|
61
|
+
// Real-time session monitoring (Socket.IO)
|
|
62
|
+
this.sessionSocket = null; // SessionSocket instance
|
|
59
63
|
this.apiKey = config.apiKey;
|
|
60
64
|
this.apiKeyHeader = config.apiKeyHeader || 'X-API-Key';
|
|
61
65
|
// Apply advanced config if provided
|
|
@@ -107,6 +111,8 @@ class AuthClient {
|
|
|
107
111
|
]);
|
|
108
112
|
this.token = newToken;
|
|
109
113
|
requestConfig.headers['Authorization'] = `Bearer ${newToken}`;
|
|
114
|
+
// Update session socket token if real-time monitoring is enabled
|
|
115
|
+
this.updateSessionSocketToken(newToken);
|
|
110
116
|
logger_1.logger.info('Token refreshed successfully (critical)');
|
|
111
117
|
}
|
|
112
118
|
catch (error) {
|
|
@@ -261,24 +267,29 @@ class AuthClient {
|
|
|
261
267
|
/**
|
|
262
268
|
* Set JWT token for authenticated requests
|
|
263
269
|
*
|
|
270
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
271
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ใช้ `createAuthGuard()` หรือ `authMiddleware()` แทน (ไม่ต้อง setToken)
|
|
272
|
+
*
|
|
264
273
|
* @param token - JWT access token
|
|
265
274
|
* @param type - Token type: 'jwt' (default), 'oauth', or 'hybrid'
|
|
266
275
|
*
|
|
267
276
|
* @example
|
|
268
277
|
* ```typescript
|
|
269
|
-
* // JWT token from /auth/login
|
|
278
|
+
* // Frontend: JWT token from /auth/login
|
|
270
279
|
* authClient.setToken(session.token, 'jwt');
|
|
271
280
|
*
|
|
272
|
-
* // OAuth access token
|
|
281
|
+
* // Frontend: OAuth access token
|
|
273
282
|
* authClient.setToken(oauthToken, 'oauth');
|
|
274
283
|
*
|
|
275
|
-
* //
|
|
276
|
-
*
|
|
284
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
285
|
+
* // @UseGuards(AuthGuard)
|
|
277
286
|
* ```
|
|
278
287
|
*/
|
|
279
288
|
setToken(token, type = 'jwt') {
|
|
280
289
|
this.token = token;
|
|
281
290
|
this.authType = type;
|
|
291
|
+
// Update session socket token if real-time monitoring is enabled
|
|
292
|
+
this.updateSessionSocketToken(token);
|
|
282
293
|
logger_1.logger.debug(`Token set with type: ${type}`);
|
|
283
294
|
// Reset warning time when token changes
|
|
284
295
|
this.lastWarningTime = 0;
|
|
@@ -287,6 +298,18 @@ class AuthClient {
|
|
|
287
298
|
this.checkSessionExpiration();
|
|
288
299
|
}
|
|
289
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Update session socket token if real-time monitoring is enabled
|
|
303
|
+
*
|
|
304
|
+
* @private
|
|
305
|
+
* @param token - New JWT token to update
|
|
306
|
+
*/
|
|
307
|
+
updateSessionSocketToken(token) {
|
|
308
|
+
if (this.sessionSocket && typeof this.sessionSocket.updateToken === 'function') {
|
|
309
|
+
this.sessionSocket.updateToken(token);
|
|
310
|
+
logger_1.logger.debug('Session socket token updated');
|
|
311
|
+
}
|
|
312
|
+
}
|
|
290
313
|
/**
|
|
291
314
|
* Get current token type
|
|
292
315
|
*/
|
|
@@ -329,33 +352,30 @@ class AuthClient {
|
|
|
329
352
|
}
|
|
330
353
|
/**
|
|
331
354
|
* Enable automatic token refresh
|
|
332
|
-
*
|
|
355
|
+
*
|
|
356
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
357
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ถือ token, Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป
|
|
358
|
+
*
|
|
359
|
+
* Call this after user is authenticated to enable automatic refresh.
|
|
360
|
+
* SDK จะ refresh token อัตโนมัติก่อนหมดอายุผ่าน axios interceptor.
|
|
333
361
|
*
|
|
334
362
|
* @param options - Options for automatic refresh (optional - SDK will use session-based refresh if not provided)
|
|
335
363
|
*
|
|
336
364
|
* @example
|
|
337
365
|
* ```typescript
|
|
338
|
-
* //
|
|
339
|
-
* // Works when login only returns access_token
|
|
366
|
+
* // Frontend: Session-based refresh (default - no refresh token needed)
|
|
340
367
|
* await authClient.enableAutomaticRefresh({
|
|
341
368
|
* onRefreshFailure: () => window.location.href = '/login'
|
|
342
369
|
* });
|
|
343
370
|
*
|
|
344
|
-
* //
|
|
371
|
+
* // Frontend: With refresh token (if login returns refresh_token)
|
|
345
372
|
* await authClient.enableAutomaticRefresh({
|
|
346
373
|
* refreshTokenKey: 'refresh_token',
|
|
347
374
|
* onRefreshFailure: () => window.location.href = '/login'
|
|
348
375
|
* });
|
|
349
376
|
*
|
|
350
|
-
* //
|
|
351
|
-
*
|
|
352
|
-
* callbacks: {
|
|
353
|
-
* getRefreshToken: () => customStorage.get('refresh_token'),
|
|
354
|
-
* setRefreshToken: (token) => customStorage.set('refresh_token', token),
|
|
355
|
-
* clearRefreshToken: () => customStorage.remove('refresh_token'),
|
|
356
|
-
* onRefreshFailure: () => window.location.href = '/login'
|
|
357
|
-
* }
|
|
358
|
-
* });
|
|
377
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
378
|
+
* // @UseGuards(AuthGuard) // Guard จะ validate token อัตโนมัติ
|
|
359
379
|
* ```
|
|
360
380
|
*/
|
|
361
381
|
async enableAutomaticRefresh(options) {
|
|
@@ -432,7 +452,7 @@ class AuthClient {
|
|
|
432
452
|
*/
|
|
433
453
|
async performJwtConfigLoad() {
|
|
434
454
|
try {
|
|
435
|
-
const config = await this.systemConfig.
|
|
455
|
+
const config = (await this.systemConfig.get('security', 'jwt')).value;
|
|
436
456
|
this.refreshThresholdMinutes = config.refresh_threshold_minutes;
|
|
437
457
|
this.automaticRefreshEnabled = config.automatic_refresh ?? true;
|
|
438
458
|
logger_1.logger.debug(`JWT config loaded: refresh_threshold_minutes=${this.refreshThresholdMinutes} minutes, automatic_refresh=${this.automaticRefreshEnabled}`);
|
|
@@ -478,6 +498,8 @@ class AuthClient {
|
|
|
478
498
|
const newAccessToken = result.token;
|
|
479
499
|
// Update token in client
|
|
480
500
|
this.token = newAccessToken;
|
|
501
|
+
// Update session socket token if real-time monitoring is enabled
|
|
502
|
+
this.updateSessionSocketToken(newAccessToken);
|
|
481
503
|
logger_1.logger.debug('Token refreshed successfully (session-based)');
|
|
482
504
|
return newAccessToken;
|
|
483
505
|
}
|
|
@@ -499,6 +521,8 @@ class AuthClient {
|
|
|
499
521
|
const newAccessToken = session.access_token;
|
|
500
522
|
// Update token in client
|
|
501
523
|
this.token = newAccessToken;
|
|
524
|
+
// Update session socket token if real-time monitoring is enabled
|
|
525
|
+
this.updateSessionSocketToken(newAccessToken);
|
|
502
526
|
// Save new refresh token if rotated
|
|
503
527
|
if (session.refresh_token) {
|
|
504
528
|
await this.refreshTokenCallbacks.setRefreshToken(session.refresh_token);
|
|
@@ -526,12 +550,17 @@ class AuthClient {
|
|
|
526
550
|
}
|
|
527
551
|
/**
|
|
528
552
|
* Enable session expiration monitoring
|
|
553
|
+
*
|
|
554
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
555
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ track session expiration, Frontend เป็นคนจัดการ
|
|
556
|
+
*
|
|
529
557
|
* จะตรวจสอบ session expiration ตาม config จาก settings/sessions และเรียก callback เมื่อใกล้หมดอายุ
|
|
530
558
|
*
|
|
531
559
|
* @param options - Options for session expiration monitoring
|
|
532
560
|
*
|
|
533
561
|
* @example
|
|
534
562
|
* ```typescript
|
|
563
|
+
* // Frontend: Monitor session expiration
|
|
535
564
|
* await authClient.enableSessionExpirationMonitoring({
|
|
536
565
|
* callbacks: {
|
|
537
566
|
* onSessionExpiring: (remainingMinutes, expirationType) => {
|
|
@@ -545,6 +574,8 @@ class AuthClient {
|
|
|
545
574
|
* },
|
|
546
575
|
* checkIntervalSeconds: 30 // ตรวจสอบทุก 30 วินาที
|
|
547
576
|
* });
|
|
577
|
+
*
|
|
578
|
+
* // Backend: ไม่ต้องใช้ - ใช้ createAuthGuard() แทน
|
|
548
579
|
* ```
|
|
549
580
|
*/
|
|
550
581
|
async enableSessionExpirationMonitoring(options) {
|
|
@@ -703,12 +734,18 @@ class AuthClient {
|
|
|
703
734
|
}
|
|
704
735
|
/**
|
|
705
736
|
* Enable inactivity detection
|
|
706
|
-
*
|
|
737
|
+
*
|
|
738
|
+
* @platform **Frontend only** - สำหรับ React/Next.js applications
|
|
739
|
+
* @platform **Backend**: ไม่ต้องใช้ - Backend ไม่ได้ track user activity, Frontend เป็นคนจัดการ
|
|
740
|
+
*
|
|
741
|
+
* จับ user activity (mouse/keyboard/touch/scroll) และ trigger callback เมื่อ inactivity timeout.
|
|
742
|
+
* เมื่อมี activity จะ trigger token refresh เพื่อ update server-side `last_access_at`.
|
|
707
743
|
*
|
|
708
744
|
* @param options - Options for inactivity detection
|
|
709
745
|
*
|
|
710
746
|
* @example
|
|
711
747
|
* ```typescript
|
|
748
|
+
* // Frontend: Track user activity and trigger token refresh
|
|
712
749
|
* await authClient.enableInactivityDetection({
|
|
713
750
|
* callbacks: {
|
|
714
751
|
* onInactivityWarning: (remainingSeconds) => {
|
|
@@ -726,6 +763,8 @@ class AuthClient {
|
|
|
726
763
|
* warningSeconds: 300, // 5 minutes warning (optional, default: จาก session management config)
|
|
727
764
|
* events: ['mousemove', 'keydown', 'touchstart', 'scroll'] // (optional, default: ทั้งหมด)
|
|
728
765
|
* });
|
|
766
|
+
*
|
|
767
|
+
* // Backend: ไม่ต้องใช้ - Server-side inactivity enforcement ทำงานอัตโนมัติ
|
|
729
768
|
* ```
|
|
730
769
|
*/
|
|
731
770
|
async enableInactivityDetection(options) {
|
|
@@ -799,6 +838,7 @@ class AuthClient {
|
|
|
799
838
|
}
|
|
800
839
|
/**
|
|
801
840
|
* Handle user activity - reset inactivity timer with throttle
|
|
841
|
+
* Also trigger token refresh to update server-side last_access_at (if auto-refresh enabled)
|
|
802
842
|
*/
|
|
803
843
|
handleUserActivity() {
|
|
804
844
|
if (!this.inactivityDetectionEnabled) {
|
|
@@ -810,6 +850,29 @@ class AuthClient {
|
|
|
810
850
|
}
|
|
811
851
|
this.lastActivityTime = Date.now();
|
|
812
852
|
this.resetInactivityTimer();
|
|
853
|
+
// ✅ Connect inactivity detection with auto-refresh: trigger refresh to update server-side last_access_at
|
|
854
|
+
// This ensures server knows user is active even if no API calls are made
|
|
855
|
+
if (this.automaticRefreshEnabled &&
|
|
856
|
+
this.refreshTokenCallbacks &&
|
|
857
|
+
this.token &&
|
|
858
|
+
(0, token_utils_1.isTokenValid)(this.token)) {
|
|
859
|
+
const now = Date.now();
|
|
860
|
+
const timeSinceLastActivityRefresh = now - this.lastActivityRefreshTime;
|
|
861
|
+
// Refresh token if:
|
|
862
|
+
// 1. Token is near expiration (use refresh_threshold_minutes)
|
|
863
|
+
// 2. OR it's been 5 minutes since last activity refresh (keep-alive)
|
|
864
|
+
const shouldRefresh = (this.refreshThresholdMinutes !== null &&
|
|
865
|
+
(0, token_utils_1.isTokenNearExpiration)(this.token, this.refreshThresholdMinutes)) ||
|
|
866
|
+
timeSinceLastActivityRefresh >= this.ACTIVITY_REFRESH_INTERVAL_MS;
|
|
867
|
+
if (shouldRefresh && !this.refreshPromise) {
|
|
868
|
+
this.lastActivityRefreshTime = now;
|
|
869
|
+
// Trigger background refresh (non-blocking)
|
|
870
|
+
this.performRefresh().catch((error) => {
|
|
871
|
+
logger_1.logger.debug('Activity-triggered token refresh failed:', error);
|
|
872
|
+
// Don't call onRefreshFailure here - this is just a keep-alive, not critical
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
}
|
|
813
876
|
this.activityThrottleTimeout = setTimeout(() => {
|
|
814
877
|
this.activityThrottleTimeout = null;
|
|
815
878
|
}, this.activityThrottleMs);
|
package/dist/client/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Client exports for frontend applications
|
|
3
3
|
*/
|
|
4
4
|
export { AuthClient } from './auth-client';
|
|
5
|
+
export { SessionSocket, type SessionSocketOptions, type SessionEventData } from './session-socket';
|
|
5
6
|
export type { RefreshTokenCallbacks, AutomaticRefreshOptions, SessionExpirationCallbacks, SessionExpirationOptions, InactivityCallbacks, InactivityDetectionOptions, } from './auth-client';
|
|
6
7
|
export * from './api';
|
|
7
8
|
//# 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,EACxB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AACvB,cAAc,OAAO,CAAC"}
|
|
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,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACnG,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AACvB,cAAc,OAAO,CAAC"}
|
package/dist/client/index.js
CHANGED
|
@@ -17,7 +17,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.AuthClient = void 0;
|
|
20
|
+
exports.SessionSocket = exports.AuthClient = void 0;
|
|
21
21
|
var auth_client_1 = require("./auth-client");
|
|
22
22
|
Object.defineProperty(exports, "AuthClient", { enumerable: true, get: function () { return auth_client_1.AuthClient; } });
|
|
23
|
+
var session_socket_1 = require("./session-socket");
|
|
24
|
+
Object.defineProperty(exports, "SessionSocket", { enumerable: true, get: function () { return session_socket_1.SessionSocket; } });
|
|
23
25
|
__exportStar(require("./api"), exports);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Socket Options
|
|
3
|
+
*/
|
|
4
|
+
export interface SessionSocketOptions {
|
|
5
|
+
/** Portal API URL (same as AuthClient baseURL) */
|
|
6
|
+
baseURL: string;
|
|
7
|
+
/** JWT token for authentication */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Namespace (default: /app-sessions) */
|
|
10
|
+
namespace?: string;
|
|
11
|
+
/** Callbacks */
|
|
12
|
+
onSessionExpired?: (data: SessionEventData) => void;
|
|
13
|
+
onSessionRevoked?: (data: SessionEventData) => void;
|
|
14
|
+
onSessionExpiring?: (data: {
|
|
15
|
+
remaining_seconds: number;
|
|
16
|
+
reason: string;
|
|
17
|
+
}) => void;
|
|
18
|
+
onConnectionChange?: (connected: boolean) => void;
|
|
19
|
+
/** Auto-reconnect (default: true) */
|
|
20
|
+
autoReconnect?: boolean;
|
|
21
|
+
/** Reconnect attempts (default: 5) */
|
|
22
|
+
reconnectAttempts?: number;
|
|
23
|
+
/** Reconnect delay in ms (default: 1000) */
|
|
24
|
+
reconnectDelay?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Session Event Data
|
|
28
|
+
*/
|
|
29
|
+
export interface SessionEventData {
|
|
30
|
+
session_id: string;
|
|
31
|
+
reason: string;
|
|
32
|
+
expired_at?: string;
|
|
33
|
+
last_access_at?: string;
|
|
34
|
+
revoked_by?: string;
|
|
35
|
+
revoked_at?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Session Socket Client
|
|
39
|
+
*
|
|
40
|
+
* @description Socket.IO client wrapper for real-time session events
|
|
41
|
+
* Requires socket.io-client as peer dependency
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const socket = new SessionSocket({
|
|
46
|
+
* baseURL: 'https://portal.example.com',
|
|
47
|
+
* token: 'jwt-token',
|
|
48
|
+
* onSessionExpired: (data) => {
|
|
49
|
+
* console.log('Session expired:', data);
|
|
50
|
+
* window.location.href = '/login';
|
|
51
|
+
* },
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* socket.connect();
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare class SessionSocket {
|
|
58
|
+
private socket;
|
|
59
|
+
private options;
|
|
60
|
+
private reconnectAttempts;
|
|
61
|
+
private reconnectTimeout;
|
|
62
|
+
private isConnecting;
|
|
63
|
+
constructor(options: SessionSocketOptions);
|
|
64
|
+
/**
|
|
65
|
+
* Connect to Socket.IO server
|
|
66
|
+
*/
|
|
67
|
+
connect(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Disconnect from Socket.IO server
|
|
70
|
+
*/
|
|
71
|
+
disconnect(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Check if socket is connected
|
|
74
|
+
*/
|
|
75
|
+
isConnected(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Update JWT token (useful when token is refreshed)
|
|
78
|
+
*/
|
|
79
|
+
updateToken(token: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Setup Socket.IO event listeners
|
|
82
|
+
*/
|
|
83
|
+
private setupEventListeners;
|
|
84
|
+
/**
|
|
85
|
+
* Schedule reconnection attempt
|
|
86
|
+
*/
|
|
87
|
+
private scheduleReconnect;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=session-socket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-socket.d.ts","sourceRoot":"","sources":["../../src/client/session-socket.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACpD,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACpD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClF,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,qCAAqC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,YAAY,CAAS;gBAEjB,OAAO,EAAE,oBAAoB;IAUzC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC9B;;OAEG;IACH,UAAU,IAAI,IAAI;IAgBlB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAYhC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiD3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAiB1B"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.SessionSocket = void 0;
|
|
27
|
+
const logger_1 = require("../utils/logger");
|
|
28
|
+
/**
|
|
29
|
+
* Session Socket Client
|
|
30
|
+
*
|
|
31
|
+
* @description Socket.IO client wrapper for real-time session events
|
|
32
|
+
* Requires socket.io-client as peer dependency
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const socket = new SessionSocket({
|
|
37
|
+
* baseURL: 'https://portal.example.com',
|
|
38
|
+
* token: 'jwt-token',
|
|
39
|
+
* onSessionExpired: (data) => {
|
|
40
|
+
* console.log('Session expired:', data);
|
|
41
|
+
* window.location.href = '/login';
|
|
42
|
+
* },
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* socket.connect();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
class SessionSocket {
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.socket = null; // socket.io-client Socket
|
|
51
|
+
this.reconnectAttempts = 0;
|
|
52
|
+
this.reconnectTimeout = null;
|
|
53
|
+
this.isConnecting = false;
|
|
54
|
+
this.options = {
|
|
55
|
+
namespace: '/app-sessions',
|
|
56
|
+
autoReconnect: true,
|
|
57
|
+
reconnectAttempts: 5,
|
|
58
|
+
reconnectDelay: 1000,
|
|
59
|
+
...options,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Connect to Socket.IO server
|
|
64
|
+
*/
|
|
65
|
+
async connect() {
|
|
66
|
+
if (this.isConnecting || this.isConnected()) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
// Dynamic import socket.io-client
|
|
71
|
+
const { io } = await Promise.resolve().then(() => __importStar(require('socket.io-client')));
|
|
72
|
+
this.isConnecting = true;
|
|
73
|
+
const url = `${this.options.baseURL}${this.options.namespace}`;
|
|
74
|
+
this.socket = io(url, {
|
|
75
|
+
auth: {
|
|
76
|
+
token: this.options.token,
|
|
77
|
+
},
|
|
78
|
+
transports: ['websocket', 'polling'],
|
|
79
|
+
reconnection: this.options.autoReconnect,
|
|
80
|
+
reconnectionAttempts: this.options.reconnectAttempts,
|
|
81
|
+
reconnectionDelay: this.options.reconnectDelay,
|
|
82
|
+
});
|
|
83
|
+
// Setup event listeners
|
|
84
|
+
this.setupEventListeners();
|
|
85
|
+
logger_1.logger.debug('SessionSocket connecting...', { url, namespace: this.options.namespace });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
this.isConnecting = false;
|
|
89
|
+
if (error.message?.includes('Cannot find module') || error.message?.includes('socket.io-client')) {
|
|
90
|
+
logger_1.logger.warn('socket.io-client not installed. Install it to enable real-time session monitoring: npm install socket.io-client');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
logger_1.logger.error('Failed to connect SessionSocket:', error);
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Disconnect from Socket.IO server
|
|
100
|
+
*/
|
|
101
|
+
disconnect() {
|
|
102
|
+
if (this.socket) {
|
|
103
|
+
this.socket.disconnect();
|
|
104
|
+
this.socket = null;
|
|
105
|
+
}
|
|
106
|
+
if (this.reconnectTimeout) {
|
|
107
|
+
clearTimeout(this.reconnectTimeout);
|
|
108
|
+
this.reconnectTimeout = null;
|
|
109
|
+
}
|
|
110
|
+
this.reconnectAttempts = 0;
|
|
111
|
+
this.isConnecting = false;
|
|
112
|
+
logger_1.logger.debug('SessionSocket disconnected');
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check if socket is connected
|
|
116
|
+
*/
|
|
117
|
+
isConnected() {
|
|
118
|
+
return this.socket?.connected === true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Update JWT token (useful when token is refreshed)
|
|
122
|
+
*/
|
|
123
|
+
updateToken(token) {
|
|
124
|
+
this.options.token = token;
|
|
125
|
+
if (this.socket) {
|
|
126
|
+
this.socket.auth = { token };
|
|
127
|
+
// Reconnect with new token
|
|
128
|
+
if (this.isConnected()) {
|
|
129
|
+
this.disconnect();
|
|
130
|
+
this.connect();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Setup Socket.IO event listeners
|
|
136
|
+
*/
|
|
137
|
+
setupEventListeners() {
|
|
138
|
+
if (!this.socket) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Connection events
|
|
142
|
+
this.socket.on('connect', () => {
|
|
143
|
+
this.isConnecting = false;
|
|
144
|
+
this.reconnectAttempts = 0;
|
|
145
|
+
logger_1.logger.debug('SessionSocket connected');
|
|
146
|
+
this.options.onConnectionChange?.(true);
|
|
147
|
+
});
|
|
148
|
+
this.socket.on('disconnect', (reason) => {
|
|
149
|
+
logger_1.logger.debug('SessionSocket disconnected:', reason);
|
|
150
|
+
this.options.onConnectionChange?.(false);
|
|
151
|
+
// Auto-reconnect if enabled and not manually disconnected
|
|
152
|
+
if (this.options.autoReconnect && reason !== 'io client disconnect') {
|
|
153
|
+
this.scheduleReconnect();
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
this.socket.on('connect_error', (error) => {
|
|
157
|
+
logger_1.logger.warn('SessionSocket connection error:', error.message);
|
|
158
|
+
this.isConnecting = false;
|
|
159
|
+
});
|
|
160
|
+
// Session events
|
|
161
|
+
this.socket.on('session_expired', (data) => {
|
|
162
|
+
logger_1.logger.debug('Session expired event received:', data);
|
|
163
|
+
this.options.onSessionExpired?.(data);
|
|
164
|
+
});
|
|
165
|
+
this.socket.on('session_revoked', (data) => {
|
|
166
|
+
logger_1.logger.debug('Session revoked event received:', data);
|
|
167
|
+
this.options.onSessionRevoked?.(data);
|
|
168
|
+
});
|
|
169
|
+
this.socket.on('session_expiring', (data) => {
|
|
170
|
+
logger_1.logger.debug('Session expiring event received:', data);
|
|
171
|
+
this.options.onSessionExpiring?.(data);
|
|
172
|
+
});
|
|
173
|
+
this.socket.on('connection_status', (data) => {
|
|
174
|
+
logger_1.logger.debug('Connection status:', data);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Schedule reconnection attempt
|
|
179
|
+
*/
|
|
180
|
+
scheduleReconnect() {
|
|
181
|
+
if (this.reconnectAttempts >= (this.options.reconnectAttempts || 5)) {
|
|
182
|
+
logger_1.logger.warn('Max reconnection attempts reached');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.reconnectAttempts++;
|
|
186
|
+
const delay = (this.options.reconnectDelay || 1000) * this.reconnectAttempts; // Exponential backoff
|
|
187
|
+
logger_1.logger.debug(`Scheduling reconnect attempt ${this.reconnectAttempts} in ${delay}ms`);
|
|
188
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
189
|
+
this.connect().catch((error) => {
|
|
190
|
+
logger_1.logger.error('Reconnection failed:', error);
|
|
191
|
+
});
|
|
192
|
+
}, delay);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
exports.SessionSocket = SessionSocket;
|
|
@@ -9,21 +9,34 @@ import './express.types';
|
|
|
9
9
|
/**
|
|
10
10
|
* Create Express middleware
|
|
11
11
|
*
|
|
12
|
+
* @platform **Backend only** - สำหรับ Express applications
|
|
13
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
14
|
+
*
|
|
15
|
+
* Validate token จาก request header และ attach user profile ลง `req.user`.
|
|
16
|
+
* Backend ไม่ต้อง refresh token - Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป.
|
|
17
|
+
*
|
|
18
|
+
* @param config - Configuration สำหรับ auth middleware
|
|
19
|
+
* @returns Express middleware function
|
|
20
|
+
*
|
|
12
21
|
* @example
|
|
13
22
|
* ```typescript
|
|
23
|
+
* // Backend: Express middleware
|
|
14
24
|
* import { authMiddleware } from 'win-portal-auth-sdk';
|
|
15
25
|
*
|
|
16
|
-
* // Express
|
|
17
26
|
* app.use(authMiddleware({
|
|
18
|
-
* baseURL:
|
|
19
|
-
* apiKey:
|
|
27
|
+
* baseURL: process.env.PORTAL_API_URL!,
|
|
28
|
+
* apiKey: process.env.PORTAL_API_KEY!,
|
|
29
|
+
* cacheTimeout: 300, // Cache user profile 5 นาที (default)
|
|
20
30
|
* }));
|
|
21
31
|
*
|
|
22
32
|
* // In routes
|
|
23
33
|
* app.get('/profile', (req, res) => {
|
|
24
|
-
* const user = req.user; //
|
|
25
|
-
* const token = req.token;
|
|
34
|
+
* const user = req.user; // UserProfileResponseDto from Portal
|
|
35
|
+
* const token = req.token; // JWT token
|
|
36
|
+
* res.json({ user });
|
|
26
37
|
* });
|
|
38
|
+
*
|
|
39
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
27
40
|
* ```
|
|
28
41
|
*/
|
|
29
42
|
export declare function authMiddleware(config: MiddlewareConfig): (req: any, res: any, next: any) => Promise<any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/express.middleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMxD,OAAO,iBAAiB,CAAC;AAEzB
|
|
1
|
+
{"version":3,"file":"express.middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/express.middleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMxD,OAAO,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,SAGlC,GAAG,OAAO,GAAG,QAAQ,GAAG,kBA4B5C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAK7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG;IACrC,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CASA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,QAM5C"}
|
|
@@ -14,21 +14,34 @@ require("./express.types");
|
|
|
14
14
|
/**
|
|
15
15
|
* Create Express middleware
|
|
16
16
|
*
|
|
17
|
+
* @platform **Backend only** - สำหรับ Express applications
|
|
18
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
19
|
+
*
|
|
20
|
+
* Validate token จาก request header และ attach user profile ลง `req.user`.
|
|
21
|
+
* Backend ไม่ต้อง refresh token - Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป.
|
|
22
|
+
*
|
|
23
|
+
* @param config - Configuration สำหรับ auth middleware
|
|
24
|
+
* @returns Express middleware function
|
|
25
|
+
*
|
|
17
26
|
* @example
|
|
18
27
|
* ```typescript
|
|
28
|
+
* // Backend: Express middleware
|
|
19
29
|
* import { authMiddleware } from 'win-portal-auth-sdk';
|
|
20
30
|
*
|
|
21
|
-
* // Express
|
|
22
31
|
* app.use(authMiddleware({
|
|
23
|
-
* baseURL:
|
|
24
|
-
* apiKey:
|
|
32
|
+
* baseURL: process.env.PORTAL_API_URL!,
|
|
33
|
+
* apiKey: process.env.PORTAL_API_KEY!,
|
|
34
|
+
* cacheTimeout: 300, // Cache user profile 5 นาที (default)
|
|
25
35
|
* }));
|
|
26
36
|
*
|
|
27
37
|
* // In routes
|
|
28
38
|
* app.get('/profile', (req, res) => {
|
|
29
|
-
* const user = req.user; //
|
|
30
|
-
* const token = req.token;
|
|
39
|
+
* const user = req.user; // UserProfileResponseDto from Portal
|
|
40
|
+
* const token = req.token; // JWT token
|
|
41
|
+
* res.json({ user });
|
|
31
42
|
* });
|
|
43
|
+
*
|
|
44
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
32
45
|
* ```
|
|
33
46
|
*/
|
|
34
47
|
function authMiddleware(config) {
|
|
@@ -7,22 +7,34 @@ import { MiddlewareConfig } from './types';
|
|
|
7
7
|
/**
|
|
8
8
|
* NestJS Auth Guard
|
|
9
9
|
*
|
|
10
|
+
* @platform **Backend only** - สำหรับ NestJS applications
|
|
11
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
12
|
+
*
|
|
13
|
+
* Validate token จาก request header และ attach user profile ลง `request.user`.
|
|
14
|
+
* Backend ไม่ต้อง refresh token - Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป.
|
|
15
|
+
*
|
|
16
|
+
* @param config - Configuration สำหรับ auth guard
|
|
17
|
+
* @returns NestJS Guard class ที่สามารถใช้กับ `@UseGuards()` decorator
|
|
18
|
+
*
|
|
10
19
|
* @example
|
|
11
20
|
* ```typescript
|
|
12
|
-
* // In your auth.guard.ts
|
|
21
|
+
* // Backend: In your auth.guard.ts
|
|
13
22
|
* import { createAuthGuard } from 'win-portal-auth-sdk';
|
|
14
23
|
*
|
|
15
24
|
* export const AuthGuard = createAuthGuard({
|
|
16
|
-
* baseURL: process.env.
|
|
17
|
-
* apiKey: process.env.
|
|
25
|
+
* baseURL: process.env.PORTAL_API_URL!,
|
|
26
|
+
* apiKey: process.env.PORTAL_API_KEY!,
|
|
27
|
+
* cacheTimeout: 300, // Cache user profile 5 นาที (default)
|
|
18
28
|
* });
|
|
19
29
|
*
|
|
20
30
|
* // In your controller
|
|
21
31
|
* @UseGuards(AuthGuard)
|
|
22
32
|
* @Get('profile')
|
|
23
|
-
* getProfile(@CurrentUser() user:
|
|
24
|
-
* return user;
|
|
33
|
+
* getProfile(@CurrentUser() user: UserProfileResponseDto) {
|
|
34
|
+
* return user; // user มาจาก Portal API (ผ่าน Guard validation)
|
|
25
35
|
* }
|
|
36
|
+
*
|
|
37
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
26
38
|
* ```
|
|
27
39
|
*/
|
|
28
40
|
export declare function createAuthGuard(config: Omit<MiddlewareConfig, 'optional'>): {
|
|
@@ -33,14 +45,26 @@ export declare function createAuthGuard(config: Omit<MiddlewareConfig, 'optional
|
|
|
33
45
|
/**
|
|
34
46
|
* Optional Auth Guard - Does not block if no token
|
|
35
47
|
*
|
|
48
|
+
* @platform **Backend only** - สำหรับ NestJS applications
|
|
49
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
50
|
+
*
|
|
51
|
+
* Similar to `createAuthGuard()` แต่ไม่ block request ถ้าไม่มี token.
|
|
52
|
+
* ใช้สำหรับ routes ที่ต้องการ user ถ้ามี แต่ยังทำงานได้ถ้าไม่มี.
|
|
53
|
+
*
|
|
54
|
+
* @param config - Configuration สำหรับ auth guard
|
|
55
|
+
* @returns NestJS Guard class ที่สามารถใช้กับ `@UseGuards()` decorator
|
|
56
|
+
*
|
|
36
57
|
* @example
|
|
37
58
|
* ```typescript
|
|
59
|
+
* // Backend: Optional auth guard
|
|
38
60
|
* @UseGuards(OptionalAuthGuard)
|
|
39
61
|
* @Get('posts')
|
|
40
|
-
* getPosts(@CurrentUser() user:
|
|
62
|
+
* getPosts(@CurrentUser() user: UserProfileResponseDto | null) {
|
|
41
63
|
* // user may be null
|
|
42
64
|
* return user ? 'Your posts' : 'Public posts';
|
|
43
65
|
* }
|
|
66
|
+
*
|
|
67
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
44
68
|
* ```
|
|
45
69
|
*/
|
|
46
70
|
export declare function createOptionalAuthGuard(config: Omit<MiddlewareConfig, 'optional'>): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nestjs.guard.d.ts","sourceRoot":"","sources":["../../src/middleware/nestjs.guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI3C
|
|
1
|
+
{"version":3,"file":"nestjs.guard.d.ts","sourceRoot":"","sources":["../../src/middleware/nestjs.guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC;;6BAO3C,GAAG,GAAG,QAAQ,OAAO,CAAC;;EAoBpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC;;6BAOnD,GAAG,GAAG,QAAQ,OAAO,CAAC;;EAepD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,QAMhD"}
|
|
@@ -11,22 +11,34 @@ const user_cache_1 = require("./shared/user-cache");
|
|
|
11
11
|
/**
|
|
12
12
|
* NestJS Auth Guard
|
|
13
13
|
*
|
|
14
|
+
* @platform **Backend only** - สำหรับ NestJS applications
|
|
15
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
16
|
+
*
|
|
17
|
+
* Validate token จาก request header และ attach user profile ลง `request.user`.
|
|
18
|
+
* Backend ไม่ต้อง refresh token - Frontend เป็นคน refresh และส่ง token ใหม่มาใน request ถัดไป.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Configuration สำหรับ auth guard
|
|
21
|
+
* @returns NestJS Guard class ที่สามารถใช้กับ `@UseGuards()` decorator
|
|
22
|
+
*
|
|
14
23
|
* @example
|
|
15
24
|
* ```typescript
|
|
16
|
-
* // In your auth.guard.ts
|
|
25
|
+
* // Backend: In your auth.guard.ts
|
|
17
26
|
* import { createAuthGuard } from 'win-portal-auth-sdk';
|
|
18
27
|
*
|
|
19
28
|
* export const AuthGuard = createAuthGuard({
|
|
20
|
-
* baseURL: process.env.
|
|
21
|
-
* apiKey: process.env.
|
|
29
|
+
* baseURL: process.env.PORTAL_API_URL!,
|
|
30
|
+
* apiKey: process.env.PORTAL_API_KEY!,
|
|
31
|
+
* cacheTimeout: 300, // Cache user profile 5 นาที (default)
|
|
22
32
|
* });
|
|
23
33
|
*
|
|
24
34
|
* // In your controller
|
|
25
35
|
* @UseGuards(AuthGuard)
|
|
26
36
|
* @Get('profile')
|
|
27
|
-
* getProfile(@CurrentUser() user:
|
|
28
|
-
* return user;
|
|
37
|
+
* getProfile(@CurrentUser() user: UserProfileResponseDto) {
|
|
38
|
+
* return user; // user มาจาก Portal API (ผ่าน Guard validation)
|
|
29
39
|
* }
|
|
40
|
+
*
|
|
41
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
30
42
|
* ```
|
|
31
43
|
*/
|
|
32
44
|
function createAuthGuard(config) {
|
|
@@ -55,14 +67,26 @@ exports.createAuthGuard = createAuthGuard;
|
|
|
55
67
|
/**
|
|
56
68
|
* Optional Auth Guard - Does not block if no token
|
|
57
69
|
*
|
|
70
|
+
* @platform **Backend only** - สำหรับ NestJS applications
|
|
71
|
+
* @platform **Frontend**: ไม่ต้องใช้ - Frontend ใช้ `AuthClient` แทน
|
|
72
|
+
*
|
|
73
|
+
* Similar to `createAuthGuard()` แต่ไม่ block request ถ้าไม่มี token.
|
|
74
|
+
* ใช้สำหรับ routes ที่ต้องการ user ถ้ามี แต่ยังทำงานได้ถ้าไม่มี.
|
|
75
|
+
*
|
|
76
|
+
* @param config - Configuration สำหรับ auth guard
|
|
77
|
+
* @returns NestJS Guard class ที่สามารถใช้กับ `@UseGuards()` decorator
|
|
78
|
+
*
|
|
58
79
|
* @example
|
|
59
80
|
* ```typescript
|
|
81
|
+
* // Backend: Optional auth guard
|
|
60
82
|
* @UseGuards(OptionalAuthGuard)
|
|
61
83
|
* @Get('posts')
|
|
62
|
-
* getPosts(@CurrentUser() user:
|
|
84
|
+
* getPosts(@CurrentUser() user: UserProfileResponseDto | null) {
|
|
63
85
|
* // user may be null
|
|
64
86
|
* return user ? 'Your posts' : 'Public posts';
|
|
65
87
|
* }
|
|
88
|
+
*
|
|
89
|
+
* // Frontend: ไม่ต้องใช้ - ใช้ AuthClient แทน
|
|
66
90
|
* ```
|
|
67
91
|
*/
|
|
68
92
|
function createOptionalAuthGuard(config) {
|
|
@@ -69,8 +69,10 @@ export interface WebhookLogDetail {
|
|
|
69
69
|
status: 'pending' | 'success' | 'failed' | 'retrying';
|
|
70
70
|
/** HTTP status code ที่ได้รับกลับมา */
|
|
71
71
|
http_status?: number;
|
|
72
|
-
/**
|
|
72
|
+
/** HTTP request headers จาก external ที่เรียกเข้ามา */
|
|
73
73
|
request_headers?: Record<string, string>;
|
|
74
|
+
/** Headers ที่จะใช้ส่งไปกับ axios (จาก DTO หรือ webhook config) */
|
|
75
|
+
headers?: Record<string, string>;
|
|
74
76
|
/** Headers ที่ได้รับกลับมาจาก response */
|
|
75
77
|
response_headers?: Record<string, string>;
|
|
76
78
|
/** Response body ที่ได้รับกลับมา */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.types.d.ts","sourceRoot":"","sources":["../../src/types/webhook.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,oFAAoF;IACpF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IAEvB,0BAA0B;IAC1B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEtD,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IAEX,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,gDAAgD;IAChD,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAEhC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7B,6BAA6B;IAC7B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEtD,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,
|
|
1
|
+
{"version":3,"file":"webhook.types.d.ts","sourceRoot":"","sources":["../../src/types/webhook.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,oFAAoF;IACpF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IAEvB,0BAA0B;IAC1B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEtD,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IAEX,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,gDAAgD;IAChD,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAEhC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7B,6BAA6B;IAC7B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEtD,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEzC,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1C,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IAEpB,iCAAiC;IACjC,aAAa,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAE9B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAE7B,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,kBAAkB;IAClB,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;IAE1B,yBAAyB;IACzB,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;CAC3B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "win-portal-auth-sdk",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "Shared authentication SDK for Win Portal applications with JWT and OAuth support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,6 +47,14 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"axios": "^1.6.0"
|
|
49
49
|
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"socket.io-client": "^4.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"socket.io-client": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
50
58
|
"devDependencies": {
|
|
51
59
|
"@types/node": "^20.0.0",
|
|
52
60
|
"typescript": "^5.3.0"
|