@onrails/result 0.1.2 → 0.1.4

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.
Files changed (56) hide show
  1. package/DESIGN.md +0 -1
  2. package/README.md +10 -17
  3. package/RECIPES.md +157 -34
  4. package/dist/$.cjs +40 -0
  5. package/dist/$.cjs.map +1 -0
  6. package/dist/$.js +36 -0
  7. package/dist/$.js.map +1 -0
  8. package/dist/_.d.cts +2 -0
  9. package/dist/_.d.ts +2 -0
  10. package/dist/{async-CCA1yK8q.d.cts → async-CH8Cs8KE.d.cts} +14 -0
  11. package/dist/{async-DH_-dNIo.d.ts → async-DKISqIBc.d.ts} +14 -0
  12. package/dist/compat/neverthrow.cjs +30 -12
  13. package/dist/compat/neverthrow.cjs.map +1 -1
  14. package/dist/compat/neverthrow.d.cts +1 -1
  15. package/dist/compat/neverthrow.d.ts +1 -1
  16. package/dist/compat/neverthrow.js +30 -12
  17. package/dist/compat/neverthrow.js.map +1 -1
  18. package/dist/extra.cjs +17 -10
  19. package/dist/extra.cjs.map +1 -1
  20. package/dist/extra.d.cts +10 -2
  21. package/dist/extra.d.ts +10 -2
  22. package/dist/extra.js +17 -10
  23. package/dist/extra.js.map +1 -1
  24. package/dist/fluent.cjs.map +1 -1
  25. package/dist/fluent.d.cts +3 -1
  26. package/dist/fluent.d.ts +3 -1
  27. package/dist/fluent.js.map +1 -1
  28. package/dist/index.cjs +37 -13
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +21 -5
  31. package/dist/index.d.ts +21 -5
  32. package/dist/index.js +37 -13
  33. package/dist/index.js.map +1 -1
  34. package/dist/interop.cjs +37 -13
  35. package/dist/interop.cjs.map +1 -1
  36. package/dist/interop.d.cts +13 -3
  37. package/dist/interop.d.ts +13 -3
  38. package/dist/interop.js +37 -13
  39. package/dist/interop.js.map +1 -1
  40. package/dist/railway.cjs +32 -12
  41. package/dist/railway.cjs.map +1 -1
  42. package/dist/railway.d.cts +19 -2
  43. package/dist/railway.d.ts +19 -2
  44. package/dist/railway.js +32 -13
  45. package/dist/railway.js.map +1 -1
  46. package/dist/try-gen.cjs.map +1 -1
  47. package/dist/try-gen.js.map +1 -1
  48. package/dist/validation.cjs.map +1 -1
  49. package/dist/validation.js.map +1 -1
  50. package/package.json +6 -6
  51. package/dist/mcp.cjs +0 -273
  52. package/dist/mcp.cjs.map +0 -1
  53. package/dist/mcp.d.cts +0 -62
  54. package/dist/mcp.d.ts +0 -62
  55. package/dist/mcp.js +0 -265
  56. package/dist/mcp.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/result.ts","../src/fluent.ts"],"names":[],"mappings":"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","file":"fluent.cjs","sourcesContent":["import 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<number, never>\n * const typed: Result<number, \"parse\"> = ok(1);\n * ```\n */\nexport const ok = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\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, { kind: \"parse\"; message: string }>\n * ```\n */\nexport const err = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n 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/** Fantasy Land `of` — alias of {@link ok}. */\nexport const of = ok;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity at the call site selects the overload.\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst mapImpl = <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? ok(fn(result.value)) : err(result.error);\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 function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\nexport function map<T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\nexport function map(\n ...args: [Result<unknown, unknown>, (value: unknown) => unknown] | [(value: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapImpl(result, fn);\n}\n\nconst mapErrImpl = <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? err(fn(result.error)) : ok(result.value);\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 function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\nexport function mapErr<E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\nexport function mapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => unknown] | [(error: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapErrImpl(result, fn);\n}\n\nconst bimapImpl = <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) ? ok(onOk(result.value)) : err(onErr(result.error)));\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 function bimap<T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F>;\nexport function bimap<T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): (result: Result<T, E>) => Result<U, F>;\nexport function bimap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return bimapImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => bimapImpl(result, onOk, onErr);\n}\n\nconst flatMapImpl = <T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F> => (isOk(result) ? fn(result.value) : err(result.error));\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 function flatMap<T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F>;\nexport function flatMap<T, U, F>(\n fn: (value: T) => Result<U, F>,\n): <E>(result: Result<T, E>) => Result<U, E | F>;\nexport function flatMap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => Result<unknown, unknown>]\n | [(value: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return flatMapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => flatMapImpl(result, fn);\n}\n\nconst recoverImpl = <T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> => (isErr(result) ? fn(result.error) : ok(result.value));\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 function recover<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F>;\nexport function recover<T, E, F>(\n fn: (error: E) => Result<T, F>,\n): (result: Result<T, E>) => Result<T, F>;\nexport function recover(\n ...args:\n | [Result<unknown, unknown>, (error: unknown) => Result<unknown, unknown>]\n | [(error: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return recoverImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => recoverImpl(result, fn);\n}\n\nconst tapImpl = <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 `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 function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\nexport function tap<T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\nexport function tap(\n ...args: [Result<unknown, unknown>, (value: unknown) => void] | [(value: unknown) => void]\n): unknown {\n if (args.length === 2) return tapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapImpl(result, fn);\n}\n\nconst tapErrImpl = <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 * 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 function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\nexport function tapErr<E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\nexport function tapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => void] | [(error: unknown) => void]\n): unknown {\n if (args.length === 2) return tapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapErrImpl(result, fn);\n}\n\nconst matchImpl = <T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U => (isOk(result) ? onOk(result.value) : onErr(result.error));\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`, the\n * collision-free alias {@link matchResult} is identical.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U;\nexport function match<T, E, U>(\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): (result: Result<T, E>) => U;\nexport function match(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return matchImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => matchImpl(result, onOk, onErr);\n}\n\n/** Collision-free alias for files that also import `match` from ts-pattern. */\nexport const matchResult = match;\n\n/**\n * Curried collapse with named slots — escape valve when positional `match`\n * order is unclear at the call site (e.g. when both handlers return the same\n * type and a transposed `match(r, onErr, onOk)` would silently compile).\n */\nexport const fold =\n <T, E, U>(handlers: { readonly ok: (value: T) => U; readonly err: (error: E) => U }) =>\n (result: Result<T, E>): U =>\n matchImpl(result, handlers.ok, handlers.err);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\");\n * ```\n */\nexport const unwrapOr = <T, E>(result: Result<T, E>, defaultValue: T): T =>\n isOk(result) ? result.value : defaultValue;\n\n/** Test/assert helper — throws the original Err value when called on Err. */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Test/assert helper — throws TypeError when called on Ok. */\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/** Wrap a throwing sync function — neverthrow `Result.fromThrowable` */\nexport function trySync<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function trySync<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function trySync(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return ok(fn(...args));\n } catch (error) {\n return err(onThrow(error));\n }\n };\n}\n\n/** First failure wins; otherwise collects values in order */\nexport const combine = <T, E>(results: readonly Result<T, E>[]): Result<T[], E> => {\n const values: T[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error);\n values.push(result.value);\n }\n return ok(values);\n};\n\n/** Tuple-preserving combine (neverthrow-style) */\nexport const combineTuple = <const R extends readonly Result<unknown, unknown>[]>(\n results: R,\n): CombineTuple<R> =>\n // Runtime identical to combine; the cast restores per-index tuple types.\n combine(results as readonly Result<unknown, unknown>[]) as CombineTuple<R>;\n\ntype _OkValue<R> = R extends { _tag: \"Ok\"; readonly value: infer T } ? T : never;\ntype _ErrValue<R> = R extends { _tag: \"Err\"; readonly error: infer E } ? E : never;\n\ntype CombineTuple<R extends readonly Result<unknown, unknown>[]> = Result<\n { [K in keyof R]: _OkValue<R[K]> },\n { [K in keyof R]: _ErrValue<R[K]> }[number]\n>;\n\n/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns.\n *\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => name ? ok(name) : err({ kind: \"empty\" })),\n * tap(log),\n * );\n * ```\n */\nexport function pipe<A>(value: A): A;\nexport function pipe<A, B>(value: A, ab: (a: A) => B): B;\nexport function pipe<A, B, C>(value: A, ab: (a: A) => B, bc: (b: B) => C): C;\nexport function pipe<A, B, C, D>(value: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n hi: (h: H) => I,\n): I;\nexport function pipe(value: unknown, ...fns: ReadonlyArray<(x: unknown) => unknown>): unknown {\n let acc = value;\n for (const fn of fns) {\n acc = fn(acc);\n }\n return acc;\n}\n","import type { ResultAsync } from \"./async.js\";\nimport { flatMap, map, mapErr, match, unwrapOr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Opt-in dot chaining over a sync {@link Result} */\nexport type FluentResult<T, E> = {\n readonly result: Result<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResult<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;\n flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: (defaultValue: T) => T;\n};\n\nexport const fluent = <T, E>(result: Result<T, E>): FluentResult<T, E> => ({\n result,\n map: (fn) => fluent(map(result, fn)),\n mapErr: (fn) => fluent(mapErr(result, fn)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n chain: (fn) => fluent(flatMap(result, fn)),\n match: (onOk, onErr) => match(onOk, onErr)(result),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n});\n\n/** Opt-in dot chaining over {@link ResultAsync} */\nexport type FluentResultAsync<T, E> = {\n readonly resultAsync: ResultAsync<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResultAsync<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;\n flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;\n};\n\nexport const fluentAsync = <T, E>(resultAsync: ResultAsync<T, E>): FluentResultAsync<T, E> => ({\n resultAsync,\n map: (fn) => fluentAsync(resultAsync.map(fn)),\n mapErr: (fn) => fluentAsync(resultAsync.mapErr(fn)),\n flatMap: (fn) => fluentAsync(resultAsync.flatMap(fn)),\n andThen: (fn) => fluentAsync(resultAsync.andThen(fn)),\n chain: (fn) => fluentAsync(resultAsync.chain(fn)),\n match: (onOk, onErr) => resultAsync.match(onOk, onErr),\n});\n"]}
