hc-axios
Version:
A powerful wrapper around Axios that simplifies token management, adds retry logic, provides useful debugging features, and eliminates common boilerplate patterns with advanced utilities.
468 lines (401 loc) • 16 kB
TypeScript
import {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
AxiosStatic
} from 'axios';
export interface RefreshTokenOptions {
getAccessToken: () => string | null | undefined;
getRefreshToken: () => string | null | undefined;
setAccessToken: (token: string) => void;
setRefreshToken: (token: string) => void;
onRefreshTokenFail: () => void;
refreshUrl: string;
refreshRequestConfig?: (refreshToken: string) => AxiosRequestConfig;
handleRefreshResponse?: (response: AxiosResponse) => { token: string; refreshToken: string };
}
export interface ConditionalInterceptorConfig {
condition: (config: AxiosRequestConfig) => boolean;
config?: any;
}
export interface InterceptorConditionFunction {
(config: AxiosRequestConfig): boolean;
}
export interface InterceptorGroupStatus {
enabled: boolean;
interceptors: string[];
}
export interface ConditionalInterceptorStatus {
enabled: boolean;
hasCondition: boolean;
}
export interface InterceptorManagerStatus {
groups: Record<string, InterceptorGroupStatus>;
conditional: Record<string, ConditionalInterceptorStatus>;
activeInterceptors: string[];
}
export interface EnhancedInterceptorStatus {
auth: boolean;
refreshToken: boolean;
retry: boolean;
logging: boolean;
uploadProgress: boolean;
cache: boolean;
smartTimeout: boolean;
rateLimit: boolean;
interceptorManager: InterceptorManagerStatus;
}
export interface InterceptorManagerMetrics {
groups: number;
conditionalInterceptors: number;
}
export interface EnhancedInstanceMetrics {
requestQueue: QueueMetrics | null;
interceptorManager: InterceptorManagerMetrics;
}
export interface TimeRangeCondition {
start: number; // Hour (0-23)
end: number; // Hour (0-23)
}
export interface HeaderConditions {
[headerName: string]: string | RegExp | ((value: string) => boolean);
}
export interface SmartRoutingConfig {
[pattern: string]: string[];
}
// Interceptor Conditions class
export declare class InterceptorConditions {
static urlMatches(patterns: string | RegExp | (string | RegExp)[]): InterceptorConditionFunction;
static methodMatches(methods: string | string[]): InterceptorConditionFunction;
static environmentMatches(environments: string | string[]): InterceptorConditionFunction;
static headerMatches(headerConditions: HeaderConditions): InterceptorConditionFunction;
static hasDataKeys(dataKeys: string | string[]): InterceptorConditionFunction;
static timeRange(timeRange: TimeRangeCondition): InterceptorConditionFunction;
static isAuthenticated(getAuthStatus?: () => boolean): InterceptorConditionFunction;
static isOnline(): InterceptorConditionFunction;
static isFileUpload(): InterceptorConditionFunction;
static requestSizeBelow(maxSize: number): InterceptorConditionFunction;
static isPublicEndpoint(publicPaths?: string[]): InterceptorConditionFunction;
static userAgentMatches(pattern: string | RegExp): InterceptorConditionFunction;
static and(...conditions: InterceptorConditionFunction[]): InterceptorConditionFunction;
static or(...conditions: InterceptorConditionFunction[]): InterceptorConditionFunction;
static not(condition: InterceptorConditionFunction): InterceptorConditionFunction;
static custom(conditionFn: InterceptorConditionFunction): InterceptorConditionFunction;
}
// Common Conditions
export declare const CommonConditions: {
isDevelopment: InterceptorConditionFunction;
isProduction: InterceptorConditionFunction;
isGetRequest: InterceptorConditionFunction;
isPostRequest: InterceptorConditionFunction;
isWriteRequest: InterceptorConditionFunction;
isApiCall: InterceptorConditionFunction;
isAuthCall: InterceptorConditionFunction;
isPublicRoute: InterceptorConditionFunction;
requiresAuth: InterceptorConditionFunction;
isFileUpload: InterceptorConditionFunction;
isSmallRequest: InterceptorConditionFunction;
isOnline: InterceptorConditionFunction;
isBusinessHours: InterceptorConditionFunction;
isNightTime: InterceptorConditionFunction;
isMobile: InterceptorConditionFunction;
isDesktop: InterceptorConditionFunction;
};
// Interceptor Manager class
export declare class InterceptorManager {
constructor(instance: AxiosInstance);
createGroup(groupName: string, interceptorNames: string[]): InterceptorManager;
enableGroup(groupName: string): InterceptorManager;
disableGroup(groupName: string): InterceptorManager;
toggleGroup(groupName: string): InterceptorManager;
useConditionalInterceptors(config: Record<string, ConditionalInterceptorConfig>): InterceptorManager;
addConditionalInterceptor(interceptorName: string, options: ConditionalInterceptorConfig): InterceptorManager;
removeConditionalInterceptor(interceptorName: string): InterceptorManager;
enableInterceptor(interceptorName: string): InterceptorManager;
disableInterceptor(interceptorName: string): InterceptorManager;
getStatus(): InterceptorManagerStatus;
getGroups(): string[];
getConditionalInterceptors(): string[];
clearGroups(): InterceptorManager;
clearConditionalInterceptors(): InterceptorManager;
}
// Enhanced HCAxiosInstance with interceptor management
export interface HCAxiosInstance extends AxiosInstance {
// Auth methods
useAuth(getToken: () => string | null | undefined): HCAxiosInstance;
removeAuth(): HCAxiosInstance;
// Refresh token methods
useRefreshToken(options: RefreshTokenOptions): HCAxiosInstance;
removeRefreshToken(): HCAxiosInstance;
// Retry methods
useRetry(options?: RetryOptions): HCAxiosInstance;
removeRetry(): HCAxiosInstance;
// Logging methods
useLogging(options?: LoggingOptions): HCAxiosInstance;
removeLogging(): HCAxiosInstance;
// Upload progress methods
useUploadProgress(options?: UploadOptions): HCAxiosInstance;
removeUploadProgress(): HCAxiosInstance;
// Cache methods
useCache(options?: CacheOptions): HCAxiosInstance;
removeCache(): HCAxiosInstance;
// Timeout methods
useSmartTimeout(options?: TimeoutOptions): HCAxiosInstance;
removeSmartTimeout(): HCAxiosInstance;
// Rate limit methods
useRateLimit(options?: RateLimitOptions): HCAxiosInstance;
removeRateLimit(): HCAxiosInstance;
// Response transformation methods
useResponseTransform(transformer: (data: any) => any): HCAxiosInstance;
useCamelCase(): HCAxiosInstance;
// Queue methods
useQueue(maxConcurrent?: number): HCAxiosInstance;
// Group management
createInterceptorGroup(groupName: string, interceptorNames: string[]): HCAxiosInstance;
enableGroup(groupName: string): HCAxiosInstance;
disableGroup(groupName: string): HCAxiosInstance;
toggleGroup(groupName: string): HCAxiosInstance;
getInterceptorGroups(): string[];
clearInterceptorGroups(): HCAxiosInstance;
// Conditional interceptors
useConditionalInterceptors(config: Record<string, ConditionalInterceptorConfig>): HCAxiosInstance;
addConditionalInterceptor(interceptorName: string, options: ConditionalInterceptorConfig): HCAxiosInstance;
removeConditionalInterceptor(interceptorName: string): HCAxiosInstance;
getConditionalInterceptors(): string[];
clearConditionalInterceptors(): HCAxiosInstance;
// Individual interceptor control
enableInterceptor(interceptorName: string): HCAxiosInstance;
disableInterceptor(interceptorName: string): HCAxiosInstance;
// Enhanced setup methods
setupCommonGroups(): HCAxiosInstance;
setupEnvironmentInterceptors(): HCAxiosInstance;
setupSmartRouting(routes?: SmartRoutingConfig): HCAxiosInstance;
// Enhanced status and metrics
getInterceptorManagerStatus(): InterceptorManagerStatus;
getInterceptorStatus(): EnhancedInterceptorStatus;
getMetrics(): EnhancedInstanceMetrics;
// Condition utilities (exposed for advanced users)
InterceptorConditions: typeof InterceptorConditions;
CommonConditions: typeof CommonConditions;
uploadFile(file: File, options?: FileUploadOptions): Promise<AxiosResponse>;
batch<T = any>(requests: Array<(() => Promise<AxiosResponse<T>>) | AxiosRequestConfig>): Promise<AxiosResponse<T>[]>;
cancellable<T = any>(key: string, config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
cancel(key: string): void;
cancelAll(): void;
paginate<T = any>(url: string, options?: AxiosRequestConfig): AsyncIterableIterator<PaginationPage<T>>;
fetchAll<T = any>(url: string, options?: AxiosRequestConfig): Promise<T[]>;
resource<T = any>(resourcePath: string): ResourceMethods<T>;
healthCheck(endpoint?: string): HealthCheck;
poll<T = any>(url: string, options?: PollingOptions): Promise<AxiosResponse<T>>;
concurrent<T = any>(requests: Array<() => Promise<AxiosResponse<T>>>, limit?: number): Promise<AxiosResponse<T>[]>;
retryRequest<T = any>(config: AxiosRequestConfig, options?: RetryRequestOptions): Promise<AxiosResponse<T>>;
withCircuitBreaker(options?: CircuitBreakerOptions): HCAxiosInstance;
dedupe(): HCAxiosInstance;
mock(mocks: MockConfig): HCAxiosInstance;
unmock?(): HCAxiosInstance;
// Setup helpers
setupAuth(config: AuthConfig): HCAxiosInstance;
setupDevelopment(options?: DevelopmentSetupOptions): HCAxiosInstance;
setupProduction(options?: ProductionSetupOptions): HCAxiosInstance;
// Internal properties
_queue?: any;
}
// Enhanced setup options with interceptor management
export interface EnhancedDevelopmentSetupOptions extends DevelopmentSetupOptions {
interceptorGroups?: string[];
conditionalInterceptors?: Record<string, ConditionalInterceptorConfig>;
smartRouting?: SmartRoutingConfig;
}
export interface EnhancedProductionSetupOptions extends ProductionSetupOptions {
interceptorGroups?: string[];
conditionalInterceptors?: Record<string, ConditionalInterceptorConfig>;
smartRouting?: SmartRoutingConfig;
}
// Enhanced configuration interface
export interface InterceptorManagementConfig {
groups?: Record<string, string[]>;
conditionalInterceptors?: Record<string, ConditionalInterceptorConfig>;
smartRouting?: SmartRoutingConfig;
autoSetupEnvironment?: boolean;
autoSetupCommonGroups?: boolean;
}
// Testing helpers interface
export interface InterceptorTestingHelpers {
saveState(): any;
restoreState(): void;
createTestInstance(config?: any): HCAxiosInstance;
validateInterceptors(): Promise<Record<string, boolean>>;
}
// Controls interface for runtime management
export interface InterceptorControls {
toggleApiCalls(): void;
toggleDevelopment(): void;
toggleProduction(): void;
enableAuth(): void;
disableAuth(): void;
enableLogging(): void;
disableLogging(): void;
addTempLogging(): void;
getStatus(): EnhancedInterceptorStatus;
getMetrics(): EnhancedInstanceMetrics;
}
export interface UploadProgressInfo {
loaded: number;
total: number;
percentage: number;
speed: number;
remaining: number;
}
export interface PaginationPage<T = any> {
data: T[];
page: number;
total?: number;
hasMore: boolean;
}
export interface PollingOptions {
interval?: number;
maxAttempts?: number;
condition?: (data: any) => boolean;
onUpdate?: (response: AxiosResponse, attempt: number) => void;
onError?: (error: any, attempt: number) => boolean;
config?: AxiosRequestConfig;
}
export interface ResourceMethods<T = any> {
list(params?: any): Promise<AxiosResponse<T[]>>;
get(id: string | number): Promise<AxiosResponse<T>>;
create(data: Partial<T>): Promise<AxiosResponse<T>>;
update(id: string | number, data: Partial<T>): Promise<AxiosResponse<T>>;
patch(id: string | number, data: Partial<T>): Promise<AxiosResponse<T>>;
delete(id: string | number): Promise<AxiosResponse<void>>;
}
export interface QueueMetrics {
running: number;
queued: number;
}
export interface HealthCheckResult {
healthy: boolean;
status?: number;
data?: any;
error?: string;
}
export interface HealthCheck {
check(): Promise<HealthCheckResult>;
}
export interface MockConfig {
[key: string]: any;
}
export interface RetryOptions {
retries?: number;
retryDelay?: number | ((retryCount: number) => number);
retryCondition?: (error: any) => boolean;
shouldResetTimeout?: boolean;
}
export interface LoggingOptions {
logRequests?: boolean;
logResponses?: boolean;
logErrors?: boolean;
logger?: {
log: (...args: any[]) => void;
error: (...args: any[]) => void;
};
requestFormatter?: (config: AxiosRequestConfig) => any;
responseFormatter?: (response: AxiosResponse) => any;
errorFormatter?: (error: any) => any;
}
export interface UploadOptions {
onProgress?: (info: UploadProgressInfo) => void;
onStart?: (config: AxiosRequestConfig) => void;
onComplete?: (response: AxiosResponse, duration: number) => void;
onError?: (error: any) => void;
}
export interface CacheOptions {
maxAge?: number;
maxSize?: number;
keyGenerator?: (config: AxiosRequestConfig) => string;
}
export interface TimeoutOptions {
defaultTimeout?: number;
endpointTimeouts?: Record<string, number>;
onTimeout?: (error: any, config: AxiosRequestConfig) => void;
}
export interface RateLimitOptions {
maxRequests?: number;
windowMs?: number;
onLimit?: (error: any, config: AxiosRequestConfig) => void;
}
export interface AuthConfig {
getToken: () => string | null | undefined;
refresh?: RefreshTokenOptions;
}
export interface DevelopmentSetupOptions {
logging?: LoggingOptions;
retry?: RetryOptions;
uploadProgress?: UploadOptions;
timeout?: TimeoutOptions;
}
export interface ProductionSetupOptions {
retry?: RetryOptions;
cache?: CacheOptions;
rateLimit?: RateLimitOptions;
timeout?: TimeoutOptions;
logging?: LoggingOptions;
}
export interface CircuitBreakerOptions {
failureThreshold?: number;
resetTimeout?: number;
monitoringPeriod?: number;
}
export interface RetryRequestOptions {
retries?: number;
baseDelay?: number;
maxDelay?: number;
backoffFactor?: number;
}
export interface FileUploadOptions {
url?: string;
fieldName?: string;
onProgress?: (info: UploadProgressInfo) => void;
headers?: Record<string, string>;
config?: AxiosRequestConfig;
}
// Main hcAxios static interface
export interface HCAxiosStatic {
create(config?: string | AxiosRequestConfig): HCAxiosInstance;
VERSION: string;
isHCAxios: boolean;
}
// Utility exports
export declare const responseTransformers: {
toCamelCase: (data: any) => any;
toSnakeCase: (data: any) => any;
extractData: (dataPath?: string) => (response: any) => any;
addMetadata: (response: any) => any;
};
export declare const commonPatterns: {
createApiClient: (baseURL: string, options?: AxiosRequestConfig) => AxiosInstance;
createResource: <T = any>(instance: AxiosInstance, resourcePath: string) => ResourceMethods<T>;
uploadFile: (instance: AxiosInstance, file: File, options?: FileUploadOptions) => Promise<AxiosResponse>;
createHealthCheck: (instance: AxiosInstance, endpoint?: string) => HealthCheck;
};
// Main export
declare const hcAxios: HCAxiosStatic;
export { hcAxios };
export default hcAxios;
// Type helpers
export type InterceptorCondition = InterceptorConditionFunction;
export type ConditionalConfig = Record<string, ConditionalInterceptorConfig>;
export type GroupConfig = Record<string, string[]>;
// Enhanced error types
export interface HCAxiosError extends Error {
isHCAxiosError: true;
code?: string;
config?: AxiosRequestConfig;
response?: AxiosResponse;
request?: any;
interceptorContext?: {
activeGroups: string[];
activeConditionals: string[];
appliedInterceptors: string[];
};
toJSON(): object;
}