UNPKG

s3db.js

Version:

Use AWS S3, the world's most reliable document storage, as a database with this ORM.

152 lines (142 loc) 4.44 kB
/** * tryFn - A robust error handling utility for JavaScript functions and values. * * This utility provides a consistent way to handle errors and return values across different types: * - Synchronous functions * - Asynchronous functions (Promises) * - Direct values * - Promises * - null/undefined values * * @param {Function|Promise|*} fnOrPromise - The input to process, can be: * - A synchronous function that returns a value * - An async function that returns a Promise * - A Promise directly * - Any direct value (number, string, object, etc) * * @returns {Array} A tuple containing: * - [0] ok: boolean - Indicates if the operation succeeded * - [1] err: Error|null - Error object if failed, null if succeeded * - [2] data: any - The result data if succeeded, undefined if failed * * Key Features: * - Unified error handling interface for all types of operations * - Preserves and enhances error stack traces for better debugging * - Zero dependencies * - TypeScript friendly return tuple * - Handles edge cases like null/undefined gracefully * - Perfect for functional programming patterns * - Ideal for Promise chains and async/await flows * - Reduces try/catch boilerplate code * * Error Handling: * - All errors maintain their original properties * - Stack traces are automatically enhanced to show the tryFn call site * - Errors from async operations are properly caught and formatted * * Common Use Cases: * - API request wrappers * - Database operations * - File system operations * - Data parsing and validation * - Service integration points * * Examples: * ```js * // Handling synchronous operations * const [ok, err, data] = tryFn(() => JSON.parse(jsonString)); * * // Handling async operations * const [ok, err, data] = await tryFn(async () => { * const response = await fetch(url); * return response.json(); * }); * * // Direct promise handling * const [ok, err, data] = await tryFn(fetch(url)); * * // Value passthrough * const [ok, err, data] = tryFn(42); // [true, null, 42] * ``` */ export function tryFn(fnOrPromise) { if (fnOrPromise == null) { const err = new Error('fnOrPromise cannot be null or undefined'); err.stack = new Error().stack; return [false, err, undefined]; } if (typeof fnOrPromise === 'function') { try { const result = fnOrPromise(); if (result == null) { return [true, null, result]; } if (typeof result.then === 'function') { return result .then(data => [true, null, data]) .catch(error => { if ( error instanceof Error && Object.isExtensible(error) ) { const desc = Object.getOwnPropertyDescriptor(error, 'stack'); if ( desc && desc.writable && desc.configurable && error.hasOwnProperty('stack') ) { try { error.stack = new Error().stack; } catch (_) {} } } return [false, error, undefined]; }); } return [true, null, result]; } catch (error) { if ( error instanceof Error && Object.isExtensible(error) ) { const desc = Object.getOwnPropertyDescriptor(error, 'stack'); if ( desc && desc.writable && desc.configurable && error.hasOwnProperty('stack') ) { try { error.stack = new Error().stack; } catch (_) {} } } return [false, error, undefined]; } } if (typeof fnOrPromise.then === 'function') { return Promise.resolve(fnOrPromise) .then(data => [true, null, data]) .catch(error => { if ( error instanceof Error && Object.isExtensible(error) ) { const desc = Object.getOwnPropertyDescriptor(error, 'stack'); if ( desc && desc.writable && desc.configurable && error.hasOwnProperty('stack') ) { try { error.stack = new Error().stack; } catch (_) {} } } return [false, error, undefined]; }); } return [true, null, fnOrPromise]; } export function tryFnSync(fn) { try { const result = fn(); return [true, null, result]; } catch (err) { return [false, err, null]; } } export default tryFn;