⚠️ 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
- Roadmap
- 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 onceSimplified 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 downCombine 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 concurrentAutomatic 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, retryApply 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
- 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