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/integration.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import type { TokenKitConfig } from './types';
|
|
|
4
4
|
* Astro integration for TokenKit
|
|
5
5
|
*
|
|
6
6
|
* This integration facilitates the setup of TokenKit in an Astro project.
|
|
7
|
+
* It performs the following:
|
|
8
|
+
* - Sets the global configuration for the API client.
|
|
9
|
+
* - Injects the configuration into the client-side via Vite's `define`.
|
|
10
|
+
* - Automatically registers the TokenKit middleware (unless `autoMiddleware` is set to `false`).
|
|
11
|
+
* - Injects a client-side script (`astro-tokenkit/client-init`) to handle idle session monitoring and automatic logout.
|
|
12
|
+
*
|
|
13
|
+
* @param config - TokenKit configuration options.
|
|
7
14
|
*
|
|
8
15
|
* @example
|
|
9
16
|
* ```ts
|
|
@@ -17,6 +24,10 @@ import type { TokenKitConfig } from './types';
|
|
|
17
24
|
* auth: {
|
|
18
25
|
* login: '/auth/login',
|
|
19
26
|
* refresh: '/auth/refresh',
|
|
27
|
+
* },
|
|
28
|
+
* idle: {
|
|
29
|
+
* timeout: 3600, // 1 hour
|
|
30
|
+
* alert: { title: 'Session Expired' }
|
|
20
31
|
* }
|
|
21
32
|
* })
|
|
22
33
|
* ]
|
|
@@ -25,6 +36,17 @@ import type { TokenKitConfig } from './types';
|
|
|
25
36
|
*/
|
|
26
37
|
export declare function tokenKit(config: TokenKitConfig): AstroIntegration;
|
|
27
38
|
/**
|
|
28
|
-
* Helper to
|
|
39
|
+
* Helper to create the TokenKit middleware.
|
|
40
|
+
*
|
|
41
|
+
* Use this if you have `autoMiddleware: false` in your integration configuration
|
|
42
|
+
* and want to manually register the middleware in your `src/middleware.ts` file.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // src/middleware.ts
|
|
47
|
+
* import { defineMiddleware } from 'astro-tokenkit';
|
|
48
|
+
*
|
|
49
|
+
* export const onRequest = defineMiddleware();
|
|
50
|
+
* ```
|
|
29
51
|
*/
|
|
30
52
|
export declare const defineMiddleware: () => import("astro").MiddlewareHandler;
|
package/dist/integration.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
// packages/astro-tokenkit/src/integration.ts
|
|
2
2
|
import { createMiddleware } from './middleware';
|
|
3
3
|
import { setConfig } from './config';
|
|
4
|
+
import { logger } from './utils/logger';
|
|
4
5
|
/**
|
|
5
6
|
* Astro integration for TokenKit
|
|
6
7
|
*
|
|
7
8
|
* This integration facilitates the setup of TokenKit in an Astro project.
|
|
9
|
+
* It performs the following:
|
|
10
|
+
* - Sets the global configuration for the API client.
|
|
11
|
+
* - Injects the configuration into the client-side via Vite's `define`.
|
|
12
|
+
* - Automatically registers the TokenKit middleware (unless `autoMiddleware` is set to `false`).
|
|
13
|
+
* - Injects a client-side script (`astro-tokenkit/client-init`) to handle idle session monitoring and automatic logout.
|
|
14
|
+
*
|
|
15
|
+
* @param config - TokenKit configuration options.
|
|
8
16
|
*
|
|
9
17
|
* @example
|
|
10
18
|
* ```ts
|
|
@@ -18,6 +26,10 @@ import { setConfig } from './config';
|
|
|
18
26
|
* auth: {
|
|
19
27
|
* login: '/auth/login',
|
|
20
28
|
* refresh: '/auth/refresh',
|
|
29
|
+
* },
|
|
30
|
+
* idle: {
|
|
31
|
+
* timeout: 3600, // 1 hour
|
|
32
|
+
* alert: { title: 'Session Expired' }
|
|
21
33
|
* }
|
|
22
34
|
* })
|
|
23
35
|
* ]
|
|
@@ -35,7 +47,7 @@ export function tokenKit(config) {
|
|
|
35
47
|
return {
|
|
36
48
|
name: 'astro-tokenkit',
|
|
37
49
|
hooks: {
|
|
38
|
-
'astro:config:setup': ({ updateConfig, addMiddleware }) => {
|
|
50
|
+
'astro:config:setup': ({ updateConfig, addMiddleware, injectScript }) => {
|
|
39
51
|
updateConfig({
|
|
40
52
|
vite: {
|
|
41
53
|
define: {
|
|
@@ -50,12 +62,25 @@ export function tokenKit(config) {
|
|
|
50
62
|
order: 'pre'
|
|
51
63
|
});
|
|
52
64
|
}
|
|
53
|
-
|
|
65
|
+
// Always inject the client-side script for idle monitoring
|
|
66
|
+
injectScript('page', `import 'astro-tokenkit/client-init';`);
|
|
67
|
+
logger.debug('[TokenKit] Integration initialized');
|
|
54
68
|
},
|
|
55
69
|
},
|
|
56
70
|
};
|
|
57
71
|
}
|
|
58
72
|
/**
|
|
59
|
-
* Helper to
|
|
73
|
+
* Helper to create the TokenKit middleware.
|
|
74
|
+
*
|
|
75
|
+
* Use this if you have `autoMiddleware: false` in your integration configuration
|
|
76
|
+
* and want to manually register the middleware in your `src/middleware.ts` file.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* // src/middleware.ts
|
|
81
|
+
* import { defineMiddleware } from 'astro-tokenkit';
|
|
82
|
+
*
|
|
83
|
+
* export const onRequest = defineMiddleware();
|
|
84
|
+
* ```
|
|
60
85
|
*/
|
|
61
86
|
export const defineMiddleware = () => createMiddleware();
|
package/dist/middleware.cjs
CHANGED
|
@@ -39,20 +39,23 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
39
39
|
* API Error
|
|
40
40
|
*/
|
|
41
41
|
class APIError extends Error {
|
|
42
|
-
constructor(message, status, response, request) {
|
|
42
|
+
constructor(message, status, response, request, cause) {
|
|
43
43
|
super(message);
|
|
44
44
|
this.status = status;
|
|
45
45
|
this.response = response;
|
|
46
46
|
this.request = request;
|
|
47
|
+
this.cause = cause;
|
|
47
48
|
this.name = 'APIError';
|
|
49
|
+
if (cause && !this.cause)
|
|
50
|
+
this.cause = cause;
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* Authentication Error
|
|
52
55
|
*/
|
|
53
56
|
class AuthError extends APIError {
|
|
54
|
-
constructor(message, status, response, request) {
|
|
55
|
-
super(message, status, response, request);
|
|
57
|
+
constructor(message, status, response, request, cause) {
|
|
58
|
+
super(message, status, response, request, cause);
|
|
56
59
|
this.name = 'AuthError';
|
|
57
60
|
}
|
|
58
61
|
}
|
|
@@ -366,6 +369,56 @@ function isExpired(expiresAt, now, policy = {}) {
|
|
|
366
369
|
return now + clockSkew > expiresAt;
|
|
367
370
|
}
|
|
368
371
|
|
|
372
|
+
// packages/astro-tokenkit/src/utils/fetch.ts
|
|
373
|
+
/**
|
|
374
|
+
* Perform a fetch request with optional certificate validation bypass
|
|
375
|
+
*/
|
|
376
|
+
function safeFetch(url, init, config) {
|
|
377
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
378
|
+
const fetchFn = config.fetch || fetch;
|
|
379
|
+
const fetchOptions = Object.assign({}, init);
|
|
380
|
+
if (config.dangerouslyIgnoreCertificateErrors && typeof process !== 'undefined') {
|
|
381
|
+
// In Node.js environment
|
|
382
|
+
try {
|
|
383
|
+
// Try to use undici Agent if available (it is built-in in Node 18+)
|
|
384
|
+
// However, we might need to import it if we want to create an Agent.
|
|
385
|
+
// Since we don't want to depend on undici in package.json, we use dynamic import.
|
|
386
|
+
// But wait, undici's Agent is what we need.
|
|
387
|
+
// As a fallback and most reliable way for self-signed certs in Node without extra deps:
|
|
388
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
389
|
+
// NOTE: This affects the whole process. We should ideally only do this if it's not already 0.
|
|
390
|
+
// But for a dev tool / specialized library, it's often what's needed.
|
|
391
|
+
}
|
|
392
|
+
catch (e) {
|
|
393
|
+
// Ignore
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return fetchFn(url, fetchOptions);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Logger utility that respects the debug flag in the configuration
|
|
402
|
+
*/
|
|
403
|
+
const logger = {
|
|
404
|
+
debug: (message, ...args) => {
|
|
405
|
+
if (getConfig().debug) {
|
|
406
|
+
console.debug(message, ...args);
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
info: (message, ...args) => {
|
|
410
|
+
if (getConfig().debug) {
|
|
411
|
+
console.log(message, ...args);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
warn: (message, ...args) => {
|
|
415
|
+
console.warn(message, ...args);
|
|
416
|
+
},
|
|
417
|
+
error: (message, ...args) => {
|
|
418
|
+
console.error(message, ...args);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
369
422
|
// packages/astro-tokenkit/src/auth/manager.ts
|
|
370
423
|
/**
|
|
371
424
|
* Single-flight refresh manager
|
|
@@ -422,14 +475,14 @@ class TokenManager {
|
|
|
422
475
|
}
|
|
423
476
|
let response;
|
|
424
477
|
try {
|
|
425
|
-
response = yield
|
|
478
|
+
response = yield safeFetch(url, {
|
|
426
479
|
method: 'POST',
|
|
427
480
|
headers,
|
|
428
481
|
body: requestBody,
|
|
429
|
-
});
|
|
482
|
+
}, this.config);
|
|
430
483
|
}
|
|
431
484
|
catch (error) {
|
|
432
|
-
const authError = new AuthError(`Login request failed: ${error.message}
|
|
485
|
+
const authError = new AuthError(`Login request failed: ${error.message}`, undefined, undefined, undefined, error);
|
|
433
486
|
if (options === null || options === void 0 ? void 0 : options.onError)
|
|
434
487
|
yield options.onError(authError, ctx);
|
|
435
488
|
throw authError;
|
|
@@ -503,14 +556,14 @@ class TokenManager {
|
|
|
503
556
|
}
|
|
504
557
|
let response;
|
|
505
558
|
try {
|
|
506
|
-
response = yield
|
|
559
|
+
response = yield safeFetch(url, {
|
|
507
560
|
method: 'POST',
|
|
508
561
|
headers,
|
|
509
562
|
body: requestBody,
|
|
510
|
-
});
|
|
563
|
+
}, this.config);
|
|
511
564
|
}
|
|
512
565
|
catch (error) {
|
|
513
|
-
throw new AuthError(`Refresh request failed: ${error.message}
|
|
566
|
+
throw new AuthError(`Refresh request failed: ${error.message}`, undefined, undefined, undefined, error);
|
|
514
567
|
}
|
|
515
568
|
if (!response.ok) {
|
|
516
569
|
// 401/403 = invalid refresh token
|
|
@@ -608,11 +661,11 @@ class TokenManager {
|
|
|
608
661
|
const injectFn = (_a = this.config.injectToken) !== null && _a !== void 0 ? _a : ((token, type) => `${type !== null && type !== void 0 ? type : 'Bearer'} ${token}`);
|
|
609
662
|
headers['Authorization'] = injectFn(session.accessToken, session.tokenType);
|
|
610
663
|
}
|
|
611
|
-
yield
|
|
664
|
+
yield safeFetch(url, { method: 'POST', headers }, this.config);
|
|
612
665
|
}
|
|
613
666
|
catch (error) {
|
|
614
667
|
// Ignore logout endpoint errors
|
|
615
|
-
|
|
668
|
+
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
616
669
|
}
|
|
617
670
|
}
|
|
618
671
|
clearTokens(ctx, this.config.cookies);
|
|
@@ -669,12 +722,14 @@ if (!globalStorage[CONFIG_KEY]) {
|
|
|
669
722
|
getContextStore: undefined,
|
|
670
723
|
setContextStore: undefined,
|
|
671
724
|
baseURL: "",
|
|
725
|
+
debug: false,
|
|
672
726
|
};
|
|
673
727
|
}
|
|
674
728
|
/**
|
|
675
729
|
* Set configuration
|
|
676
730
|
*/
|
|
677
731
|
function setConfig(userConfig) {
|
|
732
|
+
var _a, _b;
|
|
678
733
|
const currentConfig = globalStorage[CONFIG_KEY];
|
|
679
734
|
const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
|
|
680
735
|
// Validate that getter and setter are defined together
|
|
@@ -685,7 +740,8 @@ function setConfig(userConfig) {
|
|
|
685
740
|
globalStorage[CONFIG_KEY] = finalConfig;
|
|
686
741
|
// Re-initialize global token manager if auth changed
|
|
687
742
|
if (finalConfig.auth) {
|
|
688
|
-
|
|
743
|
+
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 });
|
|
744
|
+
globalStorage[MANAGER_KEY] = new TokenManager(authConfig, finalConfig.baseURL);
|
|
689
745
|
}
|
|
690
746
|
else {
|
|
691
747
|
globalStorage[MANAGER_KEY] = undefined;
|
|
@@ -754,7 +810,7 @@ function createMiddleware() {
|
|
|
754
810
|
else if (config.context) {
|
|
755
811
|
contextStrategy = 'custom (external AsyncLocalStorage)';
|
|
756
812
|
}
|
|
757
|
-
|
|
813
|
+
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`);
|
|
758
814
|
globalStorage[LOGGED_KEY] = true;
|
|
759
815
|
}
|
|
760
816
|
const runLogic = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -766,7 +822,7 @@ function createMiddleware() {
|
|
|
766
822
|
}
|
|
767
823
|
catch (error) {
|
|
768
824
|
// Log only the message to avoid leaking sensitive data in the error object
|
|
769
|
-
|
|
825
|
+
logger.debug('[TokenKit] Automatic token rotation failed:', error.message || error);
|
|
770
826
|
}
|
|
771
827
|
}
|
|
772
828
|
return next();
|