1
+ {"version":3,"sources":["../src/result.ts","../src/fluent.ts"],"names":[],"mappings":"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","file":"fluent.cjs","sourcesContent":["import 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<number, never>\n * const typed: Result<number, \"parse\"> = ok(1);\n * ```\n */\nexport const ok = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\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, { kind: \"parse\"; message: string }>\n * ```\n */\nexport const err = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n 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 * Fantasy Land `of` — alias of {@link ok}.\n * @deprecated Use {@link ok} instead.\n */\nexport const of = ok;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity at the call site selects the overload.\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst mapImpl = <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? ok(fn(result.value)) : err(result.error);\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 function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\nexport function map<T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\nexport function map(\n ...args: [Result<unknown, unknown>, (value: unknown) => unknown] | [(value: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapImpl(result, fn);\n}\n\nconst mapErrImpl = <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? err(fn(result.error)) : ok(result.value);\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 function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\nexport function mapErr<E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\nexport function mapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => unknown] | [(error: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapErrImpl(result, fn);\n}\n\nconst bimapImpl = <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) ? ok(onOk(result.value)) : err(onErr(result.error)));\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 function bimap<T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F>;\nexport function bimap<T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): (result: Result<T, E>) => Result<U, F>;\nexport function bimap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return bimapImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => bimapImpl(result, onOk, onErr);\n}\n\nconst flatMapImpl = <T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F> => (isOk(result) ? fn(result.value) : err(result.error));\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 function flatMap<T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F>;\nexport function flatMap<T, U, F>(\n fn: (value: T) => Result<U, F>,\n): <E>(result: Result<T, E>) => Result<U, E | F>;\nexport function flatMap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => Result<unknown, unknown>]\n | [(value: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return flatMapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => flatMapImpl(result, fn);\n}\n\nconst recoverImpl = <T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> => (isErr(result) ? fn(result.error) : ok(result.value));\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 function recover<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F>;\nexport function recover<T, E, F>(\n fn: (error: E) => Result<T, F>,\n): (result: Result<T, E>) => Result<T, F>;\nexport function recover(\n ...args:\n | [Result<unknown, unknown>, (error: unknown) => Result<unknown, unknown>]\n | [(error: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return recoverImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => recoverImpl(result, fn);\n}\n\nconst tapImpl = <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 `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 function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\nexport function tap<T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\nexport function tap(\n ...args: [Result<unknown, unknown>, (value: unknown) => void] | [(value: unknown) => void]\n): unknown {\n if (args.length === 2) return tapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapImpl(result, fn);\n}\n\nconst tapErrImpl = <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 * 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 function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\nexport function tapErr<E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\nexport function tapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => void] | [(error: unknown) => void]\n): unknown {\n if (args.length === 2) return tapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapErrImpl(result, fn);\n}\n\nconst matchImpl = <T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U => (isOk(result) ? onOk(result.value) : onErr(result.error));\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`, the\n * collision-free alias {@link matchResult} is identical.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U;\nexport function match<T, E, U>(\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): (result: Result<T, E>) => U;\nexport function match(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return matchImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => matchImpl(result, onOk, onErr);\n}\n\n/**\n * Collision-free alias for files that also import `match` from ts-pattern.\n * @deprecated Namespace import carriers (e.g., `import * as R from \"@onrails/result\"`) and use canonical {@link match} instead.\n */\nexport const matchResult = match;\n\n/**\n * Curried collapse with named slots — escape valve when positional `match`\n * order is unclear at the call site (e.g. when both handlers return the same\n * type and a transposed `match(r, onErr, onOk)` would silently compile).\n * @deprecated Use curried {@link match}(onOk, onErr)(result) instead.\n */\nexport const fold =\n <T, E, U>(handlers: { readonly ok: (value: T) => U; readonly err: (error: E) => U }) =>\n (result: Result<T, E>): U =>\n matchImpl(result, handlers.ok, handlers.err);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\");\n * ```\n */\nexport const unwrapOr = <T, E>(result: Result<T, E>, defaultValue: T): T =>\n isOk(result) ? result.value : defaultValue;\n\n/**\n * Test/assert helper — throws the original Err value when called on Err.\n *\n * @throws when the result is Err — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.\n * Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.\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/**\n * Test/assert helper — throws TypeError when called on Ok.\n *\n * @throws when the result is Ok — assertion-tier; allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.\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/** Wrap a throwing sync function — neverthrow `Result.fromThrowable` */\nexport function trySync<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function trySync<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function trySync(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return ok(fn(...args));\n } catch (error) {\n return err(onThrow(error));\n }\n };\n}\n\n/** First failure wins; otherwise collects values in order */\nexport const combine = <T, E>(results: readonly Result<T, E>[]): Result<T[], E> => {\n const values: T[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error);\n values.push(result.value);\n }\n return ok(values);\n};\n\n/** Tuple-preserving combine (neverthrow-style) */\nexport const combineTuple = <const R extends readonly Result<unknown, unknown>[]>(\n results: R,\n): CombineTuple<R> =>\n // Runtime identical to combine; the cast restores per-index tuple types.\n combine(results as readonly Result<unknown, unknown>[]) as CombineTuple<R>;\n\ntype _OkValue<R> = R extends { _tag: \"Ok\"; readonly value: infer T } ? T : never;\ntype _ErrValue<R> = R extends { _tag: \"Err\"; readonly error: infer E } ? E : never;\n\ntype CombineTuple<R extends readonly Result<unknown, unknown>[]> = Result<\n { [K in keyof R]: _OkValue<R[K]> },\n { [K in keyof R]: _ErrValue<R[K]> }[number]\n>;\n\n/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns.\n *\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => name ? ok(name) : err({ kind: \"empty\" })),\n * tap(log),\n * );\n * ```\n */\nexport function pipe<A>(value: A): A;\nexport function pipe<A, B>(value: A, ab: (a: A) => B): B;\nexport function pipe<A, B, C>(value: A, ab: (a: A) => B, bc: (b: B) => C): C;\nexport function pipe<A, B, C, D>(value: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n hi: (h: H) => I,\n): I;\nexport function pipe(value: unknown, ...fns: ReadonlyArray<(x: unknown) => unknown>): unknown {\n let acc = value;\n for (const fn of fns) {\n acc = fn(acc);\n }\n return acc;\n}\n","import type { ResultAsync } from \"./async.js\";\nimport { flatMap, map, mapErr, match, unwrapOr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Opt-in dot chaining over a sync {@link Result} */\nexport type FluentResult<T, E> = {\n readonly result: Result<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResult<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;\n flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */\n chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: (defaultValue: T) => T;\n};\n\nexport const fluent = <T, E>(result: Result<T, E>): FluentResult<T, E> => ({\n result,\n map: (fn) => fluent(map(result, fn)),\n mapErr: (fn) => fluent(mapErr(result, fn)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n chain: (fn) => fluent(flatMap(result, fn)),\n match: (onOk, onErr) => match(onOk, onErr)(result),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n});\n\n/** Opt-in dot chaining over {@link ResultAsync} */\nexport type FluentResultAsync<T, E> = {\n readonly resultAsync: ResultAsync<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResultAsync<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;\n flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */\n chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;\n};\n\nexport const fluentAsync = <T, E>(resultAsync: ResultAsync<T, E>): FluentResultAsync<T, E> => ({\n resultAsync,\n map: (fn) => fluentAsync(resultAsync.map(fn)),\n mapErr: (fn) => fluentAsync(resultAsync.mapErr(fn)),\n flatMap: (fn) => fluentAsync(resultAsync.flatMap(fn)),\n andThen: (fn) => fluentAsync(resultAsync.andThen(fn)),\n chain: (fn) => fluentAsync(resultAsync.chain(fn)),\n match: (onOk, onErr) => resultAsync.match(onOk, onErr),\n});\n"]}
package/dist/fluent.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as ResultAsync } from './async-CCA1yK8q.cjs';
1
+ import { R as ResultAsync } from './async-CH8Cs8KE.cjs';
2
2
  import { R as Result } from './types-C2Dp1d5J.cjs';
