@dbs-portal/core-api
Version:
HTTP client and API utilities for DBS Portal
318 lines • 8.66 kB
JavaScript
/**
* Common interceptors for API requests and responses
*/
/**
* Authentication interceptor that adds bearer token to requests
*/
export function createAuthInterceptor(getToken) {
return {
onFulfilled: config => {
const token = getToken();
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
};
}
return config;
},
};
}
/**
* Base URL interceptor
*/
export function createBaseUrlInterceptor(baseURL) {
return {
onFulfilled: config => {
if (!config.baseURL && !isAbsoluteUrl(config.url)) {
config.baseURL = baseURL;
}
return config;
},
};
}
/**
* Request ID interceptor that adds unique request IDs
*/
export function createRequestIdInterceptor() {
return {
onFulfilled: config => {
config.headers = {
...config.headers,
'X-Request-ID': generateRequestId(),
};
return config;
},
};
}
/**
* Content type interceptor
*/
export function createContentTypeInterceptor(contentType) {
return {
onFulfilled: config => {
if (config.data && !config.headers?.['Content-Type'] && !config.headers?.['content-type']) {
config.headers = {
...config.headers,
'Content-Type': contentType,
};
}
return config;
},
};
}
/**
* User agent interceptor
*/
export function createUserAgentInterceptor(userAgent) {
return {
onFulfilled: config => {
config.headers = {
...config.headers,
'User-Agent': userAgent,
};
return config;
},
};
}
/**
* API version interceptor
*/
export function createApiVersionInterceptor(version, headerName = 'X-API-Version') {
return {
onFulfilled: config => {
config.headers = {
...config.headers,
[headerName]: version,
};
return config;
},
};
}
/**
* Logging interceptor for requests
*/
export function createRequestLoggingInterceptor(logger = console.log) {
return {
onFulfilled: config => {
logger('API Request', {
method: config.method,
url: config.url,
headers: config.headers,
data: config.data,
});
return config;
},
onRejected: error => {
logger('API Request Error', error);
return Promise.reject(error);
},
};
}
/**
* Logging interceptor for responses
*/
export function createResponseLoggingInterceptor(logger = console.log) {
return {
onFulfilled: response => {
logger('API Response', {
status: response.status,
statusText: response.statusText,
headers: response.headers,
data: response.data,
});
return response;
},
onRejected: error => {
logger('API Response Error', {
status: error.response?.status,
statusText: error.response?.statusText,
message: error.message,
data: error.response?.data,
});
return Promise.reject(error);
},
};
}
/**
* Response transformation interceptor
*/
export function createResponseTransformInterceptor(transformer) {
return {
onFulfilled: response => {
response.data = transformer(response.data);
return response;
},
};
}
/**
* Error handling interceptor
*/
export function createErrorHandlingInterceptor(errorHandler) {
return {
onRejected: error => {
return errorHandler(error);
},
};
}
/**
* Timeout interceptor
*/
export function createTimeoutInterceptor(timeout) {
return {
onFulfilled: config => {
if (!config.timeout) {
config.timeout = timeout;
}
return config;
},
};
}
/**
* Cache control interceptor
*/
export function createCacheControlInterceptor(cacheControl) {
return {
onFulfilled: config => {
config.headers = {
...config.headers,
'Cache-Control': cacheControl,
};
return config;
},
};
}
/**
* CSRF token interceptor
*/
export function createCsrfInterceptor(getToken, headerName = 'X-CSRF-Token') {
return {
onFulfilled: config => {
const token = getToken();
if (token &&
['POST', 'PUT', 'PATCH', 'DELETE'].includes(config.method?.toUpperCase() || '')) {
config.headers = {
...config.headers,
[headerName]: token,
};
}
return config;
},
};
}
/**
* Rate limit handling interceptor
*/
export function createRateLimitInterceptor(onRateLimit) {
return {
onRejected: error => {
if (error.response?.status === 429) {
const retryAfter = Number.parseInt(error.response.headers['retry-after'] || '60');
if (onRateLimit) {
onRateLimit(retryAfter);
}
}
return Promise.reject(error);
},
};
}
/**
* Response validation interceptor
*/
export function createResponseValidationInterceptor(validator, errorMessage = 'Invalid response data') {
return {
onFulfilled: response => {
if (!validator(response.data)) {
throw new Error(errorMessage);
}
return response;
},
};
}
/**
* Request deduplication interceptor
*/
export function createDeduplicationInterceptor() {
const pendingRequests = new Map();
const generateKey = (config) => {
return `${config.method || 'GET'}:${config.url}:${JSON.stringify(config.params || {})}`;
};
return {
requestInterceptor: {
onFulfilled: config => {
const key = generateKey(config);
config.__requestKey = key;
return config;
},
},
responseInterceptor: {
onFulfilled: response => {
const key = response.config.__requestKey;
if (key) {
pendingRequests.delete(key);
}
return response;
},
onRejected: error => {
const key = error.config.__requestKey;
if (key) {
pendingRequests.delete(key);
}
return Promise.reject(error);
},
},
};
}
/**
* Performance monitoring interceptor
*/
export function createPerformanceInterceptor(onMetrics) {
return {
requestInterceptor: {
onFulfilled: config => {
;
config.__startTime = Date.now();
return config;
},
},
responseInterceptor: {
onFulfilled: response => {
const startTime = response.config.__startTime;
if (startTime && onMetrics) {
onMetrics({
url: response.config.url,
method: response.config.method || 'GET',
duration: Date.now() - startTime,
status: response.status,
});
}
return response;
},
onRejected: error => {
const startTime = error.config.__startTime;
if (startTime && onMetrics) {
onMetrics({
url: error.config?.url || '',
method: error.config?.method || 'GET',
duration: Date.now() - startTime,
status: error.response?.status || 0,
});
}
return Promise.reject(error);
},
},
};
}
/**
* Helper function to check if URL is absolute
*/
function isAbsoluteUrl(url) {
return /^https?:\/\//.test(url);
}
/**
* Helper function to generate request ID
*/
function generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
//# sourceMappingURL=common-interceptors.js.map