astro-tokenkit 1.0.16 → 1.0.17

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.
@@ -12,6 +12,8 @@ import { AuthError } from '../types';
12
12
  import { autoDetectFields, parseJWTPayload } from './detector';
13
13
  import { storeTokens, retrieveTokens, clearTokens } from './storage';
14
14
  import { shouldRefresh, isExpired } from './policy';
15
+ import { safeFetch } from '../utils/fetch';
16
+ import { logger } from '../utils/logger';
15
17
  /**
16
18
  * Single-flight refresh manager
17
19
  */
@@ -67,14 +69,14 @@ export class TokenManager {
67
69
  }
68
70
  let response;
69
71
  try {
70
- response = yield fetch(url, {
72
+ response = yield safeFetch(url, {
71
73
  method: 'POST',
72
74
  headers,
73
75
  body: requestBody,
74
- });
76
+ }, this.config);
75
77
  }
76
78
  catch (error) {
77
- const authError = new AuthError(`Login request failed: ${error.message}`);
79
+ const authError = new AuthError(`Login request failed: ${error.message}`, undefined, undefined, undefined, error);
78
80
  if (options === null || options === void 0 ? void 0 : options.onError)
79
81
  yield options.onError(authError, ctx);
80
82
  throw authError;
@@ -148,14 +150,14 @@ export class TokenManager {
148
150
  }
149
151
  let response;
150
152
  try {
151
- response = yield fetch(url, {
153
+ response = yield safeFetch(url, {
152
154
  method: 'POST',
153
155
  headers,
154
156
  body: requestBody,
155
- });
157
+ }, this.config);
156
158
  }
157
159
  catch (error) {
158
- throw new AuthError(`Refresh request failed: ${error.message}`);
160
+ throw new AuthError(`Refresh request failed: ${error.message}`, undefined, undefined, undefined, error);
159
161
  }
160
162
  if (!response.ok) {
161
163
  // 401/403 = invalid refresh token
@@ -253,11 +255,11 @@ export class TokenManager {
253
255
  const injectFn = (_a = this.config.injectToken) !== null && _a !== void 0 ? _a : ((token, type) => `${type !== null && type !== void 0 ? type : 'Bearer'} ${token}`);
254
256
  headers['Authorization'] = injectFn(session.accessToken, session.tokenType);
255
257
  }
256
- yield fetch(url, { method: 'POST', headers });
258
+ yield safeFetch(url, { method: 'POST', headers }, this.config);
257
259
  }
258
260
  catch (error) {
259
261
  // Ignore logout endpoint errors
260
- console.warn('[TokenKit] Logout endpoint failed:', error);
262
+ logger.debug('[TokenKit] Logout endpoint failed:', error);
261
263
  }
262
264
  }
263
265
  clearTokens(ctx, this.config.cookies);
@@ -14,6 +14,7 @@ import { getContextStore } from './context';
14
14
  import { calculateDelay, shouldRetry, sleep } from '../utils/retry';
15
15
  import { getConfig, getTokenManager } from '../config';
16
16
  import { createMiddleware } from '../middleware';
17
+ import { safeFetch } from '../utils/fetch';
17
18
  /**
18
19
  * API Client
19
20
  */