3
3
 
4
4
  /** Opt-in dot chaining over a sync {@link Result} */
@@ -8,6 +8,7 @@ type FluentResult<T, E> = {
8
8
  mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;
9
9
  flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
10
10
  andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
11
+ /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */
11
12
  chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
12
13
  match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;
13
14
  unwrapOr: (defaultValue: T) => T;
@@ -20,6 +21,7 @@ type FluentResultAsync<T, E> = {
20
21
  mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;
21
22
  flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
22
23
  andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
24
+ /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */
23
25
  chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
24
26
  match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;
25
27
  };
package/dist/fluent.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as ResultAsync } from './async-DH_-dNIo.js';
1
+ import { R as ResultAsync } from './async-DKISqIBc.js';
2
2
  import { R as Result } from './types-C2Dp1d5J.js';
3
3
 
4
4
  /** Opt-in dot chaining over a sync {@link Result} */
@@ -8,6 +8,7 @@ type FluentResult<T, E> = {
8
8
  mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;
9
9
  flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
10
10
  andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
11
+ /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */
11
12
  chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;
12
13
  match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;
13
14
  unwrapOr: (defaultValue: T) => T;
@@ -20,6 +21,7 @@ type FluentResultAsync<T, E> = {
20
21
  mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;
21
22
  flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
22
23
  andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
24
+ /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */
23
25
  chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;
24
26
  match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;
25
27
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/result.ts","../src/fluent.ts"],"names":[],"mappings":";AAaO,IAAM,EAAA,GAAK,CAAe,KAAA,MAA4B;AAAA,EAC3D,IAAA,EAAM,IAAA;AAAA,EACN;AACF,CAAA,CAAA;AAWO,IAAM,GAAA,GAAM,CAAyB,KAAA,MAA4B;AAAA,EACtE,IAAA,EAAM,KAAA;AAAA,EACN;AACF,CAAA,CAAA;AAYO,IAAM,IAAA,GAAO,CAAO,MAAA,KAA6C,MAAA,CAAO,IAAA,KAAS,IAAA;AAYjF,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;AAY1F,IAAM,OAAA,GAAU,CAAU,MAAA,EAAsB,EAAA,KAC9C,KAAK,MAAM,CAAA,GAAI,EAAA,CAAG,EAAA,CAAG,OAAO,KAAK,CAAC,CAAA,GAAI,GAAA,CAAI,OAAO,KAAK,CAAA;AAcjD,SAAS,OACX,IAAA,EACM;AACT,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,OAAA,CAAQ,KAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AACtD,EAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,EAAA,OAAO,CAAC,MAAA,KAAqC,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACjE;AAEA,IAAM,UAAA,GAAa,CAAU,MAAA,EAAsB,EAAA,KACjD,MAAM,MAAM,CAAA,GAAI,GAAA,CAAI,EAAA,CAAG,OAAO,KAAK,CAAC,CAAA,GAAI,EAAA,CAAG,OAAO,KAAK,CAAA;AAiBlD,SAAS,UACX,IAAA,EACM;AACT,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AACzD,EAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,EAAA,OAAO,CAAC,MAAA,KAAqC,UAAA,CAAW,MAAA,EAAQ,EAAE,CAAA;AACpE;AAoCA,IAAM,WAAA,GAAc,CAClB,MAAA,EACA,EAAA,KACsB,IAAA,CAAK,MAAM,CAAA,GAAI,EAAA,CAAG,MAAA,CAAO,KAAK,CAAA,GAAI,GAAA,CAAI,OAAO,KAAK,CAAA;AAqBnE,SAAS,WACX,IAAA,EAGM;AACT,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,WAAA,CAAY,KAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AAC1D,EAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,EAAA,OAAO,CAAC,MAAA,KAAqC,WAAA,CAAY,MAAA,EAAQ,EAAE,CAAA;AACrE;AA2FA,IAAM,SAAA,GAAY,CAChB,MAAA,EACA,IAAA,EACA,UACO,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA,CAAM,OAAO,KAAK,CAAA;AAwBxD,SAAS,SACX,IAAA,EAGM;AACT,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AACjE,EAAA,MAAM,CAAC,IAAA,EAAM,KAAK,CAAA,GAAI,IAAA;AACtB,EAAA,OAAO,CAAC,MAAA,KAAqC,SAAA,CAAU,MAAA,EAAQ,MAAM,KAAK,CAAA;AAC5E;AAuBO,IAAM,QAAA,GAAW,CAAO,MAAA,EAAsB,YAAA,KACnD,KAAK,MAAM,CAAA,GAAI,OAAO,KAAA,GAAQ,YAAA;;;AC5TzB,IAAM,MAAA,GAAS,CAAO,MAAA,MAA8C;AAAA,EACzE,MAAA;AAAA,EACA,KAAK,CAAC,EAAA,KAAO,OAAO,GAAA,CAAI,MAAA,EAAQ,EAAE,CAAC,CAAA;AAAA,EACnC,QAAQ,CAAC,EAAA,KAAO,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,CAAC,CAAA;AAAA,EACzC,SAAS,CAAC,EAAA,KAAO,OAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA;AAAA,EAC3C,SAAS,CAAC,EAAA,KAAO,OAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA;AAAA,EAC3C,OAAO,CAAC,EAAA,KAAO,OAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA;AAAA,EACzC,KAAA,EAAO,CAAC,IAAA,EAAM,KAAA,KAAU,MAAM,IAAA,EAAM,KAAK,EAAE,MAAM,CAAA;AAAA,EACjD,QAAA,EAAU,CAAC,YAAA,KAAiB,QAAA,CAAS,QAAQ,YAAY;AAC3D,CAAA;AAaO,IAAM,WAAA,GAAc,CAAO,WAAA,MAA6D;AAAA,EAC7F,WAAA;AAAA,EACA,KAAK,CAAC,EAAA,KAAO,YAAY,WAAA,CAAY,GAAA,CAAI,EAAE,CAAC,CAAA;AAAA,EAC5C,QAAQ,CAAC,EAAA,KAAO,YAAY,WAAA,CAAY,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,EAClD,SAAS,CAAC,EAAA,KAAO,YAAY,WAAA,CAAY,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,EACpD,SAAS,CAAC,EAAA,KAAO,YAAY,WAAA,CAAY,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,EACpD,OAAO,CAAC,EAAA,KAAO,YAAY,WAAA,CAAY,KAAA,CAAM,EAAE,CAAC,CAAA;AAAA,EAChD,OAAO,CAAC,IAAA,EAAM,UAAU,WAAA,CAAY,KAAA,CAAM,MAAM,KAAK;AACvD,CAAA","file":"fluent.js","sourcesContent":["import 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<number, never>\n * const typed: Result<number, \"parse\"> = ok(1);\n * ```\n */\nexport const ok = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\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, { kind: \"parse\"; message: string }>\n * ```\n */\nexport const err = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n 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/** Fantasy Land `of` — alias of {@link ok}. */\nexport const of = ok;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity at the call site selects the overload.\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst mapImpl = <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? ok(fn(result.value)) : err(result.error);\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 function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\nexport function map<T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\nexport function map(\n ...args: [Result<unknown, unknown>, (value: unknown) => unknown] | [(value: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapImpl(result, fn);\n}\n\nconst mapErrImpl = <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? err(fn(result.error)) : ok(result.value);\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 function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\nexport function mapErr<E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\nexport function mapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => unknown] | [(error: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapErrImpl(result, fn);\n}\n\nconst bimapImpl = <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) ? ok(onOk(result.value)) : err(onErr(result.error)));\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 function bimap<T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F>;\nexport function bimap<T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): (result: Result<T, E>) => Result<U, F>;\nexport function bimap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return bimapImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => bimapImpl(result, onOk, onErr);\n}\n\nconst flatMapImpl = <T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F> => (isOk(result) ? fn(result.value) : err(result.error));\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 function flatMap<T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F>;\nexport function flatMap<T, U, F>(\n fn: (value: T) => Result<U, F>,\n): <E>(result: Result<T, E>) => Result<U, E | F>;\nexport function flatMap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => Result<unknown, unknown>]\n | [(value: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return flatMapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => flatMapImpl(result, fn);\n}\n\nconst recoverImpl = <T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> => (isErr(result) ? fn(result.error) : ok(result.value));\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 function recover<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F>;\nexport function recover<T, E, F>(\n fn: (error: E) => Result<T, F>,\n): (result: Result<T, E>) => Result<T, F>;\nexport function recover(\n ...args:\n | [Result<unknown, unknown>, (error: unknown) => Result<unknown, unknown>]\n | [(error: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return recoverImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => recoverImpl(result, fn);\n}\n\nconst tapImpl = <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 `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 function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\nexport function tap<T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\nexport function tap(\n ...args: [Result<unknown, unknown>, (value: unknown) => void] | [(value: unknown) => void]\n): unknown {\n if (args.length === 2) return tapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapImpl(result, fn);\n}\n\nconst tapErrImpl = <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 * 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 function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\nexport function tapErr<E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\nexport function tapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => void] | [(error: unknown) => void]\n): unknown {\n if (args.length === 2) return tapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapErrImpl(result, fn);\n}\n\nconst matchImpl = <T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U => (isOk(result) ? onOk(result.value) : onErr(result.error));\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`, the\n * collision-free alias {@link matchResult} is identical.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U;\nexport function match<T, E, U>(\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): (result: Result<T, E>) => U;\nexport function match(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return matchImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => matchImpl(result, onOk, onErr);\n}\n\n/** Collision-free alias for files that also import `match` from ts-pattern. */\nexport const matchResult = match;\n\n/**\n * Curried collapse with named slots — escape valve when positional `match`\n * order is unclear at the call site (e.g. when both handlers return the same\n * type and a transposed `match(r, onErr, onOk)` would silently compile).\n */\nexport const fold =\n <T, E, U>(handlers: { readonly ok: (value: T) => U; readonly err: (error: E) => U }) =>\n (result: Result<T, E>): U =>\n matchImpl(result, handlers.ok, handlers.err);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\");\n * ```\n */\nexport const unwrapOr = <T, E>(result: Result<T, E>, defaultValue: T): T =>\n isOk(result) ? result.value : defaultValue;\n\n/** Test/assert helper — throws the original Err value when called on Err. */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Test/assert helper — throws TypeError when called on Ok. */\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/** Wrap a throwing sync function — neverthrow `Result.fromThrowable` */\nexport function trySync<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function trySync<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function trySync(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return ok(fn(...args));\n } catch (error) {\n return err(onThrow(error));\n }\n };\n}\n\n/** First failure wins; otherwise collects values in order */\nexport const combine = <T, E>(results: readonly Result<T, E>[]): Result<T[], E> => {\n const values: T[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error);\n values.push(result.value);\n }\n return ok(values);\n};\n\n/** Tuple-preserving combine (neverthrow-style) */\nexport const combineTuple = <const R extends readonly Result<unknown, unknown>[]>(\n results: R,\n): CombineTuple<R> =>\n // Runtime identical to combine; the cast restores per-index tuple types.\n combine(results as readonly Result<unknown, unknown>[]) as CombineTuple<R>;\n\ntype _OkValue<R> = R extends { _tag: \"Ok\"; readonly value: infer T } ? T : never;\ntype _ErrValue<R> = R extends { _tag: \"Err\"; readonly error: infer E } ? E : never;\n\ntype CombineTuple<R extends readonly Result<unknown, unknown>[]> = Result<\n { [K in keyof R]: _OkValue<R[K]> },\n { [K in keyof R]: _ErrValue<R[K]> }[number]\n>;\n\n/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns.\n *\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => name ? ok(name) : err({ kind: \"empty\" })),\n * tap(log),\n * );\n * ```\n */\nexport function pipe<A>(value: A): A;\nexport function pipe<A, B>(value: A, ab: (a: A) => B): B;\nexport function pipe<A, B, C>(value: A, ab: (a: A) => B, bc: (b: B) => C): C;\nexport function pipe<A, B, C, D>(value: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n hi: (h: H) => I,\n): I;\nexport function pipe(value: unknown, ...fns: ReadonlyArray<(x: unknown) => unknown>): unknown {\n let acc = value;\n for (const fn of fns) {\n acc = fn(acc);\n }\n return acc;\n}\n","import type { ResultAsync } from \"./async.js\";\nimport { flatMap, map, mapErr, match, unwrapOr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Opt-in dot chaining over a sync {@link Result} */\nexport type FluentResult<T, E> = {\n readonly result: Result<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResult<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;\n flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: (defaultValue: T) => T;\n};\n\nexport const fluent = <T, E>(result: Result<T, E>): FluentResult<T, E> => ({\n result,\n map: (fn) => fluent(map(result, fn)),\n mapErr: (fn) => fluent(mapErr(result, fn)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n chain: (fn) => fluent(flatMap(result, fn)),\n match: (onOk, onErr) => match(onOk, onErr)(result),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n});\n\n/** Opt-in dot chaining over {@link ResultAsync} */\nexport type FluentResultAsync<T, E> = {\n readonly resultAsync: ResultAsync<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResultAsync<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;\n flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;\n};\n\nexport const fluentAsync = <T, E>(resultAsync: ResultAsync<T, E>): FluentResultAsync<T, E> => ({\n resultAsync,\n map: (fn) => fluentAsync(resultAsync.map(fn)),\n mapErr: (fn) => fluentAsync(resultAsync.mapErr(fn)),\n flatMap: (fn) => fluentAsync(resultAsync.flatMap(fn)),\n andThen: (fn) => fluentAsync(resultAsync.andThen(fn)),\n chain: (fn) => fluentAsync(resultAsync.chain(fn)),\n match: (onOk, onErr) => resultAsync.match(onOk, onErr),\n});\n"]}
1
+ {"version":3,"sources":["../src/result.ts","../src/fluent.ts"],"names":[],"mappings":"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","file":"fluent.js","sourcesContent":["import 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<number, never>\n * const typed: Result<number, \"parse\"> = ok(1);\n * ```\n */\nexport const ok = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\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, { kind: \"parse\"; message: string }>\n * ```\n */\nexport const err = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n 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 * Fantasy Land `of` — alias of {@link ok}.\n * @deprecated Use {@link ok} instead.\n */\nexport const of = ok;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity at the call site selects the overload.\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst mapImpl = <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? ok(fn(result.value)) : err(result.error);\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 function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\nexport function map<T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\nexport function map(\n ...args: [Result<unknown, unknown>, (value: unknown) => unknown] | [(value: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapImpl(result, fn);\n}\n\nconst mapErrImpl = <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? err(fn(result.error)) : ok(result.value);\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 function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\nexport function mapErr<E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\nexport function mapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => unknown] | [(error: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapErrImpl(result, fn);\n}\n\nconst bimapImpl = <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) ? ok(onOk(result.value)) : err(onErr(result.error)));\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 function bimap<T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F>;\nexport function bimap<T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): (result: Result<T, E>) => Result<U, F>;\nexport function bimap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return bimapImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => bimapImpl(result, onOk, onErr);\n}\n\nconst flatMapImpl = <T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F> => (isOk(result) ? fn(result.value) : err(result.error));\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 function flatMap<T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F>;\nexport function flatMap<T, U, F>(\n fn: (value: T) => Result<U, F>,\n): <E>(result: Result<T, E>) => Result<U, E | F>;\nexport function flatMap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => Result<unknown, unknown>]\n | [(value: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return flatMapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => flatMapImpl(result, fn);\n}\n\nconst recoverImpl = <T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> => (isErr(result) ? fn(result.error) : ok(result.value));\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 function recover<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F>;\nexport function recover<T, E, F>(\n fn: (error: E) => Result<T, F>,\n): (result: Result<T, E>) => Result<T, F>;\nexport function recover(\n ...args:\n | [Result<unknown, unknown>, (error: unknown) => Result<unknown, unknown>]\n | [(error: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return recoverImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => recoverImpl(result, fn);\n}\n\nconst tapImpl = <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 `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 function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\nexport function tap<T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\nexport function tap(\n ...args: [Result<unknown, unknown>, (value: unknown) => void] | [(value: unknown) => void]\n): unknown {\n if (args.length === 2) return tapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapImpl(result, fn);\n}\n\nconst tapErrImpl = <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 * 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 function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\nexport function tapErr<E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\nexport function tapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => void] | [(error: unknown) => void]\n): unknown {\n if (args.length === 2) return tapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapErrImpl(result, fn);\n}\n\nconst matchImpl = <T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U => (isOk(result) ? onOk(result.value) : onErr(result.error));\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`, the\n * collision-free alias {@link matchResult} is identical.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U;\nexport function match<T, E, U>(\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): (result: Result<T, E>) => U;\nexport function match(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return matchImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => matchImpl(result, onOk, onErr);\n}\n\n/**\n * Collision-free alias for files that also import `match` from ts-pattern.\n * @deprecated Namespace import carriers (e.g., `import * as R from \"@onrails/result\"`) and use canonical {@link match} instead.\n */\nexport const matchResult = match;\n\n/**\n * Curried collapse with named slots — escape valve when positional `match`\n * order is unclear at the call site (e.g. when both handlers return the same\n * type and a transposed `match(r, onErr, onOk)` would silently compile).\n * @deprecated Use curried {@link match}(onOk, onErr)(result) instead.\n */\nexport const fold =\n <T, E, U>(handlers: { readonly ok: (value: T) => U; readonly err: (error: E) => U }) =>\n (result: Result<T, E>): U =>\n matchImpl(result, handlers.ok, handlers.err);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\");\n * ```\n */\nexport const unwrapOr = <T, E>(result: Result<T, E>, defaultValue: T): T =>\n isOk(result) ? result.value : defaultValue;\n\n/**\n * Test/assert helper — throws the original Err value when called on Err.\n *\n * @throws when the result is Err — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.\n * Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.\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/**\n * Test/assert helper — throws TypeError when called on Ok.\n *\n * @throws when the result is Ok — assertion-tier; allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.\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/** Wrap a throwing sync function — neverthrow `Result.fromThrowable` */\nexport function trySync<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function trySync<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function trySync(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return ok(fn(...args));\n } catch (error) {\n return err(onThrow(error));\n }\n };\n}\n\n/** First failure wins; otherwise collects values in order */\nexport const combine = <T, E>(results: readonly Result<T, E>[]): Result<T[], E> => {\n const values: T[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error);\n values.push(result.value);\n }\n return ok(values);\n};\n\n/** Tuple-preserving combine (neverthrow-style) */\nexport const combineTuple = <const R extends readonly Result<unknown, unknown>[]>(\n results: R,\n): CombineTuple<R> =>\n // Runtime identical to combine; the cast restores per-index tuple types.\n combine(results as readonly Result<unknown, unknown>[]) as CombineTuple<R>;\n\ntype _OkValue<R> = R extends { _tag: \"Ok\"; readonly value: infer T } ? T : never;\ntype _ErrValue<R> = R extends { _tag: \"Err\"; readonly error: infer E } ? E : never;\n\ntype CombineTuple<R extends readonly Result<unknown, unknown>[]> = Result<\n { [K in keyof R]: _OkValue<R[K]> },\n { [K in keyof R]: _ErrValue<R[K]> }[number]\n>;\n\n/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns.\n *\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => name ? ok(name) : err({ kind: \"empty\" })),\n * tap(log),\n * );\n * ```\n */\nexport function pipe<A>(value: A): A;\nexport function pipe<A, B>(value: A, ab: (a: A) => B): B;\nexport function pipe<A, B, C>(value: A, ab: (a: A) => B, bc: (b: B) => C): C;\nexport function pipe<A, B, C, D>(value: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n hi: (h: H) => I,\n): I;\nexport function pipe(value: unknown, ...fns: ReadonlyArray<(x: unknown) => unknown>): unknown {\n let acc = value;\n for (const fn of fns) {\n acc = fn(acc);\n }\n return acc;\n}\n","import type { ResultAsync } from \"./async.js\";\nimport { flatMap, map, mapErr, match, unwrapOr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Opt-in dot chaining over a sync {@link Result} */\nexport type FluentResult<T, E> = {\n readonly result: Result<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResult<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResult<T, F>;\n flatMap: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n andThen: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */\n chain: <U>(fn: (value: T) => Result<U, E>) => FluentResult<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: (defaultValue: T) => T;\n};\n\nexport const fluent = <T, E>(result: Result<T, E>): FluentResult<T, E> => ({\n result,\n map: (fn) => fluent(map(result, fn)),\n mapErr: (fn) => fluent(mapErr(result, fn)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n chain: (fn) => fluent(flatMap(result, fn)),\n match: (onOk, onErr) => match(onOk, onErr)(result),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n});\n\n/** Opt-in dot chaining over {@link ResultAsync} */\nexport type FluentResultAsync<T, E> = {\n readonly resultAsync: ResultAsync<T, E>;\n map: <U>(fn: (value: T) => U) => FluentResultAsync<U, E>;\n mapErr: <F>(fn: (error: E) => F) => FluentResultAsync<T, F>;\n flatMap: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n andThen: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n /** @deprecated Use {@link flatMap} or compat {@link andThen} instead. */\n chain: <U>(fn: (value: T) => ResultAsync<U, E>) => FluentResultAsync<U, E>;\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => Promise<U>;\n};\n\nexport const fluentAsync = <T, E>(resultAsync: ResultAsync<T, E>): FluentResultAsync<T, E> => ({\n resultAsync,\n map: (fn) => fluentAsync(resultAsync.map(fn)),\n mapErr: (fn) => fluentAsync(resultAsync.mapErr(fn)),\n flatMap: (fn) => fluentAsync(resultAsync.flatMap(fn)),\n andThen: (fn) => fluentAsync(resultAsync.andThen(fn)),\n chain: (fn) => fluentAsync(resultAsync.chain(fn)),\n match: (onOk, onErr) => resultAsync.match(onOk, onErr),\n});\n"]}
package/dist/index.cjs CHANGED
@@ -143,6 +143,7 @@ var ResultAsync = class _ResultAsync {
143
143
  this.run = run;
144
144
  }
