astro-tokenkit 1.0.9 → 1.0.11
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 +24 -3
- package/dist/auth/manager.d.ts +4 -4
- package/dist/auth/manager.js +34 -13
- package/dist/client/client.d.ts +5 -5
- package/dist/client/client.js +11 -21
- package/dist/client/context-shared.d.ts +1 -1
- package/dist/client/context-shared.js +2 -8
- package/dist/client/context.d.ts +2 -2
- package/dist/client/context.js +6 -9
- package/dist/config.js +8 -2
- package/dist/index.cjs +68 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +41 -13
- package/dist/index.js +67 -52
- package/dist/index.js.map +1 -1
- package/dist/middleware.js +9 -8
- package/dist/types.d.ts +24 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -415,13 +415,23 @@ class TokenManager {
|
|
|
415
415
|
/**
|
|
416
416
|
* Perform login
|
|
417
417
|
*/
|
|
418
|
-
login(ctx, credentials,
|
|
418
|
+
login(ctx, credentials, options) {
|
|
419
419
|
return __awaiter(this, void 0, void 0, function* () {
|
|
420
420
|
const url = this.baseURL + this.config.login;
|
|
421
|
+
const contentType = this.config.contentType || 'application/json';
|
|
422
|
+
const headers = Object.assign(Object.assign({ 'Content-Type': contentType }, this.config.headers), options === null || options === void 0 ? void 0 : options.headers);
|
|
423
|
+
const data = Object.assign(Object.assign(Object.assign({}, this.config.loginData), options === null || options === void 0 ? void 0 : options.data), credentials);
|
|
424
|
+
let requestBody;
|
|
425
|
+
if (contentType === 'application/x-www-form-urlencoded') {
|
|
426
|
+
requestBody = new URLSearchParams(data).toString();
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
requestBody = JSON.stringify(data);
|
|
430
|
+
}
|
|
421
431
|
const response = yield fetch(url, {
|
|
422
432
|
method: 'POST',
|
|
423
|
-
headers
|
|
424
|
-
body:
|
|
433
|
+
headers,
|
|
434
|
+
body: requestBody,
|
|
425
435
|
}).catch(error => {
|
|
426
436
|
throw new AuthError(`Login request failed: ${error.message}`);
|
|
427
437
|
});
|
|
@@ -442,8 +452,8 @@ class TokenManager {
|
|
|
442
452
|
// Store in cookies
|
|
443
453
|
storeTokens(ctx, bundle, this.config.cookies);
|
|
444
454
|
// Call onLogin callback if provided
|
|
445
|
-
if (onLogin) {
|
|
446
|
-
yield onLogin(bundle, body, ctx);
|
|
455
|
+
if (options === null || options === void 0 ? void 0 : options.onLogin) {
|
|
456
|
+
yield options.onLogin(bundle, body, ctx);
|
|
447
457
|
}
|
|
448
458
|
return bundle;
|
|
449
459
|
});
|
|
@@ -451,10 +461,10 @@ class TokenManager {
|
|
|
451
461
|
/**
|
|
452
462
|
* Perform token refresh
|
|
453
463
|
*/
|
|
454
|
-
refresh(ctx, refreshToken) {
|
|
464
|
+
refresh(ctx, refreshToken, options, headers) {
|
|
455
465
|
return __awaiter(this, void 0, void 0, function* () {
|
|
456
466
|
try {
|
|
457
|
-
return yield this.performRefresh(ctx, refreshToken);
|
|
467
|
+
return yield this.performRefresh(ctx, refreshToken, options, headers);
|
|
458
468
|
}
|
|
459
469
|
catch (error) {
|
|
460
470
|
clearTokens(ctx, this.config.cookies);
|
|
@@ -465,13 +475,24 @@ class TokenManager {
|
|
|
465
475
|
/**
|
|
466
476
|
* Internal refresh implementation
|
|
467
477
|
*/
|
|
468
|
-
performRefresh(ctx, refreshToken) {
|
|
478
|
+
performRefresh(ctx, refreshToken, options, extraHeaders) {
|
|
469
479
|
return __awaiter(this, void 0, void 0, function* () {
|
|
470
480
|
const url = this.baseURL + this.config.refresh;
|
|
481
|
+
const contentType = this.config.contentType || 'application/json';
|
|
482
|
+
const headers = Object.assign(Object.assign({ 'Content-Type': contentType }, this.config.headers), extraHeaders);
|
|
483
|
+
const refreshField = this.config.refreshRequestField || 'refreshToken';
|
|
484
|
+
const data = Object.assign(Object.assign(Object.assign({}, this.config.refreshData), options === null || options === void 0 ? void 0 : options.data), { [refreshField]: refreshToken });
|
|
485
|
+
let requestBody;
|
|
486
|
+
if (contentType === 'application/x-www-form-urlencoded') {
|
|
487
|
+
requestBody = new URLSearchParams(data).toString();
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
requestBody = JSON.stringify(data);
|
|
491
|
+
}
|
|
471
492
|
const response = yield fetch(url, {
|
|
472
493
|
method: 'POST',
|
|
473
|
-
headers
|
|
474
|
-
body:
|
|
494
|
+
headers,
|
|
495
|
+
body: requestBody,
|
|
475
496
|
}).catch(error => {
|
|
476
497
|
throw new AuthError(`Refresh request failed: ${error.message}`);
|
|
477
498
|
});
|
|
@@ -506,7 +527,7 @@ class TokenManager {
|
|
|
506
527
|
/**
|
|
507
528
|
* Ensure valid tokens (with automatic refresh)
|
|
508
529
|
*/
|
|
509
|
-
ensure(ctx) {
|
|
530
|
+
ensure(ctx, options, headers) {
|
|
510
531
|
return __awaiter(this, void 0, void 0, function* () {
|
|
511
532
|
var _a, _b, _c, _d, _e;
|
|
512
533
|
const now = Math.floor(Date.now() / 1000);
|
|
@@ -518,7 +539,7 @@ class TokenManager {
|
|
|
518
539
|
// Token expired
|
|
519
540
|
if (isExpired(tokens.expiresAt, now, this.config.policy)) {
|
|
520
541
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
521
|
-
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken));
|
|
542
|
+
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
522
543
|
if (!bundle)
|
|
523
544
|
return null;
|
|
524
545
|
return {
|
|
@@ -530,7 +551,7 @@ class TokenManager {
|
|
|
530
551
|
// Proactive refresh
|
|
531
552
|
if (shouldRefresh(tokens.expiresAt, now, tokens.lastRefreshAt, this.config.policy)) {
|
|
532
553
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
533
|
-
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken));
|
|
554
|
+
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
534
555
|
if (bundle) {
|
|
535
556
|
return {
|
|
536
557
|
accessToken: bundle.accessToken,
|
|
@@ -611,6 +632,7 @@ class TokenManager {
|
|
|
611
632
|
let config = {
|
|
612
633
|
runWithContext: undefined,
|
|
613
634
|
getContextStore: undefined,
|
|
635
|
+
setContextStore: undefined,
|
|
614
636
|
baseURL: "",
|
|
615
637
|
};
|
|
616
638
|
let tokenManager;
|
|
@@ -618,8 +640,13 @@ let tokenManager;
|
|
|
618
640
|
* Set configuration
|
|
619
641
|
*/
|
|
620
642
|
function setConfig(userConfig) {
|
|
621
|
-
|
|
622
|
-
|
|
643
|
+
const finalConfig = Object.assign(Object.assign({}, config), userConfig);
|
|
644
|
+
// Validate that getter and setter are defined together
|
|
645
|
+
if ((finalConfig.getContextStore && !finalConfig.setContextStore) ||
|
|
646
|
+
(!finalConfig.getContextStore && finalConfig.setContextStore)) {
|
|
647
|
+
throw new Error("[TokenKit] getContextStore and setContextStore must be defined together.");
|
|
648
|
+
}
|
|
649
|
+
config = finalConfig;
|
|
623
650
|
// Re-initialize global token manager if auth changed
|
|
624
651
|
if (config.auth) {
|
|
625
652
|
tokenManager = new TokenManager(config.auth, config.baseURL);
|
|
@@ -663,20 +690,17 @@ function runWithContext(ctx, fn) {
|
|
|
663
690
|
/**
|
|
664
691
|
* Get current Astro context (from middleware binding or explicit)
|
|
665
692
|
*/
|
|
666
|
-
function getContextStore(
|
|
693
|
+
function getContextStore() {
|
|
667
694
|
const config = getConfig();
|
|
668
695
|
const getStore = config.getContextStore;
|
|
669
696
|
const context = config.context || als;
|
|
670
697
|
const store = getStore
|
|
671
698
|
? getStore()
|
|
672
699
|
: context.getStore();
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
throw new Error('Astro context not found. Either:\n' +
|
|
676
|
-
'1. Use api.middleware() to bind context automatically, or\n' +
|
|
677
|
-
'2. Pass context explicitly: api.get("/path", { ctx: Astro })');
|
|
700
|
+
if (!store) {
|
|
701
|
+
throw new Error('Astro context not found. Make sure to use api.middleware() to bind context automatically.');
|
|
678
702
|
}
|
|
679
|
-
return
|
|
703
|
+
return store;
|
|
680
704
|
}
|
|
681
705
|
|
|
682
706
|
// packages/astro-tokenkit/src/utils/retry.ts
|
|
@@ -731,14 +755,14 @@ function createMiddleware() {
|
|
|
731
755
|
const tokenManager = getTokenManager();
|
|
732
756
|
const config = getConfig();
|
|
733
757
|
const runLogic = () => __awaiter(this, void 0, void 0, function* () {
|
|
734
|
-
// Proactively ensure valid session if auth is configured
|
|
758
|
+
// Proactively ensure a valid session if auth is configured
|
|
735
759
|
if (tokenManager) {
|
|
736
760
|
try {
|
|
737
761
|
// This handles token rotation (refresh) if needed
|
|
738
762
|
yield tokenManager.ensure(ctx);
|
|
739
763
|
}
|
|
740
764
|
catch (error) {
|
|
741
|
-
// Log but don't block request if rotation fails
|
|
765
|
+
// Log but don't block a request if rotation fails
|
|
742
766
|
console.error('[TokenKit] Automatic token rotation failed:', error);
|
|
743
767
|
}
|
|
744
768
|
}
|
|
@@ -748,13 +772,14 @@ function createMiddleware() {
|
|
|
748
772
|
// We skip runWithContext to avoid nesting ALS.run() unnecessarily,
|
|
749
773
|
// UNLESS a custom runWithContext is provided.
|
|
750
774
|
if (config.getContextStore && !config.runWithContext) {
|
|
751
|
-
|
|
752
|
-
if (storage)
|
|
775
|
+
let storage = config.getContextStore();
|
|
776
|
+
if (storage)
|
|
777
|
+
// Update existing reference
|
|
753
778
|
storage.cookies = ctx.cookies;
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
779
|
+
else if (config.setContextStore)
|
|
780
|
+
config.setContextStore({ cookies: ctx.cookies });
|
|
781
|
+
else
|
|
782
|
+
console.error("[TokenKit] getContextStore returned null or undefined and no setter was found");
|
|
758
783
|
return runLogic();
|
|
759
784
|
}
|
|
760
785
|
const runner = (_a = config.runWithContext) !== null && _a !== void 0 ? _a : runWithContext;
|
|
@@ -862,7 +887,7 @@ class APIClient {
|
|
|
862
887
|
*/
|
|
863
888
|
request(config) {
|
|
864
889
|
return __awaiter(this, void 0, void 0, function* () {
|
|
865
|
-
const ctx = getContextStore(
|
|
890
|
+
const ctx = getContextStore();
|
|
866
891
|
let attempt = 0;
|
|
867
892
|
while (true) {
|
|
868
893
|
attempt++;
|
|
@@ -891,7 +916,7 @@ class APIClient {
|
|
|
891
916
|
var _a, _b, _c, _d, _e;
|
|
892
917
|
// Ensure valid session (if auth is enabled)
|
|
893
918
|
if (this.tokenManager && !config.skipAuth) {
|
|
894
|
-
yield this.tokenManager.ensure(ctx);
|
|
919
|
+
yield this.tokenManager.ensure(ctx, config.auth, config.headers);
|
|
895
920
|
}
|
|
896
921
|
// Build full URL
|
|
897
922
|
const fullURL = this.buildURL(config.url, config.params);
|
|
@@ -924,7 +949,7 @@ class APIClient {
|
|
|
924
949
|
// Handle 401 (try refresh and retry once)
|
|
925
950
|
if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
|
|
926
951
|
// Clear and try fresh session
|
|
927
|
-
const session = yield this.tokenManager.ensure(ctx);
|
|
952
|
+
const session = yield this.tokenManager.ensure(ctx, config.auth, config.headers);
|
|
928
953
|
if (session) {
|
|
929
954
|
// Retry with new token
|
|
930
955
|
return this.executeRequest(config, ctx, attempt + 1);
|
|
@@ -1035,48 +1060,38 @@ class APIClient {
|
|
|
1035
1060
|
if (!this.tokenManager) {
|
|
1036
1061
|
throw new Error('Auth is not configured for this client');
|
|
1037
1062
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
if (options && 'cookies' in options) {
|
|
1041
|
-
ctx = options;
|
|
1042
|
-
}
|
|
1043
|
-
else if (options) {
|
|
1044
|
-
const opt = options;
|
|
1045
|
-
ctx = opt.ctx;
|
|
1046
|
-
onLogin = opt.onLogin;
|
|
1047
|
-
}
|
|
1048
|
-
const context = getContextStore(ctx);
|
|
1049
|
-
yield this.tokenManager.login(context, credentials, onLogin);
|
|
1063
|
+
const context = getContextStore();
|
|
1064
|
+
yield this.tokenManager.login(context, credentials, options);
|
|
1050
1065
|
});
|
|
1051
1066
|
}
|
|
1052
1067
|
/**
|
|
1053
1068
|
* Logout
|
|
1054
1069
|
*/
|
|
1055
|
-
logout(
|
|
1070
|
+
logout() {
|
|
1056
1071
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1057
1072
|
if (!this.tokenManager) {
|
|
1058
1073
|
throw new Error('Auth is not configured for this client');
|
|
1059
1074
|
}
|
|
1060
|
-
const context = getContextStore(
|
|
1075
|
+
const context = getContextStore();
|
|
1061
1076
|
yield this.tokenManager.logout(context);
|
|
1062
1077
|
});
|
|
1063
1078
|
}
|
|
1064
1079
|
/**
|
|
1065
1080
|
* Check if authenticated
|
|
1066
1081
|
*/
|
|
1067
|
-
isAuthenticated(
|
|
1082
|
+
isAuthenticated() {
|
|
1068
1083
|
if (!this.tokenManager)
|
|
1069
1084
|
return false;
|
|
1070
|
-
const context = getContextStore(
|
|
1085
|
+
const context = getContextStore();
|
|
1071
1086
|
return this.tokenManager.isAuthenticated(context);
|
|
1072
1087
|
}
|
|
1073
1088
|
/**
|
|
1074
1089
|
* Get current session
|
|
1075
1090
|
*/
|
|
1076
|
-
getSession(
|
|
1091
|
+
getSession() {
|
|
1077
1092
|
if (!this.tokenManager)
|
|
1078
1093
|
return null;
|
|
1079
|
-
const context = getContextStore(
|
|
1094
|
+
const context = getContextStore();
|
|
1080
1095
|
return this.tokenManager.getSession(context);
|
|
1081
1096
|
}
|
|
1082
1097
|
}
|
|
@@ -1150,8 +1165,10 @@ exports.createMiddleware = createMiddleware;
|
|
|
1150
1165
|
exports.defineMiddleware = defineMiddleware;
|
|
1151
1166
|
exports.formatTime = formatTime;
|
|
1152
1167
|
exports.getConfig = getConfig;
|
|
1168
|
+
exports.getContextStore = getContextStore;
|
|
1153
1169
|
exports.getTokenManager = getTokenManager;
|
|
1154
1170
|
exports.parseTime = parseTime;
|
|
1171
|
+
exports.runWithContext = runWithContext;
|
|
1155
1172
|
exports.setConfig = setConfig;
|
|
1156
1173
|
exports.setTokenManager = setTokenManager;
|
|
1157
1174
|
exports.tokenKit = tokenKit;
|