astro-tokenkit 1.0.20 → 1.0.21
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/auth/manager.js +44 -16
- package/dist/client/client.js +9 -3
- package/dist/index.cjs +59 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +59 -26
- package/dist/index.js.map +1 -1
- package/dist/integration.js +1 -1
- package/dist/middleware.cjs +50 -22
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.js +50 -22
- package/dist/middleware.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/utils/logger.d.ts +2 -2
- package/dist/utils/logger.js +4 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -106,6 +106,14 @@ interface LoginOptions extends AuthOptions {
|
|
|
106
106
|
/** Callback after failed login */
|
|
107
107
|
onError?: OnErrorCallback;
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* OnRefresh callback
|
|
111
|
+
*/
|
|
112
|
+
type OnRefreshCallback = (bundle: TokenBundle, ctx: TokenKitContext) => void | Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* OnRefreshError callback
|
|
115
|
+
*/
|
|
116
|
+
type OnRefreshErrorCallback = (error: AuthError, ctx: TokenKitContext) => void | Promise<void>;
|
|
109
117
|
/**
|
|
110
118
|
* Auth configuration
|
|
111
119
|
*/
|
|
@@ -144,6 +152,12 @@ interface AuthConfig {
|
|
|
144
152
|
fetch?: typeof fetch;
|
|
145
153
|
/** Dangerously ignore certificate errors (bypass SSL validation) */
|
|
146
154
|
dangerouslyIgnoreCertificateErrors?: boolean;
|
|
155
|
+
/** Enable debug logging for auth operations */
|
|
156
|
+
debug?: boolean;
|
|
157
|
+
/** Callback after successful refresh */
|
|
158
|
+
onRefresh?: OnRefreshCallback;
|
|
159
|
+
/** Callback after failed refresh */
|
|
160
|
+
onRefreshError?: OnRefreshErrorCallback;
|
|
147
161
|
}
|
|
148
162
|
/**
|
|
149
163
|
* Refresh policy
|
package/dist/index.js
CHANGED
|
@@ -506,13 +506,13 @@ catch (e) {
|
|
|
506
506
|
* Logger utility that respects the debug flag in the configuration
|
|
507
507
|
*/
|
|
508
508
|
const logger = {
|
|
509
|
-
debug: (message, ...args) => {
|
|
510
|
-
if (getConfig().debug) {
|
|
509
|
+
debug: (message, force, ...args) => {
|
|
510
|
+
if (force || getConfig().debug) {
|
|
511
511
|
console.debug(message, ...args);
|
|
512
512
|
}
|
|
513
513
|
},
|
|
514
|
-
info: (message, ...args) => {
|
|
515
|
-
if (getConfig().debug) {
|
|
514
|
+
info: (message, force, ...args) => {
|
|
515
|
+
if (force || getConfig().debug) {
|
|
516
516
|
console.log(message, ...args);
|
|
517
517
|
}
|
|
518
518
|
},
|
|
@@ -638,11 +638,27 @@ class TokenManager {
|
|
|
638
638
|
*/
|
|
639
639
|
refresh(ctx, refreshToken, options, headers) {
|
|
640
640
|
return __awaiter(this, void 0, void 0, function* () {
|
|
641
|
+
logger.debug('[TokenKit] Starting token refresh', !!this.config.debug);
|
|
641
642
|
try {
|
|
642
|
-
|
|
643
|
+
const bundle = yield this.performRefresh(ctx, refreshToken, options, headers);
|
|
644
|
+
if (bundle) {
|
|
645
|
+
if (this.config.onRefresh) {
|
|
646
|
+
yield this.config.onRefresh(bundle, ctx);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
logger.debug('[TokenKit] Token refresh returned no bundle (invalid or expired)', !!this.config.debug);
|
|
651
|
+
if (this.config.onRefreshError) {
|
|
652
|
+
yield this.config.onRefreshError(new AuthError('Refresh token invalid or expired', 401), ctx);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return bundle;
|
|
643
656
|
}
|
|
644
657
|
catch (error) {
|
|
645
|
-
|
|
658
|
+
logger.debug(`[TokenKit] Token refresh failed: ${error.message}`, !!this.config.debug);
|
|
659
|
+
if (this.config.onRefreshError) {
|
|
660
|
+
yield this.config.onRefreshError(error, ctx);
|
|
661
|
+
}
|
|
646
662
|
throw error;
|
|
647
663
|
}
|
|
648
664
|
});
|
|
@@ -721,14 +737,19 @@ class TokenManager {
|
|
|
721
737
|
const tokens = retrieveTokens(ctx, this.config.cookies);
|
|
722
738
|
// No tokens
|
|
723
739
|
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresAt) {
|
|
740
|
+
logger.debug('[TokenKit] No valid session found, refresh impossible', !!this.config.debug);
|
|
724
741
|
return null;
|
|
725
742
|
}
|
|
726
743
|
// Token expired or force refresh
|
|
727
|
-
|
|
744
|
+
const expired = isExpired(tokens.expiresAt, now, this.config.policy);
|
|
745
|
+
if (force || expired) {
|
|
746
|
+
logger.debug(`[TokenKit] Token ${force ? 'force refresh' : 'expired'}, refreshing...`, !!this.config.debug);
|
|
728
747
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
729
748
|
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
730
|
-
if (!bundle)
|
|
749
|
+
if (!bundle) {
|
|
750
|
+
logger.debug('[TokenKit] Refresh returned no bundle, session lost', !!this.config.debug);
|
|
731
751
|
return null;
|
|
752
|
+
}
|
|
732
753
|
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
733
754
|
storeTokens(ctx, bundle, this.config.cookies);
|
|
734
755
|
return {
|
|
@@ -740,19 +761,26 @@ class TokenManager {
|
|
|
740
761
|
}
|
|
741
762
|
// Proactive refresh
|
|
742
763
|
if (shouldRefresh(tokens.expiresAt, now, tokens.lastRefreshAt, this.config.policy)) {
|
|
764
|
+
logger.debug('[TokenKit] Token near expiration, performing proactive refresh', !!this.config.debug);
|
|
743
765
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
766
|
+
try {
|
|
767
|
+
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
768
|
+
if (bundle) {
|
|
769
|
+
logger.debug('[TokenKit] Proactive refresh successful', !!this.config.debug);
|
|
770
|
+
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
771
|
+
storeTokens(ctx, bundle, this.config.cookies);
|
|
772
|
+
return {
|
|
773
|
+
accessToken: bundle.accessToken,
|
|
774
|
+
expiresAt: bundle.accessExpiresAt,
|
|
775
|
+
tokenType: bundle.tokenType,
|
|
776
|
+
payload: (_d = (_c = bundle.sessionPayload) !== null && _c !== void 0 ? _c : parseJWTPayload(bundle.accessToken)) !== null && _d !== void 0 ? _d : undefined,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
754
779
|
}
|
|
755
|
-
|
|
780
|
+
catch (error) {
|
|
781
|
+
logger.debug(`[TokenKit] Proactive refresh failed: ${error.message}. Continuing with current token.`, !!this.config.debug);
|
|
782
|
+
}
|
|
783
|
+
// Refresh failed or returned no bundle, check if tokens still exist
|
|
756
784
|
const currentTokens = retrieveTokens(ctx, this.config.cookies);
|
|
757
785
|
if (!currentTokens.accessToken) {
|
|
758
786
|
return null;
|
|
@@ -794,7 +822,7 @@ class TokenManager {
|
|
|
794
822
|
}
|
|
795
823
|
catch (error) {
|
|
796
824
|
// Ignore logout endpoint errors
|
|
797
|
-
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
825
|
+
logger.debug('[TokenKit] Logout endpoint failed:', !!this.config.debug, error);
|
|
798
826
|
}
|
|
799
827
|
finally {
|
|
800
828
|
clearTimeout(timeoutId);
|
|
@@ -939,7 +967,7 @@ function createMiddleware() {
|
|
|
939
967
|
else if (config.context) {
|
|
940
968
|
contextStrategy = 'custom (external AsyncLocalStorage)';
|
|
941
969
|
}
|
|
942
|
-
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})
|
|
970
|
+
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`, !!config.debug);
|
|
943
971
|
globalStorage[LOGGED_KEY] = true;
|
|
944
972
|
}
|
|
945
973
|
const runLogic = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -951,7 +979,7 @@ function createMiddleware() {
|
|
|
951
979
|
}
|
|
952
980
|
catch (error) {
|
|
953
981
|
// Log only the message to avoid leaking sensitive data in the error object
|
|
954
|
-
logger.debug('[TokenKit] Automatic token rotation failed:', error.message || error);
|
|
982
|
+
logger.debug('[TokenKit] Automatic token rotation failed:', !!config.debug, error.message || error);
|
|
955
983
|
}
|
|
956
984
|
}
|
|
957
985
|
return next();
|
|
@@ -996,7 +1024,7 @@ class APIClient {
|
|
|
996
1024
|
* Get token manager
|
|
997
1025
|
*/
|
|
998
1026
|
get tokenManager() {
|
|
999
|
-
var _a, _b;
|
|
1027
|
+
var _a, _b, _c;
|
|
1000
1028
|
const config = this.config;
|
|
1001
1029
|
if (!config.auth)
|
|
1002
1030
|
return undefined;
|
|
@@ -1012,8 +1040,8 @@ class APIClient {
|
|
|
1012
1040
|
if (!this._localTokenManager ||
|
|
1013
1041
|
this._lastUsedAuth !== config.auth ||
|
|
1014
1042
|
this._lastUsedBaseURL !== config.baseURL) {
|
|
1015
|
-
// Merge client-level fetch and
|
|
1016
|
-
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 });
|
|
1043
|
+
// Merge client-level fetch, SSL and debug settings into auth config
|
|
1044
|
+
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, debug: (_c = config.auth.debug) !== null && _c !== void 0 ? _c : config.debug });
|
|
1017
1045
|
this._localTokenManager = new TokenManager(authConfig, config.baseURL);
|
|
1018
1046
|
this._lastUsedAuth = config.auth;
|
|
1019
1047
|
this._lastUsedBaseURL = config.baseURL;
|
|
@@ -1102,8 +1130,10 @@ class APIClient {
|
|
|
1102
1130
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1103
1131
|
var _a, _b, _c, _d, _e;
|
|
1104
1132
|
const method = config.method.toUpperCase();
|
|
1133
|
+
const debug = this.config.debug;
|
|
1105
1134
|
// Ensure valid session (if auth is enabled)
|
|
1106
1135
|
if (this.tokenManager && !config.skipAuth) {
|
|
1136
|
+
logger.debug(`[TokenKit] Ensuring valid session for ${method} ${config.url}`, !!debug);
|
|
1107
1137
|
yield this.tokenManager.ensure(ctx, config.auth, config.headers);
|
|
1108
1138
|
}
|
|
1109
1139
|
// Build full URL
|
|
@@ -1141,12 +1171,15 @@ class APIClient {
|
|
|
1141
1171
|
clearTimeout(timeoutId);
|
|
1142
1172
|
// Handle 401 (try refresh and retry once)
|
|
1143
1173
|
if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
|
|
1174
|
+
logger.debug('[TokenKit] Received 401, attempting force refresh and retry...', !!debug);
|
|
1144
1175
|
// Clear and try fresh session (force refresh)
|
|
1145
1176
|
const session = yield this.tokenManager.ensure(ctx, config.auth, config.headers, true);
|
|
1146
1177
|
if (session) {
|
|
1178
|
+
logger.debug('[TokenKit] Force refresh successful, retrying request...', !!debug);
|
|
1147
1179
|
// Retry with new token
|
|
1148
1180
|
return this.executeRequest(config, ctx, attempt + 1);
|
|
1149
1181
|
}
|
|
1182
|
+
logger.debug('[TokenKit] Force refresh failed or returned no session', !!debug);
|
|
1150
1183
|
}
|
|
1151
1184
|
// Parse response
|
|
1152
1185
|
const apiResponse = yield this.parseResponse(response, fullURL);
|
|
@@ -1384,7 +1417,7 @@ function tokenKit(config) {
|
|
|
1384
1417
|
}
|
|
1385
1418
|
// Always inject the client-side script for idle monitoring
|
|
1386
1419
|
injectScript('page', `import 'astro-tokenkit/client-init';`);
|
|
1387
|
-
logger.debug('[TokenKit] Integration initialized');
|
|
1420
|
+
logger.debug('[TokenKit] Integration initialized', !!config.debug);
|
|
1388
1421
|
},
|
|
1389
1422
|
},
|
|
1390
1423
|
};
|