@onrails/result 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +12 -1
- package/README.md +45 -1
- package/dist/compat/neverthrow.cjs +234 -48
- package/dist/compat/neverthrow.cjs.map +1 -1
- package/dist/compat/neverthrow.d.cts +38 -4
- package/dist/compat/neverthrow.d.ts +38 -4
- package/dist/compat/neverthrow.js +230 -49
- package/dist/compat/neverthrow.js.map +1 -1
- package/dist/extra.cjs +43 -2
- package/dist/extra.cjs.map +1 -1
- package/dist/extra.js +43 -2
- package/dist/extra.js.map +1 -1
- package/dist/fluent.cjs +88 -14
- package/dist/fluent.cjs.map +1 -1
- package/dist/fluent.js +88 -14
- package/dist/fluent.js.map +1 -1
- package/dist/index.cjs +120 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +120 -38
- package/dist/index.js.map +1 -1
- package/dist/internal/ctor.d.cts +8 -8
- package/dist/internal/ctor.d.ts +8 -8
- package/dist/internal/proto.d.cts +3 -0
- package/dist/internal/proto.d.ts +3 -0
- package/dist/railway.cjs +105 -31
- package/dist/railway.cjs.map +1 -1
- package/dist/railway.js +105 -31
- package/dist/railway.js.map +1 -1
- package/dist/try-gen.cjs +43 -6
- package/dist/try-gen.cjs.map +1 -1
- package/dist/try-gen.js +43 -6
- package/dist/try-gen.js.map +1 -1
- package/dist/types.d.cts +67 -9
- package/dist/types.d.ts +67 -9
- package/package.json +2 -1
package/dist/try-gen.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/ctor.ts","../src/result.ts","../src/try-gen.ts"],"names":[],"mappings":";;;AAeO,IAAM,KAAA,GAAQ,CAAyB,KAAA,MAA4B;AAAA,EACxE,IAAA,EAAM,KAAA;AAAA,EACN;AACF,CAAA,CAAA;ACyEO,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;ACtF1F,IAAM,YAAN,MAAmB;AAAA,EAEjB,YAAqB,KAAA,EAAU;AAAV,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAW;AAAA,EAAX,KAAA;AAAA,EADZ,IAAA,GAAO,WAAA;AAElB,CAAA;AAmBO,IAAM,WAAA,GAAc,CAAO,MAAA,KAA4B;AAC5D,EAAA,IAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AACjB,IAAA,MAAM,IAAI,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA,CAAO,KAAA;AAChB;AAeO,IAAM,CAAA,GAAI;AAcV,IAAM,MAAA,GAAS,CAAO,EAAA,KAAyC;AACpE,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,SAAA,EAAW;AAC9B,MAAA,OAAO,KAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAC1B;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF","file":"try-gen.cjs","sourcesContent":["import type { Result } from \"../types.js\";\n\n/**\n * Unlocked `Ok` constructor for library internals.\n *\n * The public {@link ok} takes a `const` type parameter so caller literals stay\n * narrow. Internals must never narrow a payload type, so they build results\n * through this constructor instead.\n */\nexport const mkOk = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\n\n/** Unlocked `Err` constructor for library internals. Mirror of {@link mkOk}. */\nexport const mkErr = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n error,\n});\n","import { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { dual } from \"./internal/dual.js\";\nimport type { Payload } from \"./internal/payload.js\";\nimport { toError } from \"./internal/to-error.js\";\nimport type { Err, Ok, Result } from \"./types.js\";\n\nexport type { Err, Ok, Result } from \"./types.js\";\n\n/**\n * Lifts a value into the success track.\n *\n * @example\n * ```ts\n * const r = ok(42); // Result<42, never> — literal locked\n * const typed: Result<number, \"parse\"> = ok(1);\n * const lift = <T, E>(v: T): Result<T, E> => ok(v); // generic T passes through\n * ```\n *\n * @remarks\n * An inline literal keeps its narrow type instead of widening (`ok(\"a\")` is\n * `Result<\"a\", never>`, not `Result<string, never>`), and an array literal\n * stays a mutable tuple (`ok([1, 2])` satisfies `Result<number[], E>`). A\n * generic `T` always comes back as `T`. Passing both type arguments opts out\n * of locking entirely.\n */\nexport function ok<const T extends Payload[]>(value: T): Result<T, never>;\nexport function ok<const T>(value: T): Result<T, never>;\nexport function ok<T, E>(value: T): Result<T, E>;\nexport function ok<T>(value: T): Result<T, never> {\n return mkOk(value);\n}\n\n/**\n * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<42, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\n\n/**\n * Lifts a value into the error track.\n *\n * @example\n * ```ts\n * const r = err({ kind: \"parse\", message: \"bad json\" });\n * // Result<never, { readonly kind: \"parse\"; readonly message: string }>\n *\n * type AppError = { kind: \"parse\" } | { kind: \"io\" };\n * err<AppError>({ kind: \"io\" }); // Result<never, AppError> — one arg names the error\n * err<number, AppError>({ kind: \"io\" }); // Result<number, AppError> — neverthrow's T, E order\n * ```\n *\n * @remarks\n * One explicit type argument names the **error** channel, which is what the\n * call site almost always means. Both channels still take neverthrow's `T, E`\n * order. Inference locks literals the same way as {@link ok}, and a generic\n * `E` always comes back as `E`.\n */\nexport function err<const E extends Payload[]>(error: E): Result<never, E>;\nexport function err<const E>(error: E): Result<never, E>;\nexport function err<T, E>(error: E): Result<T, E>;\nexport function err<E>(error: E): Result<never, E> {\n return mkErr(error);\n}\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Ok`.\n *\n * @example\n * ```ts\n * if (isOk(r)) {\n * console.log(r.value); // narrowed to Ok branch\n * }\n * ```\n */\nexport const isOk = <T, E>(result: Result<T, E>): result is Ok<T, E> => result._tag === \"Ok\";\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Err`.\n *\n * @example\n * ```ts\n * if (isErr(r)) {\n * metrics.inc(\"error\", { kind: r.error.kind });\n * }\n * ```\n */\nexport const isErr = <T, E>(result: Result<T, E>): result is Err<T, E> => result._tag === \"Err\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transform the `Ok` value, passing `Err` through unchanged. Dual-form:\n * call data-first or curried (for use with {@link pipe}).\n *\n * @example\n * ```ts\n * map(ok(2), (n) => n * 3); // Ok 6 — data-first\n * pipe(ok(\"x\"), map((s) => s.length));// Ok 1 — curried\n * ```\n */\nexport const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error),\n);\n\n/**\n * Transform the `Err` value, passing `Ok` through unchanged. Useful for\n * unifying heterogeneous failure types into one app-level union.\n *\n * @example\n * ```ts\n * type AppError = { kind: \"http\"; status: number } | { kind: \"parse\" };\n * pipe(\n * fetchSync(url), // Result<Body, { status: number }>\n * mapErr((e): AppError => ({ kind: \"http\", status: e.status })),\n * );\n * ```\n */\nexport const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value),\n);\n\n/**\n * Transform both tracks at once — `Ok` via `onOk`, `Err` via `onErr`.\n * Equivalent to `mapErr(onErr)(map(onOk)(result))` but in one pass.\n *\n * @example\n * ```ts\n * bimap(parsed, (cfg) => cfg.name, (e) => ({ kind: \"input\", cause: e }));\n * ```\n */\nexport const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): Result<U, F> => (isOk(result) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))),\n);\n\n/**\n * Canonical bind (Fantasy Land `chain`). Chains a Result-returning step,\n * widening the error union to `E | F`. Short-circuits on `Err`.\n *\n * @example\n * ```ts\n * flatMap(parseInput(raw), (data) =>\n * data.id != null ? ok(data) : err({ kind: \"missing_id\" as const }),\n * );\n * // Result<Data, ParseError | { kind: \"missing_id\" }>\n * ```\n */\nexport const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : mkErr(result.error),\n);\n\n/**\n * Error-track bind — runs `fn` only when the result is `Err`, allowing\n * a failed workflow to recover to `Ok` or remap the failure. Mirror of\n * {@link flatMap} on the error channel.\n *\n * @example\n * ```ts\n * recover(networkResult, (e) =>\n * e.kind === \"rate_limit\" ? ok(cachedBody) : err(e),\n * );\n * ```\n */\nexport const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : mkOk(result.value),\n);\n\n/**\n * Observe the `Ok` value for side effects (logging, metrics) without\n * changing the carried value. Passes `Err` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * tap((cfg) => log.info({ msg: \"parsed\", name: cfg.name })),\n * flatMap(validate),\n * );\n * ```\n */\nexport const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> => {\n if (isOk(result)) fn(result.value);\n return result;\n});\n\n/**\n * Observe the `Err` value for side effects (logging, metrics) without\n * changing the carried error. Passes `Ok` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * loadUser(id),\n * tapErr((e) => metrics.inc(\"user.load.fail\", { kind: e.kind })),\n * );\n * ```\n */\nexport const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> => {\n if (isErr(result)) fn(result.error);\n return result;\n});\n\n/**\n * Terminal collapse — fold both tracks into a single value. Dual-form:\n * 3-args data-first, 2-args curried for {@link pipe}. Returns whatever\n * the handlers return.\n *\n * For files that also import `match` from `ts-pattern`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`. The\n * fallback may be a different type from `T` — the return widens to `T | U`,\n * matching `ResultAsync.unwrapOr` and the compat shim.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\"); // string\n * unwrapOr(parsedPort, null); // number | null\n * ```\n */\nexport const unwrapOr: {\n <T, E, U>(result: Result<T, E>, defaultValue: U): T | U;\n <U>(defaultValue: U): <T, E>(result: Result<T, E>) => T | U;\n} = dual(2, <T, E, U>(result: Result<T, E>, defaultValue: U): T | U =>\n isOk(result) ? result.value : defaultValue,\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\nexport function unwrapErr<T, E>(result: Result<T, E>): E {\n if (isOk(result)) throw new TypeError(\"unwrapErr called on Ok\");\n return result.error;\n}\n\n/**\n * Wraps a throwing sync **function**, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. Same name and shape as\n * neverthrow's `Result.fromThrowable`.\n *\n * Reach for {@link trySync} instead when you want to run the call right now\n * rather than build a reusable wrapper.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = fromThrowable(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\nexport function fromThrowable<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function fromThrowable<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function fromThrowable(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return mkOk(fn(...args));\n } catch (error) {\n return mkErr(onThrow(error));\n }\n };\n}\n\n/**\n * Runs `fn` **now**, catching a throw into the `Err` track — the sync mirror\n * of `tryAsync`. Without `onThrow` the thrown value is normalized to an\n * `Error`; pass a mapper for a typed error.\n *\n * To lift a throwing function once and call it many times, use\n * {@link fromThrowable}.\n *\n * @param fn - the throwing thunk to run\n * @param onThrow - maps a thrown value to the `Err` channel\n *\n * @example\n * ```ts\n * trySync(() => JSON.parse(raw)); // Result<unknown, Error>\n * trySync(() => Schema.parse(input), (e): SchemaError => ({\n * kind: \"schema\",\n * cause: e,\n * }));\n * ```\n */\nexport function trySync<T>(fn: () => T): Result<T, Error>;\nexport function trySync<T, E>(fn: () => T, onThrow: (error: unknown) => E): Result<T, E>;\nexport function trySync<T, E>(fn: () => T, onThrow?: (error: unknown) => E): Result<T, E | Error> {\n try {\n return mkOk(fn());\n } catch (error) {\n return mkErr(onThrow ? onThrow(error) : toError(error));\n }\n}\n\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","import { mkErr } from \"./internal/ctor.js\";\nimport { isErr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Internal control-flow signal — not part of public error types */\nclass ErrSignal<E> {\n readonly _tag = \"ErrSignal\" as const;\n constructor(readonly error: E) {}\n}\n\n/**\n * Unwraps a {@link Result} inside a {@link tryGen} block — the sync analogue of\n * Rust's `?` operator. On `Ok` it returns the value; on `Err` it short-circuits\n * the enclosing `tryGen`, which returns that `Err`. Only valid inside `tryGen`;\n * prefer {@link flatMap} / `pipe` for long pipelines.\n *\n * @returns the unwrapped `Ok` value\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = yieldResult(parseA()); // unwrap or short-circuit\n * const b = yieldResult(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const yieldResult = <T, E>(result: Result<T, E>): T => {\n if (isErr(result)) {\n throw new ErrSignal(result.error);\n }\n return result.value;\n};\n\n/**\n * Terse alias of {@link yieldResult} (mirrors Rust's `?`), for compact\n * {@link tryGen} blocks.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const $ = yieldResult;\n\n/**\n * Run a block that uses {@link yieldResult}; returns the final `Result` or the first Err.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const tryGen = <T, E>(fn: () => Result<T, E>): Result<T, E> => {\n try {\n return fn();\n } catch (error) {\n if (error instanceof ErrSignal) {\n return mkErr(error.error);\n }\n throw error;\n }\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/proto.ts","../src/result.ts","../src/try-gen.ts"],"names":[],"mappings":";;;AAMA,IAAM,OAAA,mBAAU,MAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA;AAqDvD,IAAM,OAAA,GAAN,MAAM,QAAA,CAA6C;AAAA,EACxC,IAAA;AAAA,EACA,KAAA;AAAA,EACT,YAAY,KAAA,EAAU;AACpB,IAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AAAA,EACA,CAAC,OAAO,CAAA,CAAE,MAAA,EAAgB,SAAkB,OAAA,EAA0B;AACpE,IAAA,OAAO,CAAA,IAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,OAAO,CAAC,CAAA,CAAA,CAAA;AAAA,EAC5C;AAAA,EACA,IAAO,GAAA,EAAoC;AACzC,IAAA,OAAO,IAAI,QAAA,CAAc,IAAA,CAAK,KAAK,CAAA;AAAA,EACrC;AAAA,EACA,OAAU,EAAA,EAAmC;AAC3C,IAAA,OAAO,IAAI,QAAA,CAAc,EAAA,CAAG,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,EACzC;AAAA,EACA,QAAc,GAAA,EAAmD;AAC/D,IAAA,OAAO,IAAI,QAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACzC;AAAA,EACA,QAAc,GAAA,EAAmD;AAC/D,IAAA,OAAO,IAAI,QAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACzC;AAAA,EACA,QAAW,EAAA,EAA8C;AACvD,IAAA,OAAO,EAAA,CAAG,KAAK,KAAK,CAAA;AAAA,EACtB;AAAA,EACA,IAAI,GAAA,EAAuC;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EACA,OAAO,EAAA,EAAsC;AAC3C,IAAA,EAAA,CAAG,KAAK,KAAK,CAAA;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EACA,KAAA,CAAS,OAAwB,KAAA,EAA2B;AAC1D,IAAA,OAAO,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EACA,SAAY,YAAA,EAAwB;AAClC,IAAA,OAAO,YAAA;AAAA,EACT;AACF,CAAA;AAGO,IAAM,MAAA,GAAS,CAAO,KAAA,KAA2B,IAAI,QAAc,KAAK,CAAA;ACNxE,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;ACzF1F,IAAM,YAAN,MAAmB;AAAA,EAEjB,YAAqB,KAAA,EAAU;AAAV,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAW;AAAA,EAAX,KAAA;AAAA,EADZ,IAAA,GAAO,WAAA;AAElB,CAAA;AAmBO,IAAM,WAAA,GAAc,CAAO,MAAA,KAA4B;AAC5D,EAAA,IAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AACjB,IAAA,MAAM,IAAI,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA,CAAO,KAAA;AAChB;AAeO,IAAM,CAAA,GAAI;AAcV,IAAM,MAAA,GAAS,CAAO,EAAA,KAAyC;AACpE,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,SAAA,EAAW;AAC9B,MAAA,OAAO,MAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAC1B;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF","file":"try-gen.cjs","sourcesContent":["import type { Result, ResultMethods } from \"../types.js\";\n\n/**\n * `util.inspect` / `Bun.inspect` / `console.log` hook: render `Ok(1)` instead of dumping the class\n * name and every prototype method. Symbol-keyed, so it adds no enumerable field and JSON is unchanged.\n */\nconst INSPECT = Symbol.for(\"nodejs.util.inspect.custom\");\ntype Inspect = (value: unknown, options?: unknown) => string;\n\n/**\n * Live carrier classes. `_tag` and `value` / `error` are own enumerable\n * fields, so JSON and `structuredClone` see plain data; every method lives on\n * the prototype and is therefore non-enumerable.\n *\n * Internal only: reach carriers through {@link newOk} / {@link newErr}\n * (aliased as `mkOk` / `mkErr` for unlocked internals) or the public\n * `ok` / `err`.\n */\nclass OkImpl<T, E> implements ResultMethods<T, E> {\n readonly _tag: \"Ok\";\n readonly value: T;\n // explicit assignment order keeps `_tag` first, so JSON key order matches the plain-data shape\n constructor(value: T) {\n this._tag = \"Ok\";\n this.value = value;\n }\n [INSPECT](_depth: number, options: unknown, inspect: Inspect): string {\n return `Ok(${inspect(this.value, options)})`;\n }\n map<U>(fn: (value: T) => U): Result<U, E> {\n return new OkImpl<U, E>(fn(this.value));\n }\n mapErr<F>(_fn: (error: E) => F): Result<T, F> {\n return new OkImpl<T, F>(this.value);\n }\n flatMap<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return fn(this.value);\n }\n andThen<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return fn(this.value);\n }\n recover<F>(_fn: (error: E) => Result<T, F>): Result<T, F> {\n return new OkImpl<T, F>(this.value);\n }\n tap(fn: (value: T) => void): Result<T, E> {\n fn(this.value);\n return this;\n }\n tapErr(_fn: (error: E) => void): Result<T, E> {\n return this;\n }\n match<U>(onOk: (value: T) => U, _onErr: (error: E) => U): U {\n return onOk(this.value);\n }\n unwrapOr<U>(_defaultValue: U): T | U {\n return this.value;\n }\n}\n\nclass ErrImpl<T, E> implements ResultMethods<T, E> {\n readonly _tag: \"Err\";\n readonly error: E;\n constructor(error: E) {\n this._tag = \"Err\";\n this.error = error;\n }\n [INSPECT](_depth: number, options: unknown, inspect: Inspect): string {\n return `Err(${inspect(this.error, options)})`;\n }\n map<U>(_fn: (value: T) => U): Result<U, E> {\n return new ErrImpl<U, E>(this.error);\n }\n mapErr<F>(fn: (error: E) => F): Result<T, F> {\n return new ErrImpl<T, F>(fn(this.error));\n }\n flatMap<U, F>(_fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return new ErrImpl<U, E | F>(this.error);\n }\n andThen<U, F>(_fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return new ErrImpl<U, E | F>(this.error);\n }\n recover<F>(fn: (error: E) => Result<T, F>): Result<T, F> {\n return fn(this.error);\n }\n tap(_fn: (value: T) => void): Result<T, E> {\n return this;\n }\n tapErr(fn: (error: E) => void): Result<T, E> {\n fn(this.error);\n return this;\n }\n match<U>(_onOk: (value: T) => U, onErr: (error: E) => U): U {\n return onErr(this.error);\n }\n unwrapOr<U>(defaultValue: U): T | U {\n return defaultValue;\n }\n}\n\nexport const newOk = <T, E>(value: T): Result<T, E> => new OkImpl<T, E>(value);\nexport const newErr = <T, E>(error: E): Result<T, E> => new ErrImpl<T, E>(error);\n","import { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { dual } from \"./internal/dual.js\";\nimport type { Payload } from \"./internal/payload.js\";\nimport { newErr, newOk } from \"./internal/proto.js\";\nimport { toError } from \"./internal/to-error.js\";\nimport type { Err, Ok, Result } from \"./types.js\";\n\nexport type { Err, Ok, Result } from \"./types.js\";\n\n/**\n * Lifts a value into the success track.\n *\n * @example\n * ```ts\n * const r = ok(42); // Result<42, never> — literal locked\n * const typed: Result<number, \"parse\"> = ok(1);\n * const lift = <T, E>(v: T): Result<T, E> => ok(v); // generic T passes through\n * ```\n *\n * @remarks\n * An inline literal keeps its narrow type instead of widening (`ok(\"a\")` is\n * `Result<\"a\", never>`, not `Result<string, never>`), and an array literal\n * stays a mutable tuple (`ok([1, 2])` satisfies `Result<number[], E>`). A\n * generic `T` always comes back as `T`. Passing both type arguments opts out\n * of locking entirely.\n */\nexport function ok<const T extends Payload[]>(value: T): Result<T, never>;\nexport function ok<const T>(value: T): Result<T, never>;\nexport function ok<T, E>(value: T): Result<T, E>;\nexport function ok<T>(value: T): Result<T, never> {\n // Direct carrier construct — skip the unlocked `mkOk` alias hop on the hot path.\n return newOk(value);\n}\n\n/**\n * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<42, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\n\n/**\n * Lifts a value into the error track.\n *\n * @example\n * ```ts\n * const r = err({ kind: \"parse\", message: \"bad json\" });\n * // Result<never, { readonly kind: \"parse\"; readonly message: string }>\n *\n * type AppError = { kind: \"parse\" } | { kind: \"io\" };\n * err<AppError>({ kind: \"io\" }); // Result<never, AppError> — one arg names the error\n * err<number, AppError>({ kind: \"io\" }); // Result<number, AppError> — neverthrow's T, E order\n * ```\n *\n * @remarks\n * One explicit type argument names the **error** channel, which is what the\n * call site almost always means. Both channels still take neverthrow's `T, E`\n * order. Inference locks literals the same way as {@link ok}, and a generic\n * `E` always comes back as `E`.\n */\nexport function err<const E extends Payload[]>(error: E): Result<never, E>;\nexport function err<const E>(error: E): Result<never, E>;\nexport function err<T, E>(error: E): Result<T, E>;\nexport function err<E>(error: E): Result<never, E> {\n // Direct carrier construct — skip the unlocked `mkErr` alias hop on the hot path.\n return newErr(error);\n}\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Ok`.\n *\n * @example\n * ```ts\n * if (isOk(r)) {\n * console.log(r.value); // narrowed to Ok branch\n * }\n * ```\n */\nexport const isOk = <T, E>(result: Result<T, E>): result is Ok<T, E> => result._tag === \"Ok\";\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Err`.\n *\n * @example\n * ```ts\n * if (isErr(r)) {\n * metrics.inc(\"error\", { kind: r.error.kind });\n * }\n * ```\n */\nexport const isErr = <T, E>(result: Result<T, E>): result is Err<T, E> => result._tag === \"Err\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transform the `Ok` value, passing `Err` through unchanged. Dual-form:\n * call data-first or curried (for use with {@link pipe}).\n *\n * @example\n * ```ts\n * map(ok(2), (n) => n * 3); // Ok 6 — data-first\n * pipe(ok(\"x\"), map((s) => s.length));// Ok 1 — curried\n * ```\n */\nexport const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error),\n);\n\n/**\n * Transform the `Err` value, passing `Ok` through unchanged. Useful for\n * unifying heterogeneous failure types into one app-level union.\n *\n * @example\n * ```ts\n * type AppError = { kind: \"http\"; status: number } | { kind: \"parse\" };\n * pipe(\n * fetchSync(url), // Result<Body, { status: number }>\n * mapErr((e): AppError => ({ kind: \"http\", status: e.status })),\n * );\n * ```\n */\nexport const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value),\n);\n\n/**\n * Transform both tracks at once — `Ok` via `onOk`, `Err` via `onErr`.\n * Equivalent to `mapErr(onErr)(map(onOk)(result))` but in one pass.\n *\n * @example\n * ```ts\n * bimap(parsed, (cfg) => cfg.name, (e) => ({ kind: \"input\", cause: e }));\n * ```\n */\nexport const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): Result<U, F> => (isOk(result) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))),\n);\n\n/**\n * Canonical bind (Fantasy Land `chain`). Chains a Result-returning step,\n * widening the error union to `E | F`. Short-circuits on `Err`.\n *\n * @example\n * ```ts\n * flatMap(parseInput(raw), (data) =>\n * data.id != null ? ok(data) : err({ kind: \"missing_id\" as const }),\n * );\n * // Result<Data, ParseError | { kind: \"missing_id\" }>\n * ```\n */\nexport const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : mkErr(result.error),\n);\n\n/**\n * Error-track bind — runs `fn` only when the result is `Err`, allowing\n * a failed workflow to recover to `Ok` or remap the failure. Mirror of\n * {@link flatMap} on the error channel.\n *\n * @example\n * ```ts\n * recover(networkResult, (e) =>\n * e.kind === \"rate_limit\" ? ok(cachedBody) : err(e),\n * );\n * ```\n */\nexport const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : mkOk(result.value),\n);\n\n/**\n * Observe the `Ok` value for side effects (logging, metrics) without\n * changing the carried value. Passes `Err` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * tap((cfg) => log.info({ msg: \"parsed\", name: cfg.name })),\n * flatMap(validate),\n * );\n * ```\n */\nexport const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> => {\n if (isOk(result)) fn(result.value);\n return result;\n});\n\n/**\n * Observe the `Err` value for side effects (logging, metrics) without\n * changing the carried error. Passes `Ok` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * loadUser(id),\n * tapErr((e) => metrics.inc(\"user.load.fail\", { kind: e.kind })),\n * );\n * ```\n */\nexport const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> => {\n if (isErr(result)) fn(result.error);\n return result;\n});\n\n/**\n * Terminal collapse — fold both tracks into a single value. Dual-form:\n * 3-args data-first, 2-args curried for {@link pipe}. Returns whatever\n * the handlers return.\n *\n * For files that also import `match` from `ts-pattern`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`. The\n * fallback may be a different type from `T` — the return widens to `T | U`,\n * matching `ResultAsync.unwrapOr` and the compat shim.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\"); // string\n * unwrapOr(parsedPort, null); // number | null\n * ```\n */\nexport const unwrapOr: {\n <T, E, U>(result: Result<T, E>, defaultValue: U): T | U;\n <U>(defaultValue: U): <T, E>(result: Result<T, E>) => T | U;\n} = dual(2, <T, E, U>(result: Result<T, E>, defaultValue: U): T | U =>\n isOk(result) ? result.value : defaultValue,\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\nexport function unwrapErr<T, E>(result: Result<T, E>): E {\n if (isOk(result)) throw new TypeError(\"unwrapErr called on Ok\");\n return result.error;\n}\n\n/**\n * Wraps a throwing sync **function**, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. Same name and shape as\n * neverthrow's `Result.fromThrowable`.\n *\n * Reach for {@link trySync} instead when you want to run the call right now\n * rather than build a reusable wrapper.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = fromThrowable(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\nexport function fromThrowable<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function fromThrowable<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function fromThrowable(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return mkOk(fn(...args));\n } catch (error) {\n return mkErr(onThrow(error));\n }\n };\n}\n\n/**\n * Runs `fn` **now**, catching a throw into the `Err` track — the sync mirror\n * of `tryAsync`. Without `onThrow` the thrown value is normalized to an\n * `Error`; pass a mapper for a typed error.\n *\n * To lift a throwing function once and call it many times, use\n * {@link fromThrowable}.\n *\n * @param fn - the throwing thunk to run\n * @param onThrow - maps a thrown value to the `Err` channel\n *\n * @example\n * ```ts\n * trySync(() => JSON.parse(raw)); // Result<unknown, Error>\n * trySync(() => Schema.parse(input), (e): SchemaError => ({\n * kind: \"schema\",\n * cause: e,\n * }));\n * ```\n */\nexport function trySync<T>(fn: () => T): Result<T, Error>;\nexport function trySync<T, E>(fn: () => T, onThrow: (error: unknown) => E): Result<T, E>;\nexport function trySync<T, E>(fn: () => T, onThrow?: (error: unknown) => E): Result<T, E | Error> {\n try {\n return mkOk(fn());\n } catch (error) {\n return mkErr(onThrow ? onThrow(error) : toError(error));\n }\n}\n\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","import { mkErr } from \"./internal/ctor.js\";\nimport { isErr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Internal control-flow signal — not part of public error types */\nclass ErrSignal<E> {\n readonly _tag = \"ErrSignal\" as const;\n constructor(readonly error: E) {}\n}\n\n/**\n * Unwraps a {@link Result} inside a {@link tryGen} block — the sync analogue of\n * Rust's `?` operator. On `Ok` it returns the value; on `Err` it short-circuits\n * the enclosing `tryGen`, which returns that `Err`. Only valid inside `tryGen`;\n * prefer {@link flatMap} / `pipe` for long pipelines.\n *\n * @returns the unwrapped `Ok` value\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = yieldResult(parseA()); // unwrap or short-circuit\n * const b = yieldResult(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const yieldResult = <T, E>(result: Result<T, E>): T => {\n if (isErr(result)) {\n throw new ErrSignal(result.error);\n }\n return result.value;\n};\n\n/**\n * Terse alias of {@link yieldResult} (mirrors Rust's `?`), for compact\n * {@link tryGen} blocks.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const $ = yieldResult;\n\n/**\n * Run a block that uses {@link yieldResult}; returns the final `Result` or the first Err.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const tryGen = <T, E>(fn: () => Result<T, E>): Result<T, E> => {\n try {\n return fn();\n } catch (error) {\n if (error instanceof ErrSignal) {\n return mkErr(error.error);\n }\n throw error;\n }\n};\n"]}
|
package/dist/try-gen.js
CHANGED
|
@@ -1,8 +1,45 @@
|
|
|
1
|
-
// src/internal/
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// src/internal/proto.ts
|
|
2
|
+
var INSPECT = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
3
|
+
var ErrImpl = class _ErrImpl {
|
|
4
|
+
_tag;
|
|
5
|
+
error;
|
|
6
|
+
constructor(error) {
|
|
7
|
+
this._tag = "Err";
|
|
8
|
+
this.error = error;
|
|
9
|
+
}
|
|
10
|
+
[INSPECT](_depth, options, inspect) {
|
|
11
|
+
return `Err(${inspect(this.error, options)})`;
|
|
12
|
+
}
|
|
13
|
+
map(_fn) {
|
|
14
|
+
return new _ErrImpl(this.error);
|
|
15
|
+
}
|
|
16
|
+
mapErr(fn) {
|
|
17
|
+
return new _ErrImpl(fn(this.error));
|
|
18
|
+
}
|
|
19
|
+
flatMap(_fn) {
|
|
20
|
+
return new _ErrImpl(this.error);
|
|
21
|
+
}
|
|
22
|
+
andThen(_fn) {
|
|
23
|
+
return new _ErrImpl(this.error);
|
|
24
|
+
}
|
|
25
|
+
recover(fn) {
|
|
26
|
+
return fn(this.error);
|
|
27
|
+
}
|
|
28
|
+
tap(_fn) {
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
tapErr(fn) {
|
|
32
|
+
fn(this.error);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
match(_onOk, onErr) {
|
|
36
|
+
return onErr(this.error);
|
|
37
|
+
}
|
|
38
|
+
unwrapOr(defaultValue) {
|
|
39
|
+
return defaultValue;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var newErr = (error) => new ErrImpl(error);
|
|
6
43
|
var isErr = (result) => result._tag === "Err";
|
|
7
44
|
|
|
8
45
|
// src/try-gen.ts
|
|
@@ -25,7 +62,7 @@ var tryGen = (fn) => {
|
|
|
25
62
|
return fn();
|
|
26
63
|
} catch (error) {
|
|
27
64
|
if (error instanceof ErrSignal) {
|
|
28
|
-
return
|
|
65
|
+
return newErr(error.error);
|
|
29
66
|
}
|
|
30
67
|
throw error;
|
|
31
68
|
}
|
package/dist/try-gen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/ctor.ts","../src/result.ts","../src/try-gen.ts"],"names":[],"mappings":";AAeO,IAAM,KAAA,GAAQ,CAAyB,KAAA,MAA4B;AAAA,EACxE,IAAA,EAAM,KAAA;AAAA,EACN;AACF,CAAA,CAAA;ACyEO,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;ACtF1F,IAAM,YAAN,MAAmB;AAAA,EAEjB,YAAqB,KAAA,EAAU;AAAV,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAW;AAAA,EAAX,KAAA;AAAA,EADZ,IAAA,GAAO,WAAA;AAElB,CAAA;AAmBO,IAAM,WAAA,GAAc,CAAO,MAAA,KAA4B;AAC5D,EAAA,IAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AACjB,IAAA,MAAM,IAAI,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA,CAAO,KAAA;AAChB;AAeO,IAAM,CAAA,GAAI;AAcV,IAAM,MAAA,GAAS,CAAO,EAAA,KAAyC;AACpE,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,SAAA,EAAW;AAC9B,MAAA,OAAO,KAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAC1B;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF","file":"try-gen.js","sourcesContent":["import type { Result } from \"../types.js\";\n\n/**\n * Unlocked `Ok` constructor for library internals.\n *\n * The public {@link ok} takes a `const` type parameter so caller literals stay\n * narrow. Internals must never narrow a payload type, so they build results\n * through this constructor instead.\n */\nexport const mkOk = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\n\n/** Unlocked `Err` constructor for library internals. Mirror of {@link mkOk}. */\nexport const mkErr = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n error,\n});\n","import { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { dual } from \"./internal/dual.js\";\nimport type { Payload } from \"./internal/payload.js\";\nimport { toError } from \"./internal/to-error.js\";\nimport type { Err, Ok, Result } from \"./types.js\";\n\nexport type { Err, Ok, Result } from \"./types.js\";\n\n/**\n * Lifts a value into the success track.\n *\n * @example\n * ```ts\n * const r = ok(42); // Result<42, never> — literal locked\n * const typed: Result<number, \"parse\"> = ok(1);\n * const lift = <T, E>(v: T): Result<T, E> => ok(v); // generic T passes through\n * ```\n *\n * @remarks\n * An inline literal keeps its narrow type instead of widening (`ok(\"a\")` is\n * `Result<\"a\", never>`, not `Result<string, never>`), and an array literal\n * stays a mutable tuple (`ok([1, 2])` satisfies `Result<number[], E>`). A\n * generic `T` always comes back as `T`. Passing both type arguments opts out\n * of locking entirely.\n */\nexport function ok<const T extends Payload[]>(value: T): Result<T, never>;\nexport function ok<const T>(value: T): Result<T, never>;\nexport function ok<T, E>(value: T): Result<T, E>;\nexport function ok<T>(value: T): Result<T, never> {\n return mkOk(value);\n}\n\n/**\n * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<42, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\n\n/**\n * Lifts a value into the error track.\n *\n * @example\n * ```ts\n * const r = err({ kind: \"parse\", message: \"bad json\" });\n * // Result<never, { readonly kind: \"parse\"; readonly message: string }>\n *\n * type AppError = { kind: \"parse\" } | { kind: \"io\" };\n * err<AppError>({ kind: \"io\" }); // Result<never, AppError> — one arg names the error\n * err<number, AppError>({ kind: \"io\" }); // Result<number, AppError> — neverthrow's T, E order\n * ```\n *\n * @remarks\n * One explicit type argument names the **error** channel, which is what the\n * call site almost always means. Both channels still take neverthrow's `T, E`\n * order. Inference locks literals the same way as {@link ok}, and a generic\n * `E` always comes back as `E`.\n */\nexport function err<const E extends Payload[]>(error: E): Result<never, E>;\nexport function err<const E>(error: E): Result<never, E>;\nexport function err<T, E>(error: E): Result<T, E>;\nexport function err<E>(error: E): Result<never, E> {\n return mkErr(error);\n}\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Ok`.\n *\n * @example\n * ```ts\n * if (isOk(r)) {\n * console.log(r.value); // narrowed to Ok branch\n * }\n * ```\n */\nexport const isOk = <T, E>(result: Result<T, E>): result is Ok<T, E> => result._tag === \"Ok\";\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Err`.\n *\n * @example\n * ```ts\n * if (isErr(r)) {\n * metrics.inc(\"error\", { kind: r.error.kind });\n * }\n * ```\n */\nexport const isErr = <T, E>(result: Result<T, E>): result is Err<T, E> => result._tag === \"Err\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transform the `Ok` value, passing `Err` through unchanged. Dual-form:\n * call data-first or curried (for use with {@link pipe}).\n *\n * @example\n * ```ts\n * map(ok(2), (n) => n * 3); // Ok 6 — data-first\n * pipe(ok(\"x\"), map((s) => s.length));// Ok 1 — curried\n * ```\n */\nexport const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error),\n);\n\n/**\n * Transform the `Err` value, passing `Ok` through unchanged. Useful for\n * unifying heterogeneous failure types into one app-level union.\n *\n * @example\n * ```ts\n * type AppError = { kind: \"http\"; status: number } | { kind: \"parse\" };\n * pipe(\n * fetchSync(url), // Result<Body, { status: number }>\n * mapErr((e): AppError => ({ kind: \"http\", status: e.status })),\n * );\n * ```\n */\nexport const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value),\n);\n\n/**\n * Transform both tracks at once — `Ok` via `onOk`, `Err` via `onErr`.\n * Equivalent to `mapErr(onErr)(map(onOk)(result))` but in one pass.\n *\n * @example\n * ```ts\n * bimap(parsed, (cfg) => cfg.name, (e) => ({ kind: \"input\", cause: e }));\n * ```\n */\nexport const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): Result<U, F> => (isOk(result) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))),\n);\n\n/**\n * Canonical bind (Fantasy Land `chain`). Chains a Result-returning step,\n * widening the error union to `E | F`. Short-circuits on `Err`.\n *\n * @example\n * ```ts\n * flatMap(parseInput(raw), (data) =>\n * data.id != null ? ok(data) : err({ kind: \"missing_id\" as const }),\n * );\n * // Result<Data, ParseError | { kind: \"missing_id\" }>\n * ```\n */\nexport const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : mkErr(result.error),\n);\n\n/**\n * Error-track bind — runs `fn` only when the result is `Err`, allowing\n * a failed workflow to recover to `Ok` or remap the failure. Mirror of\n * {@link flatMap} on the error channel.\n *\n * @example\n * ```ts\n * recover(networkResult, (e) =>\n * e.kind === \"rate_limit\" ? ok(cachedBody) : err(e),\n * );\n * ```\n */\nexport const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : mkOk(result.value),\n);\n\n/**\n * Observe the `Ok` value for side effects (logging, metrics) without\n * changing the carried value. Passes `Err` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * tap((cfg) => log.info({ msg: \"parsed\", name: cfg.name })),\n * flatMap(validate),\n * );\n * ```\n */\nexport const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> => {\n if (isOk(result)) fn(result.value);\n return result;\n});\n\n/**\n * Observe the `Err` value for side effects (logging, metrics) without\n * changing the carried error. Passes `Ok` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * loadUser(id),\n * tapErr((e) => metrics.inc(\"user.load.fail\", { kind: e.kind })),\n * );\n * ```\n */\nexport const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> => {\n if (isErr(result)) fn(result.error);\n return result;\n});\n\n/**\n * Terminal collapse — fold both tracks into a single value. Dual-form:\n * 3-args data-first, 2-args curried for {@link pipe}. Returns whatever\n * the handlers return.\n *\n * For files that also import `match` from `ts-pattern`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`. The\n * fallback may be a different type from `T` — the return widens to `T | U`,\n * matching `ResultAsync.unwrapOr` and the compat shim.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\"); // string\n * unwrapOr(parsedPort, null); // number | null\n * ```\n */\nexport const unwrapOr: {\n <T, E, U>(result: Result<T, E>, defaultValue: U): T | U;\n <U>(defaultValue: U): <T, E>(result: Result<T, E>) => T | U;\n} = dual(2, <T, E, U>(result: Result<T, E>, defaultValue: U): T | U =>\n isOk(result) ? result.value : defaultValue,\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\nexport function unwrapErr<T, E>(result: Result<T, E>): E {\n if (isOk(result)) throw new TypeError(\"unwrapErr called on Ok\");\n return result.error;\n}\n\n/**\n * Wraps a throwing sync **function**, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. Same name and shape as\n * neverthrow's `Result.fromThrowable`.\n *\n * Reach for {@link trySync} instead when you want to run the call right now\n * rather than build a reusable wrapper.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = fromThrowable(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\nexport function fromThrowable<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function fromThrowable<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function fromThrowable(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return mkOk(fn(...args));\n } catch (error) {\n return mkErr(onThrow(error));\n }\n };\n}\n\n/**\n * Runs `fn` **now**, catching a throw into the `Err` track — the sync mirror\n * of `tryAsync`. Without `onThrow` the thrown value is normalized to an\n * `Error`; pass a mapper for a typed error.\n *\n * To lift a throwing function once and call it many times, use\n * {@link fromThrowable}.\n *\n * @param fn - the throwing thunk to run\n * @param onThrow - maps a thrown value to the `Err` channel\n *\n * @example\n * ```ts\n * trySync(() => JSON.parse(raw)); // Result<unknown, Error>\n * trySync(() => Schema.parse(input), (e): SchemaError => ({\n * kind: \"schema\",\n * cause: e,\n * }));\n * ```\n */\nexport function trySync<T>(fn: () => T): Result<T, Error>;\nexport function trySync<T, E>(fn: () => T, onThrow: (error: unknown) => E): Result<T, E>;\nexport function trySync<T, E>(fn: () => T, onThrow?: (error: unknown) => E): Result<T, E | Error> {\n try {\n return mkOk(fn());\n } catch (error) {\n return mkErr(onThrow ? onThrow(error) : toError(error));\n }\n}\n\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","import { mkErr } from \"./internal/ctor.js\";\nimport { isErr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Internal control-flow signal — not part of public error types */\nclass ErrSignal<E> {\n readonly _tag = \"ErrSignal\" as const;\n constructor(readonly error: E) {}\n}\n\n/**\n * Unwraps a {@link Result} inside a {@link tryGen} block — the sync analogue of\n * Rust's `?` operator. On `Ok` it returns the value; on `Err` it short-circuits\n * the enclosing `tryGen`, which returns that `Err`. Only valid inside `tryGen`;\n * prefer {@link flatMap} / `pipe` for long pipelines.\n *\n * @returns the unwrapped `Ok` value\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = yieldResult(parseA()); // unwrap or short-circuit\n * const b = yieldResult(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const yieldResult = <T, E>(result: Result<T, E>): T => {\n if (isErr(result)) {\n throw new ErrSignal(result.error);\n }\n return result.value;\n};\n\n/**\n * Terse alias of {@link yieldResult} (mirrors Rust's `?`), for compact\n * {@link tryGen} blocks.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const $ = yieldResult;\n\n/**\n * Run a block that uses {@link yieldResult}; returns the final `Result` or the first Err.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const tryGen = <T, E>(fn: () => Result<T, E>): Result<T, E> => {\n try {\n return fn();\n } catch (error) {\n if (error instanceof ErrSignal) {\n return mkErr(error.error);\n }\n throw error;\n }\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/proto.ts","../src/result.ts","../src/try-gen.ts"],"names":[],"mappings":";AAMA,IAAM,OAAA,mBAAU,MAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA;AAqDvD,IAAM,OAAA,GAAN,MAAM,QAAA,CAA6C;AAAA,EACxC,IAAA;AAAA,EACA,KAAA;AAAA,EACT,YAAY,KAAA,EAAU;AACpB,IAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AAAA,EACA,CAAC,OAAO,CAAA,CAAE,MAAA,EAAgB,SAAkB,OAAA,EAA0B;AACpE,IAAA,OAAO,CAAA,IAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,OAAO,CAAC,CAAA,CAAA,CAAA;AAAA,EAC5C;AAAA,EACA,IAAO,GAAA,EAAoC;AACzC,IAAA,OAAO,IAAI,QAAA,CAAc,IAAA,CAAK,KAAK,CAAA;AAAA,EACrC;AAAA,EACA,OAAU,EAAA,EAAmC;AAC3C,IAAA,OAAO,IAAI,QAAA,CAAc,EAAA,CAAG,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,EACzC;AAAA,EACA,QAAc,GAAA,EAAmD;AAC/D,IAAA,OAAO,IAAI,QAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACzC;AAAA,EACA,QAAc,GAAA,EAAmD;AAC/D,IAAA,OAAO,IAAI,QAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACzC;AAAA,EACA,QAAW,EAAA,EAA8C;AACvD,IAAA,OAAO,EAAA,CAAG,KAAK,KAAK,CAAA;AAAA,EACtB;AAAA,EACA,IAAI,GAAA,EAAuC;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EACA,OAAO,EAAA,EAAsC;AAC3C,IAAA,EAAA,CAAG,KAAK,KAAK,CAAA;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EACA,KAAA,CAAS,OAAwB,KAAA,EAA2B;AAC1D,IAAA,OAAO,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EACA,SAAY,YAAA,EAAwB;AAClC,IAAA,OAAO,YAAA;AAAA,EACT;AACF,CAAA;AAGO,IAAM,MAAA,GAAS,CAAO,KAAA,KAA2B,IAAI,QAAc,KAAK,CAAA;ACNxE,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;ACzF1F,IAAM,YAAN,MAAmB;AAAA,EAEjB,YAAqB,KAAA,EAAU;AAAV,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAW;AAAA,EAAX,KAAA;AAAA,EADZ,IAAA,GAAO,WAAA;AAElB,CAAA;AAmBO,IAAM,WAAA,GAAc,CAAO,MAAA,KAA4B;AAC5D,EAAA,IAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AACjB,IAAA,MAAM,IAAI,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA,CAAO,KAAA;AAChB;AAeO,IAAM,CAAA,GAAI;AAcV,IAAM,MAAA,GAAS,CAAO,EAAA,KAAyC;AACpE,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,SAAA,EAAW;AAC9B,MAAA,OAAO,MAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAC1B;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF","file":"try-gen.js","sourcesContent":["import type { Result, ResultMethods } from \"../types.js\";\n\n/**\n * `util.inspect` / `Bun.inspect` / `console.log` hook: render `Ok(1)` instead of dumping the class\n * name and every prototype method. Symbol-keyed, so it adds no enumerable field and JSON is unchanged.\n */\nconst INSPECT = Symbol.for(\"nodejs.util.inspect.custom\");\ntype Inspect = (value: unknown, options?: unknown) => string;\n\n/**\n * Live carrier classes. `_tag` and `value` / `error` are own enumerable\n * fields, so JSON and `structuredClone` see plain data; every method lives on\n * the prototype and is therefore non-enumerable.\n *\n * Internal only: reach carriers through {@link newOk} / {@link newErr}\n * (aliased as `mkOk` / `mkErr` for unlocked internals) or the public\n * `ok` / `err`.\n */\nclass OkImpl<T, E> implements ResultMethods<T, E> {\n readonly _tag: \"Ok\";\n readonly value: T;\n // explicit assignment order keeps `_tag` first, so JSON key order matches the plain-data shape\n constructor(value: T) {\n this._tag = \"Ok\";\n this.value = value;\n }\n [INSPECT](_depth: number, options: unknown, inspect: Inspect): string {\n return `Ok(${inspect(this.value, options)})`;\n }\n map<U>(fn: (value: T) => U): Result<U, E> {\n return new OkImpl<U, E>(fn(this.value));\n }\n mapErr<F>(_fn: (error: E) => F): Result<T, F> {\n return new OkImpl<T, F>(this.value);\n }\n flatMap<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return fn(this.value);\n }\n andThen<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return fn(this.value);\n }\n recover<F>(_fn: (error: E) => Result<T, F>): Result<T, F> {\n return new OkImpl<T, F>(this.value);\n }\n tap(fn: (value: T) => void): Result<T, E> {\n fn(this.value);\n return this;\n }\n tapErr(_fn: (error: E) => void): Result<T, E> {\n return this;\n }\n match<U>(onOk: (value: T) => U, _onErr: (error: E) => U): U {\n return onOk(this.value);\n }\n unwrapOr<U>(_defaultValue: U): T | U {\n return this.value;\n }\n}\n\nclass ErrImpl<T, E> implements ResultMethods<T, E> {\n readonly _tag: \"Err\";\n readonly error: E;\n constructor(error: E) {\n this._tag = \"Err\";\n this.error = error;\n }\n [INSPECT](_depth: number, options: unknown, inspect: Inspect): string {\n return `Err(${inspect(this.error, options)})`;\n }\n map<U>(_fn: (value: T) => U): Result<U, E> {\n return new ErrImpl<U, E>(this.error);\n }\n mapErr<F>(fn: (error: E) => F): Result<T, F> {\n return new ErrImpl<T, F>(fn(this.error));\n }\n flatMap<U, F>(_fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return new ErrImpl<U, E | F>(this.error);\n }\n andThen<U, F>(_fn: (value: T) => Result<U, F>): Result<U, E | F> {\n return new ErrImpl<U, E | F>(this.error);\n }\n recover<F>(fn: (error: E) => Result<T, F>): Result<T, F> {\n return fn(this.error);\n }\n tap(_fn: (value: T) => void): Result<T, E> {\n return this;\n }\n tapErr(fn: (error: E) => void): Result<T, E> {\n fn(this.error);\n return this;\n }\n match<U>(_onOk: (value: T) => U, onErr: (error: E) => U): U {\n return onErr(this.error);\n }\n unwrapOr<U>(defaultValue: U): T | U {\n return defaultValue;\n }\n}\n\nexport const newOk = <T, E>(value: T): Result<T, E> => new OkImpl<T, E>(value);\nexport const newErr = <T, E>(error: E): Result<T, E> => new ErrImpl<T, E>(error);\n","import { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { dual } from \"./internal/dual.js\";\nimport type { Payload } from \"./internal/payload.js\";\nimport { newErr, newOk } from \"./internal/proto.js\";\nimport { toError } from \"./internal/to-error.js\";\nimport type { Err, Ok, Result } from \"./types.js\";\n\nexport type { Err, Ok, Result } from \"./types.js\";\n\n/**\n * Lifts a value into the success track.\n *\n * @example\n * ```ts\n * const r = ok(42); // Result<42, never> — literal locked\n * const typed: Result<number, \"parse\"> = ok(1);\n * const lift = <T, E>(v: T): Result<T, E> => ok(v); // generic T passes through\n * ```\n *\n * @remarks\n * An inline literal keeps its narrow type instead of widening (`ok(\"a\")` is\n * `Result<\"a\", never>`, not `Result<string, never>`), and an array literal\n * stays a mutable tuple (`ok([1, 2])` satisfies `Result<number[], E>`). A\n * generic `T` always comes back as `T`. Passing both type arguments opts out\n * of locking entirely.\n */\nexport function ok<const T extends Payload[]>(value: T): Result<T, never>;\nexport function ok<const T>(value: T): Result<T, never>;\nexport function ok<T, E>(value: T): Result<T, E>;\nexport function ok<T>(value: T): Result<T, never> {\n // Direct carrier construct — skip the unlocked `mkOk` alias hop on the hot path.\n return newOk(value);\n}\n\n/**\n * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<42, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\n\n/**\n * Lifts a value into the error track.\n *\n * @example\n * ```ts\n * const r = err({ kind: \"parse\", message: \"bad json\" });\n * // Result<never, { readonly kind: \"parse\"; readonly message: string }>\n *\n * type AppError = { kind: \"parse\" } | { kind: \"io\" };\n * err<AppError>({ kind: \"io\" }); // Result<never, AppError> — one arg names the error\n * err<number, AppError>({ kind: \"io\" }); // Result<number, AppError> — neverthrow's T, E order\n * ```\n *\n * @remarks\n * One explicit type argument names the **error** channel, which is what the\n * call site almost always means. Both channels still take neverthrow's `T, E`\n * order. Inference locks literals the same way as {@link ok}, and a generic\n * `E` always comes back as `E`.\n */\nexport function err<const E extends Payload[]>(error: E): Result<never, E>;\nexport function err<const E>(error: E): Result<never, E>;\nexport function err<T, E>(error: E): Result<T, E>;\nexport function err<E>(error: E): Result<never, E> {\n // Direct carrier construct — skip the unlocked `mkErr` alias hop on the hot path.\n return newErr(error);\n}\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Ok`.\n *\n * @example\n * ```ts\n * if (isOk(r)) {\n * console.log(r.value); // narrowed to Ok branch\n * }\n * ```\n */\nexport const isOk = <T, E>(result: Result<T, E>): result is Ok<T, E> => result._tag === \"Ok\";\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Err`.\n *\n * @example\n * ```ts\n * if (isErr(r)) {\n * metrics.inc(\"error\", { kind: r.error.kind });\n * }\n * ```\n */\nexport const isErr = <T, E>(result: Result<T, E>): result is Err<T, E> => result._tag === \"Err\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Transform the `Ok` value, passing `Err` through unchanged. Dual-form:\n * call data-first or curried (for use with {@link pipe}).\n *\n * @example\n * ```ts\n * map(ok(2), (n) => n * 3); // Ok 6 — data-first\n * pipe(ok(\"x\"), map((s) => s.length));// Ok 1 — curried\n * ```\n */\nexport const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error),\n);\n\n/**\n * Transform the `Err` value, passing `Ok` through unchanged. Useful for\n * unifying heterogeneous failure types into one app-level union.\n *\n * @example\n * ```ts\n * type AppError = { kind: \"http\"; status: number } | { kind: \"parse\" };\n * pipe(\n * fetchSync(url), // Result<Body, { status: number }>\n * mapErr((e): AppError => ({ kind: \"http\", status: e.status })),\n * );\n * ```\n */\nexport const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value),\n);\n\n/**\n * Transform both tracks at once — `Ok` via `onOk`, `Err` via `onErr`.\n * Equivalent to `mapErr(onErr)(map(onOk)(result))` but in one pass.\n *\n * @example\n * ```ts\n * bimap(parsed, (cfg) => cfg.name, (e) => ({ kind: \"input\", cause: e }));\n * ```\n */\nexport const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): Result<U, F> => (isOk(result) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))),\n);\n\n/**\n * Canonical bind (Fantasy Land `chain`). Chains a Result-returning step,\n * widening the error union to `E | F`. Short-circuits on `Err`.\n *\n * @example\n * ```ts\n * flatMap(parseInput(raw), (data) =>\n * data.id != null ? ok(data) : err({ kind: \"missing_id\" as const }),\n * );\n * // Result<Data, ParseError | { kind: \"missing_id\" }>\n * ```\n */\nexport const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : mkErr(result.error),\n);\n\n/**\n * Error-track bind — runs `fn` only when the result is `Err`, allowing\n * a failed workflow to recover to `Ok` or remap the failure. Mirror of\n * {@link flatMap} on the error channel.\n *\n * @example\n * ```ts\n * recover(networkResult, (e) =>\n * e.kind === \"rate_limit\" ? ok(cachedBody) : err(e),\n * );\n * ```\n */\nexport const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : mkOk(result.value),\n);\n\n/**\n * Observe the `Ok` value for side effects (logging, metrics) without\n * changing the carried value. Passes `Err` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * tap((cfg) => log.info({ msg: \"parsed\", name: cfg.name })),\n * flatMap(validate),\n * );\n * ```\n */\nexport const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> => {\n if (isOk(result)) fn(result.value);\n return result;\n});\n\n/**\n * Observe the `Err` value for side effects (logging, metrics) without\n * changing the carried error. Passes `Ok` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * loadUser(id),\n * tapErr((e) => metrics.inc(\"user.load.fail\", { kind: e.kind })),\n * );\n * ```\n */\nexport const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> => {\n if (isErr(result)) fn(result.error);\n return result;\n});\n\n/**\n * Terminal collapse — fold both tracks into a single value. Dual-form:\n * 3-args data-first, 2-args curried for {@link pipe}. Returns whatever\n * the handlers return.\n *\n * For files that also import `match` from `ts-pattern`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`. The\n * fallback may be a different type from `T` — the return widens to `T | U`,\n * matching `ResultAsync.unwrapOr` and the compat shim.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\"); // string\n * unwrapOr(parsedPort, null); // number | null\n * ```\n */\nexport const unwrapOr: {\n <T, E, U>(result: Result<T, E>, defaultValue: U): T | U;\n <U>(defaultValue: U): <T, E>(result: Result<T, E>) => T | U;\n} = dual(2, <T, E, U>(result: Result<T, E>, defaultValue: U): T | U =>\n isOk(result) ? result.value : defaultValue,\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\nexport function unwrapErr<T, E>(result: Result<T, E>): E {\n if (isOk(result)) throw new TypeError(\"unwrapErr called on Ok\");\n return result.error;\n}\n\n/**\n * Wraps a throwing sync **function**, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. Same name and shape as\n * neverthrow's `Result.fromThrowable`.\n *\n * Reach for {@link trySync} instead when you want to run the call right now\n * rather than build a reusable wrapper.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = fromThrowable(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\nexport function fromThrowable<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function fromThrowable<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function fromThrowable(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return mkOk(fn(...args));\n } catch (error) {\n return mkErr(onThrow(error));\n }\n };\n}\n\n/**\n * Runs `fn` **now**, catching a throw into the `Err` track — the sync mirror\n * of `tryAsync`. Without `onThrow` the thrown value is normalized to an\n * `Error`; pass a mapper for a typed error.\n *\n * To lift a throwing function once and call it many times, use\n * {@link fromThrowable}.\n *\n * @param fn - the throwing thunk to run\n * @param onThrow - maps a thrown value to the `Err` channel\n *\n * @example\n * ```ts\n * trySync(() => JSON.parse(raw)); // Result<unknown, Error>\n * trySync(() => Schema.parse(input), (e): SchemaError => ({\n * kind: \"schema\",\n * cause: e,\n * }));\n * ```\n */\nexport function trySync<T>(fn: () => T): Result<T, Error>;\nexport function trySync<T, E>(fn: () => T, onThrow: (error: unknown) => E): Result<T, E>;\nexport function trySync<T, E>(fn: () => T, onThrow?: (error: unknown) => E): Result<T, E | Error> {\n try {\n return mkOk(fn());\n } catch (error) {\n return mkErr(onThrow ? onThrow(error) : toError(error));\n }\n}\n\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","import { mkErr } from \"./internal/ctor.js\";\nimport { isErr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Internal control-flow signal — not part of public error types */\nclass ErrSignal<E> {\n readonly _tag = \"ErrSignal\" as const;\n constructor(readonly error: E) {}\n}\n\n/**\n * Unwraps a {@link Result} inside a {@link tryGen} block — the sync analogue of\n * Rust's `?` operator. On `Ok` it returns the value; on `Err` it short-circuits\n * the enclosing `tryGen`, which returns that `Err`. Only valid inside `tryGen`;\n * prefer {@link flatMap} / `pipe` for long pipelines.\n *\n * @returns the unwrapped `Ok` value\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = yieldResult(parseA()); // unwrap or short-circuit\n * const b = yieldResult(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const yieldResult = <T, E>(result: Result<T, E>): T => {\n if (isErr(result)) {\n throw new ErrSignal(result.error);\n }\n return result.value;\n};\n\n/**\n * Terse alias of {@link yieldResult} (mirrors Rust's `?`), for compact\n * {@link tryGen} blocks.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const $ = yieldResult;\n\n/**\n * Run a block that uses {@link yieldResult}; returns the final `Result` or the first Err.\n *\n * @example\n * ```ts\n * const out = tryGen(() => {\n * const a = $(parseA());\n * const b = $(parseB());\n * return ok(a + b);\n * });\n * ```\n */\nexport const tryGen = <T, E>(fn: () => Result<T, E>): Result<T, E> => {\n try {\n return fn();\n } catch (error) {\n if (error instanceof ErrSignal) {\n return mkErr(error.error);\n }\n throw error;\n }\n};\n"]}
|
package/dist/types.d.cts
CHANGED
|
@@ -1,8 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-data shape of a {@link Result}: what `JSON.parse`, `structuredClone`
|
|
3
|
+
* and `postMessage` hand back. It has no methods; lift it with `Result.from`.
|
|
4
|
+
*/
|
|
5
|
+
export type ResultData<T, E> = {
|
|
6
|
+
readonly _tag: "Ok";
|
|
7
|
+
readonly value: T;
|
|
8
|
+
} | {
|
|
9
|
+
readonly _tag: "Err";
|
|
10
|
+
readonly error: E;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Methods every live {@link Result} carries on its (non-enumerable) prototype.
|
|
14
|
+
* Core semantics: `tap` does not swallow throws, `recover` keeps the `Ok` type.
|
|
15
|
+
* Method syntax keeps the type parameters bivariant, so `Result<T, never>` is
|
|
16
|
+
* assignable to `Result<T, E>`.
|
|
17
|
+
*/
|
|
18
|
+
export interface ResultMethods<T, E> {
|
|
19
|
+
/** Transform the `Ok` value; `Err` passes through. */
|
|
20
|
+
map<U>(fn: (value: T) => U): Result<U, E>;
|
|
21
|
+
/** Transform the `Err` value; `Ok` passes through. */
|
|
22
|
+
mapErr<F>(fn: (error: E) => F): Result<T, F>;
|
|
23
|
+
/** Canonical bind; widens the error union and short-circuits on `Err`. */
|
|
24
|
+
flatMap<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F>;
|
|
25
|
+
/** Alias of {@link ResultMethods.flatMap} for neverthrow muscle memory. */
|
|
26
|
+
andThen<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F>;
|
|
27
|
+
/** Error-track bind; recover to `Ok` or remap the failure. */
|
|
28
|
+
recover<F>(fn: (error: E) => Result<T, F>): Result<T, F>;
|
|
29
|
+
/** Observe the `Ok` value, pass the result through. */
|
|
30
|
+
tap(fn: (value: T) => void): Result<T, E>;
|
|
31
|
+
/** Observe the `Err` value, pass the result through. */
|
|
32
|
+
tapErr(fn: (error: E) => void): Result<T, E>;
|
|
33
|
+
/** Fold both tracks into one value. */
|
|
34
|
+
match<U>(onOk: (value: T) => U, onErr: (error: E) => U): U;
|
|
35
|
+
/** The `Ok` value, or `defaultValue` on `Err`. */
|
|
36
|
+
unwrapOr<U>(defaultValue: U): T | U;
|
|
37
|
+
}
|
|
1
38
|
/**
|
|
2
39
|
* The core railway type: a tagged union carrying either a success value
|
|
3
|
-
* (`Ok<T>`) or a failure value (`Err<E>`)
|
|
4
|
-
*
|
|
5
|
-
* with {@link
|
|
40
|
+
* (`Ok<T>`) or a failure value (`Err<E>`), discriminated on `_tag`. Carriers
|
|
41
|
+
* are plain data (`_tag` plus `value` / `error` as own enumerable properties)
|
|
42
|
+
* with {@link ResultMethods} on a shared non-enumerable prototype, so
|
|
43
|
+
* `JSON.stringify` output is unchanged. Narrow on `_tag` to read
|
|
44
|
+
* `.value` / `.error`.
|
|
45
|
+
*
|
|
46
|
+
* Build carriers with `ok` / `err`; a hand-written `{ _tag: "Ok", value }`
|
|
47
|
+
* literal has no methods and is not a `Result`. Data that crossed a
|
|
48
|
+
* serialization boundary is lifted back with `Result.from`.
|
|
6
49
|
*
|
|
7
50
|
* @typeParam T - the `Ok` value type
|
|
8
51
|
* @typeParam E - the `Err` error type
|
|
@@ -13,14 +56,29 @@
|
|
|
13
56
|
* const n = Number(raw);
|
|
14
57
|
* return Number.isNaN(n) ? err("nan") : ok(n);
|
|
15
58
|
* }
|
|
59
|
+
* parse("1").map((n) => n + 1);
|
|
16
60
|
* ```
|
|
17
61
|
*/
|
|
18
|
-
export type Result<T, E> =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
62
|
+
export type Result<T, E> = ResultData<T, E> & ResultMethods<T, E>;
|
|
63
|
+
/**
|
|
64
|
+
* Value-side companion of the {@link Result} type.
|
|
65
|
+
*
|
|
66
|
+
* `from` lifts plain data back into a live `Result`. Use it at every
|
|
67
|
+
* deserialization sink (`JSON.parse`, `structuredClone`, `postMessage`,
|
|
68
|
+
* IndexedDB, Redux rehydration), where the prototype and its methods are lost
|
|
69
|
+
* while the type still claims them. It trusts the shape; validate untrusted
|
|
70
|
+
* input first. An unknown `_tag` is a defect and throws a `TypeError` rather
|
|
71
|
+
* than becoming a silent `Err(undefined)`.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const wire = JSON.parse(JSON.stringify(ok(1))); // plain data, no methods
|
|
76
|
+
* const live = Result.from<number, string>(wire); // Result<number, string>
|
|
77
|
+
* live.map((n) => n + 1);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare const Result: {
|
|
81
|
+
readonly from: <T, E>(data: ResultData<T, E>) => Result<T, E>;
|
|
24
82
|
};
|
|
25
83
|
/**
|
|
26
84
|
* The success branch of a {@link Result} — `{ _tag: "Ok"; value: T }`.
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-data shape of a {@link Result}: what `JSON.parse`, `structuredClone`
|
|
3
|
+
* and `postMessage` hand back. It has no methods; lift it with `Result.from`.
|
|
4
|
+
*/
|
|
5
|
+
export type ResultData<T, E> = {
|
|
6
|
+
readonly _tag: "Ok";
|
|
7
|
+
readonly value: T;
|
|
8
|
+
} | {
|
|
9
|
+
readonly _tag: "Err";
|
|
10
|
+
readonly error: E;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Methods every live {@link Result} carries on its (non-enumerable) prototype.
|
|
14
|
+
* Core semantics: `tap` does not swallow throws, `recover` keeps the `Ok` type.
|
|
15
|
+
* Method syntax keeps the type parameters bivariant, so `Result<T, never>` is
|
|
16
|
+
* assignable to `Result<T, E>`.
|
|
17
|
+
*/
|
|
18
|
+
export interface ResultMethods<T, E> {
|
|
19
|
+
/** Transform the `Ok` value; `Err` passes through. */
|
|
20
|
+
map<U>(fn: (value: T) => U): Result<U, E>;
|
|
21
|
+
/** Transform the `Err` value; `Ok` passes through. */
|
|
22
|
+
mapErr<F>(fn: (error: E) => F): Result<T, F>;
|
|
23
|
+
/** Canonical bind; widens the error union and short-circuits on `Err`. */
|
|
24
|
+
flatMap<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F>;
|
|
25
|
+
/** Alias of {@link ResultMethods.flatMap} for neverthrow muscle memory. */
|
|
26
|
+
andThen<U, F>(fn: (value: T) => Result<U, F>): Result<U, E | F>;
|
|
27
|
+
/** Error-track bind; recover to `Ok` or remap the failure. */
|
|
28
|
+
recover<F>(fn: (error: E) => Result<T, F>): Result<T, F>;
|
|
29
|
+
/** Observe the `Ok` value, pass the result through. */
|
|
30
|
+
tap(fn: (value: T) => void): Result<T, E>;
|
|
31
|
+
/** Observe the `Err` value, pass the result through. */
|
|
32
|
+
tapErr(fn: (error: E) => void): Result<T, E>;
|
|
33
|
+
/** Fold both tracks into one value. */
|
|
34
|
+
match<U>(onOk: (value: T) => U, onErr: (error: E) => U): U;
|
|
35
|
+
/** The `Ok` value, or `defaultValue` on `Err`. */
|
|
36
|
+
unwrapOr<U>(defaultValue: U): T | U;
|
|
37
|
+
}
|
|
1
38
|
/**
|
|
2
39
|
* The core railway type: a tagged union carrying either a success value
|
|
3
|
-
* (`Ok<T>`) or a failure value (`Err<E>`)
|
|
4
|
-
*
|
|
5
|
-
* with {@link
|
|
40
|
+
* (`Ok<T>`) or a failure value (`Err<E>`), discriminated on `_tag`. Carriers
|
|
41
|
+
* are plain data (`_tag` plus `value` / `error` as own enumerable properties)
|
|
42
|
+
* with {@link ResultMethods} on a shared non-enumerable prototype, so
|
|
43
|
+
* `JSON.stringify` output is unchanged. Narrow on `_tag` to read
|
|
44
|
+
* `.value` / `.error`.
|
|
45
|
+
*
|
|
46
|
+
* Build carriers with `ok` / `err`; a hand-written `{ _tag: "Ok", value }`
|
|
47
|
+
* literal has no methods and is not a `Result`. Data that crossed a
|
|
48
|
+
* serialization boundary is lifted back with `Result.from`.
|
|
6
49
|
*
|
|
7
50
|
* @typeParam T - the `Ok` value type
|
|
8
51
|
* @typeParam E - the `Err` error type
|
|
@@ -13,14 +56,29 @@
|
|
|
13
56
|
* const n = Number(raw);
|
|
14
57
|
* return Number.isNaN(n) ? err("nan") : ok(n);
|
|
15
58
|
* }
|
|
59
|
+
* parse("1").map((n) => n + 1);
|
|
16
60
|
* ```
|
|
17
61
|
*/
|
|
18
|
-
export type Result<T, E> =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
62
|
+
export type Result<T, E> = ResultData<T, E> & ResultMethods<T, E>;
|
|
63
|
+
/**
|
|
64
|
+
* Value-side companion of the {@link Result} type.
|
|
65
|
+
*
|
|
66
|
+
* `from` lifts plain data back into a live `Result`. Use it at every
|
|
67
|
+
* deserialization sink (`JSON.parse`, `structuredClone`, `postMessage`,
|
|
68
|
+
* IndexedDB, Redux rehydration), where the prototype and its methods are lost
|
|
69
|
+
* while the type still claims them. It trusts the shape; validate untrusted
|
|
70
|
+
* input first. An unknown `_tag` is a defect and throws a `TypeError` rather
|
|
71
|
+
* than becoming a silent `Err(undefined)`.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const wire = JSON.parse(JSON.stringify(ok(1))); // plain data, no methods
|
|
76
|
+
* const live = Result.from<number, string>(wire); // Result<number, string>
|
|
77
|
+
* live.map((n) => n + 1);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare const Result: {
|
|
81
|
+
readonly from: <T, E>(data: ResultData<T, E>) => Result<T, E>;
|
|
24
82
|
};
|
|
25
83
|
/**
|
|
26
84
|
* The success branch of a {@link Result} — `{ _tag: "Ok"; value: T }`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onrails/result",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Tagged Result / ResultAsync for railway-oriented TypeScript — pure tagged unions, neverthrow-shaped compat shim, FL-friendly",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alan R. Soares",
|
|
@@ -140,6 +140,7 @@
|
|
|
140
140
|
},
|
|
141
141
|
"devDependencies": {
|
|
142
142
|
"fast-check": "^4.9.0",
|
|
143
|
+
"neverthrow": "^8.2.0",
|
|
143
144
|
"ts-expect": "^1.3.0",
|
|
144
145
|
"tsup": "^8.5.1"
|
|
145
146
|
}
|