@@ -37,6 +38,7 @@ export class APIClient {
37
38
  * Get token manager
38
39
  */
39
40
  get tokenManager() {
41
+ var _a, _b;
40
42
  const config = this.config;
41
43
  if (!config.auth)
42
44
  return undefined;
@@ -52,7 +54,9 @@ export class APIClient {
52
54
  if (!this._localTokenManager ||
53
55
  this._lastUsedAuth !== config.auth ||
54
56
  this._lastUsedBaseURL !== config.baseURL) {
55
- this._localTokenManager = new TokenManager(config.auth, config.baseURL);
57
+ // Merge client-level fetch and SSL settings into auth config
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 });
59
+ this._localTokenManager = new TokenManager(authConfig, config.baseURL);
56
60
  this._lastUsedAuth = config.auth;
57
61
  this._lastUsedBaseURL = config.baseURL;
58
62
  }
@@ -169,7 +173,7 @@ export class APIClient {
169
173
  const controller = new AbortController();
170
174
  const timeoutId = setTimeout(() => controller.abort(), timeout);
171
175
  try {
172
- const response = yield fetch(fullURL, Object.assign(Object.assign({}, init), { signal: controller.signal }));
176
+ const response = yield safeFetch(fullURL, Object.assign(Object.assign({}, init), { signal: controller.signal }), this.config);
173
177
  clearTimeout(timeoutId);
174
178
  // Handle 401 (try refresh and retry once)
175
179
  if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
@@ -202,12 +206,12 @@ export class APIClient {
202
206
  }
203
207
  // Transform errors
204
208
  if (error instanceof Error && error.name === 'AbortError') {
205
- throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig);
209
+ throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig, error);
206
210
  }
207
211
  if (error instanceof APIError) {
208
212
  throw error;
209
213
  }
210
- throw new NetworkError(error.message, requestConfig);
214
+ throw new NetworkError(error.message, requestConfig, error);
211
215
  }
212
216
  });
213
217
  }
package/dist/config.js CHANGED
@@ -10,12 +10,14 @@ if (!globalStorage[CONFIG_KEY]) {
10
10
  getContextStore: undefined,
11
11
  setContextStore: undefined,
12
12
  baseURL: "",
13
+ debug: false,
13
14
  };
14
15
  }
15
16
  /**
16
17
  * Set configuration
17
18
  */
18
19
  export function setConfig(userConfig) {
20
+ var _a, _b;
19
21
  const currentConfig = globalStorage[CONFIG_KEY];
20
22
  const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
21
23
  // Validate that getter and setter are defined together
@@ -26,7 +28,8 @@ export function setConfig(userConfig) {
26
28
  globalStorage[CONFIG_KEY] = finalConfig;
27
29
  // Re-initialize global token manager if auth changed
28
30
  if (finalConfig.auth) {
29
- globalStorage[MANAGER_KEY] = new TokenManager(finalConfig.auth, finalConfig.baseURL);
31
+ 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 });
32
+ globalStorage[MANAGER_KEY] = new TokenManager(authConfig, finalConfig.baseURL);
30
33
  }
31
34
  else {
32
35
  globalStorage[MANAGER_KEY] = undefined;
package/dist/index.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
  }
