UNPKG

@dima_aryze/reforge

Version:

TypeScript/JavaScript SDK for Reforge - Cross-chain token operations

169 lines 4.96 kB
/** * Utility functions and helpers for the Reforge SDK */ // Re-export logger utilities export { createLogger, Logger, silentLogger } from './logger'; /** * Check if an error is a Reforge SDK error */ export function isReforgeError(error) { return error instanceof Error && 'isReforgeError' in error && error.isReforgeError === true; } /** * Sleep for specified milliseconds */ export function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Create a delay with exponential backoff and jitter */ export function exponentialBackoff(attempt, baseDelay, maxDelay, multiplier = 2) { const delay = Math.min(baseDelay * Math.pow(multiplier, attempt), maxDelay); // Add jitter to prevent thundering herd effect const jitter = Math.random() * delay * 0.1; return Math.floor(delay + jitter); } /** * Validate required fields in an object */ export function validateRequired(obj, fields) { const missingFields = fields.filter(field => !(field in obj) || obj[field] === undefined || obj[field] === null); if (missingFields.length > 0) { throw new Error(`Required fields missing: ${missingFields.join(', ')}`); } } /** * Deep merge objects with proper type safety */ export function deepMerge(target, ...sources) { if (!sources.length) return target; const result = { ...target }; for (const source of sources) { if (isObject(source)) { for (const [key, value] of Object.entries(source)) { if (isObject(value) && isObject(result[key])) { result[key] = deepMerge(result[key], value); } else if (value !== undefined) { result[key] = value; } } } } return result; } /** * Type guard to check if value is a plain object */ function isObject(item) { return item !== null && typeof item === 'object' && !Array.isArray(item); } /** * Sanitize URL by removing trailing slashes and ensuring proper format */ export function sanitizeUrl(url) { if (!url || typeof url !== 'string') { throw new Error('URL must be a non-empty string'); } return url.replace(/\/+$/, ''); } /** * Build URL with query parameters */ export function buildUrl(baseUrl, path, params) { try { const url = new URL(path, sanitizeUrl(baseUrl)); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { url.searchParams.append(key, String(value)); } }); } return url.toString(); } catch (error) { throw new Error(`Invalid URL construction: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Format error for consistent logging */ export function formatError(error) { if (error instanceof Error) { return `${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ''}`; } return String(error); } /** * Check if running in browser environment */ export function isBrowser() { return typeof window !== 'undefined' && typeof window.document !== 'undefined'; } /** * Check if running in Node.js environment */ export function isNode() { return typeof process !== 'undefined' && !!process.versions?.node; } /** * Generate a unique request ID for tracking */ export function generateRequestId() { return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * Debounce function calls */ // eslint-disable-next-line no-unused-vars export function debounce(func, wait) { let timeout = null; /* eslint-disable no-unused-vars */ return (..._args) => { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => func(..._args), wait); }; /* eslint-enable no-unused-vars */ } /** * Throttle function calls */ // eslint-disable-next-line no-unused-vars export function throttle(func, wait) { let lastTime = 0; /* eslint-disable no-unused-vars */ return (..._args) => { const now = Date.now(); if (now - lastTime >= wait) { lastTime = now; func(..._args); } }; /* eslint-enable no-unused-vars */ } /** * Retry a function with exponential backoff */ export async function retry(fn, maxAttempts = 3, baseDelay = 1000) { let lastError; for (let attempt = 0; attempt < maxAttempts; attempt++) { try { return await fn(); } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); if (attempt === maxAttempts - 1) { throw lastError; } const delay = exponentialBackoff(attempt, baseDelay, 30000); await sleep(delay); } } throw lastError; } //# sourceMappingURL=index.js.map