UNPKG

@zerothrow/core

Version:

Core ZeroThrow functionality - Rust-style Result<T,E> for TypeScript

1 lines 12.1 kB
{"version":3,"sources":["../../src/error.ts","../../src/result.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export type ErrorCode = string | number | symbol;\n\nexport interface ErrorContext {\n [k: string]: unknown;\n}\n\n/**\n * ZeroError wraps a standard JS Error but adds:\n * - code : machine‑readable categorisation\n * - context : structured payload for logging\n * - cause : native Error.cause chain (ES2022)\n */\nexport class ZeroError<C extends ErrorContext = ErrorContext> extends Error {\n readonly code: ErrorCode;\n readonly context?: C;\n\n constructor(\n code: ErrorCode,\n message: string,\n opts: { cause?: Error; context?: C } = {}\n ) {\n super(message, { cause: opts.cause });\n this.code = code;\n this.context = opts.context as C;\n this.name = 'ZeroError';\n Object.setPrototypeOf(this, new.target.prototype); // fix prototype when transpiled\n }\n\n /**\n * Override toString to include full error chain with context\n */\n override toString(): string {\n let result = `${this.name} [${String(this.code)}]: ${this.message}`;\n\n // Add context if present\n if (this.context && Object.keys(this.context).length > 0) {\n result += `\\n Context: ${JSON.stringify(this.context, null, 2).replace(/\\n/g, '\\n ')}`;\n }\n\n // Add cause chain\n let currentCause = this.cause;\n let depth = 1;\n while (currentCause instanceof Error) {\n const indent = ' '.repeat(depth);\n const causeName = currentCause.name || 'Error';\n result += `\\n${indent}Caused by: ${causeName}: ${currentCause.message}`;\n\n // If the cause is also a ZeroError, include its context\n if (currentCause instanceof ZeroError && currentCause.context) {\n const contextStr = JSON.stringify(\n currentCause.context,\n null,\n 2\n ).replace(/\\n/g, `\\n${indent} `);\n result += `\\n${indent} Context: ${contextStr}`;\n }\n\n currentCause = currentCause.cause;\n depth++;\n }\n\n return result;\n }\n\n /**\n * Get the full stack trace including all causes\n */\n getFullStack(): string {\n let fullStack = this.stack || '';\n\n let currentCause = this.cause;\n while (currentCause instanceof Error) {\n fullStack +=\n '\\n\\nCaused by:\\n' + (currentCause.stack || currentCause.toString());\n currentCause = currentCause.cause;\n }\n\n return fullStack;\n }\n}\n","import { ZeroError, type ErrorContext, type ErrorCode } from './error.js';\n\nexport type Ok<T> = { ok: true; value: T };\nexport type Err<E extends Error = ZeroError> = { ok: false; error: E };\nexport type Result<T, E extends Error = ZeroError> = (Ok<T> | Err<E>) & ResultMethods<T, E>;\n\n/**\n * Result methods - every Result has these built-in\n */\nexport interface ResultMethods<T, E extends Error = ZeroError> {\n /**\n * Chain operations that can fail\n */\n andThen<U>(fn: (value: T) => Result<U, E>): Result<U, E>;\n\n /**\n * Transform errors while preserving success values\n */\n mapErr<F extends Error>(fn: (error: E) => F): Result<T, F>;\n\n /**\n * Transform success values while preserving errors\n */\n map<U>(fn: (value: T) => U): Result<U, E>;\n\n /**\n * Provide fallback value on error\n */\n orElse(fallback: () => Result<T, E>): Result<T, E>;\n\n /**\n * Get value or fallback\n */\n unwrapOr(fallback: T): T;\n\n /**\n * Get value or throw (use sparingly!)\n */\n unwrapOrThrow(): T;\n\n /**\n * Execute side effect without changing the Result\n */\n tap(fn: (value: T) => void): Result<T, E>;\n\n /**\n * Execute side effect on error without changing the Result\n */\n tapErr(fn: (error: E) => void): Result<T, E>;\n\n /**\n * Execute side effect on any result\n */\n finally(fn: (value?: T) => void): Result<T, E>;\n\n /**\n * Discard the value and return void\n */\n void(): Result<void, E>;\n}\n\n/**\n * Create a Result with built-in methods\n */\nfunction createResult<T, E extends Error>(base: Ok<T> | Err<E>): Result<T, E> {\n const result = base as Result<T, E>;\n\n result.andThen = function<U>(fn: (value: T) => Result<U, E>): Result<U, E> {\n if (!result.ok) return createResult({ ok: false, error: result.error } as Err<E>) as Result<U, E>;\n return fn(result.value);\n };\n\n result.mapErr = function<F extends Error>(fn: (error: E) => F): Result<T, F> {\n if (result.ok) return createResult({ ok: true, value: result.value } as Ok<T>) as Result<T, F>;\n return createResult({ ok: false, error: fn(result.error) });\n };\n\n result.map = function<U>(fn: (value: T) => U): Result<U, E> {\n if (!result.ok) return createResult({ ok: false, error: result.error } as Err<E>) as Result<U, E>;\n return createResult({ ok: true, value: fn(result.value) });\n };\n\n result.orElse = function(fallback: () => Result<T, E>): Result<T, E> {\n if (result.ok) return result;\n return fallback();\n };\n\n result.unwrapOr = function(fallback: T): T {\n return result.ok ? result.value : fallback;\n };\n\n result.unwrapOrThrow = function(): T {\n if (!result.ok) throw result.error;\n return result.value;\n };\n\n result.tap = function(fn: (value: T) => void): Result<T, E> {\n if (result.ok) fn(result.value);\n return result;\n };\n\n result.tapErr = function(fn: (error: E) => void): Result<T, E> {\n if (!result.ok) fn(result.error);\n return result;\n };\n\n result.finally = function(fn: (value?: T) => void): Result<T, E> {\n if (result.ok) fn(result.value);\n else fn();\n return result;\n };\n\n result.void = function(): Result<void, E> {\n if (!result.ok) return createResult({ ok: false, error: result.error } as Err<E>) as Result<void, E>;\n return createResult({ ok: true, value: undefined as void });\n };\n\n return result;\n}\n\n// Public API - all Results have combinators built-in\nexport const ok = <T>(value: T): Result<T, ZeroError> => \n createResult({ ok: true, value });\n\nexport const err = <E extends Error>(error: E): Result<never, E> => \n createResult({ ok: false, error });\n\n/**\n * Normalise an unknown thrown value into ZeroError\n * Optimized to avoid creating new errors when possible\n */\nexport const normalise = (e: unknown): ZeroError => {\n if (e instanceof ZeroError) return e;\n if (e instanceof Error) {\n // Check if it already has ZeroError-like properties to avoid allocation\n if ('code' in e && typeof e.code === 'string' && 'context' in e) {\n return e as ZeroError;\n }\n return new ZeroError('UNKNOWN_ERR', e.message, { cause: e });\n }\n return new ZeroError('UNKNOWN_ERR', String(e));\n};\n\n/**\n * wrap(cause, code?, msg?, ctx?) lifts an existing error into a new coded layer.\n * If code/msg are not provided, they are extracted from the cause error.\n */\nexport function wrap<C extends ErrorContext = ErrorContext>(\n cause: Error,\n code?: ErrorCode,\n msg?: string,\n ctx?: C\n): ZeroError<C> {\n // Extract code from cause if not provided\n const errorCode =\n code ??\n (cause instanceof ZeroError\n ? cause.code\n : 'code' in cause && cause.code\n ? (cause.code as ErrorCode)\n : 'WRAPPED_ERROR');\n\n // Use cause's message if msg not provided\n const message = msg ?? cause.message;\n\n return new ZeroError(errorCode, message, { \n cause, \n ...(ctx !== undefined && { context: ctx })\n });\n}"]}