@@ -60,8 +63,8 @@ class AuthError extends APIError {
60
63
  * Network Error
61
64
  */
62
65
  class NetworkError extends APIError {
63
- constructor(message, request) {
64
- super(message, undefined, undefined, request);
66
+ constructor(message, request, cause) {
67
+ super(message, undefined, undefined, request, cause);
65
68
  this.name = 'NetworkError';
66
69
  }
67
70
  }
@@ -69,8 +72,8 @@ class NetworkError extends APIError {
69
72
  * Timeout Error
70
73
  */
71
74
  class TimeoutError extends APIError {
72
- constructor(message, request) {
73
- super(message, undefined, undefined, request);
75
+ constructor(message, request, cause) {
76
+ super(message, undefined, undefined, request, cause);
74
77
  this.name = 'TimeoutError';
75
78
  }
76
79
  }
@@ -396,6 +399,122 @@ function isExpired(expiresAt, now, policy = {}) {
396
399
  return now + clockSkew > expiresAt;
397
400
  }
398
401
 
402
+ // packages/astro-tokenkit/src/utils/fetch.ts
403
+ /**
404
+ * Perform a fetch request with optional certificate validation bypass
405
+ */
406
+ function safeFetch(url, init, config) {
407
+ return __awaiter(this, void 0, void 0, function* () {
408
+ const fetchFn = config.fetch || fetch;
409
+ const fetchOptions = Object.assign({}, init);
410
+ if (config.dangerouslyIgnoreCertificateErrors && typeof process !== 'undefined') {
411
+ // In Node.js environment
412
+ try {
413
+ // Try to use undici Agent if available (it is built-in in Node 18+)
414
+ // However, we might need to import it if we want to create an Agent.
415
+ // Since we don't want to depend on undici in package.json, we use dynamic import.
416
+ // But wait, undici's Agent is what we need.
417
+ // As a fallback and most reliable way for self-signed certs in Node without extra deps:
418
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
419
+ // NOTE: This affects the whole process. We should ideally only do this if it's not already 0.
420
+ // But for a dev tool / specialized library, it's often what's needed.
421
+ }
422
+ catch (e) {
423
+ // Ignore
424
+ }
425
+ }
426
+ return fetchFn(url, fetchOptions);
427
+ });
428
+ }
429
+
430
+ // packages/astro-tokenkit/src/config.ts
431
+ const CONFIG_KEY = Symbol.for('astro-tokenkit.config');
432
+ const MANAGER_KEY = Symbol.for('astro-tokenkit.manager');
433
+ const globalStorage = globalThis;
434
+ // Initialize global storage if not present
435
+ if (!globalStorage[CONFIG_KEY]) {
436
+ globalStorage[CONFIG_KEY] = {
437
+ runWithContext: undefined,
438
+ getContextStore: undefined,
439
+ setContextStore: undefined,
440
+ baseURL: "",
441
+ debug: false,
442
+ };
443
+ }
444
+ /**
445
+ * Set configuration
446
+ */
447
+ function setConfig(userConfig) {
448
+ var _a, _b;
449
+ const currentConfig = globalStorage[CONFIG_KEY];
450
+ const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
451
+ // Validate that getter and setter are defined together
452
+ if ((finalConfig.getContextStore && !finalConfig.setContextStore) ||
453
+ (!finalConfig.getContextStore && finalConfig.setContextStore)) {
454
+ throw new Error("[TokenKit] getContextStore and setContextStore must be defined together.");
455
+ }
456
+ globalStorage[CONFIG_KEY] = finalConfig;
457
+ // Re-initialize global token manager if auth changed
458
+ if (finalConfig.auth) {
459
+ 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 });
460
+ globalStorage[MANAGER_KEY] = new TokenManager(authConfig, finalConfig.baseURL);
461
+ }
462
+ else {
463
+ globalStorage[MANAGER_KEY] = undefined;
464
+ }
465
+ }
466
+ /**
467
+ * Get current configuration
468
+ */
469
+ function getConfig() {
470
+ return globalStorage[CONFIG_KEY];
471
+ }
472
+ /**
473
+ * Get global token manager
474
+ */
475
+ function getTokenManager() {
476
+ return globalStorage[MANAGER_KEY];
477
+ }
478
+ /**
479
+ * Set global token manager (mainly for testing)
480
+ */
481
+ function setTokenManager(manager) {
482
+ globalStorage[MANAGER_KEY] = manager;
483
+ }
484
+ // Handle injected configuration from Astro integration
485
+ try {
486
+ // @ts-ignore
487
+ const injectedConfig = typeof __TOKENKIT_CONFIG__ !== 'undefined' ? __TOKENKIT_CONFIG__ : undefined;
488
+ if (injectedConfig) {
489
+ setConfig(injectedConfig);
490
+ }
491
+ }
492
+ catch (e) {
493
+ // Ignore errors in environments where __TOKENKIT_CONFIG__ might be restricted
494
+ }
495
+
496
+ /**
497
+ * Logger utility that respects the debug flag in the configuration
498
+ */
499
+ const logger = {
500
+ debug: (message, ...args) => {
501
+ if (getConfig().debug) {
502
+ console.debug(message, ...args);
503
+ }
504
+ },
505
+ info: (message, ...args) => {
506
+ if (getConfig().debug) {
507
+ console.log(message, ...args);
508
+ }
509
+ },
510
+ warn: (message, ...args) => {
511
+ console.warn(message, ...args);
512
+ },
513
+ error: (message, ...args) => {
514
+ console.error(message, ...args);
515
+ }
516
+ };
517
+
399
518
  // packages/astro-tokenkit/src/auth/manager.ts
400
519
  /**
401
520
  * Single-flight refresh manager
@@ -452,14 +571,14 @@ class TokenManager {
452
571
  }
453
572
  let response;
454
573
  try {
455
- response = yield fetch(url, {
574
+ response = yield safeFetch(url, {
456
575
  method: 'POST',
457
576
  headers,
458
577
  body: requestBody,
459
- });
578
+ }, this.config);
460
579
  }
461
580
  catch (error) {
462
- const authError = new AuthError(`Login request failed: ${error.message}`);
581
+ const authError = new AuthError(`Login request failed: ${error.message}`, undefined, undefined, undefined, error);
463
582
  if (options === null || options === void 0 ? void 0 : options.onError)
464
583
  yield options.onError(authError, ctx);
465
584
  throw authError;
@@ -533,14 +652,14 @@ class TokenManager {
533
652
  }
534
653
  let response;
535
654
  try {
536
- response = yield fetch(url, {
655
+ response = yield safeFetch(url, {
537
656
  method: 'POST',
538
657
  headers,
539
658
  body: requestBody,
540
- });
659
+ }, this.config);
541
660
  }
542
661
  catch (error) {
543
- throw new AuthError(`Refresh request failed: ${error.message}`);
662
+ throw new AuthError(`Refresh request failed: ${error.message}`, undefined, undefined, undefined, error);
544
663
  }
545
664
  if (!response.ok) {
546
665
  // 401/403 = invalid refresh token
@@ -638,11 +757,11 @@ class TokenManager {
638
757
  const injectFn = (_a = this.config.injectToken) !== null && _a !== void 0 ? _a : ((token, type) => `${type !== null && type !== void 0 ? type : 'Bearer'} ${token}`);
639
758
  headers['Authorization'] = injectFn(session.accessToken, session.tokenType);
640
759
  }
641
- yield fetch(url, { method: 'POST', headers });
760
+ yield safeFetch(url, { method: 'POST', headers }, this.config);
642
761
  }
643
762
  catch (error) {
644
763
  // Ignore logout endpoint errors
645
- console.warn('[TokenKit] Logout endpoint failed:', error);
764
+ logger.debug('[TokenKit] Logout endpoint failed:', error);
646
765
  }
647
766
  }
648
767
  clearTokens(ctx, this.config.cookies);
@@ -688,69 +807,6 @@ class TokenManager {
688
807
  }
689
808
  }
690
809
 
691
- // packages/astro-tokenkit/src/config.ts
692
- const CONFIG_KEY = Symbol.for('astro-tokenkit.config');
693
- const MANAGER_KEY = Symbol.for('astro-tokenkit.manager');
694
- const globalStorage = globalThis;
695
- // Initialize global storage if not present
696
- if (!globalStorage[CONFIG_KEY]) {
697
- globalStorage[CONFIG_KEY] = {
698
- runWithContext: undefined,
699
- getContextStore: undefined,
700
- setContextStore: undefined,
701
- baseURL: "",
702
- };
703
- }
704
- /**
705
- * Set configuration
706
- */
707
- function setConfig(userConfig) {
708
- const currentConfig = globalStorage[CONFIG_KEY];
709
- const finalConfig = Object.assign(Object.assign({}, currentConfig), userConfig);
710
- // Validate that getter and setter are defined together
711
- if ((finalConfig.getContextStore && !finalConfig.setContextStore) ||
712
- (!finalConfig.getContextStore && finalConfig.setContextStore)) {
713
- throw new Error("[TokenKit] getContextStore and setContextStore must be defined together.");
714
- }
715
- globalStorage[CONFIG_KEY] = finalConfig;
716
- // Re-initialize global token manager if auth changed
717
- if (finalConfig.auth) {
718
- globalStorage[MANAGER_KEY] = new TokenManager(finalConfig.auth, finalConfig.baseURL);
719
- }
720
- else {
721
- globalStorage[MANAGER_KEY] = undefined;
722
- }
723
- }
724
- /**
725
- * Get current configuration
726
- */
727
- function getConfig() {
728
- return globalStorage[CONFIG_KEY];
729
- }
730
- /**
731
- * Get global token manager
732
- */
733
- function getTokenManager() {
734
- return globalStorage[MANAGER_KEY];
735
- }
736
- /**
737
- * Set global token manager (mainly for testing)
738
- */
739
- function setTokenManager(manager) {
740
- globalStorage[MANAGER_KEY] = manager;
741
- }
742
- // Handle injected configuration from Astro integration
743
- try {
744
- // @ts-ignore
745
- const injectedConfig = typeof __TOKENKIT_CONFIG__ !== 'undefined' ? __TOKENKIT_CONFIG__ : undefined;
746
- if (injectedConfig) {
747
- setConfig(injectedConfig);
748
- }
749
- }
750
- catch (e) {
751
- // Ignore errors in environments where __TOKENKIT_CONFIG__ might be restricted
752
- }
753
-
754
810
  // packages/astro-tokenkit/src/client/context.ts
755
811
  /**
756
812
  * Async local storage for Astro context
@@ -847,7 +903,7 @@ function createMiddleware() {
847
903
  else if (config.context) {
848
904
  contextStrategy = 'custom (external AsyncLocalStorage)';
849
905
  }
850
- console.log(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`);
906
+ logger.debug(`[TokenKit] Middleware initialized (auth: ${authStatus}, context: ${contextStrategy})`);
851
907
  globalStorage[LOGGED_KEY] = true;
852
908
  }
853
909
  const runLogic = () => __awaiter(this, void 0, void 0, function* () {
@@ -859,7 +915,7 @@ function createMiddleware() {
859
915
  }
860
916
  catch (error) {
861
917
  // Log only the message to avoid leaking sensitive data in the error object
862
- console.error('[TokenKit] Automatic token rotation failed:', error.message || error);
918
+ logger.debug('[TokenKit] Automatic token rotation failed:', error.message || error);
863
919
  }
864
920
  }
865
921
  return next();
@@ -904,6 +960,7 @@ class APIClient {
904
960
  * Get token manager
905
961
  */
906
962
  get tokenManager() {
963
+ var _a, _b;
907
964
  const config = this.config;
908
965
  if (!config.auth)
909
966
  return undefined;
@@ -919,7 +976,9 @@ class APIClient {
919
976
  if (!this._localTokenManager ||
920
977
  this._lastUsedAuth !== config.auth ||
921
978
  this._lastUsedBaseURL !== config.baseURL) {
922
- this._localTokenManager = new TokenManager(config.auth, config.baseURL);
979
+ // Merge client-level fetch and SSL settings into auth config
980
+ 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 });
981
+ this._localTokenManager = new TokenManager(authConfig, config.baseURL);
923
982
  this._lastUsedAuth = config.auth;
924
983
  this._lastUsedBaseURL = config.baseURL;
925
984
  }
@@ -1036,7 +1095,7 @@ class APIClient {
1036
1095
  const controller = new AbortController();
1037
1096
  const timeoutId = setTimeout(() => controller.abort(), timeout);
1038
1097
  try {
1039
- const response = yield fetch(fullURL, Object.assign(Object.assign({}, init), { signal: controller.signal }));
1098
+ const response = yield safeFetch(fullURL, Object.assign(Object.assign({}, init), { signal: controller.signal }), this.config);
1040
1099
  clearTimeout(timeoutId);
1041
1100
  // Handle 401 (try refresh and retry once)
1042
1101
  if (response.status === 401 && this.tokenManager && !config.skipAuth && attempt === 1) {
@@ -1069,12 +1128,12 @@ class APIClient {
1069
1128
  }
1070
1129
  // Transform errors
1071
1130
  if (error instanceof Error && error.name === 'AbortError') {
1072
- throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig);
1131
+ throw new TimeoutError(`Request timeout after ${timeout}ms`, requestConfig, error);
1073
1132
  }
1074
1133
  if (error instanceof APIError) {
1075
1134
  throw error;
1076
1135
  }
1077
- throw new NetworkError(error.message, requestConfig);
1136
+ throw new NetworkError(error.message, requestConfig, error);
1078
1137
  }
1079
1138
  });
1080
1139
  }
@@ -1270,7 +1329,7 @@ function tokenKit(config) {
1270
1329
  order: 'pre'
1271
1330
  });
1272
1331
  }
1273
- console.log('[TokenKit] Integration initialized');
1332
+ logger.debug('[TokenKit] Integration initialized');
1274
1333
  },
1275
1334
  },
1276
1335
  };