@mirawision/apium
v1.0.1
Published
Advanced API management library for TypeScript with request/response interceptors, caching, retry logic, and comprehensive error handling.
Readme
@mirawision/apium
Advanced API management library for TypeScript with request/response interceptors, caching, retry logic, and comprehensive error handling. Apium provides a powerful and flexible way to manage HTTP requests with built-in features for modern web applications.
Features
- Request/Response Interceptors: Modify requests and responses globally or per-instance
- Automatic Retry Logic: Configurable retry strategies with exponential backoff
- Caching System: Built-in caching with TTL and cache invalidation
- Type Safety: Full TypeScript support with generic request/response types
- Error Handling: Comprehensive error handling with custom error types
- Request Cancellation: Support for request cancellation and timeouts
- Progress Tracking: Upload/download progress tracking
- Middleware Support: Chain multiple interceptors and middleware
- Flexible Configuration: Extensive configuration options for all features
Installation
npm install @mirawision/apiumor
yarn add @mirawision/apiumUsage
Basic Example
import { Apium, RequestConfig, Response } from '@mirawision/apium';
interface User {
id: number;
name: string;
email: string;
}
interface CreateUserRequest {
name: string;
email: string;
}
const api = new Apium({
baseURL: 'https://api.example.com',
timeout: 5000,
retries: 3
});
// GET request
const users: User[] = await api.get<User[]>('/users');
// POST request
const newUser: User = await api.post<User, CreateUserRequest>('/users', {
name: 'John Doe',
email: '[email protected]'
});
// PUT request
const updatedUser: User = await api.put<User, Partial<User>>('/users/1', {
name: 'Jane Doe'
});
// DELETE request
await api.delete('/users/1');Request/Response Interceptors
import { Apium, RequestInterceptor, ResponseInterceptor } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com'
});
// Request interceptor - add auth header
api.addRequestInterceptor((config) => {
config.headers = {
...config.headers,
'Authorization': `Bearer ${localStorage.getItem('token')}`
};
return config;
});
// Response interceptor - handle errors globally
api.addResponseInterceptor(
(response) => {
// Handle successful responses
return response;
},
(error) => {
if (error.status === 401) {
// Handle unauthorized access
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// Per-request interceptor
const userResponse = await api.get<User>('/users/1', {
interceptors: {
request: (config) => {
console.log('Making request to:', config.url);
return config;
},
response: (response) => {
console.log('Received response:', response.data);
return response;
}
}
});Retry Logic
import { Apium, RetryConfig } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com',
retries: 3,
retryDelay: 1000,
retryCondition: (error) => {
// Retry on network errors or 5xx status codes
return error.isNetworkError || (error.status >= 500 && error.status < 600);
}
});
// Custom retry for specific request
const response = await api.get<User>('/users/1', {
retries: 5,
retryDelay: 2000,
retryCondition: (error) => error.status === 429 // Rate limit
});Caching
import { Apium, CacheConfig } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com',
cache: {
enabled: true,
ttl: 5 * 60 * 1000, // 5 minutes
maxSize: 100
}
});
// Cache specific request
const users = await api.get<User[]>('/users', {
cache: {
key: 'users-list',
ttl: 10 * 60 * 1000 // 10 minutes
}
});
// Invalidate cache
api.invalidateCache('users-list');
api.clearCache(); // Clear all cacheError Handling
import { Apium, ApiError } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com'
});
try {
const user = await api.get<User>('/users/1');
} catch (error) {
if (error instanceof ApiError) {
switch (error.status) {
case 404:
console.log('User not found');
break;
case 500:
console.log('Server error');
break;
default:
console.log('Unknown error:', error.message);
}
}
}Request Cancellation
import { Apium, AbortController } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com'
});
const controller = new AbortController();
// Start request
const request = api.get<User>('/users/1', {
signal: controller.signal
});
// Cancel request after 5 seconds
setTimeout(() => {
controller.abort();
}, 5000);
try {
const user = await request;
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request was cancelled');
}
}Progress Tracking
import { Apium } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com'
});
// Upload with progress
const uploadResponse = await api.post<Response, FormData>('/upload', formData, {
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Upload progress: ${percentCompleted}%`);
}
});
// Download with progress
const downloadResponse = await api.get<Blob>('/download', {
responseType: 'blob',
onDownloadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Download progress: ${percentCompleted}%`);
}
});Advanced Configuration
import { Apium, RequestConfig } from '@mirawision/apium';
const api = new Apium({
baseURL: 'https://api.example.com',
timeout: 10000,
retries: 3,
retryDelay: 1000,
cache: {
enabled: true,
ttl: 5 * 60 * 1000,
maxSize: 100
},
headers: {
'Content-Type': 'application/json',
'User-Agent': 'MyApp/1.0'
},
validateStatus: (status) => status < 500, // Only retry on 5xx errors
transformRequest: (data) => {
// Transform request data
return JSON.stringify(data);
},
transformResponse: (data) => {
// Transform response data
return JSON.parse(data);
}
});
// Instance-specific configuration
const userApi = new Apium({
baseURL: 'https://api.example.com/users',
timeout: 5000,
headers: {
'Authorization': `Bearer ${token}`
}
});API Reference
Apium Class
Main API client class for making HTTP requests.
Constructor
constructor(config?: ApiumConfig)Methods
get<T>(url: string, config?: RequestConfig): Promise<T>- Makes a GET request
post<T, D = any>(url: string, data?: D, config?: RequestConfig): Promise<T>- Makes a POST request
put<T, D = any>(url: string, data?: D, config?: RequestConfig): Promise<T>- Makes a PUT request
patch<T, D = any>(url: string, data?: D, config?: RequestConfig): Promise<T>- Makes a PATCH request
delete<T>(url: string, config?: RequestConfig): Promise<T>- Makes a DELETE request
addRequestInterceptor(interceptor: RequestInterceptor): void- Adds a request interceptor
addResponseInterceptor(interceptor: ResponseInterceptor): void- Adds a response interceptor
invalidateCache(key?: string): void- Invalidates cache entries
clearCache(): void- Clears all cache entries
Type Definitions
interface ApiumConfig {
baseURL?: string;
timeout?: number;
retries?: number;
retryDelay?: number;
retryCondition?: (error: ApiError) => boolean;
cache?: CacheConfig;
headers?: Record<string, string>;
validateStatus?: (status: number) => boolean;
transformRequest?: (data: any) => any;
transformResponse?: (data: any) => any;
}
interface RequestConfig {
params?: Record<string, any>;
headers?: Record<string, string>;
timeout?: number;
retries?: number;
retryDelay?: number;
retryCondition?: (error: ApiError) => boolean;
cache?: CacheConfig;
signal?: AbortSignal;
onUploadProgress?: (progressEvent: ProgressEvent) => void;
onDownloadProgress?: (progressEvent: ProgressEvent) => void;
interceptors?: {
request?: RequestInterceptor;
response?: ResponseInterceptor;
};
}
interface CacheConfig {
enabled?: boolean;
key?: string;
ttl?: number;
maxSize?: number;
}
interface ApiError extends Error {
status: number;
statusText: string;
isNetworkError: boolean;
config: RequestConfig;
response?: Response;
}Contributing
Contributions are always welcome! Feel free to open issues or submit pull requests.
License
This project is licensed under the MIT License.
