
Research
/Security News
Toptalβs GitHub Organization Hijacked: 10 Malicious Packages Published
Threat actors hijacked Toptalβs GitHub org, publishing npm packages with malicious payloads that steal tokens and attempt to wipe victim systems.
A powerful wrapper around Axios that simplifies token management, adds retry logic, provides useful debugging features, and eliminates common boilerplate patterns with advanced utilities.
β οΈ 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.
npm install hc-axios
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%+ |
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 | β | β |
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: 'john@example.com' });
const updated = await users.update(123, { name: 'Jane' });
const patched = await users.patch(123, { email: 'jane@example.com' });
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: 'john@example.com' });
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:
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 | β οΈ With polyfills |
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`);
}
});
api.clearInterceptorGroups()
when reconfiguring extensively.// 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
For enterprise support, custom integrations, or consulting services, please contact the maintainer.
MIT Β© Heval Can Aslan Γzen
FAQs
A powerful wrapper around Axios that simplifies token management, adds retry logic, provides useful debugging features, and eliminates common boilerplate patterns with advanced utilities.
The npm package hc-axios receives a total of 331 weekly downloads. As such, hc-axios popularity was classified as not popular.
We found that hc-axios demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Threat actors hijacked Toptalβs GitHub org, publishing npm packages with malicious payloads that steal tokens and attempt to wipe victim systems.
Research
/Security News
Socket researchers investigate 4 malicious npm and PyPI packages with 56,000+ downloads that install surveillance malware.
Security News
The ongoing npm phishing campaign escalates as attackers hijack the popular 'is' package, embedding malware in multiple versions.