A lightweight, flexible HTTP client library with powerful interceptors for modern web applications.
- 🚀 Simple Setup - One-line client creation
- 🔧 Flexible Interceptors - Add request/response/error handlers
- 🍪 Cookie Support - Works with credentials and cross-origin requests
- 🔐 Bearer Token Support - Manual or automatic token handling
- 🔄 Auto Retry - Adaptive backoff with exponential delay
- ⚡ Built-in Features - Logging, timeout, and error handling
- 🛡️ TypeScript Support - Full type safety and IntelliSense
- 🌐 Cross-Origin Ready - Built-in credentials support
- 🔒 Developer Control - You decide how to handle authentication
import { createClient } from 'hyperwiz';
// Simple client
const api = createClient('https://api.example.com', { logging: true });
// Make requests
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'John' });
const api = createClient('https://api.example.com');
// GET request
const users = await api.get('/users');
// POST request
const newUser = await api.post('/users', { name: 'John', email: 'john@example.com' });
// PUT request
const updatedUser = await api.put('/users/1', { name: 'John Updated' });
// PATCH request
const patchedUser = await api.patch('/users/1', { email: 'john.new@example.com' });
// DELETE request
const deleted = await api.delete('/users/1');
// HEAD request - Get headers only (useful for checking if resource exists)
const userExists = await api.head('/users/123');
// OPTIONS request - Get allowed methods for a resource (CORS preflight)
const allowedMethods = await api.options('/users');
// PURGE request - Clear cache (useful for CDNs like Cloudflare)
const cacheCleared = await api.purge('/cache/clear');
// Option 1: Simple boolean (uses default retry configuration)
const api1 = createClient('https://api.example.com', {
retry: true, // Uses default: 3 retries, 1s delay, exponential backoff
logging: true
});
// Option 2: Custom retry configuration
const api2 = createClient('https://api.example.com', {
retry: {
maxRetries: 5, // Retry up to 5 times
retryDelay: 500, // Start with 500ms delay
maxDelay: 5000, // Maximum 5 second delay
backoffMultiplier: 1.5, // Gentler backoff (1.5x instead of 2x)
retryOnStatus: [408, 429, 500, 502, 503, 504], // Retry on these status codes
retryOnNetworkError: true // Retry on network errors
},
logging: true
});
// Option 3: Disable retry
const api3 = createClient('https://api.example.com', {
retry: false, // No retry attempts
logging: true
});
// All requests automatically retry if they fail
// Retries preserve the original HTTP method, headers, and body
const data = await api1.get('/unreliable-endpoint');
const user = await api2.post('/users', { name: 'John' }); // POST retries as POST
// Option 1: Simple boolean (uses default cache configuration)
const api1 = createClient('https://api.example.com', {
cache: true, // Uses default: 5min cache, memory storage, GET requests only
logging: true
});
// Option 2: Custom cache configuration
const api2 = createClient('https://api.example.com', {
cache: {
enabled: true,
maxAge: 10 * 60 * 1000, // Cache for 10 minutes
maxSize: 50, // Maximum 50 cached items
storage: 'indexeddb', // Use IndexedDB for persistence
includeQueryParams: true, // Include query params in cache key
cacheableMethods: ['GET', 'HEAD'], // Cache GET and HEAD requests
cacheableStatusCodes: [200, 304] // Cache 200 and 304 responses
},
logging: true
});
// Option 3: Memory cache with custom settings
const api3 = createClient('https://api.example.com', {
cache: {
enabled: true,
maxAge: 2 * 60 * 1000, // Cache for 2 minutes
maxSize: 20, // Maximum 20 cached items
storage: 'memory', // Use in-memory storage (faster)
includeQueryParams: false // Ignore query params for cache key
},
logging: true
});
// Option 4: Disable caching
const api4 = createClient('https://api.example.com', {
cache: false, // No caching
logging: true
});
// First request: fetches from server
const users1 = await api1.get('/users'); // ⏳ Network request
// Second request: served from cache (instant)
const users2 = await api1.get('/users'); // 💾 Cache hit (instant)
// Cache automatically expires after maxAge
// Cache automatically evicts old entries when maxSize is reached
hyperwiz supports additional HTTP methods beyond the standard REST operations for enhanced functionality:
const api = createClient('https://api.example.com');
// HEAD - Get headers only (no body)
// Useful for checking if resource exists without downloading data
const userExists = await api.head('/users/123');
if (userExists.success) {
console.log('User exists!');
console.log('Last modified:', userExists.data.headers['last-modified']);
}
// OPTIONS - Get allowed methods for a resource
// Essential for CORS preflight requests and API discovery
const capabilities = await api.options('/users');
if (capabilities.success) {
console.log('Allowed methods:', capabilities.data.headers['allow']);
console.log('CORS headers:', capabilities.data.headers['access-control-allow-methods']);
}
// PURGE - Clear cache
// Useful for CDNs like Cloudflare, Fastly, etc.
const cacheCleared = await api.purge('/cache/clear');
if (cacheCleared.success) {
console.log('Cache cleared successfully');
}
Use Cases:
- HEAD: Check resource existence, get metadata, validate URLs
- OPTIONS: CORS preflight, API discovery, check server capabilities
- PURGE: Cache invalidation, CDN management, content updates
const api = createClient('https://api.example.com');
// Developer sends token manually in each request
const profile = await api.get('/user/profile', {
'Authorization': 'Bearer your-token-here'
});
const newPost = await api.post('/posts', { title: 'Hello' }, {
'Authorization': 'Bearer your-token-here'
});
const api = createClient('https://api.example.com');
// Add token interceptor
api.addBefore((config, url) => {
const token = localStorage.getItem('token');
if (token) {
return {
...config,
headers: {
...config.headers,
'Authorization': `Bearer ${token}`
}
};
}
return config;
});
// Login (no token yet - works correctly)
const login = await api.post('/login', { username: 'admin', password: '123' });
// Store token after successful login
if (login.success) {
localStorage.setItem('token', login.data.token);
}
// Now all requests automatically include the token
const profile = await api.get('/user/profile');
const posts = await api.get('/user/posts');
// For session-based authentication with cookies
const api = createClient('http://localhost:4000', {
credentials: 'include', // Important for cookies
logging: true
});
// Login - server sets session cookie
const login = await api.post('/login', { username: 'admin' });
// Subsequent requests - cookies are automatically sent
const profile = await api.get('/user/profile');
const data = await api.get('/protected-data');
const api = createClient('https://api.example.com');
// Request interceptor - runs before each request
api.addBefore((config, url) => {
console.log(`🚀 Making ${config.method} request to ${url}`);
return config;
});
// Response interceptor - runs after successful responses
api.addAfter((response, data, url) => {
console.log(`✅ Response from ${url}:`, data);
return data;
});
// Error interceptor - runs when errors occur (includes request config)
api.addErrorHandler((error, url, requestConfig) => {
console.error(`❌ Error for ${requestConfig?.method} ${url}:`, error);
return error;
});
const api = createClient('https://api.example.com');
api.addAfter((response, data, url) => {
if (response.status === 401) {
// Token expired, refresh it
refreshToken();
}
return data;
});
// Or use error handler for more control
api.addErrorHandler((error, url, requestConfig) => {
if (isAuthError(error)) {
// Refresh token and retry the original request
return handleAuthRetry(error, url, requestConfig);
}
return error;
});
const api = createClient('https://api.example.com', {
timeout: 5000 // 5 second timeout
});
// All requests will timeout after 5 seconds
const data = await api.get('/slow-endpoint');
const api = createClient('https://api.example.com', {
logging: true, // Enable request/response logging
timeout: 30000, // Request timeout in milliseconds
credentials: 'include', // Credentials mode for cross-origin
retry: true, // Auto retry (boolean) or retry config object
// retry: { // Custom retry configuration
// maxRetries: 3, // Maximum retry attempts
// retryDelay: 1000, // Initial delay in milliseconds
// maxDelay: 10000, // Maximum delay in milliseconds
// backoffMultiplier: 2, // Exponential backoff multiplier
// retryOnStatus: [408, 429, 500, 502, 503, 504], // HTTP status codes to retry
// retryOnNetworkError: true // Retry on network errors
// },
cache: true, // Request caching (boolean) or cache config object
// cache: { // Custom cache configuration
// enabled: true, // Enable/disable caching
// maxAge: 300000, // Cache duration in milliseconds (5 minutes)
// maxSize: 100, // Maximum number of cached items
// storage: 'memory', // Storage type: 'memory' or 'indexeddb'
// includeQueryParams: true, // Include query params in cache key
// cacheableMethods: ['GET', 'HEAD'], // HTTP methods that can be cached
// cacheableStatusCodes: [200] // Status codes that can be cached
// },
interceptors: { // Custom interceptors
before: [(config, url) => { /* ... */ }],
after: [(response, data, url) => { /* ... */ }],
onError: [(error, url, requestConfig) => { /* ... */ }]
}
});
// Basic client
createClient(baseUrl: string, config?: ClientConfig): HttpClient
// Public client (with logging enabled by default)
createPublicClient(baseUrl: string): HttpClient
The createPublicClient
function is a convenience method that creates an HTTP client with logging enabled by default. Perfect for development and debugging.
import { createPublicClient } from 'hyperwiz';
// Creates a client with automatic logging
const api = createPublicClient('https://api.example.com');
// Equivalent to:
// const api = createClient('https://api.example.com', { logging: true });
// All requests are automatically logged to console
const users = await api.get('/users');
// Console output: ✅ 200 https://api.example.com/users [response data]
const newUser = await api.post('/users', { name: 'John' });
// Console output: ✅ 201 https://api.example.com/users [created user data]
For long-running applications, hyperwiz provides memory management utilities to prevent memory leaks and monitor resource usage:
import {
cleanupCircuitBreakers,
cleanupRetryAttempts,
cleanupPendingRequests,
getMemoryStats
} from 'hyperwiz';
Manually cleans up circuit breaker states that are older than 1 hour.
// Clean up circuit breaker tracking data
cleanupCircuitBreakers();
// Use in maintenance routines
setInterval(() => {
cleanupCircuitBreakers();
console.log('Circuit breakers cleaned up');
}, 30 * 60 * 1000); // Every 30 minutes
Manually cleans up retry attempt tracking data older than 30 minutes.
// Clean up retry tracking data
cleanupRetryAttempts();
// Use during user session changes
function logout() {
cleanupRetryAttempts(); // Clear retry history
// ... other logout logic
}
Immediately clears all pending request deduplication data.
// Clear all pending requests (useful during app shutdown)
cleanupPendingRequests();
// Use when switching contexts or during cleanup
function resetApplication() {
cleanupPendingRequests(); // Clear any ongoing requests
// ... other reset logic
}
Returns statistics about memory usage for monitoring and debugging.
// Monitor memory usage
const stats = getMemoryStats();
console.log('Memory stats:', stats);
// Output: {
// circuitBreakers: 5, // Number of active circuit breakers
// retryAttempts: 12, // Number of tracked retry attempts
// pendingRequests: 3, // Number of pending requests
// globalCacheStorages: 2 // Number of cache storage instances
// }
// Use in monitoring dashboards
function monitorMemoryUsage() {
const stats = getMemoryStats();
if (stats.pendingRequests > 50) {
console.warn('High number of pending requests:', stats.pendingRequests);
}
if (stats.circuitBreakers > 20) {
console.warn('Many circuit breakers active, consider cleanup');
}
// Send to analytics or monitoring service
analytics.track('hyperwiz_memory_stats', stats);
}
import {
createClient,
cleanupCircuitBreakers,
cleanupRetryAttempts,
cleanupPendingRequests,
getMemoryStats
} from 'hyperwiz';
class ApiService {
private api = createClient('https://api.example.com', {
retry: true,
cache: true,
logging: process.env.NODE_ENV === 'development'
});
constructor() {
this.startMaintenanceTimer();
}
// Periodic cleanup for memory management
private startMaintenanceTimer() {
setInterval(() => {
// Clean up old data
cleanupCircuitBreakers();
cleanupRetryAttempts();
// Monitor memory usage
const stats = getMemoryStats();
console.log('Memory cleanup completed:', stats);
// Alert if memory usage is high
if (stats.pendingRequests > 100) {
console.warn('Memory leak warning: Too many pending requests');
}
}, 10 * 60 * 1000); // Every 10 minutes
}
// Clean shutdown
async shutdown() {
console.log('Shutting down API service...');
// Force clear all pending requests
cleanupPendingRequests();
// Clean up tracking data
cleanupCircuitBreakers();
cleanupRetryAttempts();
const finalStats = getMemoryStats();
console.log('Final memory stats after cleanup:', finalStats);
}
// User logout - clear sensitive data
async logout() {
// Clear pending requests for security
cleanupPendingRequests();
console.log('User session cleaned up');
}
}
// Usage
const apiService = new ApiService();
// During app shutdown
window.addEventListener('beforeunload', () => {
apiService.shutdown();
});
Note: The library automatically runs cleanup every 10 minutes, but these manual functions give you fine-grained control for specific use cases like application shutdown, user logout, or custom maintenance schedules.
// All methods return Promise<ApiResponse<T>>
api.get<T>(url: string, headers?: HeadersInit)
api.post<T>(url: string, body: unknown, headers?: HeadersInit)
api.put<T>(url: string, body: unknown, headers?: HeadersInit)
api.patch<T>(url: string, body: unknown, headers?: HeadersInit)
api.delete<T>(url: string, headers?: HeadersInit)
// Additional HTTP methods
api.head<T>(url: string, headers?: HeadersInit)
api.options<T>(url: string, headers?: HeadersInit)
api.purge<T>(url: string, headers?: HeadersInit)
// Add interceptors
api.addBefore(handler: RequestHandler)
api.addAfter(handler: ResponseHandler)
api.addErrorHandler(handler: ErrorHandler)
// Remove interceptors
api.removeBefore(handler: RequestHandler)
api.removeAfter(handler: ResponseHandler)
api.removeErrorHandler(handler: ErrorHandler)
// Clear all interceptors
api.clearInterceptors()
// Set timeout
api.setTimeout(timeoutMs: number)
// Cancel all requests
api.cancelAllRequests()
import { createClient } from 'hyperwiz';
// Create a simple API client
const api = createClient('https://api.example.com', {
logging: true, // See all requests in console
retry: true // Auto-retry failed requests
});
// Use it like fetch but simpler
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'John' });
const updatedUser = await api.put('/users/1', { name: 'John Updated' });
const deleted = await api.delete('/users/1');
const api = createClient('https://api.example.com');
// Developer manually adds tokens to each request
const profile = await api.get('/user/profile', {
'Authorization': 'Bearer your-token-here'
});
const newPost = await api.post('/posts', { title: 'Hello' }, {
'Authorization': 'Bearer your-token-here'
});
const api = createClient('https://api.example.com');
// Add token interceptor - automatically adds token to all requests
api.addBefore((config, url) => {
const token = localStorage.getItem('token');
if (token) {
return {
...config,
headers: {
...config.headers,
'Authorization': `Bearer ${token}`
}
};
}
return config;
});
// Now all requests automatically include the token
const profile = await api.get('/user/profile'); // ✅ Token added automatically
const posts = await api.post('/posts', { title: 'New Post' }); // ✅ Token added automatically
// For server-side sessions (like Express.js sessions)
const api = createClient('http://localhost:4000', {
credentials: 'include', // Important: sends cookies automatically
logging: true
});
// Login - server sets session cookie
const login = await api.post('/login', { username: 'admin', password: '123' });
// All subsequent requests automatically include the session cookie
const profile = await api.get('/user/profile'); // ✅ Cookie sent automatically
const data = await api.get('/protected-data'); // ✅ Cookie sent automatically
const api = createClient('https://api.example.com', {
retry: {
maxRetries: 3, // Retry failed requests up to 3 times
retryDelay: 1000, // Start with 1 second delay
maxDelay: 10000, // Maximum 10 second delay
backoffMultiplier: 2, // Double the delay each retry
retryOnStatus: [408, 429, 500, 502, 503, 504], // Retry on these errors
retryOnNetworkError: true // Retry on network failures
},
timeout: 10000, // 10 second timeout
logging: true // Log all requests and retries
});
// This request will automatically retry if it fails
// Retries preserve the original method (POST), body, and headers
const result = await api.post('/orders', {
productId: 123,
quantity: 2
});
import { useState, useCallback } from 'react';
import { createClient } from 'hyperwiz';
function useApi() {
const [api] = useState(() => createClient('https://api.example.com', {
retry: true,
logging: process.env.NODE_ENV === 'development'
}));
const login = useCallback(async (credentials: any) => {
const response = await api.post('/auth/login', credentials);
if (response.success) {
localStorage.setItem('auth-token', response.data.token);
}
return response;
}, [api]);
const logout = useCallback(() => {
localStorage.removeItem('auth-token');
}, []);
const getProfile = useCallback(async () => {
const token = localStorage.getItem('auth-token');
return await api.get('/user/profile', {
'Authorization': `Bearer ${token}`
});
}, [api]);
return { api, login, logout, getProfile };
}
// Usage in component
function ProfileComponent() {
const { getProfile } = useApi();
const handleLoadProfile = async () => {
const profile = await getProfile();
if (profile.success) {
console.log('Profile:', profile.data);
}
};
}
class UserAPI {
private api = createClient('https://api.example.com', {
retry: true,
logging: true
});
constructor() {
// Add authentication interceptor
this.api.addBefore((config, url) => {
const token = localStorage.getItem('token');
if (token) {
config.headers = {
...config.headers,
'Authorization': `Bearer ${token}`
};
}
return config;
});
// Add error logging
this.api.addErrorHandler((error, url, requestConfig) => {
console.error(`API Error: ${requestConfig?.method} ${url}`, error);
return error;
});
}
async getUsers() {
const response = await this.api.get('/users');
return response.success ? response.data : [];
}
async createUser(userData: any) {
const response = await this.api.post('/users', userData);
return response.success ? response.data : null;
}
async updateUser(id: string, userData: any) {
const response = await this.api.put(`/users/${id}`, userData);
return response.success ? response.data : null;
}
async deleteUser(id: string) {
const response = await this.api.delete(`/users/${id}`);
return response.success;
}
}
// Usage
const userAPI = new UserAPI();
const users = await userAPI.getUsers();
const newUser = await userAPI.createUser({ name: 'John', email: 'john@example.com' });
class EcommerceAPI {
// Critical operations (payments, orders) - aggressive retry
private criticalApi = createClient('https://api.shop.com', {
retry: {
maxRetries: 5, // More retries for critical operations
retryDelay: 500, // Start with shorter delay
maxDelay: 5000, // Shorter max delay
backoffMultiplier: 1.5, // Gentler backoff
retryOnStatus: [500, 502, 503, 504], // Only retry server errors
retryOnNetworkError: true
}
});
// Normal operations (products, reviews) - standard retry
private normalApi = createClient('https://api.shop.com', {
retry: {
maxRetries: 3, // Standard retries
retryDelay: 1000, // Standard delay
maxDelay: 10000, // Standard max delay
backoffMultiplier: 2, // Standard backoff
retryOnStatus: [408, 429, 500, 502, 503, 504],
retryOnNetworkError: true
}
});
// Critical operation - aggressive retry
async createOrder(orderData: any) {
return await this.criticalApi.post('/orders', orderData);
}
// Normal operation - standard retry
async getProducts() {
return await this.normalApi.get('/products');
}
async getProductReviews(productId: string) {
return await this.normalApi.get(`/products/${productId}/reviews`);
}
}
const api = createClient('https://api.example.com', {
retry: true,
logging: true
});
// Custom error handling
api.addErrorHandler((error, url, requestConfig) => {
// Log specific errors
if (requestConfig?.method === 'POST' && url.includes('/orders')) {
console.error('Order creation failed:', error);
}
// Handle specific error types
if (isRateLimitError(error)) {
console.warn('Rate limit hit, will retry with backoff');
}
return error; // Let the retry mechanism handle it
});
function isRateLimitError(error: unknown): boolean {
return typeof error === 'object' && error !== null &&
'status' in error && (error as any).status === 429;
}
// E-commerce app with different caching strategies
class ProductAPI {
// Product catalog - long cache (rarely changes)
private catalogApi = createClient('https://api.shop.com', {
cache: {
enabled: true,
maxAge: 30 * 60 * 1000, // 30 minutes
maxSize: 100,
storage: 'indexeddb', // Persistent across sessions
cacheableMethods: ['GET', 'HEAD'],
cacheableStatusCodes: [200]
}
});
// User-specific data - short cache (changes frequently)
private userApi = createClient('https://api.shop.com', {
cache: {
enabled: true,
maxAge: 2 * 60 * 1000, // 2 minutes
maxSize: 20,
storage: 'memory', // Fast access
cacheableMethods: ['GET', 'HEAD'],
cacheableStatusCodes: [200]
}
});
// Real-time data - no cache
private realtimeApi = createClient('https://api.shop.com', {
cache: false, // Always fresh data
retry: true
});
// Product catalog (cached for 30 minutes)
async getProducts(category?: string) {
const url = category ? `/products?category=${category}` : '/products';
return await this.catalogApi.get(url);
}
// User cart (cached for 2 minutes)
async getUserCart() {
return await this.userApi.get('/user/cart', {
'Authorization': `Bearer ${localStorage.getItem('token')}`
});
}
// Stock levels (no cache, always fresh)
async getStockLevels(productId: string) {
return await this.realtimeApi.get(`/products/${productId}/stock`);
}
// Clear cache when user logs out
clearUserCache() {
// Note: In a real app, you'd want to clear specific cache entries
// This is a simplified example
console.log('User logged out, cache will expire naturally');
}
}
// Usage
const productAPI = new ProductAPI();
// First load: fetches from server
const products = await productAPI.getProducts('electronics'); // ⏳ Network request
// Subsequent loads: instant from cache
const products2 = await productAPI.getProducts('electronics'); // 💾 Cache hit (instant)
// User cart: cached briefly for performance
const cart = await productAPI.getUserCart(); // ⏳ Network request
const cart2 = await productAPI.getUserCart(); // 💾 Cache hit (instant)
// Stock levels: always fresh
const stock = await productAPI.getStockLevels('123'); // ⏳ Always network request
import { createClient } from 'hyperwiz';
// Create client with custom cache storage
const api = createClient('https://api.example.com', {
cache: {
enabled: true,
maxAge: 5 * 60 * 1000, // 5 minutes
maxSize: 50,
storage: 'indexeddb', // Persistent storage
includeQueryParams: true,
cacheableMethods: ['GET', 'HEAD'],
cacheableStatusCodes: [200]
},
logging: true
});
// Cache management functions
class CacheManager {
static async clearCache() {
// Clear all cached responses
const cacheStorage = new IndexedDBCacheStorage();
await cacheStorage.clear();
console.log('Cache cleared');
}
static async getCacheStats() {
const cacheStorage = new IndexedDBCacheStorage();
const keys = await cacheStorage.keys();
console.log(`Cache contains ${keys.length} items:`, keys);
return keys;
}
static async removeExpiredCache() {
const cacheStorage = new IndexedDBCacheStorage();
const keys = await cacheStorage.keys();
const now = Date.now();
for (const key of keys) {
const cached = await cacheStorage.get(key);
if (cached && (now - cached.timestamp) > 5 * 60 * 1000) {
await cacheStorage.delete(key);
console.log(`Removed expired cache: ${key}`);
}
}
}
}
// Usage
const users = await api.get('/users'); // First request: network
const users2 = await api.get('/users'); // Second request: cache
// Manage cache
await CacheManager.getCacheStats(); // See what's cached
await CacheManager.removeExpiredCache(); // Clean up expired entries
await CacheManager.clearCache(); // Clear all cache
import { useState } from 'react';
import { createClient } from 'hyperwiz';
function useApi() {
const [api] = useState(() => createClient('https://api.example.com'));
const login = async (credentials: any) => {
const response = await api.post('/auth/login', credentials);
if (response.success) {
localStorage.setItem('auth-token', response.data.token);
}
return response;
};
const logout = () => {
localStorage.removeItem('auth-token');
};
const makeAuthenticatedRequest = async (url: string, token: string) => {
return await api.get(url, {
'Authorization': `Bearer ${token}`
});
};
return { api, login, logout, makeAuthenticatedRequest };
}
class UserAPI {
private api = createClient('https://api.example.com', { logging: true });
constructor() {
// Add authentication interceptor
this.api.addBefore((config, url) => {
const token = localStorage.getItem('token');
if (token) {
config.headers = { ...config.headers, 'Authorization': `Bearer ${token}` };
}
return config;
});
}
async getUsers() {
const response = await this.api.get('/users');
return response.success ? response.data : [];
}
async createUser(userData: any) {
const response = await this.api.post('/users', userData);
return response.success ? response.data : null;
}
async updateUser(id: string, userData: any) {
const response = await this.api.put(`/users/${id}`, userData);
return response.success ? response.data : null;
}
}
class EcommerceAPI {
private criticalApi = createClient('https://api.shop.com', {
retry: {
maxRetries: 5, // More retries for critical operations
retryDelay: 500, // Start with shorter delay
maxDelay: 5000, // Shorter max delay
backoffMultiplier: 1.5, // Gentler backoff
retryOnStatus: [500, 502, 503, 504], // Only retry server errors
retryOnNetworkError: true
}
});
private normalApi = createClient('https://api.shop.com', {
retry: {
maxRetries: 3, // Standard retries
retryDelay: 1000, // Standard delay
maxDelay: 10000, // Standard max delay
backoffMultiplier: 2, // Standard backoff
retryOnStatus: [408, 429, 500, 502, 503, 504],
retryOnNetworkError: true
}
});
// Critical operation - aggressive retry
async createOrder(orderData: any) {
return await this.criticalApi.post('/orders', orderData);
}
// Normal operation - standard retry
async getProducts() {
return await this.normalApi.get('/products');
}
}
import { createClient } from 'hyperwiz';
const api = createClient('https://api.example.com');
// Server-side token
const response = await api.get('/data', {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
'X-Server-ID': process.env.SERVER_ID
});
// Full type safety
interface User {
id: number;
name: string;
email: string;
}
const api = createClient('https://api.example.com');
// TypeScript knows the response type
const users = await api.get<User[]>('/users');
if (users.success) {
users.data.forEach(user => {
console.log(user.name); // TypeScript autocomplete works
});
}
const api = createClient('https://api.example.com');
// All responses are wrapped in ApiResponse<T>
const response = await api.get('/users');
if (response.success) {
// Handle success
console.log('Users:', response.data);
} else {
// Handle error
console.error('Error:', response.error);
console.error('Status:', response.status);
}
All requests return a consistent response format:
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; status?: number; error: string };
npm install hyperwiz
- 🚀 Simple - One-line setup, no complex configuration needed
- 🔧 Flexible - Manual control over authentication or automatic via interceptors
- 🔄 Auto Retry - Built-in adaptive backoff with exponential delay and jitter
- 💾 Smart Caching - In-memory or IndexedDB caching with automatic expiration
- 🍪 Cookie Ready - Built-in support for session-based authentication
- 🔐 Token Ready - Easy Bearer token handling (manual or automatic)
- ⚡ Lightweight - Small bundle size, no unnecessary dependencies
- 🛡️ Type Safe - Full TypeScript support with proper type inference
- 🌐 Modern - Built for modern web applications with fetch API
- 📝 Developer Friendly - Clear API, comprehensive logging, and error handling
- 🎯 Production Ready - Timeout handling, request cancellation, and robust error recovery
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.