145
145
  run;
146
+ promise = null;
146
147
  static fromResult(result) {
147
148
  return new _ResultAsync(async () => result);
148
149
  }
@@ -204,14 +205,14 @@ var ResultAsync = class _ResultAsync {
204
205
  );
205
206
  }
206
207
  map(fn) {
207
- return new _ResultAsync(async () => map(await this.run(), fn));
208
+ return new _ResultAsync(async () => map(await this.resolve(), fn));
208
209
  }
209
210
  mapErr(fn) {
210
- return new _ResultAsync(async () => mapErr(await this.run(), fn));
211
+ return new _ResultAsync(async () => mapErr(await this.resolve(), fn));
211
212
  }
212
213
  flatMap(fn) {
213
214
  return new _ResultAsync(async () => {
214
- const first = await this.run();
215
+ const first = await this.resolve();
215
216
  if (isErr(first)) {
216
217
  return first;
217
218
  }
@@ -228,12 +229,16 @@ var ResultAsync = class _ResultAsync {
228
229
  andThen(fn) {
229
230
  return this.flatMap(fn);
230
231
  }
232
+ /**
233
+ * Alias for {@link flatMap}.
234
+ * @deprecated Use {@link flatMap} or keep/use compat {@link andThen} instead.
235
+ */
231
236
  chain(fn) {
232
237
  return this.flatMap(fn);
233
238
  }
234
239
  recover(fn) {
235
240
  return new _ResultAsync(async () => {
236
- const first = await this.run();
241
+ const first = await this.resolve();
237
242
  if (!isErr(first)) {
238
243
  return first;
239
244
  }
@@ -246,7 +251,7 @@ var ResultAsync = class _ResultAsync {
246
251
  }
247
252
  tap(fn) {
248
253
  return new _ResultAsync(async () => {
249
- const result = await this.run();
254
+ const result = await this.resolve();
250
255
  if (!isErr(result)) {
251
256
  fn(result.value);
252
257
  }
@@ -255,7 +260,7 @@ var ResultAsync = class _ResultAsync {
255
260
  }
256
261
  tapErr(fn) {
257
262
  return new _ResultAsync(async () => {
258
- const result = await this.run();
263
+ const result = await this.resolve();
259
264
  if (isErr(result)) {
260
265
  fn(result.error);
261
266
  }
@@ -263,19 +268,32 @@ var ResultAsync = class _ResultAsync {
263
268
  });
264
269
  }
265
270
  unwrapOr(defaultValue) {
266
- return this.run().then((result) => isErr(result) ? defaultValue : result.value);
271
+ return this.resolve().then((result) => isErr(result) ? defaultValue : result.value);
267
272
  }
273
+ /**
274
+ * @deprecated Await the ResultAsync and narrow with {@link isOk} — this method
275
+ * re-executes deferred factories and cannot narrow.
276
+ */
268
277
  isOk() {
269
- return this.run().then((result) => !isErr(result));
278
+ return this.resolve().then((result) => !isErr(result));
270
279
  }
280
+ /**
281
+ * @deprecated Await the ResultAsync and narrow with {@link isErr} — this method
282
+ * re-executes deferred factories and cannot narrow.
283
+ */
271
284
  isErr() {
272
- return this.run().then((result) => isErr(result));
285
+ return this.resolve().then((result) => isErr(result));
273
286
  }
274
287
  match(onOk, onErr) {
275
- return this.run().then((result) => isErr(result) ? onErr(result.error) : onOk(result.value));
288
+ return this.resolve().then(
289
+ (result) => isErr(result) ? onErr(result.error) : onOk(result.value)
290
+ );
276
291
  }
277
292
  resolve() {
278
- return this.run();
293
+ if (!this.promise) {
294
+ this.promise = this.run();
295
+ }
296
+ return this.promise;
279
297
  }
280
298
  /**
281
299
  * Thenable shim — `await ra` resolves to a bare tagged-union `Result<T, E>`.
@@ -283,7 +301,7 @@ var ResultAsync = class _ResultAsync {
283
301
  */
284
302
  // biome-ignore lint/suspicious/noThenProperty: makes ResultAsync awaitable
285
303
  then(onfulfilled, onrejected) {
286
- return this.run().then(
304
+ return this.resolve().then(
287
305
  // Safe: without onfulfilled, R1 stays at its Result<T, E> default.
288
306
  (r) => onfulfilled ? onfulfilled(r) : r,
289
307
  onrejected ?? void 0
@@ -312,7 +330,13 @@ function tryAsync(promise, onReject) {
312
330
 
313
331
  // src/interop.ts
314
332
  var fromResult = (result) => ResultAsync.fromResult(result);
315
- var asyncAfter = (result, fn) => fromResult(result).flatMap(fn);
333
+ function asyncAfter(resultOrFn, fn) {
334
+ if (fn === void 0) {
335
+ const f = resultOrFn;
336
+ return (result) => fromResult(result).flatMap(f);
337
+ }
338
+ return fromResult(resultOrFn).flatMap(fn);
339
+ }
316
340
  function fromAsync(fn, onDefect) {
317
341
  return (...args) => ResultAsync.fromResultPromise(fn(...args), onDefect);
318
342
  }