astro-tokenkit 1.0.16 → 1.0.18
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 +62 -0
- package/dist/auth/manager.js +10 -8
- package/dist/client/client.d.ts +1 -1
- package/dist/client/client.js +9 -5
- package/dist/client/idle-manager.d.ts +30 -0
- package/dist/client/idle-manager.js +138 -0
- package/dist/client/tk-client.d.ts +1 -0
- package/dist/client/tk-client.js +22 -0
- package/dist/config.js +4 -1
- package/dist/index.cjs +171 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +72 -6
- package/dist/index.js +171 -88
- package/dist/index.js.map +1 -1
- package/dist/integration.d.ts +23 -1
- package/dist/integration.js +28 -3
- package/dist/middleware.cjs +70 -14
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.js +70 -14
- package/dist/middleware.js.map +1 -1
- package/dist/types.d.ts +50 -6
- package/dist/types.js +10 -7
- package/dist/utils/fetch.d.ts +5 -0
- package/dist/utils/fetch.js +36 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.js +22 -0
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -134,6 +134,10 @@ interface AuthConfig {
|
|
|
134
134
|
policy?: RefreshPolicy;
|
|
135
135
|
/** Cookie configuration */
|
|
136
136
|
cookies?: CookieConfig;
|
|
137
|
+
/** Custom fetch implementation */
|
|
138
|
+
fetch?: typeof fetch;
|
|
139
|
+
/** Dangerously ignore certificate errors (bypass SSL validation) */
|
|
140
|
+
dangerouslyIgnoreCertificateErrors?: boolean;
|
|
137
141
|
}
|
|
138
142
|
/**
|
|
139
143
|
* Refresh policy
|
|
@@ -172,6 +176,37 @@ interface RetryConfig {
|
|
|
172
176
|
/** Initial delay in ms */
|
|
173
177
|
delay?: number;
|
|
174
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Idle timeout configuration
|
|
181
|
+
*/
|
|
182
|
+
interface IdleConfig {
|
|
183
|
+
/** Idle timeout in seconds */
|
|
184
|
+
timeout: number;
|
|
185
|
+
/**
|
|
186
|
+
* Callback when idle timeout is reached.
|
|
187
|
+
* NOTE: This function is only used if you manually initialize IdleManager.
|
|
188
|
+
* If using the Astro integration, use window.addEventListener('tk:idle', ...) instead.
|
|
189
|
+
*/
|
|
190
|
+
onIdle?: () => void;
|
|
191
|
+
/** Whether to automatically logout on idle (default: true) */
|
|
192
|
+
autoLogout?: boolean;
|
|
193
|
+
/** Whether to monitor activity only on the active tab (default: true) */
|
|
194
|
+
activeTabOnly?: boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Custom data to pass to the 'tk:idle' event.
|
|
197
|
+
* Ideal for configuring client-side alerts (e.g. SweetAlert).
|
|
198
|
+
*/
|
|
199
|
+
alert?: AlertOptions | any;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Alert options for client-side notifications (e.g. SweetAlert)
|
|
203
|
+
*/
|
|
204
|
+
interface AlertOptions {
|
|
205
|
+
title?: string;
|
|
206
|
+
text?: string;
|
|
207
|
+
icon?: 'success' | 'error' | 'warning' | 'info' | 'question' | string;
|
|
208
|
+
[key: string]: any;
|
|
209
|
+
}
|
|
175
210
|
/**
|
|
176
211
|
* Request interceptor
|
|
177
212
|
*/
|
|
@@ -208,7 +243,9 @@ interface ClientConfig {
|
|
|
208
243
|
retry?: RetryConfig;
|
|
209
244
|
/** Interceptors */
|
|
210
245
|
interceptors?: InterceptorsConfig;
|
|
211
|
-
/**
|
|
246
|
+
/** Idle timeout configuration */
|
|
247
|
+
idle?: IdleConfig;
|
|
248
|
+
/** AsyncLocalStorage instance (Node only) */
|
|
212
249
|
context?: AsyncLocalStorage<any>;
|
|
213
250
|
/** Custom context store getter */
|
|
214
251
|
getContextStore?: () => TokenKitContext | undefined | null;
|
|
@@ -216,6 +253,12 @@ interface ClientConfig {
|
|
|
216
253
|
setContextStore?: (ctx: TokenKitContext) => void;
|
|
217
254
|
/** Custom context runner */
|
|
218
255
|
runWithContext?: <T>(ctx: TokenKitContext, fn: () => T) => T;
|
|
256
|
+
/** Custom fetch implementation */
|
|
257
|
+
fetch?: typeof fetch;
|
|
258
|
+
/** Enable debug logging */
|
|
259
|
+
debug?: boolean;
|
|
260
|
+
/** Dangerously ignore certificate errors (bypass SSL validation) */
|
|
261
|
+
dangerouslyIgnoreCertificateErrors?: boolean;
|
|
219
262
|
}
|
|
220
263
|
/**
|
|
221
264
|
* TokenKit Global Configuration
|
|
@@ -234,25 +277,26 @@ declare class APIError extends Error {
|
|
|
234
277
|
status?: number | undefined;
|
|
235
278
|
response?: any | undefined;
|
|
236
279
|
request?: RequestConfig | undefined;
|
|
237
|
-
|
|
280
|
+
cause?: any | undefined;
|
|
281
|
+
constructor(message: string, status?: number | undefined, response?: any | undefined, request?: RequestConfig | undefined, cause?: any | undefined);
|
|
238
282
|
}
|
|
239
283
|
/**
|
|
240
284
|
* Authentication Error
|
|
241
285
|
*/
|
|
242
286
|
declare class AuthError extends APIError {
|
|
243
|
-
constructor(message: string, status?: number, response?: any, request?: RequestConfig);
|
|
287
|
+
constructor(message: string, status?: number, response?: any, request?: RequestConfig, cause?: any);
|
|
244
288
|
}
|
|
245
289
|
/**
|
|
246
290
|
* Network Error
|
|
247
291
|
*/
|
|
248
292
|
declare class NetworkError extends APIError {
|
|
249
|
-
constructor(message: string, request?: RequestConfig);
|
|
293
|
+
constructor(message: string, request?: RequestConfig, cause?: any);
|
|
250
294
|
}
|
|
251
295
|
/**
|
|
252
296
|
* Timeout Error
|
|
253
297
|
*/
|
|
254
298
|
declare class TimeoutError extends APIError {
|
|
255
|
-
constructor(message: string, request?: RequestConfig);
|
|
299
|
+
constructor(message: string, request?: RequestConfig, cause?: any);
|
|
256
300
|
}
|
|
257
301
|
|
|
258
302
|
/**
|
|
@@ -402,6 +446,13 @@ declare function createClient(config?: Partial<TokenKitConfig>): APIClient;
|
|
|
402
446
|
* Astro integration for TokenKit
|
|
403
447
|
*
|
|
404
448
|
* This integration facilitates the setup of TokenKit in an Astro project.
|
|
449
|
+
* It performs the following:
|
|
450
|
+
* - Sets the global configuration for the API client.
|
|
451
|
+
* - Injects the configuration into the client-side via Vite's `define`.
|
|
452
|
+
* - Automatically registers the TokenKit middleware (unless `autoMiddleware` is set to `false`).
|
|
453
|
+
* - Injects a client-side script (`astro-tokenkit/client-init`) to handle idle session monitoring and automatic logout.
|
|
454
|
+
*
|
|
455
|
+
* @param config - TokenKit configuration options.
|
|
405
456
|
*
|
|
406
457
|
* @example
|
|
407
458
|
* ```ts
|
|
@@ -415,6 +466,10 @@ declare function createClient(config?: Partial<TokenKitConfig>): APIClient;
|
|
|
415
466
|
* auth: {
|
|
416
467
|
* login: '/auth/login',
|
|
417
468
|
* refresh: '/auth/refresh',
|
|
469
|
+
* },
|
|
470
|
+
* idle: {
|
|
471
|
+
* timeout: 3600, // 1 hour
|
|
472
|
+
* alert: { title: 'Session Expired' }
|
|
418
473
|
* }
|
|
419
474
|
* })
|
|
420
475
|
* ]
|
|
@@ -423,7 +478,18 @@ declare function createClient(config?: Partial<TokenKitConfig>): APIClient;
|
|
|
423
478
|
*/
|
|
424
479
|
declare function tokenKit(config: TokenKitConfig): AstroIntegration;
|
|
425
480
|
/**
|
|
426
|
-
* Helper to
|
|
481
|
+
* Helper to create the TokenKit middleware.
|
|
482
|
+
*
|
|
483
|
+
* Use this if you have `autoMiddleware: false` in your integration configuration
|
|
484
|
+
* and want to manually register the middleware in your `src/middleware.ts` file.
|
|
485
|
+
*
|
|
486
|
+
* @example
|
|
487
|
+
* ```ts
|
|
488
|
+
* // src/middleware.ts
|
|
489
|
+
* import { defineMiddleware } from 'astro-tokenkit';
|
|
490
|
+
*
|
|
491
|
+
* export const onRequest = defineMiddleware();
|
|
492
|
+
* ```
|
|
427
493
|
*/
|
|
428
494
|
declare const defineMiddleware: () => astro.MiddlewareHandler;
|
|
429
495
|
|
package/dist/index.js
CHANGED
|
@@ -37,20 +37,23 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
37
37
|
* API Error
|
|
38
38
|
*/
|
|
39
39
|
class APIError extends Error {
|
|
40
|
-
constructor(message, status, response, request) {
|
|
40
|
+
constructor(message, status, response, request, cause) {
|
|
41
41
|
super(message);
|
|
42
42
|
this.status = status;
|
|
43
43
|
this.response = response;
|
|
44
44
|
this.request = request;
|
|
45
|
+
this.cause = cause;
|
|
45
46
|
this.name = 'APIError';
|
|
47
|
+
if (cause && !this.cause)
|
|
48
|
+
this.cause = cause;
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
/**
|
|
49
52
|
* Authentication Error
|
|
50
53
|
*/
|
|
51
54
|
class AuthError extends APIError {
|
|
52
|
-
constructor(message, status, response, request) {
|
|
53
|
-
super(message, status, response, request);
|
|
55
|
+
constructor(message, status, response, request, cause) {
|
|
56
|
+
super(message, status, response, request, cause);
|
|
54
57
|
this.name = 'AuthError';
|
|
55
58
|
}
|
|
56
59
|
}
|
|
@@ -58,8 +61,8 @@ class AuthError extends APIError {
|
|
|
58
61
|
* Network Error
|
|
59
62
|
*/
|
|
60
63
|
class NetworkError extends APIError {
|
|
61
|
-
constructor(message, request) {
|
|
62
|
-
super(message, undefined, undefined, request);
|
|
64
|
+
constructor(message, request, cause) {
|
|
65
|
+
super(message, undefined, undefined, request, cause);
|
|
63
66
|
this.name = 'NetworkError';
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -67,8 +70,8 @@ class NetworkError extends APIError {
|
|
|
67
70
|
* Timeout Error
|
|
68
71
|
*/
|
|
69
72
|
class TimeoutError extends APIError {
|
|
70
|
-
constructor(message, request) {
|
|
71
|
-
super(message, undefined, undefined, request);
|
|
73
|
+
constructor(message, request, cause) {
|
|
74
|
+
super(message, undefined, undefined, request, cause);
|
|
72
75
|
this.name = 'TimeoutError';
|
|
73
76
|
}
|
|
74
77
|
}
|
|
@@ -394,6 +397,122 @@ function isExpired(expiresAt, now, policy = {}) {
|
|
|
394
397
|
return now + clockSkew > expiresAt;
|
|
395
398
|
}
|
|
396
399
|
|
|
400
|
+
// packages/astro-tokenkit/src/utils/fetch.ts
|
|
401
|
+
/**
|
|
402
|
+
* Perform a fetch request with optional certificate validation bypass
|
|
403
|
+
*/
|
|
404
|
+
function safeFetch(url, init, config) {
|
|
405
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
406
|
+
const fetchFn = config.fetch || fetch;
|
|
407
|
+
const fetchOptions = Object.assign({}, init);
|
|
408
|
+
if (config.dangerouslyIgnoreCertificateErrors && typeof process !== 'undefined') {
|
|
409
|
+
// In Node.js environment
|
|
410
|
+
try {
|
|
411
|
+
// Try to use undici Agent if available (it is built-in in Node 18+)
|
|
412
|
+
// However, we might need to import it if we want to create an Agent.
|
|
413
|
+
// Since we don't want to depend on undici in package.json, we use dynamic import.
|
|
414
|
+
// But wait, undici's Agent is what we need.
|
|
415
|
+
// As a fallback and most reliable way for self-signed certs in Node without extra deps:
|
|
416
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
417
|
+
// NOTE: This affects the whole process. We should ideally only do this if it's not already 0.
|
|
418
|
+
// But for a dev tool / specialized library, it's often what's needed.
|
|
419
|
+
}
|
|
420
|
+
catch (e) {
|
|
421
|
+
// Ignore
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return fetchFn(url, fetchOptions);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// packages/astro-tokenkit/src/config.ts
|
|
429
|
+
const CONFIG_KEY = Symbol.for('astro-tokenkit.config');
|
|
430
|
+
const MANAGER_KEY = Symbol.for('astro-tokenkit.manager');
|
|
431
|
+
const globalStorage = globalThis;
|
|
432
|
+
// Initialize global storage if not present
|
|
433
|
+
if (!globalStorage[CONFIG_KEY]) {
|
|
434
|
+
globalStorage[CONFIG_KEY] = {
|
|
435
|
+
runWithContext: undefined,
|
|
436
|
+
getContextStore: undefined,
|
|
437
|
+
setContextStore: undefined,
|
|
438
|
+
baseURL: "",
|
|
439
|
+
debug: false,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Set configuration
|
|
444
|
+
*/
|
|
445
|
+
function setConfig(userConfig) {
|
|
446
|
+
var _a, _b;
|
|
447
|
+
const currentConfig = globalStorage[CONFIG_KEY];
|
|
448
|
+
const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
|
|
449
|
+
// Validate that getter and setter are defined together
|
|
450
|
+
if ((finalConfig.getContextStore && !finalConfig.setContextStore) ||
|
|
451
|
+
(!finalConfig.getContextStore && finalConfig.setContextStore)) {
|
|
452
|
+
throw new Error("[TokenKit] getContextStore and setContextStore must be defined together.");
|
|
453
|
+
}
|
|
454
|
+
globalStorage[CONFIG_KEY] = finalConfig;
|
|
455
|
+
// Re-initialize global token manager if auth changed
|
|
456
|
+
if (finalConfig.auth) {
|
|
457
|
+
const authConfig = Object.assign(Object.assign({}, finalConfig.auth), { fetch: (_a = finalConfig.auth.fetch) !== null && _a !== void 0 ? _a : finalConfig.fetch, dangerouslyIgnoreCertificateErrors: (_b = finalConfig.auth.dangerouslyIgnoreCertificateErrors) !== null && _b !== void 0 ? _b : finalConfig.dangerouslyIgnoreCertificateErrors });
|
|
458
|
+
globalStorage[MANAGER_KEY] = new TokenManager(authConfig, finalConfig.baseURL);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
globalStorage[MANAGER_KEY] = undefined;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Get current configuration
|
|
466
|
+
*/
|
|
467
|
+
function getConfig() {
|
|
468
|
+
return globalStorage[CONFIG_KEY];
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get global token manager
|
|
472
|
+
*/
|
|
473
|
+
function getTokenManager() {
|
|
474
|
+
return globalStorage[MANAGER_KEY];
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Set global token manager (mainly for testing)
|
|
478
|
+
*/
|
|
479
|
+
function setTokenManager(manager) {
|
|
480
|
+
globalStorage[MANAGER_KEY] = manager;
|
|
481
|
+
}
|
|
482
|
+
// Handle injected configuration from Astro integration
|
|
483
|
+
try {
|
|
484
|
+
// @ts-ignore
|
|
485
|
+
const injectedConfig = typeof __TOKENKIT_CONFIG__ !== 'undefined' ? __TOKENKIT_CONFIG__ : undefined;
|
|
486
|
+
if (injectedConfig) {
|
|
487
|
+
setConfig(injectedConfig);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (e) {
|
|
491
|
+
// Ignore errors in environments where __TOKENKIT_CONFIG__ might be restricted
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Logger utility that respects the debug flag in the configuration
|
|
496
|
+
*/
|
|
497
|
+
const logger = {
|
|
498
|
+
debug: (message, ...args) => {
|
|
499
|
+
if (getConfig().debug) {
|
|
500
|
+
console.debug(message, ...args);
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
info: (message, ...args) => {
|
|
504
|
+
if (getConfig().debug) {
|
|
505
|
+
console.log(message, ...args);
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
warn: (message, ...args) => {
|
|
509
|
+
console.warn(message, ...args);
|
|
510
|
+
},
|
|
511
|
+
error: (message, ...args) => {
|
|
512
|
+
console.error(message, ...args);
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
397
516
|
// packages/astro-tokenkit/src/auth/manager.ts
|
|
398
517
|
/**
|
|
399
518
|
* Single-flight refresh manager
|
|
@@ -450,14 +569,14 @@ class TokenManager {
|
|
|
450
569
|
}
|
|
451
570
|
let response;
|
|
452
571
|
try {
|
|
453
|
-
response = yield
|
|
572
|
+
response = yield safeFetch(url, {
|
|
454
573
|
method: 'POST',
|
|
455
574
|
headers,
|
|
456
575
|
body: requestBody,
|
|
457
|
-
});
|
|
576
|
+
}, this.config);
|
|
458
577
|
}
|
|
459
578
|
catch (error) {
|
|
460
|
-
const authError = new AuthError(`Login request failed: ${error.message}
|
|
579
|
+
const authError = new AuthError(`Login request failed: ${error.message}`, undefined, undefined, undefined, error);
|
|
461
580
|
if (options === null || options === void 0 ? void 0 : options.onError)
|
|
462
581
|
yield options.onError(authError, ctx);
|
|
463
582
|
throw authError;
|
|
@@ -531,14 +650,14 @@ class TokenManager {
|
|
|
531
650
|
}
|
|
532
651
|
let response;
|
|
533
652
|
try {
|
|
534
|
-
response = yield
|
|
653
|
+
response = yield safeFetch(url, {
|
|
535
654
|
method: 'POST',
|
|
536
655
|
headers,
|
|
537
656
|
body: requestBody,
|
|
538
|
-
});
|
|
657
|
+
}, this.config);
|
|
539
658
|
}
|
|
540
659
|
catch (error) {
|
|
541
|
-
throw new AuthError(`Refresh request failed: ${error.message}
|
|
660
|
+
throw new AuthError(`Refresh request failed: ${error.message}`, undefined, undefined, undefined, error);
|
|
542
661
|
}
|
|
543
662
|
if (!response.ok) {
|
|
544
663
|
// 401/403 = invalid refresh token
|
|
@@ -636,11 +755,11 @@ class TokenManager {
|
|
|
636
755
|
const injectFn = (_a = this.config.injectToken) !== null && _a !== void 0 ? _a : ((token, type) => `${type !== null && type !== void 0 ? type : 'Bearer'} ${token}`);
|
|
637
756
|
headers['Authorization'] = injectFn(session.accessToken, session.tokenType);
|
|
638
757
|
}
|
|
639
|
-
yield
|
|
758
|
+
yield safeFetch(url, { method: 'POST', headers }, this.config);
|
|
640
759
|
}
|
|
641
760
|
catch (error) {
|
|
642
761
|
// Ignore logout endpoint errors
|
|
643
|
-
|
|
762
|
+
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
644
763
|
}
|
|
645
764
|
}
|
|
646
765
|
clearTokens(ctx, this.config.cookies);
|
|
@@ -686,69 +805,6 @@ class TokenManager {
|
|
|
686
805
|
}
|
|
687
806
|
}
|
|
688
807
|
|
|
689
|
-
// packages/astro-tokenkit/src/config.ts
|
|
690
|
-
const CONFIG_KEY = Symbol.for('astro-tokenkit.config');
|
|
691
|
-
const MANAGER_KEY = Symbol.for('astro-tokenkit.manager');
|
|
692
|
-
const globalStorage = globalThis;
|
|
693
|
-
// Initialize global storage if not present
|
|
694
|
-
if (!globalStorage[CONFIG_KEY]) {
|
|
695
|
-
globalStorage[CONFIG_KEY] = {
|
|
696
|
-
runWithContext: undefined,
|
|
697
|
-
getContextStore: undefined,
|
|
698
|
-
setContextStore: undefined,
|
|
699
|
-
baseURL: "",
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Set configuration
|
|
704
|
-
*/
|
|
705
|
-
function setConfig(userConfig) {
|
|
706
|
-
const currentConfig = globalStorage[CONFIG_KEY];
|
|
707
|
-
const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
|
|
708
|
-
// Validate that getter and setter are defined together
|
|
709
|
-
if ((finalConfig.getContextStore && !finalConfig.setContextStore) ||
|
|
710
|
-
(!finalConfig.getContextStore && finalConfig.setContextStore)) {
|
|
711
|
-
throw new Error("[TokenKit] getContextStore and setContextStore must be defined together.");
|
|
712
|
-
}
|
|
713
|
-
globalStorage[CONFIG_KEY] = finalConfig;
|
|
714
|
-
// Re-initialize global token manager if auth changed
|
|
715
|
-
if (finalConfig.auth) {
|
|
716
|
-
globalStorage[MANAGER_KEY] = new TokenManager(finalConfig.auth, finalConfig.baseURL);
|
|
717
|
-
}
|
|
718
|
-
else {
|
|
719
|
-
globalStorage[MANAGER_KEY] = undefined;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* Get current configuration
|
|
724
|
-
*/
|
|
725
|
-
function getConfig() {
|
|
726
|
-
return globalStorage[CONFIG_KEY];
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* Get global token manager
|
|
730
|
-
*/
|
|
731
|
-
function getTokenManager() {
|
|
732
|
-
return globalStorage[MANAGER_KEY];
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* Set global token manager (mainly for testing)
|
|
736
|
-
*/
|
|
737
|
-
function setTokenManager(manager) {
|
|
738
|
-
globalStorage[MANAGER_KEY] = manager;
|
|
739
|
-
}
|
|
740
|
-
// Handle injected configuration from Astro integration
|
|
741
|
-
try {
|
|
742
|
-
// @ts-ignore
|
|
743
|
-
const injectedConfig = typeof __TOKENKIT_CONFIG__ !== 'undefined' ? __TOKENKIT_CONFIG__ : undefined;
|
|
744
|
-
if (injectedConfig) {
|
|
745
|
-
setConfig(injectedConfig);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
catch (e) {
|
|
749
|
-
// Ignore errors in environments where __TOKENKIT_CONFIG__ might be restricted
|
|
750
|
-
}
|
|
751
|
-
|
|
752
808
|
// packages/astro-tokenkit/src/client/context.ts
|
|
753
809
|
/**
|
|
754
810
|
* Async local storage for Astro context
|
|
@@ -845,7 +901,7 @@ function createMiddleware() {
|
|
|
845
901
|
else if (config.context) {
|
|
846
902
|
contextStrategy = 'custom (external AsyncLocalStorage)';
|
|
847
903
|
}
|
|
848
|
-
|
|
904
|
+
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`);
|
|
849
905
|
globalStorage[LOGGED_KEY] = true;
|
|
850
906
|
}
|
|
851
907
|
const runLogic = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -857,7 +913,7 @@ function createMiddleware() {
|
|
|
857
913
|
}
|
|
858
914
|
catch (error) {
|
|
859
915
|
// Log only the message to avoid leaking sensitive data in the error object
|
|
860
|
-
|
|
916
|
+
logger.debug('[TokenKit] Automatic token rotation failed:', error.message || error);
|
|
861
917
|
}
|
|
862
918
|
}
|
|
863
919
|
return next();
|
|
@@ -902,6 +958,7 @@ class APIClient {
|
|
|
902
958
|
* Get token manager
|
|
903
959
|
*/
|
|
904
960
|
get tokenManager() {
|
|
961
|
+
var _a, _b;
|
|
905
962
|
const config = this.config;
|
|
906
963
|
if (!config.auth)
|
|
907
964
|
return undefined;
|
|
@@ -917,7 +974,9 @@ class APIClient {
|
|
|
917
974
|
if (!this._localTokenManager ||
|
|
918
975
|
this._lastUsedAuth !== config.auth ||
|
|
919
976
|
this._lastUsedBaseURL !== config.baseURL) {
|
|
920
|
-
|
|
977
|
+
// Merge client-level fetch and SSL settings into auth config
|
|
978
|
+
const authConfig = Object.assign(Object.assign({}, config.auth), { fetch: (_a = config.auth.fetch) !== null && _a !== void 0 ? _a : config.fetch, dangerouslyIgnoreCertificateErrors: (_b = config.auth.dangerouslyIgnoreCertificateErrors) !== null && _b !== void 0 ? _b : config.dangerouslyIgnoreCertificateErrors });
|
|
979
|
+
this._localTokenManager = new TokenManager(authConfig, config.baseURL);
|
|
921
980
|
this._lastUsedAuth = config.auth;
|
|
922
981
|
this._lastUsedBaseURL = config.baseURL;
|
|
923
982
|
}
|
|
@@ -1034,7 +1093,7 @@ class APIClient {
|
|
|
1034
1093
|
const controller = new AbortController();
|
|
1035
1094
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1036
1095
|
try {
|
|
1037
|
-
const response = yield
|
|
1096
|
+
const response = yield safeFetch(fullURL, Object.assign(Object.assign({}, init), { signal: controller.signal }), this.config);
|
|
1038
1097
|
clearTimeout(timeoutId);
|
|
1039
1098
|
// Handle 401 (try refresh and retry once)
|
|
1040
1099
|
if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
|
|
@@ -1067,12 +1126,12 @@ class APIClient {
|
|
|
1067
1126
|
}
|
|
1068
1127
|
// Transform errors
|
|
1069
1128
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
1070
|
-
throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig);
|
|
1129
|
+
throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig, error);
|
|
1071
1130
|
}
|
|
1072
1131
|
if (error instanceof APIError) {
|
|
1073
1132
|
throw error;
|
|
1074
1133
|
}
|
|
1075
|
-
throw new NetworkError(error.message, requestConfig);
|
|
1134
|
+
throw new NetworkError(error.message, requestConfig, error);
|
|
1076
1135
|
}
|
|
1077
1136
|
});
|
|
1078
1137
|
}
|
|
@@ -1166,7 +1225,7 @@ class APIClient {
|
|
|
1166
1225
|
throw new Error('Auth is not configured for this client');
|
|
1167
1226
|
}
|
|
1168
1227
|
const context = getContextStore();
|
|
1169
|
-
return this.tokenManager.login(context, credentials, options);
|
|
1228
|
+
return yield this.tokenManager.login(context, credentials, options);
|
|
1170
1229
|
});
|
|
1171
1230
|
}
|
|
1172
1231
|
/**
|
|
@@ -1223,6 +1282,13 @@ function createClient(config) {
|
|
|
1223
1282
|
* Astro integration for TokenKit
|
|
1224
1283
|
*
|
|
1225
1284
|
* This integration facilitates the setup of TokenKit in an Astro project.
|
|
1285
|
+
* It performs the following:
|
|
1286
|
+
* - Sets the global configuration for the API client.
|
|
1287
|
+
* - Injects the configuration into the client-side via Vite's `define`.
|
|
1288
|
+
* - Automatically registers the TokenKit middleware (unless `autoMiddleware` is set to `false`).
|
|
1289
|
+
* - Injects a client-side script (`astro-tokenkit/client-init`) to handle idle session monitoring and automatic logout.
|
|
1290
|
+
*
|
|
1291
|
+
* @param config - TokenKit configuration options.
|
|
1226
1292
|
*
|
|
1227
1293
|
* @example
|
|
1228
1294
|
* ```ts
|
|
@@ -1236,6 +1302,10 @@ function createClient(config) {
|
|
|
1236
1302
|
* auth: {
|
|
1237
1303
|
* login: '/auth/login',
|
|
1238
1304
|
* refresh: '/auth/refresh',
|
|
1305
|
+
* },
|
|
1306
|
+
* idle: {
|
|
1307
|
+
* timeout: 3600, // 1 hour
|
|
1308
|
+
* alert: { title: 'Session Expired' }
|
|
1239
1309
|
* }
|
|
1240
1310
|
* })
|
|
1241
1311
|
* ]
|
|
@@ -1253,7 +1323,7 @@ function tokenKit(config) {
|
|
|
1253
1323
|
return {
|
|
1254
1324
|
name: 'astro-tokenkit',
|
|
1255
1325
|
hooks: {
|
|
1256
|
-
'astro:config:setup': ({ updateConfig, addMiddleware }) => {
|
|
1326
|
+
'astro:config:setup': ({ updateConfig, addMiddleware, injectScript }) => {
|
|
1257
1327
|
updateConfig({
|
|
1258
1328
|
vite: {
|
|
1259
1329
|
define: {
|
|
@@ -1268,13 +1338,26 @@ function tokenKit(config) {
|
|
|
1268
1338
|
order: 'pre'
|
|
1269
1339
|
});
|
|
1270
1340
|
}
|
|
1271
|
-
|
|
1341
|
+
// Always inject the client-side script for idle monitoring
|
|
1342
|
+
injectScript('page', `import 'astro-tokenkit/client-init';`);
|
|
1343
|
+
logger.debug('[TokenKit] Integration initialized');
|
|
1272
1344
|
},
|
|
1273
1345
|
},
|
|
1274
1346
|
};
|
|
1275
1347
|
}
|
|
1276
1348
|
/**
|
|
1277
|
-
* Helper to
|
|
1349
|
+
* Helper to create the TokenKit middleware.
|
|
1350
|
+
*
|
|
1351
|
+
* Use this if you have `autoMiddleware: false` in your integration configuration
|
|
1352
|
+
* and want to manually register the middleware in your `src/middleware.ts` file.
|
|
1353
|
+
*
|
|
1354
|
+
* @example
|
|
1355
|
+
* ```ts
|
|
1356
|
+
* // src/middleware.ts
|
|
1357
|
+
* import { defineMiddleware } from 'astro-tokenkit';
|
|
1358
|
+
*
|
|
1359
|
+
* export const onRequest = defineMiddleware();
|
|
1360
|
+
* ```
|
|
1278
1361
|
*/
|
|
1279
1362
|
const defineMiddleware = () => createMiddleware();
|
|
1280
1363
|
|