astro-tokenkit 1.0.19 → 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/README.md +14 -0
- package/dist/auth/manager.js +44 -16
- package/dist/client/client.js +19 -7
- package/dist/index.cjs +69 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +69 -30
- 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 +4 -2
package/README.md
CHANGED
|
@@ -307,3 +307,17 @@ Run on a standard development machine using `npm run bench`:
|
|
|
307
307
|
## License
|
|
308
308
|
|
|
309
309
|
MIT © [oamm](https://github.com/oamm)
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Playground
|
|
314
|
+
|
|
315
|
+
We've included a [playground](./playground) project to quickly test the integration.
|
|
316
|
+
|
|
317
|
+
To run the playground:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
npm run playground
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
This will install the dependencies and start the Astro dev server for the playground.
|
package/dist/auth/manager.js
CHANGED
|
@@ -127,11 +127,27 @@ export class TokenManager {
|
|
|
127
127
|
*/
|
|
128
128
|
refresh(ctx, refreshToken, options, headers) {
|
|
129
129
|
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
logger.debug('[TokenKit] Starting token refresh', !!this.config.debug);
|
|
130
131
|
try {
|
|
131
|
-
|
|
132
|
+
const bundle = yield this.performRefresh(ctx, refreshToken, options, headers);
|
|
133
|
+
if (bundle) {
|
|
134
|
+
if (this.config.onRefresh) {
|
|
135
|
+
yield this.config.onRefresh(bundle, ctx);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
logger.debug('[TokenKit] Token refresh returned no bundle (invalid or expired)', !!this.config.debug);
|
|
140
|
+
if (this.config.onRefreshError) {
|
|
141
|
+
yield this.config.onRefreshError(new AuthError('Refresh token invalid or expired', 401), ctx);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return bundle;
|
|
132
145
|
}
|
|
133
146
|
catch (error) {
|
|
134
|
-
|
|
147
|
+
logger.debug(`[TokenKit] Token refresh failed: ${error.message}`, !!this.config.debug);
|
|
148
|
+
if (this.config.onRefreshError) {
|
|
149
|
+
yield this.config.onRefreshError(error, ctx);
|
|
150
|
+
}
|
|
135
151
|
throw error;
|
|
136
152
|
}
|
|
137
153
|
});
|
|
@@ -210,14 +226,19 @@ export class TokenManager {
|
|
|
210
226
|
const tokens = retrieveTokens(ctx, this.config.cookies);
|
|
211
227
|
// No tokens
|
|
212
228
|
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresAt) {
|
|
229
|
+
logger.debug('[TokenKit] No valid session found, refresh impossible', !!this.config.debug);
|
|
213
230
|
return null;
|
|
214
231
|
}
|
|
215
232
|
// Token expired or force refresh
|
|
216
|
-
|
|
233
|
+
const expired = isExpired(tokens.expiresAt, now, this.config.policy);
|
|
234
|
+
if (force || expired) {
|
|
235
|
+
logger.debug(`[TokenKit] Token ${force ? 'force refresh' : 'expired'}, refreshing...`, !!this.config.debug);
|
|
217
236
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
218
237
|
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
219
|
-
if (!bundle)
|
|
238
|
+
if (!bundle) {
|
|
239
|
+
logger.debug('[TokenKit] Refresh returned no bundle, session lost', !!this.config.debug);
|
|
220
240
|
return null;
|
|
241
|
+
}
|
|
221
242
|
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
222
243
|
storeTokens(ctx, bundle, this.config.cookies);
|
|
223
244
|
return {
|
|
@@ -229,19 +250,26 @@ export class TokenManager {
|
|
|
229
250
|
}
|
|
230
251
|
// Proactive refresh
|
|
231
252
|
if (shouldRefresh(tokens.expiresAt, now, tokens.lastRefreshAt, this.config.policy)) {
|
|
253
|
+
logger.debug('[TokenKit] Token near expiration, performing proactive refresh', !!this.config.debug);
|
|
232
254
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
255
|
+
try {
|
|
256
|
+
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
257
|
+
if (bundle) {
|
|
258
|
+
logger.debug('[TokenKit] Proactive refresh successful', !!this.config.debug);
|
|
259
|
+
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
260
|
+
storeTokens(ctx, bundle, this.config.cookies);
|
|
261
|
+
return {
|
|
262
|
+
accessToken: bundle.accessToken,
|
|
263
|
+
expiresAt: bundle.accessExpiresAt,
|
|
264
|
+
tokenType: bundle.tokenType,
|
|
265
|
+
payload: (_d = (_c = bundle.sessionPayload) !== null && _c !== void 0 ? _c : parseJWTPayload(bundle.accessToken)) !== null && _d !== void 0 ? _d : undefined,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
logger.debug(`[TokenKit] Proactive refresh failed: ${error.message}. Continuing with current token.`, !!this.config.debug);
|
|
243
271
|
}
|
|
244
|
-
// Refresh failed, check if tokens still exist
|
|
272
|
+
// Refresh failed or returned no bundle, check if tokens still exist
|
|
245
273
|
const currentTokens = retrieveTokens(ctx, this.config.cookies);
|
|
246
274
|
if (!currentTokens.accessToken) {
|
|
247
275
|
return null;
|
|
@@ -283,7 +311,7 @@ export class TokenManager {
|
|
|
283
311
|
}
|
|
284
312
|
catch (error) {
|
|
285
313
|
// Ignore logout endpoint errors
|
|
286
|
-
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
314
|
+
logger.debug('[TokenKit] Logout endpoint failed:', !!this.config.debug, error);
|
|
287
315
|
}
|
|
288
316
|
finally {
|
|
289
317
|
clearTimeout(timeoutId);
|
package/dist/client/client.js
CHANGED
|
@@ -15,6 +15,7 @@ import { calculateDelay, shouldRetry, sleep } from '../utils/retry';
|
|
|
15
15
|
import { getConfig, getTokenManager } from '../config';
|
|
16
16
|
import { createMiddleware } from '../middleware';
|
|
17
17
|
import { safeFetch } from '../utils/fetch';
|
|
18
|
+
import { logger } from '../utils/logger';
|
|
18
19
|
/**
|
|
19
20
|
* API Client
|
|
20
21
|
*/
|
|
@@ -38,7 +39,7 @@ export class APIClient {
|
|
|
38
39
|
* Get token manager
|
|
39
40
|
*/
|
|
40
41
|
get tokenManager() {
|
|
41
|
-
var _a, _b;
|
|
42
|
+
var _a, _b, _c;
|
|
42
43
|
const config = this.config;
|
|
43
44
|
if (!config.auth)
|
|
44
45
|
return undefined;
|
|
@@ -54,8 +55,8 @@ export class APIClient {
|
|
|
54
55
|
if (!this._localTokenManager ||
|
|
55
56
|
this._lastUsedAuth !== config.auth ||
|
|
56
57
|
this._lastUsedBaseURL !== config.baseURL) {
|
|
57
|
-
// Merge client-level fetch and
|
|
58
|
-
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 });
|
|
58
|
+
// Merge client-level fetch, SSL and debug settings into auth config
|
|
59
|
+
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 });
|
|
59
60
|
this._localTokenManager = new TokenManager(authConfig, config.baseURL);
|
|
60
61
|
this._lastUsedAuth = config.auth;
|
|
61
62
|
this._lastUsedBaseURL = config.baseURL;
|
|
@@ -143,8 +144,11 @@ export class APIClient {
|
|
|
143
144
|
executeRequest(config, ctx, attempt) {
|
|
144
145
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
146
|
var _a, _b, _c, _d, _e;
|
|
147
|
+
const method = config.method.toUpperCase();
|
|
148
|
+
const debug = this.config.debug;
|
|
146
149
|
// Ensure valid session (if auth is enabled)
|
|
147
150
|
if (this.tokenManager && !config.skipAuth) {
|
|
151
|
+
logger.debug(`[TokenKit] Ensuring valid session for ${method} ${config.url}`, !!debug);
|
|
148
152
|
yield this.tokenManager.ensure(ctx, config.auth, config.headers);
|
|
149
153
|
}
|
|
150
154
|
// Build full URL
|
|
@@ -153,13 +157,18 @@ export class APIClient {
|
|
|
153
157
|
const headers = this.buildHeaders(config, ctx, fullURL);
|
|
154
158
|
// Build request init
|
|
155
159
|
const init = {
|
|
156
|
-
method
|
|
160
|
+
method,
|
|
157
161
|
headers,
|
|
158
162
|
signal: config.signal,
|
|
159
163
|
};
|
|
160
|
-
// Add body for
|
|
161
|
-
|
|
164
|
+
// Add body for appropriate methods
|
|
165
|
+
const methodsWithNoBody = ['GET', 'HEAD', 'DELETE'];
|
|
166
|
+
if (config.data && !methodsWithNoBody.includes(method)) {
|
|
162
167
|
init.body = JSON.stringify(config.data);
|
|
168
|
+
// Add Content-Type if not already present
|
|
169
|
+
if (!headers['Content-Type'] && !headers['content-type']) {
|
|
170
|
+
headers['Content-Type'] = 'application/json';
|
|
171
|
+
}
|
|
163
172
|
}
|
|
164
173
|
// Apply request interceptors
|
|
165
174
|
let requestConfig = Object.assign({}, config);
|
|
@@ -177,12 +186,15 @@ export class APIClient {
|
|
|
177
186
|
clearTimeout(timeoutId);
|
|
178
187
|
// Handle 401 (try refresh and retry once)
|
|
179
188
|
if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
|
|
189
|
+
logger.debug('[TokenKit] Received 401, attempting force refresh and retry...', !!debug);
|
|
180
190
|
// Clear and try fresh session (force refresh)
|
|
181
191
|
const session = yield this.tokenManager.ensure(ctx, config.auth, config.headers, true);
|
|
182
192
|
if (session) {
|
|
193
|
+
logger.debug('[TokenKit] Force refresh successful, retrying request...', !!debug);
|
|
183
194
|
// Retry with new token
|
|
184
195
|
return this.executeRequest(config, ctx, attempt + 1);
|
|
185
196
|
}
|
|
197
|
+
logger.debug('[TokenKit] Force refresh failed or returned no session', !!debug);
|
|
186
198
|
}
|
|
187
199
|
// Parse response
|
|
188
200
|
const apiResponse = yield this.parseResponse(response, fullURL);
|
|
@@ -271,7 +283,7 @@ export class APIClient {
|
|
|
271
283
|
*/
|
|
272
284
|
buildHeaders(config, ctx, targetURL) {
|
|
273
285
|
var _a, _b;
|
|
274
|
-
const headers = Object.assign(Object.assign({
|
|
286
|
+
const headers = Object.assign(Object.assign({}, this.config.headers), config.headers);
|
|
275
287
|
// Add auth token if available (only for safe URLs)
|
|
276
288
|
if (this.tokenManager && !config.skipAuth && this.isSafeURL(targetURL)) {
|
|
277
289
|
const session = this.tokenManager.getSession(ctx);
|
package/dist/index.cjs
CHANGED
|
@@ -508,13 +508,13 @@ catch (e) {
|
|
|
508
508
|
* Logger utility that respects the debug flag in the configuration
|
|
509
509
|
*/
|
|
510
510
|
const logger = {
|
|
511
|
-
debug: (message, ...args) => {
|
|
512
|
-
if (getConfig().debug) {
|
|
511
|
+
debug: (message, force, ...args) => {
|
|
512
|
+
if (force || getConfig().debug) {
|
|
513
513
|
console.debug(message, ...args);
|
|
514
514
|
}
|
|
515
515
|
},
|
|
516
|
-
info: (message, ...args) => {
|
|
517
|
-
if (getConfig().debug) {
|
|
516
|
+
info: (message, force, ...args) => {
|
|
517
|
+
if (force || getConfig().debug) {
|
|
518
518
|
console.log(message, ...args);
|
|
519
519
|
}
|
|
520
520
|
},
|
|
@@ -640,11 +640,27 @@ class TokenManager {
|
|
|
640
640
|
*/
|
|
641
641
|
refresh(ctx, refreshToken, options, headers) {
|
|
642
642
|
return __awaiter(this, void 0, void 0, function* () {
|
|
643
|
+
logger.debug('[TokenKit] Starting token refresh', !!this.config.debug);
|
|
643
644
|
try {
|
|
644
|
-
|
|
645
|
+
const bundle = yield this.performRefresh(ctx, refreshToken, options, headers);
|
|
646
|
+
if (bundle) {
|
|
647
|
+
if (this.config.onRefresh) {
|
|
648
|
+
yield this.config.onRefresh(bundle, ctx);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
logger.debug('[TokenKit] Token refresh returned no bundle (invalid or expired)', !!this.config.debug);
|
|
653
|
+
if (this.config.onRefreshError) {
|
|
654
|
+
yield this.config.onRefreshError(new AuthError('Refresh token invalid or expired', 401), ctx);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return bundle;
|
|
645
658
|
}
|
|
646
659
|
catch (error) {
|
|
647
|
-
|
|
660
|
+
logger.debug(`[TokenKit] Token refresh failed: ${error.message}`, !!this.config.debug);
|
|
661
|
+
if (this.config.onRefreshError) {
|
|
662
|
+
yield this.config.onRefreshError(error, ctx);
|
|
663
|
+
}
|
|
648
664
|
throw error;
|
|
649
665
|
}
|
|
650
666
|
});
|
|
@@ -723,14 +739,19 @@ class TokenManager {
|
|
|
723
739
|
const tokens = retrieveTokens(ctx, this.config.cookies);
|
|
724
740
|
// No tokens
|
|
725
741
|
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresAt) {
|
|
742
|
+
logger.debug('[TokenKit] No valid session found, refresh impossible', !!this.config.debug);
|
|
726
743
|
return null;
|
|
727
744
|
}
|
|
728
745
|
// Token expired or force refresh
|
|
729
|
-
|
|
746
|
+
const expired = isExpired(tokens.expiresAt, now, this.config.policy);
|
|
747
|
+
if (force || expired) {
|
|
748
|
+
logger.debug(`[TokenKit] Token ${force ? 'force refresh' : 'expired'}, refreshing...`, !!this.config.debug);
|
|
730
749
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
731
750
|
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
732
|
-
if (!bundle)
|
|
751
|
+
if (!bundle) {
|
|
752
|
+
logger.debug('[TokenKit] Refresh returned no bundle, session lost', !!this.config.debug);
|
|
733
753
|
return null;
|
|
754
|
+
}
|
|
734
755
|
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
735
756
|
storeTokens(ctx, bundle, this.config.cookies);
|
|
736
757
|
return {
|
|
@@ -742,19 +763,26 @@ class TokenManager {
|
|
|
742
763
|
}
|
|
743
764
|
// Proactive refresh
|
|
744
765
|
if (shouldRefresh(tokens.expiresAt, now, tokens.lastRefreshAt, this.config.policy)) {
|
|
766
|
+
logger.debug('[TokenKit] Token near expiration, performing proactive refresh', !!this.config.debug);
|
|
745
767
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
768
|
+
try {
|
|
769
|
+
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
770
|
+
if (bundle) {
|
|
771
|
+
logger.debug('[TokenKit] Proactive refresh successful', !!this.config.debug);
|
|
772
|
+
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
773
|
+
storeTokens(ctx, bundle, this.config.cookies);
|
|
774
|
+
return {
|
|
775
|
+
accessToken: bundle.accessToken,
|
|
776
|
+
expiresAt: bundle.accessExpiresAt,
|
|
777
|
+
tokenType: bundle.tokenType,
|
|
778
|
+
payload: (_d = (_c = bundle.sessionPayload) !== null && _c !== void 0 ? _c : parseJWTPayload(bundle.accessToken)) !== null && _d !== void 0 ? _d : undefined,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
756
781
|
}
|
|
757
|
-
|
|
782
|
+
catch (error) {
|
|
783
|
+
logger.debug(`[TokenKit] Proactive refresh failed: ${error.message}. Continuing with current token.`, !!this.config.debug);
|
|
784
|
+
}
|
|
785
|
+
// Refresh failed or returned no bundle, check if tokens still exist
|
|
758
786
|
const currentTokens = retrieveTokens(ctx, this.config.cookies);
|
|
759
787
|
if (!currentTokens.accessToken) {
|
|
760
788
|
return null;
|
|
@@ -796,7 +824,7 @@ class TokenManager {
|
|
|
796
824
|
}
|
|
797
825
|
catch (error) {
|
|
798
826
|
// Ignore logout endpoint errors
|
|
799
|
-
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
827
|
+
logger.debug('[TokenKit] Logout endpoint failed:', !!this.config.debug, error);
|
|
800
828
|
}
|
|
801
829
|
finally {
|
|
802
830
|
clearTimeout(timeoutId);
|
|
@@ -941,7 +969,7 @@ function createMiddleware() {
|
|
|
941
969
|
else if (config.context) {
|
|
942
970
|
contextStrategy = 'custom (external AsyncLocalStorage)';
|
|
943
971
|
}
|
|
944
|
-
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})
|
|
972
|
+
logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`, !!config.debug);
|
|
945
973
|
globalStorage[LOGGED_KEY] = true;
|
|
946
974
|
}
|
|
947
975
|
const runLogic = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -953,7 +981,7 @@ function createMiddleware() {
|
|
|
953
981
|
}
|
|
954
982
|
catch (error) {
|
|
955
983
|
// Log only the message to avoid leaking sensitive data in the error object
|
|
956
|
-
logger.debug('[TokenKit] Automatic token rotation failed:', error.message || error);
|
|
984
|
+
logger.debug('[TokenKit] Automatic token rotation failed:', !!config.debug, error.message || error);
|
|
957
985
|
}
|
|
958
986
|
}
|
|
959
987
|
return next();
|
|
@@ -998,7 +1026,7 @@ class APIClient {
|
|
|
998
1026
|
* Get token manager
|
|
999
1027
|
*/
|
|
1000
1028
|
get tokenManager() {
|
|
1001
|
-
var _a, _b;
|
|
1029
|
+
var _a, _b, _c;
|
|
1002
1030
|
const config = this.config;
|
|
1003
1031
|
if (!config.auth)
|
|
1004
1032
|
return undefined;
|
|
@@ -1014,8 +1042,8 @@ class APIClient {
|
|
|
1014
1042
|
if (!this._localTokenManager ||
|
|
1015
1043
|
this._lastUsedAuth !== config.auth ||
|
|
1016
1044
|
this._lastUsedBaseURL !== config.baseURL) {
|
|
1017
|
-
// Merge client-level fetch and
|
|
1018
|
-
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 });
|
|
1045
|
+
// Merge client-level fetch, SSL and debug settings into auth config
|
|
1046
|
+
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 });
|
|
1019
1047
|
this._localTokenManager = new TokenManager(authConfig, config.baseURL);
|
|
1020
1048
|
this._lastUsedAuth = config.auth;
|
|
1021
1049
|
this._lastUsedBaseURL = config.baseURL;
|
|
@@ -1103,8 +1131,11 @@ class APIClient {
|
|
|
1103
1131
|
executeRequest(config, ctx, attempt) {
|
|
1104
1132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1105
1133
|
var _a, _b, _c, _d, _e;
|
|
1134
|
+
const method = config.method.toUpperCase();
|
|
1135
|
+
const debug = this.config.debug;
|
|
1106
1136
|
// Ensure valid session (if auth is enabled)
|
|
1107
1137
|
if (this.tokenManager && !config.skipAuth) {
|
|
1138
|
+
logger.debug(`[TokenKit] Ensuring valid session for ${method} ${config.url}`, !!debug);
|
|
1108
1139
|
yield this.tokenManager.ensure(ctx, config.auth, config.headers);
|
|
1109
1140
|
}
|
|
1110
1141
|
// Build full URL
|
|
@@ -1113,13 +1144,18 @@ class APIClient {
|
|
|
1113
1144
|
const headers = this.buildHeaders(config, ctx, fullURL);
|
|
1114
1145
|
// Build request init
|
|
1115
1146
|
const init = {
|
|
1116
|
-
method
|
|
1147
|
+
method,
|
|
1117
1148
|
headers,
|
|
1118
1149
|
signal: config.signal,
|
|
1119
1150
|
};
|
|
1120
|
-
// Add body for
|
|
1121
|
-
|
|
1151
|
+
// Add body for appropriate methods
|
|
1152
|
+
const methodsWithNoBody = ['GET', 'HEAD', 'DELETE'];
|
|
1153
|
+
if (config.data && !methodsWithNoBody.includes(method)) {
|
|
1122
1154
|
init.body = JSON.stringify(config.data);
|
|
1155
|
+
// Add Content-Type if not already present
|
|
1156
|
+
if (!headers['Content-Type'] && !headers['content-type']) {
|
|
1157
|
+
headers['Content-Type'] = 'application/json';
|
|
1158
|
+
}
|
|
1123
1159
|
}
|
|
1124
1160
|
// Apply request interceptors
|
|
1125
1161
|
let requestConfig = Object.assign({}, config);
|
|
@@ -1137,12 +1173,15 @@ class APIClient {
|
|
|
1137
1173
|
clearTimeout(timeoutId);
|
|
1138
1174
|
// Handle 401 (try refresh and retry once)
|
|
1139
1175
|
if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
|
|
1176
|
+
logger.debug('[TokenKit] Received 401, attempting force refresh and retry...', !!debug);
|
|
1140
1177
|
// Clear and try fresh session (force refresh)
|
|
1141
1178
|
const session = yield this.tokenManager.ensure(ctx, config.auth, config.headers, true);
|
|
1142
1179
|
if (session) {
|
|
1180
|
+
logger.debug('[TokenKit] Force refresh successful, retrying request...', !!debug);
|
|
1143
1181
|
// Retry with new token
|
|
1144
1182
|
return this.executeRequest(config, ctx, attempt + 1);
|
|
1145
1183
|
}
|
|
1184
|
+
logger.debug('[TokenKit] Force refresh failed or returned no session', !!debug);
|
|
1146
1185
|
}
|
|
1147
1186
|
// Parse response
|
|
1148
1187
|
const apiResponse = yield this.parseResponse(response, fullURL);
|
|
@@ -1231,7 +1270,7 @@ class APIClient {
|
|
|
1231
1270
|
*/
|
|
1232
1271
|
buildHeaders(config, ctx, targetURL) {
|
|
1233
1272
|
var _a, _b;
|
|
1234
|
-
const headers = Object.assign(Object.assign({
|
|
1273
|
+
const headers = Object.assign(Object.assign({}, this.config.headers), config.headers);
|
|
1235
1274
|
// Add auth token if available (only for safe URLs)
|
|
1236
1275
|
if (this.tokenManager && !config.skipAuth && this.isSafeURL(targetURL)) {
|
|
1237
1276
|
const session = this.tokenManager.getSession(ctx);
|
|
@@ -1380,7 +1419,7 @@ function tokenKit(config) {
|
|
|
1380
1419
|
}
|
|
1381
1420
|
// Always inject the client-side script for idle monitoring
|
|
1382
1421
|
injectScript('page', `import 'astro-tokenkit/client-init';`);
|
|
1383
|
-
logger.debug('[TokenKit] Integration initialized');
|
|
1422
|
+
logger.debug('[TokenKit] Integration initialized', !!config.debug);
|
|
1384
1423
|
},
|
|
1385
1424
|
},
|
|
1386
1425
|
};
|