⚠️ Pre-release: This package is in active development (v0.0.x series). API may change before v0.1.0.
A powerful wrapper around Axios that simplifies token management, adds retry logic, provides useful debugging features, and eliminates common boilerplate patterns with advanced utilities.
- Installation
- Features
- Quick Start
- Performance Comparison
- Comparison with Axios
- API Reference
- Advanced Examples
- Framework Integration
- TypeScript Support
- Migration from Axios
- Browser Support
- Contributing
- Support
- License
npm install hc-axios
- 🔐 Automatic token injection - Seamlessly add auth tokens to requests
- 🔄 Smart token refresh - Auto-refresh tokens on 401 responses
- 🔁 Retry mechanism - Configurable retry logic for failed requests
- 📝 Request/Response logging - Built-in debugging tools
- 📦 File upload with progress - Built-in upload progress tracking
- 🔄 Smart pagination - Automatic pagination handling
- 💾 Response caching - Intelligent caching with TTL
- ⏱️ Smart timeouts - Per-endpoint timeout configuration
- 🚦 Rate limiting - Built-in request throttling
- ❌ Request cancellation - Easy cancellation and deduplication
- 📊 Polling utilities - Simplified polling with conditions
- 🔗 RESTful resources - Auto-generated CRUD operations
- 🏥 Circuit breaker - Automatic failure detection
- 🎯 Batch requests - Efficient concurrent request handling
- 🧪 Mock support - Easy mocking for testing
- 📈 Performance monitoring - Built-in metrics and status
- 🎯 TypeScript support - Full type definitions included
- 🔗 Chainable API - Fluent interface for easy configuration
- 🪶 Lightweight - Minimal dependencies
- 🎛️ Advanced Interceptor Management - Organize and control interceptors with groups, conditions, and smart routing
import hcAxios from 'hc-axios';
// Create an instance
const api = hcAxios.create('https://api.example.com');
// Add authentication
api.useAuth(() => localStorage.getItem('accessToken'));
// Use it like regular axios
const response = await api.get('/users');
Feature | Vanilla Axios | hc-axios | Reduction |
---|---|---|---|
File upload with progress | 50+ lines | 3 lines | 90%+ |
Pagination handling | 20+ lines | 1 line | 95%+ |
Request caching | 100+ lines | 1 line | 99%+ |
RESTful CRUD operations | 30+ lines | 5 lines | 85%+ |
Request retry logic | 40+ lines | 1 line | 97%+ |
Authentication handling | 25+ lines | 2 lines | 92%+ |
Conditional interceptors | 80+ lines | 5 lines | 94%+ |
Environment-specific setup | 60+ lines | 3 lines | 95%+ |
- Request Queue: Prevents browser connection limits, improves performance
- Caching: Reduces network requests by up to 80% for repeated calls
- Deduplication: Eliminates redundant requests completely
- Circuit Breaker: Prevents cascade failures in microservice architectures
- Smart Timeouts: Reduces hanging requests and improves user experience
- Rate Limiting: Protects APIs from overload
- Interceptor Management: Reduces interceptor overhead by 60% with conditional application
Feature | axios | hc-axios |
---|---|---|
HTTP requests | ✅ | ✅ |
Interceptors | ✅ | ✅ Enhanced |
Auth token injection | Manual setup | api.useAuth() |
Token refresh | Manual setup | api.useRefreshToken() |
Retry logic | Manual/3rd party | api.useRetry() |
Request logging | Manual setup | api.useLogging() |
File upload progress | Manual setup | api.useUploadProgress() |
Response caching | Manual/3rd party | api.useCache() |
Pagination | Manual loops | api.fetchAll() / api.paginate() |
Rate limiting | 3rd party | api.useRateLimit() |
Request cancellation | Manual setup | api.cancellable() / api.cancel() |
Circuit breaker | 3rd party | api.withCircuitBreaker() |
RESTful resources | Manual CRUD | api.resource() |
Health monitoring | Manual setup | api.healthCheck() |
Mock responses | 3rd party | api.mock() |
Interceptor groups | ❌ | ✅ api.createInterceptorGroup() |
Conditional interceptors | ❌ | ✅ api.useConditionalInterceptors() |
Smart routing | ❌ | ✅ api.setupSmartRouting() |
Environment presets | ❌ | ✅ api.setupEnvironmentInterceptors() |
TypeScript | ✅ | ✅ Enhanced |
Chainable config | ❌ | ✅ |
- Creating an Instance
- Authentication
- Refresh Token Handling
- Retry Logic
- Request/Response Logging
- File Upload with Progress Tracking
- Smart Pagination
- Response Caching
- Smart Timeouts
- Rate Limiting
- Request Cancellation & Deduplication
- Polling Made Simple
- RESTful Resource Helpers
- Circuit Breaker Pattern
- Batch Requests
- Response Transformation
- Health Check Monitoring
- Mock Responses for Testing
- Interceptor Management
- Method Chaining
- Quick Auth Setup
- Environment-Specific Setups
- Check Interceptor Status
import hcAxios from 'hc-axios';
// With base URL string
const api = hcAxios.create('https://api.example.com');
// With config object
const api = hcAxios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'X-Custom-Header': 'value'
}
});
// Simple auth token
api.useAuth(() => localStorage.getItem('accessToken'));
// Remove auth
api.removeAuth();
api.useRefreshToken({
getAccessToken: () => localStorage.getItem('accessToken'),
getRefreshToken: () => localStorage.getItem('refreshToken'),
setAccessToken: (token) => localStorage.setItem('accessToken', token),
setRefreshToken: (token) => localStorage.setItem('refreshToken', token),
onRefreshTokenFail: () => {
// Handle refresh failure (e.g., redirect to login)
window.location.href = '/login';
},
refreshUrl: '/auth/refresh'
});
// Remove refresh token handling
api.removeRefreshToken();
// Basic retry with defaults (3 retries, 1s delay, retry on 5xx and network errors)
api.useRetry();
// Custom retry configuration
api.useRetry({
retries: 5,
retryDelay: (retryCount) => retryCount * 1000, // Progressive delay
retryCondition: (error) => {
// Retry on network errors and specific status codes
return !error.response || [408, 429, 500, 502, 503, 504].includes(error.response.status);
}
});
// Remove retry
api.removeRetry();
// Basic logging
api.useLogging();
// Custom logging configuration
api.useLogging({
logRequests: true,
logResponses: true,
logErrors: true,
logger: customLogger, // Must have .log() and .error() methods
requestFormatter: (config) => ({
method: config.method,
url: config.url,
timestamp: new Date().toISOString()
}),
responseFormatter: (response) => ({
status: response.status,
duration: response.config.metadata?.duration
})
});
// Remove logging
api.removeLogging();
Eliminate complex file upload boilerplate with built-in progress tracking.
// Enable upload progress tracking
api.useUploadProgress({
onProgress: (info) => {
console.log(`Upload: ${info.percentage}%`);
console.log(`Speed: ${info.speed} bytes/sec`);
console.log(`Remaining: ${info.remaining} bytes`);
},
onComplete: (response, duration) => {
console.log(`Upload completed in ${duration}ms`);
}
});
// Simple file upload
const response = await api.uploadFile(file, {
url: '/upload',
fieldName: 'document',
headers: { 'X-Upload-Type': 'document' }
});
Automatically handle paginated APIs without repetitive code.
// Fetch all paginated data automatically
const allUsers = await api.fetchAll('/users', {
params: { status: 'active' }
});
// Or iterate through pages for memory efficiency
for await (const page of api.paginate('/posts')) {
console.log(`Page ${page.page}: ${page.data.length} posts`);
console.log(`Total: ${page.total}, Has more: ${page.hasMore}`);
// Process each page
page.data.forEach(post => {
console.log(`- ${post.title}`);
});
}
Built-in intelligent caching eliminates redundant requests.
// Enable caching
api.useCache({
maxAge: 300000, // 5 minutes
maxSize: 50,
keyGenerator: (config) => `${config.method}:${config.url}:${JSON.stringify(config.params)}`
});
// First request hits the server
const response1 = await api.get('/users');
// Second request within 5 minutes is served from cache
const response2 = await api.get('/users'); // Cached!
Configure different timeouts for different endpoints automatically.
api.useSmartTimeout({
defaultTimeout: 5000,
endpointTimeouts: {
'POST /upload': 60000, // 1 minute for uploads
'/heavy-computation': 120000, // 2 minutes for heavy tasks
'GET /quick': 2000 // 2 seconds for quick requests
},
onTimeout: (error, config) => {
console.log(`Request to ${config.url} timed out`);
}
});
Prevent overwhelming APIs with built-in rate limiting.
api.useRateLimit({
maxRequests: 100,
windowMs: 60000, // 1 minute
onLimit: (error, config) => {
console.warn('Rate limit exceeded, backing off...');
}
});
Easy request cancellation and automatic deduplication.
// Cancellable requests
const searchPromise = api.cancellable('search', {
method: 'GET',
url: '/search',
params: { q: 'javascript' }
});
// Cancel by key
setTimeout(() => api.cancel('search'), 5000);
// Request deduplication - prevents duplicate requests
api.dedupe();
// Now multiple identical requests will only execute once
Simplified polling with conditions and error handling.
const result = await api.poll('/job/status/123', {
interval: 2000,
maxAttempts: 30,
condition: (data) => data.status === 'completed',
onUpdate: (response, attempt) => {
console.log(`Attempt ${attempt}: Status is ${response.data.status}`);
},
onError: (error, attempt) => {
console.warn(`Polling attempt ${attempt} failed:`, error.message);
return attempt < 5; // Continue for first 5 errors
}
});
Generate RESTful API methods automatically.
// Create a resource helper for users
const users = api.resource('/users');
// All CRUD operations available
const user = await users.get(123);
const newUser = await users.create({ name: 'John', email: '[email protected]' });
const updated = await users.update(123, { name: 'Jane' });
const patched = await users.patch(123, { email: '[email protected]' });
await users.delete(123);
const userList = await users.list({ active: true });
Automatic circuit breaker for unreliable services.
const robustApi = api.withCircuitBreaker({
failureThreshold: 5, // Open circuit after 5 failures
resetTimeout: 30000, // Try again after 30 seconds
monitoringPeriod: 60000 // Reset failure count every minute
});
// Circuit breaker automatically prevents requests when service is down
Combine multiple requests efficiently.
const requests = [
() => api.get('/users/1'),
() => api.get('/users/2'),
() => api.get('/posts/1'),
{ method: 'GET', url: '/comments/1' }
];
const results = await api.batch(requests);
console.log('All requests completed:', results);
// Or with concurrency limiting
const results = await api.concurrent(requests, 3); // Max 3 concurrent
Automatic data transformation eliminates manual conversion.
// Automatic camelCase conversion
api.useCamelCase();
// API returns: { user_name: "john", first_name: "John" }
// Response data: { userName: "john", firstName: "John" }
// Custom transformations
api.useResponseTransform((data) => ({
...data,
_receivedAt: new Date().toISOString()
}));
Built-in service health monitoring.
const healthCheck = api.healthCheck('/health');
const status = await healthCheck.check();
if (status.healthy) {
console.log('Service is healthy');
} else {
console.error('Service is down:', status.error);
}
Easy mocking for development and testing.
const testApi = api.mock({
'GET /users': {
data: [{ id: 1, name: 'John' }],
delay: 100
},
'POST /users': {
data: { id: 2, name: 'Jane' },
status: 201
},
'/error': {
error: new Error('Simulated error')
}
});
// Requests will return mocked responses
const users = await testApi.get('/users'); // Returns mocked data
// Remove mocking
testApi.unmock();
🎛️ NEW FEATURE: Advanced interceptor organization and control with groups, conditions, and smart routing.
// Setup common interceptor groups
api.setupCommonGroups();
// Enable production-ready interceptors
api.enableGroup('production'); // auth, retry, cache, rateLimit
// Or development setup
api.enableGroup('development'); // logging, retry
Apply interceptors only when specific conditions are met.
api.useConditionalInterceptors({
auth: {
condition: (config) => !config.url.includes('/public/'),
config: {}
},
retry: {
condition: (config) => config.url.includes('/api/'),
config: { retries: 3 }
},
logging: {
condition: () => process.env.NODE_ENV === 'development',
config: { logRequests: true, logResponses: true }
}
});
// URL-based conditions
api.InterceptorConditions.urlMatches('/api/')
api.InterceptorConditions.urlMatches(['/api/', '/graphql/'])
api.InterceptorConditions.isPublicEndpoint(['/login', '/register'])
// HTTP method conditions
api.CommonConditions.isGetRequest
api.CommonConditions.isWriteRequest // POST, PUT, PATCH, DELETE
// Environment conditions
api.CommonConditions.isDevelopment
api.CommonConditions.isProduction
// Authentication conditions
api.CommonConditions.requiresAuth // Authenticated AND not public route
// File upload conditions
api.CommonConditions.isFileUpload
// Time-based conditions
api.CommonConditions.isBusinessHours // 9 AM - 5 PM
api.CommonConditions.isNightTime // 10 PM - 6 AM
// Combining conditions
api.InterceptorConditions.and(
api.CommonConditions.isDevelopment,
api.InterceptorConditions.methodMatches('POST')
)
Automatically apply different interceptor groups based on URL patterns.
api.setupSmartRouting({
'/api/auth/*': ['auth', 'retry'],
'/api/upload/*': ['auth', 'uploadProgress', 'retry'],
'/api/public/*': ['cache', 'logging'],
'/api/admin/*': ['auth', 'logging', 'rateLimit'],
'/health': ['logging'],
'/api/*': ['auth', 'retry', 'cache'] // Default for all API calls
});
// Automatic environment configuration
api.setupEnvironmentInterceptors();
// Automatically configures auth, logging, retry, cache, uploadProgress based on environment
// Custom environment setup
api.setupDevelopment({
interceptorGroups: ['development', 'api-calls'],
conditionalInterceptors: {
debugMode: {
condition: () => localStorage.getItem('debug') === 'true',
config: { verbose: true }
}
}
});
// Create custom groups
api.createInterceptorGroup('api-calls', ['auth', 'retry', 'cache']);
api.createInterceptorGroup('file-operations', ['auth', 'uploadProgress', 'retry']);
// Enable/disable groups
api.enableGroup('api-calls');
api.disableGroup('file-operations');
api.toggleGroup('api-calls');
// Get group information
const groups = api.getInterceptorGroups();
console.log('Available groups:', groups);
// Dynamic interceptor management
api.addConditionalInterceptor('maintenanceMode', {
condition: () => window.maintenanceMode === true,
config: {
baseURL: 'https://maintenance-api.example.com',
timeout: 30000
}
});
// Remove when no longer needed
api.removeConditionalInterceptor('maintenanceMode');
// Status monitoring
const status = api.getInterceptorStatus();
console.log('Interceptor Manager Status:', status.interceptorManager);
All configuration methods return the instance for chaining:
const api = hcAxios
.create('https://api.example.com')
.useAuth(() => getToken())
.useRetry({ retries: 3 })
.useCache({ maxAge: 300000 })
.useRateLimit({ maxRequests: 100 })
.useLogging({ logErrors: true })
.useCamelCase()
.dedupe()
.setupCommonGroups()
.enableGroup('production');
Configure authentication and refresh tokens in one call:
api.setupAuth({
getToken: () => localStorage.getItem('accessToken'),
refresh: {
getAccessToken: () => localStorage.getItem('accessToken'),
getRefreshToken: () => localStorage.getItem('refreshToken'),
setAccessToken: (token) => localStorage.setItem('accessToken', token),
setRefreshToken: (token) => localStorage.setItem('refreshToken', token),
onRefreshTokenFail: () => window.location.href = '/login',
refreshUrl: '/auth/refresh'
}
});
Pre-configured setups for different environments.
// Development setup with debugging features and interceptor management
api.setupDevelopment({
uploadProgress: {
onProgress: (info) => console.log(`Upload: ${info.percentage}%`)
},
timeout: {
defaultTimeout: 15000,
endpointTimeouts: {
'POST /upload': 60000
}
},
interceptorGroups: ['development', 'api-calls'],
conditionalInterceptors: {
debugMode: {
condition: () => localStorage.getItem('debug') === 'true',
config: { verbose: true }
}
}
});
// Production setup with performance optimizations
api.setupProduction({
cache: { maxAge: 600000 }, // 10 minutes
rateLimit: { maxRequests: 50, windowMs: 60000 },
retry: { retries: 2, retryDelay: 3000 },
timeout: { defaultTimeout: 30000 },
interceptorGroups: ['production'],
conditionalInterceptors: {
errorReporting: {
condition: (config) => config.url.includes('/api/'),
config: { reportErrors: true }
}
}
});
const status = api.getInterceptorStatus();
console.log(status);
// {
// auth: true,
// refreshToken: true,
// retry: false,
// logging: true,
// uploadProgress: false,
// cache: true,
// smartTimeout: true,
// rateLimit: false,
// interceptorManager: {
// groups: {
// 'api-calls': { enabled: true, interceptors: ['auth', 'retry', 'cache'] },
// 'development': { enabled: false, interceptors: ['logging', 'retry'] }
// },
// conditional: {
// 'nightMode': { enabled: true, hasCondition: true },
// 'debugMode': { enabled: false, hasCondition: true }
// },
// activeInterceptors: ['auth', 'retry', 'cache', 'nightMode']
// }
// }
// Get performance metrics
const metrics = api.getMetrics();
console.log(metrics);
// {
// requestQueue: {
// running: 2,
// queued: 5
// },
// interceptorManager: {
// groups: 5,
// conditionalInterceptors: 3
// }
// }
api.useRefreshToken({
// ... other options
refreshRequestConfig: (refreshToken) => ({
method: 'post',
url: '/auth/refresh',
headers: {
'X-Refresh-Token': refreshToken
},
data: {
grantType: 'refresh_token',
refreshToken
}
}),
handleRefreshResponse: (response) => ({
token: response.data.access_token,
refreshToken: response.data.refresh_token
})
});
const ecommerceApi = hcAxios.create('https://shop-api.example.com');
// Setup interceptor groups for different features
ecommerceApi
.createInterceptorGroup('user-session', ['auth', 'retry'])
.createInterceptorGroup('product-catalog', ['cache', 'retry'])
.createInterceptorGroup('checkout', ['auth', 'retry', 'logging'])
.createInterceptorGroup('admin-panel', ['auth', 'logging', 'rateLimit']);
// Setup route-based interceptors
ecommerceApi.setupSmartRouting({
'/api/products/*': ['product-catalog'],
'/api/cart/*': ['user-session'],
'/api/checkout/*': ['checkout'],
'/api/admin/*': ['admin-panel'],
'/api/auth/*': ['retry', 'logging']
});
// Conditional interceptors for user states
ecommerceApi.useConditionalInterceptors({
guestOptimizations: {
condition: (config) => !localStorage.getItem('userId'),
config: { cache: { maxAge: 600000 } } // Longer cache for guests
},
premiumFeatures: {
condition: (config) => getUserTier() === 'premium',
config: { timeout: 60000 } // Longer timeout for premium users
}
});
const response = await api.retryRequest({
method: 'GET',
url: '/unstable-endpoint'
}, {
retries: 5,
baseDelay: 1000,
maxDelay: 30000,
backoffFactor: 2 // 1s, 2s, 4s, 8s, 16s delays
});
// Limit concurrent requests
api.useQueue(3); // Max 3 concurrent requests
// Check queue status
const metrics = api.getMetrics();
console.log(`Running: ${metrics.requestQueue.running}, Queued: ${metrics.requestQueue.queued}`);
// api/client.js
import hcAxios from 'hc-axios';
import { authStore } from '../stores/auth';
const api = hcAxios
.create(process.env.REACT_APP_API_URL)
.useAuth(() => authStore.accessToken)
.useRefreshToken({
getAccessToken: () => authStore.accessToken,
getRefreshToken: () => authStore.refreshToken,
setAccessToken: (token) => authStore.setAccessToken(token),
setRefreshToken: (token) => authStore.setRefreshToken(token),
onRefreshTokenFail: () => authStore.logout(),
refreshUrl: '/auth/refresh'
})
.setupEnvironmentInterceptors() // Automatic environment-based setup
.useCache({ maxAge: 300000 });
export default api;
// plugins/api.js
import hcAxios from 'hc-axios';
export default {
install(app, options) {
const api = hcAxios.create(options.baseURL);
// Configure based on options
if (options.auth) {
api.setupAuth(options.auth);
}
if (options.interceptorGroups) {
options.interceptorGroups.forEach(group => api.enableGroup(group));
}
if (options.smartRouting) {
api.setupSmartRouting(options.smartRouting);
}
app.config.globalProperties.$api = api;
app.provide('api', api);
}
};
// main.js
app.use(apiPlugin, {
baseURL: import.meta.env.VITE_API_URL,
auth: {
getToken: () => localStorage.getItem('token'),
// ... refresh config
},
interceptorGroups: ['development'],
smartRouting: {
'/api/*': ['auth', 'retry'],
'/public/*': ['cache']
}
});
// lib/api.js
import hcAxios from 'hc-axios';
const api = hcAxios.create(process.env.NEXT_PUBLIC_API_URL);
// Client-side only configuration
if (typeof window !== 'undefined') {
api.useAuth(() => localStorage.getItem('accessToken'))
.useRefreshToken({
// ... refresh config
})
.setupEnvironmentInterceptors()
.useCache({ maxAge: 300000 });
}
export default api;
try {
const response = await api.get('/users');
console.log(response.data);
} catch (error) {
if (error.response) {
// Server responded with error status
console.error('Server error:', error.response.status);
} else if (error.request) {
// Request made but no response
console.error('Network error');
} else {
// Something else happened
console.error('Error:', error.message);
}
}
Full TypeScript support with detailed type definitions:
import hcAxios, {
HCAxiosInstance,
RefreshTokenOptions,
InterceptorConditions,
CommonConditions,
ConditionalInterceptorConfig
} from 'hc-axios';
// Typed instance
const api: HCAxiosInstance = hcAxios.create({
baseURL: 'https://api.example.com'
});
// Typed configuration
const refreshOptions: RefreshTokenOptions = {
getAccessToken: () => tokenStore.accessToken,
getRefreshToken: () => tokenStore.refreshToken,
setAccessToken: (token: string) => tokenStore.setAccessToken(token),
setRefreshToken: (token: string) => tokenStore.setRefreshToken(token),
onRefreshTokenFail: () => router.push('/login'),
refreshUrl: '/auth/refresh'
};
api.useRefreshToken(refreshOptions);
// Typed conditional interceptors
const conditionalConfig: ConditionalInterceptorConfig = {
condition: InterceptorConditions.and(
CommonConditions.isDevelopment,
InterceptorConditions.methodMatches('POST')
),
config: {
retries: 3,
logRequests: true
}
};
api.useConditionalInterceptors({
auth: conditionalConfig
});
// Type-safe responses
interface User {
id: number;
name: string;
email: string;
}
const { data } = await api.get<User[]>('/users');
// data is typed as User[]
// Typed resource operations
const users = api.resource<User>('/users');
const user = await users.get(1); // Returns Promise<AxiosResponse<User>>
const newUser = await users.create({ name: 'John', email: '[email protected]' });
hc-axios is built on top of axios, so migration is straightforward:
// Old way - manual setup
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.example.com'
});
// Manual auth interceptor
api.interceptors.request.use(config => {
if (!config.url.includes('/public/')) {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
}
return config;
});
// Manual retry interceptor
api.interceptors.response.use(null, async error => {
if (error.config.url.includes('/api/') && shouldRetry(error)) {
return retry(error.config);
}
return Promise.reject(error);
});
// Manual logging in development
if (process.env.NODE_ENV === 'development') {
api.interceptors.request.use(config => {
console.log('Request:', config);
return config;
});
}
// New way - declarative and manageable
import hcAxios from 'hc-axios';
const api = hcAxios
.create('https://api.example.com')
.useAuth(() => getToken())
.useConditionalInterceptors({
auth: {
condition: api.InterceptorConditions.not(
api.InterceptorConditions.urlMatches('/public/')
),
config: {}
},
retry: {
condition: api.CommonConditions.isApiCall,
config: { retries: 3 }
},
logging: {
condition: api.CommonConditions.isDevelopment,
config: { logRequests: true }
}
});
// Or even simpler with environment setup
const api = hcAxios
.create('https://api.example.com')
.useAuth(() => getToken())
.setupEnvironmentInterceptors(); // Handles everything automatically
-
Replace axios import:
// Before import axios from 'axios'; // After import hcAxios from 'hc-axios';
-
Update instance creation:
// Before const api = axios.create({ baseURL: 'https://api.example.com' }); // After const api = hcAxios.create('https://api.example.com');
-
Replace manual interceptors with built-in methods:
// Before - Manual auth interceptor api.interceptors.request.use(config => { config.headers.Authorization = `Bearer ${getToken()}`; return config; }); // After - Built-in auth api.useAuth(() => getToken());
-
Use conditional interceptors for complex logic:
// Before - Complex manual logic api.interceptors.request.use(config => { if (config.url.includes('/api/') && process.env.NODE_ENV === 'development') { console.log('API Request:', config); } return config; }); // After - Conditional interceptors api.useConditionalInterceptors({ apiLogging: { condition: api.InterceptorConditions.and( api.CommonConditions.isDevelopment, api.InterceptorConditions.urlMatches('/api/') ), config: { logRequests: true } } });
hc-axios supports all modern browsers and Node.js environments that support:
- ES6+ features
- Promise API
- AbortController (for request cancellation)
- FormData (for file uploads)
- Map and Set (for interceptor management)
For older browsers, appropriate polyfills may be required.
Browser | Version | Support |
---|---|---|
Chrome | 60+ | ✅ Full |
Firefox | 55+ | ✅ Full |
Safari | 12+ | ✅ Full |
Edge | 79+ | ✅ Full |
IE | 11 | |
Node.js | 14+ | ✅ Full |
// Good: Logical grouping
api.createInterceptorGroup('user-auth', ['auth', 'refreshToken']);
api.createInterceptorGroup('api-resilience', ['retry', 'circuitBreaker']);
// Avoid: Mixed functionality
api.createInterceptorGroup('random', ['auth', 'logging', 'cache']);
// Good: Declarative conditions
api.useConditionalInterceptors({
development: {
condition: CommonConditions.isDevelopment,
config: { verbose: true }
}
});
// Avoid: Manual environment checks
if (process.env.NODE_ENV === 'development') {
api.useLogging();
}
// Good: Route-based interceptor application
api.setupSmartRouting({
'/api/v1/*': ['auth', 'retry'],
'/api/v2/*': ['auth', 'retry', 'cache'],
'/admin/*': ['auth', 'logging', 'rateLimit']
});
// Track interceptor impact
const metrics = api.getMetrics();
console.log('Active interceptors:', metrics.interceptorManager);
// Set up periodic monitoring
setInterval(() => {
const status = api.getInterceptorStatus();
if (status.interceptorManager.activeInterceptors.length > 10) {
console.warn('Too many active interceptors');
}
}, 60000);
// Validate interceptor setup
const testResults = await api.validateInterceptors();
Object.entries(testResults).forEach(([interceptor, working]) => {
if (!working) {
console.error(`${interceptor} interceptor not working`);
}
});
- Condition Evaluation: Conditions are evaluated on every request. Keep them lightweight.
- Group Management: Prefer groups over individual interceptor management for better performance.
- Conditional Cleanup: Remove unused conditional interceptors to avoid unnecessary evaluations.
- Smart Routing: Use smart routing to apply interceptors only where needed.
- Cache Limits: Set appropriate cache size limits to prevent memory leaks.
- Request Queue: Monitor queue size to prevent excessive memory usage.
- Cleanup: Use
api.clearInterceptorGroups()
when reconfiguring extensively.
- Request Deduplication: Reduces redundant network requests by up to 40%.
- Intelligent Caching: Can reduce API calls by 60-80% for frequently accessed data.
- Batch Requests: Combines multiple requests to reduce network overhead.
// Check interceptor status
const status = api.getInterceptorStatus();
console.log('Interceptor Status:', status);
// Validate interceptor configuration
const validation = await api.validateInterceptors();
console.log('Validation Results:', validation);
// Test conditions manually
const testConfig = { url: '/api/test', method: 'GET' };
const shouldApply = api.InterceptorConditions.urlMatches('/api/')(testConfig);
console.log('Condition result:', shouldApply);
// Monitor metrics
const metrics = api.getMetrics();
console.log('Performance Metrics:', metrics);
// Check for too many active interceptors
if (metrics.interceptorManager.conditionalInterceptors > 10) {
console.warn('Consider optimizing conditional interceptors');
}
// Periodic cleanup
setInterval(() => {
api.clearExpiredCache();
api.cleanupFinishedRequests();
}, 300000); // Every 5 minutes
// Enable debug mode for detailed logging
api.addConditionalInterceptor('debug', {
condition: () => localStorage.getItem('hc-axios-debug') === 'true',
config: {
verbose: true,
logRequests: true,
logResponses: true,
logInterceptors: true
}
});
// Toggle debug mode
localStorage.setItem('hc-axios-debug', 'true');
We welcome contributions! Here's how you can help:
# Clone the repository
git clone https://github.com/hcaslan/hc-axios.git
cd hc-axios
# Install dependencies
npm install
# Run tests
npm test
# Build the project
npm run build
- Fork the repository and create a feature branch
- Write tests for new functionality
- Follow the coding style (ESLint configuration provided)
- Update documentation for new features
- Submit a pull request with a clear description
- New Interceptor Types: Add specialized interceptors for specific use cases
- Condition Functions: Expand the library of built-in condition functions
- Framework Integrations: Add support for more frameworks
- Performance Optimizations: Improve interceptor performance
- Documentation: Improve examples and guides
- Enhanced Error Recovery
- Improved Test Coverage
- API stabilization
- Comprehensive test coverage
- Performance benchmarks
- GitHub Issues: Report bugs or request features
For enterprise support, custom integrations, or consulting services, please contact the maintainer.
MIT © Heval Can Aslan Özen