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
JavaScript
;
// 🛡️ 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