@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/extra.js
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
|
-
// src/internal/
|
|
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);
|
|
2
43
|
|
|
3
44
|
// src/result.ts
|
|
4
45
|
var isOk = (result) => result._tag === "Ok";
|
|
@@ -10,7 +51,7 @@ var declareErrors = () => ({
|
|
|
10
51
|
annotateAsync: (result) => result
|
|
11
52
|
});
|
|
12
53
|
var hasKind = (error, kind) => error.kind === kind;
|
|
13
|
-
var mapErrKind = (kind, fn) => (result) => isErr(result) && hasKind(result.error, kind) ?
|
|
54
|
+
var mapErrKind = (kind, fn) => (result) => isErr(result) && hasKind(result.error, kind) ? newErr(fn(result.error)) : result;
|
|
14
55
|
var allOk = (results) => results.every(isOk);
|
|
15
56
|
|
|
16
57
|
export { allOk, declareErrors, hasKind, mapErrKind };
|
package/dist/extra.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/result.ts","../src/extra.ts"],"names":[],"mappings":";;;AA+EO,IAAM,IAAA,GAAO,CAAO,MAAA,KAA6C,MAAA,CAAO,IAAA,KAAS,IAAA;AAYjF,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;AC3DnF,IAAM,gBAAgB,OAAU;AAAA,EACrC,QAAA,EAAU,CAAI,MAAA,KAA6C,MAAA;AAAA,EAC3D,aAAA,EAAe,CAAI,MAAA,KACjB;AACJ,CAAA;AAGO,IAAM,OAAA,GAAU,CACrB,KAAA,EACA,IAAA,KACqC,MAAM,IAAA,KAAS;AAG/C,IAAM,UAAA,GACX,CACE,IAAA,EACA,EAAA,KAEF,CAAI,MAAA,KACF,KAAA,CAAM,MAAM,CAAA,IAAK,OAAA,CAAQ,MAAA,CAAO,OAAO,IAAI,CAAA,GACvC,EAAE,IAAA,EAAM,KAAA,EAAO,OAAO,EAAA,CAAG,MAAA,CAAO,KAAK,CAAA,EAAE,GACvC;AAGD,IAAM,KAAA,GAAQ,CAAO,OAAA,KAA8C,OAAA,CAAQ,MAAM,IAAI","file":"extra.js","sourcesContent":["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","/**\n * @onrails/result/extra — tagged-error helpers.\n */\n\nimport type { ResultAsync } from \"./async.js\";\nimport type { InferErr, InferOk } from \"./internal/infer.js\";\nimport { isErr, isOk } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Extract error type from a {@link Result} — alias of {@link InferErr} */\nexport type ErrOf<R> = InferErr<R>;\n\n/** Extract success type from a {@link Result} — alias of {@link InferOk} */\nexport type OkOf<R> = InferOk<R>;\n\n/** Union of error types from a tuple/readonly array of results */\nexport type UnionErrors<R extends readonly Result<unknown, unknown>[]> = {\n [K in keyof R]: ErrOf<R[K]>;\n}[number];\n\n/** Manual union when TS fails to infer multi-step errors (neverthrow #603) */\nexport type AccumulateErrors<Errors extends readonly unknown[]> = Errors[number];\n\n/**\n * Declare the error union for a pipeline when inference only picks the first step.\n *\n * @example\n * ```ts\n * const errors = declareErrors<ParseError | NetworkError>();\n * const step = errors.annotate(parseThing());\n * ```\n */\nexport const declareErrors = <E>() => ({\n annotate: <T>(result: Result<T, unknown>): Result<T, E> => result as Result<T, E>,\n annotateAsync: <T>(result: ResultAsync<T, unknown>): ResultAsync<T, E> =>\n result as ResultAsync<T, E>,\n});\n\n/** Narrow an error by `kind` when using discriminated unions */\nexport const hasKind = <E extends { kind: string }, K extends E[\"kind\"]>(\n error: E,\n kind: K,\n): error is Extract<E, { kind: K }> => error.kind === kind;\n\n/** Map only errors matching `kind`, leave others unchanged */\nexport const mapErrKind =\n <E extends { kind: string }, K extends E[\"kind\"], F>(\n kind: K,\n fn: (error: Extract<E, { kind: K }>) => F,\n ) =>\n <T>(result: Result<T, E>): Result<T, E | F> =>\n isErr(result) && hasKind(result.error, kind)\n ? { _tag: \"Err\", error: fn(result.error) }\n : result;\n\n/** True when no result is Err */\nexport const allOk = <T, E>(results: readonly Result<T, E>[]): boolean => results.every(isOk);\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/proto.ts","../src/result.ts","../src/extra.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;;;AClBxE,IAAM,IAAA,GAAO,CAAO,MAAA,KAA6C,MAAA,CAAO,IAAA,KAAS,IAAA;AAYjF,IAAM,KAAA,GAAQ,CAAO,MAAA,KAA8C,MAAA,CAAO,IAAA,KAAS,KAAA;;;AC7DnF,IAAM,gBAAgB,OAAU;AAAA,EACrC,QAAA,EAAU,CAAI,MAAA,KAA6C,MAAA;AAAA,EAC3D,aAAA,EAAe,CAAI,MAAA,KACjB;AACJ,CAAA;AAGO,IAAM,OAAA,GAAU,CACrB,KAAA,EACA,IAAA,KACqC,MAAM,IAAA,KAAS;AAG/C,IAAM,aACX,CACE,IAAA,EACA,OAEF,CAAI,MAAA,KACF,MAAM,MAAM,CAAA,IAAK,QAAQ,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA,GAAI,MAAA,CAAM,GAAG,MAAA,CAAO,KAAK,CAAC,CAAA,GAAI;AAGtE,IAAM,KAAA,GAAQ,CAAO,OAAA,KAA8C,OAAA,CAAQ,MAAM,IAAI","file":"extra.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","/**\n * @onrails/result/extra — tagged-error helpers.\n */\n\nimport type { ResultAsync } from \"./async.js\";\nimport { mkErr } from \"./internal/ctor.js\";\nimport type { InferErr, InferOk } from \"./internal/infer.js\";\nimport { isErr, isOk } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/** Extract error type from a {@link Result} — alias of {@link InferErr} */\nexport type ErrOf<R> = InferErr<R>;\n\n/** Extract success type from a {@link Result} — alias of {@link InferOk} */\nexport type OkOf<R> = InferOk<R>;\n\n/** Union of error types from a tuple/readonly array of results */\nexport type UnionErrors<R extends readonly Result<unknown, unknown>[]> = {\n [K in keyof R]: ErrOf<R[K]>;\n}[number];\n\n/** Manual union when TS fails to infer multi-step errors (neverthrow #603) */\nexport type AccumulateErrors<Errors extends readonly unknown[]> = Errors[number];\n\n/**\n * Declare the error union for a pipeline when inference only picks the first step.\n *\n * @example\n * ```ts\n * const errors = declareErrors<ParseError | NetworkError>();\n * const step = errors.annotate(parseThing());\n * ```\n */\nexport const declareErrors = <E>() => ({\n annotate: <T>(result: Result<T, unknown>): Result<T, E> => result as Result<T, E>,\n annotateAsync: <T>(result: ResultAsync<T, unknown>): ResultAsync<T, E> =>\n result as ResultAsync<T, E>,\n});\n\n/** Narrow an error by `kind` when using discriminated unions */\nexport const hasKind = <E extends { kind: string }, K extends E[\"kind\"]>(\n error: E,\n kind: K,\n): error is Extract<E, { kind: K }> => error.kind === kind;\n\n/** Map only errors matching `kind`, leave others unchanged */\nexport const mapErrKind =\n <E extends { kind: string }, K extends E[\"kind\"], F>(\n kind: K,\n fn: (error: Extract<E, { kind: K }>) => F,\n ) =>\n <T>(result: Result<T, E>): Result<T, E | F> =>\n isErr(result) && hasKind(result.error, kind) ? mkErr(fn(result.error)) : result;\n\n/** True when no result is Err */\nexport const allOk = <T, E>(results: readonly Result<T, E>[]): boolean => results.every(isOk);\n"]}
|
package/dist/fluent.cjs
CHANGED
|
@@ -1,14 +1,88 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// src/internal/
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
// src/internal/proto.ts
|
|
4
|
+
var INSPECT = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
5
|
+
var OkImpl = class _OkImpl {
|
|
6
|
+
_tag;
|
|
7
|
+
value;
|
|
8
|
+
// explicit assignment order keeps `_tag` first, so JSON key order matches the plain-data shape
|
|
9
|
+
constructor(value) {
|
|
10
|
+
this._tag = "Ok";
|
|
11
|
+
this.value = value;
|
|
12
|
+
}
|
|
13
|
+
[INSPECT](_depth, options, inspect) {
|
|
14
|
+
return `Ok(${inspect(this.value, options)})`;
|
|
15
|
+
}
|
|
16
|
+
map(fn) {
|
|
17
|
+
return new _OkImpl(fn(this.value));
|
|
18
|
+
}
|
|
19
|
+
mapErr(_fn) {
|
|
20
|
+
return new _OkImpl(this.value);
|
|
21
|
+
}
|
|
22
|
+
flatMap(fn) {
|
|
23
|
+
return fn(this.value);
|
|
24
|
+
}
|
|
25
|
+
andThen(fn) {
|
|
26
|
+
return fn(this.value);
|
|
27
|
+
}
|
|
28
|
+
recover(_fn) {
|
|
29
|
+
return new _OkImpl(this.value);
|
|
30
|
+
}
|
|
31
|
+
tap(fn) {
|
|
32
|
+
fn(this.value);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
tapErr(_fn) {
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
match(onOk, _onErr) {
|
|
39
|
+
return onOk(this.value);
|
|
40
|
+
}
|
|
41
|
+
unwrapOr(_defaultValue) {
|
|
42
|
+
return this.value;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var ErrImpl = class _ErrImpl {
|
|
46
|
+
_tag;
|
|
47
|
+
error;
|
|
48
|
+
constructor(error) {
|
|
49
|
+
this._tag = "Err";
|
|
50
|
+
this.error = error;
|
|
51
|
+
}
|
|
52
|
+
[INSPECT](_depth, options, inspect) {
|
|
53
|
+
return `Err(${inspect(this.error, options)})`;
|
|
54
|
+
}
|
|
55
|
+
map(_fn) {
|
|
56
|
+
return new _ErrImpl(this.error);
|
|
57
|
+
}
|
|
58
|
+
mapErr(fn) {
|
|
59
|
+
return new _ErrImpl(fn(this.error));
|
|
60
|
+
}
|
|
61
|
+
flatMap(_fn) {
|
|
62
|
+
return new _ErrImpl(this.error);
|
|
63
|
+
}
|
|
64
|
+
andThen(_fn) {
|
|
65
|
+
return new _ErrImpl(this.error);
|
|
66
|
+
}
|
|
67
|
+
recover(fn) {
|
|
68
|
+
return fn(this.error);
|
|
69
|
+
}
|
|
70
|
+
tap(_fn) {
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
tapErr(fn) {
|
|
74
|
+
fn(this.error);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
match(_onOk, onErr) {
|
|
78
|
+
return onErr(this.error);
|
|
79
|
+
}
|
|
80
|
+
unwrapOr(defaultValue) {
|
|
81
|
+
return defaultValue;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var newOk = (value) => new OkImpl(value);
|
|
85
|
+
var newErr = (error) => new ErrImpl(error);
|
|
12
86
|
|
|
13
87
|
// src/internal/dual.ts
|
|
14
88
|
var dual = (arity, body) => {
|
|
@@ -22,23 +96,23 @@ var isOk = (result) => result._tag === "Ok";
|
|
|
22
96
|
var isErr = (result) => result._tag === "Err";
|
|
23
97
|
var map = dual(
|
|
24
98
|
2,
|
|
25
|
-
(result, fn) => isOk(result) ?
|
|
99
|
+
(result, fn) => isOk(result) ? newOk(fn(result.value)) : newErr(result.error)
|
|
26
100
|
);
|
|
27
101
|
var mapErr = dual(
|
|
28
102
|
2,
|
|
29
|
-
(result, fn) => isErr(result) ?
|
|
103
|
+
(result, fn) => isErr(result) ? newErr(fn(result.error)) : newOk(result.value)
|
|
30
104
|
);
|
|
31
105
|
var bimap = dual(
|
|
32
106
|
3,
|
|
33
|
-
(result, onOk, onErr) => isOk(result) ?
|
|
107
|
+
(result, onOk, onErr) => isOk(result) ? newOk(onOk(result.value)) : newErr(onErr(result.error))
|
|
34
108
|
);
|
|
35
109
|
var flatMap = dual(
|
|
36
110
|
2,
|
|
37
|
-
(result, fn) => isOk(result) ? fn(result.value) :
|
|
111
|
+
(result, fn) => isOk(result) ? fn(result.value) : newErr(result.error)
|
|
38
112
|
);
|
|
39
113
|
var recover = dual(
|
|
40
114
|
2,
|
|
41
|
-
(result, fn) => isErr(result) ? fn(result.error) :
|
|
115
|
+
(result, fn) => isErr(result) ? fn(result.error) : newOk(result.value)
|
|
42
116
|
);
|
|
43
117
|
var tap = dual(2, (result, fn) => {
|
|
44
118
|
if (isOk(result)) fn(result.value);
|
package/dist/fluent.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/ctor.ts","../src/internal/dual.ts","../src/result.ts","../src/fluent.ts"],"names":[],"mappings":"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","file":"fluent.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","/**\n * @onrails/result internal — owning module for the **dual-form idiom**.\n *\n * Every dual-form transform in this package (`map`, `flatMap`, `match`, …)\n * accepts either shape:\n *\n * data-first: `map(result, fn)` — full arity, runs immediately\n * curried: `map(fn)(result)` — arity minus the leading `self`, returns\n * a unary function awaiting the data\n *\n * {@link dual} is the single arity dispatcher those transforms derive from;\n * hand-rolled `args.length` checks are not allowed elsewhere.\n *\n * NOTE: a twin copy of this module lives at `packages/maybe/src/internal/dual.ts`\n * — keep the two in sync when editing.\n *\n * Internal only: not listed in package.json `exports` or tsup entries.\n */\n\n/**\n * Derive a dual-form (data-first / curried) function from a single\n * data-first `body`.\n *\n * When called with `args.length >= arity` the wrapper runs `body(...args)`\n * (data-first). With fewer arguments it returns `(self) => body(self, ...args)`\n * — the curried, data-last-`self` form used with `pipe`/`flow`.\n *\n * The public type is supplied entirely by the caller: annotate the exported\n * const with the exact overload set and let `F` be inferred from it.\n *\n * @example\n * ```ts\n * export 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) ? ok(fn(result.value)) : err(result.error),\n * );\n * ```\n */\nexport const dual = <F>(arity: number, body: (...args: never[]) => unknown): F => {\n // `(...args: never[]) => unknown` is the top function type, so every typed\n // body is assignable to the parameter — but it cannot be invoked with\n // `unknown` arguments. Re-view it through the variadic shape the dispatcher\n // actually forwards; the constraint is that `body` only ever receives the\n // arguments the caller's overload annotation admitted.\n const run = body as (...args: readonly unknown[]) => unknown;\n const dispatcher = (...args: readonly unknown[]): unknown =>\n args.length >= arity ? run(...args) : (self: unknown) => run(self, ...args);\n // The caller's overload annotation on the exported const supplies the real\n // public type; internally the dispatcher stays `unknown`-typed.\n return dispatcher as F;\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 {\n bimap,\n flatMap,\n map,\n mapErr,\n match,\n recover,\n show,\n tap,\n tapErr,\n unwrapOr,\n} 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 bimap: <U, F>(onOk: (value: T) => U, onErr: (error: E) => F) => FluentResult<U, F>;\n flatMap: <U, F = E>(fn: (value: T) => Result<U, F>) => FluentResult<U, E | F>;\n andThen: <U, F = E>(fn: (value: T) => Result<U, F>) => FluentResult<U, E | F>;\n recover: <F>(fn: (error: E) => Result<T, F>) => FluentResult<T, F>;\n tap: (fn: (value: T) => void) => FluentResult<T, E>;\n tapErr: (fn: (error: E) => void) => FluentResult<T, E>;\n\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: <U>(defaultValue: U) => T | U;\n /** Exit the wrapper — hand back the canonical plain-data result. */\n toResult: () => Result<T, E>;\n /** Debug terminal — `Ok(…)` / `Err(…)`, same output as {@link show}. */\n toString: () => string;\n};\n\n/**\n * Wrap a {@link Result} for opt-in dot chaining — app-edge sugar. Keep the\n * data-first helpers ({@link map}, {@link flatMap}) in library internals.\n *\n * Mirrors every core transform; `test/parity.spec.ts` enforces the mirror.\n *\n * @example\n * ```ts\n * fluent(ok(2)).map((n) => n * 3).unwrapOr(0); // 6\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 bimap: (onOk, onErr) => fluent(bimap(result, onOk, onErr)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n recover: (fn) => fluent(recover(result, fn)),\n tap: (fn) => fluent(tap(result, fn)),\n tapErr: (fn) => fluent(tapErr(result, fn)),\n\n match: (onOk, onErr) => match(result, onOk, onErr),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n toResult: () => result,\n toString: () => show(result),\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/proto.ts","../src/internal/dual.ts","../src/result.ts","../src/fluent.ts"],"names":[],"mappings":"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","file":"fluent.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","/**\n * @onrails/result internal — owning module for the **dual-form idiom**.\n *\n * Every dual-form transform in this package (`map`, `flatMap`, `match`, …)\n * accepts either shape:\n *\n * data-first: `map(result, fn)` — full arity, runs immediately\n * curried: `map(fn)(result)` — arity minus the leading `self`, returns\n * a unary function awaiting the data\n *\n * {@link dual} is the single arity dispatcher those transforms derive from;\n * hand-rolled `args.length` checks are not allowed elsewhere.\n *\n * NOTE: a twin copy of this module lives at `packages/maybe/src/internal/dual.ts`\n * — keep the two in sync when editing.\n *\n * Internal only: not listed in package.json `exports` or tsup entries.\n */\n\n/**\n * Derive a dual-form (data-first / curried) function from a single\n * data-first `body`.\n *\n * When called with `args.length >= arity` the wrapper runs `body(...args)`\n * (data-first). With fewer arguments it returns `(self) => body(self, ...args)`\n * — the curried, data-last-`self` form used with `pipe`/`flow`.\n *\n * The public type is supplied entirely by the caller: annotate the exported\n * const with the exact overload set and let `F` be inferred from it.\n *\n * @example\n * ```ts\n * export 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) ? ok(fn(result.value)) : err(result.error),\n * );\n * ```\n */\nexport const dual = <F>(arity: number, body: (...args: never[]) => unknown): F => {\n // `(...args: never[]) => unknown` is the top function type, so every typed\n // body is assignable to the parameter — but it cannot be invoked with\n // `unknown` arguments. Re-view it through the variadic shape the dispatcher\n // actually forwards; the constraint is that `body` only ever receives the\n // arguments the caller's overload annotation admitted.\n const run = body as (...args: readonly unknown[]) => unknown;\n const dispatcher = (...args: readonly unknown[]): unknown =>\n args.length >= arity ? run(...args) : (self: unknown) => run(self, ...args);\n // The caller's overload annotation on the exported const supplies the real\n // public type; internally the dispatcher stays `unknown`-typed.\n return dispatcher as F;\n};\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 {\n bimap,\n flatMap,\n map,\n mapErr,\n match,\n recover,\n show,\n tap,\n tapErr,\n unwrapOr,\n} 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 bimap: <U, F>(onOk: (value: T) => U, onErr: (error: E) => F) => FluentResult<U, F>;\n flatMap: <U, F = E>(fn: (value: T) => Result<U, F>) => FluentResult<U, E | F>;\n andThen: <U, F = E>(fn: (value: T) => Result<U, F>) => FluentResult<U, E | F>;\n recover: <F>(fn: (error: E) => Result<T, F>) => FluentResult<T, F>;\n tap: (fn: (value: T) => void) => FluentResult<T, E>;\n tapErr: (fn: (error: E) => void) => FluentResult<T, E>;\n\n match: <U>(onOk: (value: T) => U, onErr: (error: E) => U) => U;\n unwrapOr: <U>(defaultValue: U) => T | U;\n /** Exit the wrapper — hand back the canonical plain-data result. */\n toResult: () => Result<T, E>;\n /** Debug terminal — `Ok(…)` / `Err(…)`, same output as {@link show}. */\n toString: () => string;\n};\n\n/**\n * Wrap a {@link Result} for opt-in dot chaining — app-edge sugar. Keep the\n * data-first helpers ({@link map}, {@link flatMap}) in library internals.\n *\n * Mirrors every core transform; `test/parity.spec.ts` enforces the mirror.\n *\n * @example\n * ```ts\n * fluent(ok(2)).map((n) => n * 3).unwrapOr(0); // 6\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 bimap: (onOk, onErr) => fluent(bimap(result, onOk, onErr)),\n flatMap: (fn) => fluent(flatMap(result, fn)),\n andThen: (fn) => fluent(flatMap(result, fn)),\n recover: (fn) => fluent(recover(result, fn)),\n tap: (fn) => fluent(tap(result, fn)),\n tapErr: (fn) => fluent(tapErr(result, fn)),\n\n match: (onOk, onErr) => match(result, onOk, onErr),\n unwrapOr: (defaultValue) => unwrapOr(result, defaultValue),\n toResult: () => result,\n toString: () => show(result),\n});\n"]}
|
package/dist/fluent.js
CHANGED
|
@@ -1,12 +1,86 @@
|
|
|
1
|
-
// src/internal/
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/internal/proto.ts
|
|
2
|
+
var INSPECT = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
3
|
+
var OkImpl = class _OkImpl {
|
|
4
|
+
_tag;
|
|
5
|
+
value;
|
|
6
|
+
// explicit assignment order keeps `_tag` first, so JSON key order matches the plain-data shape
|
|
7
|
+
constructor(value) {
|
|
8
|
+
this._tag = "Ok";
|
|
9
|
+
this.value = value;
|
|
10
|
+
}
|
|
11
|
+
[INSPECT](_depth, options, inspect) {
|
|
12
|
+
return `Ok(${inspect(this.value, options)})`;
|
|
13
|
+
}
|
|
14
|
+
map(fn) {
|
|
15
|
+
return new _OkImpl(fn(this.value));
|
|
16
|
+
}
|
|
17
|
+
mapErr(_fn) {
|
|
18
|
+
return new _OkImpl(this.value);
|
|
19
|
+
}
|
|
20
|
+
flatMap(fn) {
|
|
21
|
+
return fn(this.value);
|
|
22
|
+
}
|
|
23
|
+
andThen(fn) {
|
|
24
|
+
return fn(this.value);
|
|
25
|
+
}
|
|
26
|
+
recover(_fn) {
|
|
27
|
+
return new _OkImpl(this.value);
|
|
28
|
+
}
|
|
29
|
+
tap(fn) {
|
|
30
|
+
fn(this.value);
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
tapErr(_fn) {
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
match(onOk, _onErr) {
|
|
37
|
+
return onOk(this.value);
|
|
38
|
+
}
|
|
39
|
+
unwrapOr(_defaultValue) {
|
|
40
|
+
return this.value;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var ErrImpl = class _ErrImpl {
|
|
44
|
+
_tag;
|
|
45
|
+
error;
|
|
46
|
+
constructor(error) {
|
|
47
|
+
this._tag = "Err";
|
|
48
|
+
this.error = error;
|
|
49
|
+
}
|
|
50
|
+
[INSPECT](_depth, options, inspect) {
|
|
51
|
+
return `Err(${inspect(this.error, options)})`;
|
|
52
|
+
}
|
|
53
|
+
map(_fn) {
|
|
54
|
+
return new _ErrImpl(this.error);
|
|
55
|
+
}
|
|
56
|
+
mapErr(fn) {
|
|
57
|
+
return new _ErrImpl(fn(this.error));
|
|
58
|
+
}
|
|
59
|
+
flatMap(_fn) {
|
|
60
|
+
return new _ErrImpl(this.error);
|
|
61
|
+
}
|
|
62
|
+
andThen(_fn) {
|
|
63
|
+
return new _ErrImpl(this.error);
|
|
64
|
+
}
|
|
65
|
+
recover(fn) {
|
|
66
|
+
return fn(this.error);
|
|
67
|
+
}
|
|
68
|
+
tap(_fn) {
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
tapErr(fn) {
|
|
72
|
+
fn(this.error);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
match(_onOk, onErr) {
|
|
76
|
+
return onErr(this.error);
|
|
77
|
+
}
|
|
78
|
+
unwrapOr(defaultValue) {
|
|
79
|
+
return defaultValue;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var newOk = (value) => new OkImpl(value);
|
|
83
|
+
var newErr = (error) => new ErrImpl(error);
|
|
10
84
|
|
|
11
85
|
// src/internal/dual.ts
|
|
12
86
|
var dual = (arity, body) => {
|
|
@@ -20,23 +94,23 @@ var isOk = (result) => result._tag === "Ok";
|
|
|
20
94
|
var isErr = (result) => result._tag === "Err";
|
|
21
95
|
var map = dual(
|
|
22
96
|
2,
|
|
23
|
-
(result, fn) => isOk(result) ?
|
|
97
|
+
(result, fn) => isOk(result) ? newOk(fn(result.value)) : newErr(result.error)
|
|
24
98
|
);
|
|
25
99
|
var mapErr = dual(
|
|
26
100
|
2,
|
|
27
|
-
(result, fn) => isErr(result) ?
|
|
101
|
+
(result, fn) => isErr(result) ? newErr(fn(result.error)) : newOk(result.value)
|
|
28
102
|
);
|
|
29
103
|
var bimap = dual(
|
|
30
104
|
3,
|
|
31
|
-
(result, onOk, onErr) => isOk(result) ?
|
|
105
|
+
(result, onOk, onErr) => isOk(result) ? newOk(onOk(result.value)) : newErr(onErr(result.error))
|
|
32
106
|
);
|
|
33
107
|
var flatMap = dual(
|
|
34
108
|
2,
|
|
35
|
-
(result, fn) => isOk(result) ? fn(result.value) :
|
|
109
|
+
(result, fn) => isOk(result) ? fn(result.value) : newErr(result.error)
|
|
36
110
|
);
|
|
37
111
|
var recover = dual(
|
|
38
112
|
2,
|
|
39
|
-
(result, fn) => isErr(result) ? fn(result.error) :
|
|
113
|
+
(result, fn) => isErr(result) ? fn(result.error) : newOk(result.value)
|
|
40
114
|
);
|
|
41
115
|
var tap = dual(2, (result, fn) => {
|
|
42
116
|
if (isOk(result)) fn(result.value);
|