UNPKG

try-and-catch

Version:

Enterprise-grade TypeScript error handling with ALL limitations fixed in v5.0.0: memory management, performance optimization, enhanced cleanup, JSON serialization, concurrency protection, simplified APIs, and linter-friendly async functions. Zero dependen

229 lines 7.44 kB
"use strict"; // 🛡️ try-and-catch v6.0.0 // Performance-optimized error handling addressing critical user feedback // FIXES: Performance overhead, memory leaks, tree-shaking, API confusion Object.defineProperty(exports, "__esModule", { value: true }); exports.TryAndCatch = exports.SimpleRetry = exports.RetryStrategies = exports.ErrorTypes = exports.safe = void 0; exports.tryAndCatch = tryAndCatch; exports.tryAndCatchAsync = tryAndCatchAsync; exports.withRetry = withRetry; exports.tryAndCatchWithRetry = tryAndCatchWithRetry; exports.isSuccess = isSuccess; exports.isError = isError; exports.unwrap = unwrap; exports.unwrapOr = unwrapOr; exports.warnOnError = warnOnError; function tryAndCatch(fn, onFinally) { try { const result = fn(); if (result instanceof Promise) { return result .then((result) => ({ result, error: null })) .catch((error) => ({ result: null, error: error instanceof Error ? error : new Error(String(error)), })) .finally(async () => { if (onFinally) { try { await onFinally(); } catch (e) { console.warn("Cleanup failed:", e); } } }); } // Sync path - optimized cleanup if (onFinally) { try { onFinally(); } catch (e) { console.warn("Cleanup failed:", e); } } return { result, error: null }; } catch (error) { // Fast error handling - no context processing overhead const finalError = error instanceof Error ? error : new Error(String(error)); if (onFinally) { try { onFinally(); } catch (e) { console.warn("Cleanup failed:", e); } } return { result: null, error: finalError }; } } /** * RECOMMENDED: Main entry point for most use cases * Improves API discoverability and reduces confusion */ exports.safe = tryAndCatch; /** * Explicitly async version - eliminates linter warnings * Use this when you know your function is async */ async function tryAndCatchAsync(fn, onFinally) { try { const result = await fn(); return { result, error: null }; } catch (error) { return { result: null, error: error instanceof Error ? error : new Error(String(error)), }; } finally { if (onFinally) { try { await onFinally(); } catch (e) { console.warn("Cleanup failed:", e); } } } } /** * Lightweight retry mechanism * Optimized for performance and memory efficiency */ async function withRetry(fn, maxRetries = 3, delayMs = 1000) { let lastError; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); if (attempt < maxRetries) { await new Promise((resolve) => setTimeout(resolve, delayMs)); } } } throw lastError; } /** * Advanced retry with full configuration (tree-shakeable) * Only include if you need detailed retry control */ async function tryAndCatchWithRetry(fn, options) { const { maxRetries, delay = 1000, shouldRetry = () => true, timeout, } = options; const errors = []; const startTime = Date.now(); for (let attempt = 0; attempt <= maxRetries; attempt++) { try { let result; if (timeout) { result = await Promise.race([ fn(), new Promise((_, reject) => setTimeout(() => reject(new Error("Operation timeout")), timeout)), ]); } else { result = await fn(); } return { result, error: null, attempts: attempt + 1, errors, totalTime: Date.now() - startTime, }; } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); errors.push(err); if (attempt < maxRetries && shouldRetry(err)) { const delayMs = typeof delay === "function" ? delay(attempt) : delay; await new Promise((resolve) => setTimeout(resolve, delayMs)); } else { return { result: null, error: err, attempts: attempt + 1, errors, totalTime: Date.now() - startTime, }; } } } throw new Error("Retry logic error"); } // Tree-shakeable utilities - only bundled if imported exports.ErrorTypes = { isNetworkError: (error) => /network|fetch|request|connection/i.test(error.message), isTimeoutError: (error) => /timeout|timed out/i.test(error.message), isRetryable: (error) => exports.ErrorTypes.isNetworkError(error) || exports.ErrorTypes.isTimeoutError(error), }; exports.RetryStrategies = { exponentialBackoff: (baseMs = 1000, maxMs = 30000) => (attempt) => Math.min(baseMs * Math.pow(2, attempt) + Math.random() * 1000, maxMs), linearBackoff: (delayMs = 1000) => (attempt) => delayMs * (attempt + 1), fixedDelay: (delayMs = 1000) => () => delayMs, }; exports.SimpleRetry = { quick: async (fn, maxRetries = 3) => withRetry(fn, maxRetries, 1000), network: async (fn) => withRetry(fn, 3, 2000), database: async (fn) => withRetry(fn, 5, 3000), }; /** * 🎯 UNIFIED API - Addresses all usability concerns * Single object with clear, discoverable methods for beginners * Solves API choice paralysis mentioned in user feedback */ exports.TryAndCatch = { // Main recommended API safe: tryAndCatch, // Explicit async (for linter-friendly usage) async: tryAndCatchAsync, // Retry helpers withRetry, retry: tryAndCatchWithRetry, // Type guards for TypeScript isSuccess, isError, unwrap, unwrapOr, // Warning system warnOnError, // Utilities (tree-shakeable when imported directly) ErrorTypes: exports.ErrorTypes, RetryStrategies: exports.RetryStrategies, SimpleRetry: exports.SimpleRetry, }; // Type guards for better TypeScript integration function isSuccess(result) { return result.error === null; } function isError(result) { return result.error !== null; } // Safe unwrap functions function unwrap(result) { if (result.error) { throw result.error; } return result.result; } function unwrapOr(result, defaultValue) { return result.error ? defaultValue : result.result; } // Warning system for better debugging function warnOnError(result, context) { if (result.error) { const warning = context ? `[try-and-catch] Error in ${context}: ${result.error.message}` : `[try-and-catch] Unhandled error: ${result.error.message}`; console.warn(warning); } return result; } exports.default = tryAndCatch; //# sourceMappingURL=index.js.map