@konker.dev/neverthrow-r 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Konrad Markus <mail@konker.dev>
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12
+ SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14
+ OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # neverthrow-r
2
+
3
+ An extension for [neverthrow](https://github.com/supermacro/neverthrow) that adds a third channel — `R`, for requirements / dependencies — to `Result` and `ResultAsync`.
4
+
5
+ Inspired by effect-ts, but deliberately small: `neverthrow-r` is a thin layer of curried, pipe-friendly functions over neverthrow. There is no runtime, no context machinery, no scheduler — just two type aliases and a set of operators that thread an `R` parameter through your existing neverthrow chains.
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ pnpm add @konker.dev/neverthrow-r neverthrow
11
+ ```
12
+
13
+ `neverthrow` is a peer dependency.
14
+
15
+ ## Core types
16
+
17
+ ```ts
18
+ type ResultR<R, T, E> = (r: R) => Result<T, E>;
19
+ type ResultAsyncR<R, T, E> = (r: R) => ResultAsync<T, E>;
20
+ ```
21
+
22
+ A value of type `ResultR<R, T, E>` is a function that, given an `R`, produces a neverthrow `Result<T, E>`. `R` defaults to `unknown` (no specific requirements).
23
+
24
+ When two steps are chained, their requirement types are combined with intersection: a chain of `ResultR<R1, A, E1>` and `(a: A) => ResultR<R2, B, E2>` produces `ResultR<R1 & R2, B, E1 | E2>`.
25
+
26
+ ## `pipe`
27
+
28
+ `neverthrow-r` ships a small value-piping `pipe` implementation. It applies functions from left to right, preserves the inferred output type through the chain, and supports up to 20 function arguments:
29
+
30
+ ```ts
31
+ import { pipe } from '@konker.dev/neverthrow-r';
32
+ ```
33
+
34
+ If you already use a value-piping `pipe` from another library (e.g. `effect`, `fp-ts`, `remeda`), the operators remain shape-compatible with those too.
35
+
36
+ ## Quick example
37
+
38
+ ```ts
39
+ import { andThen, asks, pipe, provide, type ResultR } from '@konker.dev/neverthrow-r';
40
+
41
+ const loadUser =
42
+ (id: string): ResultR<{ db: Db }, User, DbError> =>
43
+ (r) =>
44
+ r.db.findUser(id);
45
+
46
+ const greet = (user: User): ResultR<{ logger: Logger }, string, never> =>
47
+ asks((r) => {
48
+ r.logger.info(`greeting ${user.name}`);
49
+ return `Hello, ${user.name}`;
50
+ });
51
+
52
+ const program = (id: string) => pipe(loadUser(id), andThen(greet));
53
+ // ^? ResultR<{ db: Db } & { logger: Logger }, string, DbError>
54
+
55
+ const result = provide(program('u-1'), { db, logger });
56
+ // ^? Result<string, DbError>
57
+ ```
58
+
59
+ Note how `program`'s requirement type is the _intersection_ of the two steps' requirements — that intersection is built up automatically as you chain.
60
+
61
+ ## Async example with do-notation
62
+
63
+ ```ts
64
+ import { okAsync } from 'neverthrow';
65
+ import { bindAsyncR, doAsyncR, fromResultAsync, pipe, provide } from '@konker.dev/neverthrow-r';
66
+
67
+ const program = pipe(
68
+ doAsyncR(),
69
+ bindAsyncR('user', () => (r: { db: Db }) => r.db.findUserAsync('u-1')),
70
+ bindAsyncR('greeting', ({ user }) => fromResultAsync(okAsync(`Hello, ${user.name}`)))
71
+ );
72
+
73
+ const result = await provide(program, { db });
74
+ // result.value === { user: User, greeting: string }
75
+ ```
76
+
77
+ Each `bindAsyncR` step:
78
+
79
+ - accumulates a named value onto the success scope,
80
+ - contributes its own requirements to the chain's `R`,
81
+ - short-circuits the whole chain on the first `Err`.
82
+
83
+ Note that `doAsyncR()` (and `doR()`) is called without a generic type argument here. `R` defaults to `unknown` and the chain's accumulated requirements are built up automatically by each `bindAsyncR` step — because `unknown & X = X`. You only need an explicit `doAsyncR<MyEnv>()` if you want to _constrain_ the chain to a known environment up front (so that subsequent steps requiring anything outside `MyEnv` become type errors).
84
+
85
+ ## Partial provision
86
+
87
+ ```ts
88
+ import { provideSome } from '@konker.dev/neverthrow-r';
89
+
90
+ declare const program: ResultR<{ db: Db; logger: Logger }, User, Error>;
91
+
92
+ // inject the logger now, leave db for later
93
+ const stillNeedsDb = provideSome(program, { logger });
94
+ // ^? ResultR<{ db: Db }, User, Error>
95
+
96
+ const result = provide(stillNeedsDb, { db });
97
+ ```
98
+
99
+ `provideSome` whole-replaces the provided keys (no deep merge); the returned `ResultR` requires whatever keys were not provided.
100
+
101
+ ## API
102
+
103
+ ### Constructors
104
+
105
+ - `okR(value)`, `errR(error)` — lift into `ResultR`
106
+ - `okAsyncR(value)`, `errAsyncR(error)` — lift into `ResultAsyncR`
107
+ - `fromResult(r)`, `fromResultAsync(ra)` — lift an existing neverthrow value
108
+ - `asks(f)` — build a `ResultR` from a selector over the environment
109
+ - `ask()` — `asks(r => r)`, returns the full environment
110
+
111
+ ### Pipe
112
+
113
+ `pipe(value, ...fns)` — apply up to 20 unary functions from left to right.
114
+
115
+ ### Sync operators (over `ResultR`)
116
+
117
+ `map`, `mapErr`, `andThen`, `orElse`, `match`, `andTee`, `orTee`, `andThrough`
118
+
119
+ ### Async operators (over `ResultAsyncR`)
120
+
121
+ `mapAsync`, `mapErrAsync`, `andThenAsync`, `orElseAsync`, `matchAsync`, `andTeeAsync`, `orTeeAsync`, `andThroughAsync`
122
+
123
+ ### Sync → async bridges
124
+
125
+ `asyncMap`, `asyncAndThen`, `asyncAndThrough` — take a `ResultR`, return a `ResultAsyncR`.
126
+
127
+ ### Do-notation
128
+
129
+ `doR`, `bindR`, `doAsyncR`, `bindAsyncR` — accumulate named values into a success-channel scope while threading `R`.
130
+
131
+ ### Provision
132
+
133
+ - `provide(rr, deps)` — supply all requirements, return the underlying `Result` / `ResultAsync`.
134
+ - `provideSome(rr, partial)` — supply some requirements, return a `ResultR` over the remaining ones.
135
+
136
+ ## API Reference
137
+
138
+ Full auto-generated reference docs (signatures, types, module summaries) live in [`./docs/reference/`](./docs/reference/). They're regenerated from source on every `ci` run and a staleness check fails the build if they drift.
139
+
140
+ ## License
141
+
142
+ ISC
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Async combinators over `ResultAsyncR`, mirroring the sync surface from
3
+ * {@link sync} 1:1. Each combinator is the `Async`-suffixed sibling of its
4
+ * sync counterpart; semantics and type signatures match, lifted to
5
+ * `ResultAsyncR`.
6
+ *
7
+ * @remarks
8
+ * Cross-link to the sync module for the full prose on each combinator. The
9
+ * docs here focus on the async-specific shape: each transformer accepts
10
+ * `Promise`-returning functions, and the operand is a `ResultAsyncR`.
11
+ *
12
+ * Reach for this module when the chain is already async (e.g. it started
13
+ * with {@link okAsyncR} or was promoted via {@link bridges}). To enter the
14
+ * async track from a sync chain mid-pipeline, use {@link bridges} instead.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
19
+ * import { andThenAsync, mapAsync } from '@konker.dev/neverthrow-r/async';
20
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
21
+ *
22
+ * const program = pipe(
23
+ * okAsyncR<number>(2),
24
+ * mapAsync(async (n) => n + 1),
25
+ * andThenAsync((n) => okAsyncR<string>(`got ${n}`)),
26
+ * );
27
+ *
28
+ * program(undefined); // ResultAsync resolving to Ok('got 3')
29
+ * ```
30
+ *
31
+ * @module
32
+ */
33
+ import type { ResultAsyncR } from './types.js';
34
+ /**
35
+ * Async variant of {@link map}. Accepts a sync- or `Promise`-returning
36
+ * transform.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
41
+ * import { mapAsync } from '@konker.dev/neverthrow-r/async';
42
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
43
+ *
44
+ * const doubled = pipe(okAsyncR<number>(2), mapAsync(async (n) => n * 2));
45
+ * ```
46
+ *
47
+ * @see {@link map}
48
+ */
49
+ export declare const mapAsync: <A, B>(f: (a: A) => B | Promise<B>) => <R, E>(rr: ResultAsyncR<R, A, E>) => ResultAsyncR<R, B, E>;
50
+ /**
51
+ * Async variant of {@link mapErr}. Accepts a sync- or `Promise`-returning
52
+ * transform.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * import { errAsyncR } from '@konker.dev/neverthrow-r/constructors';
57
+ * import { mapErrAsync } from '@konker.dev/neverthrow-r/async';
58
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
59
+ *
60
+ * const wrapped = pipe(
61
+ * errAsyncR<string>('boom'),
62
+ * mapErrAsync(async (msg) => ({ tag: 'fail' as const, msg })),
63
+ * );
64
+ * ```
65
+ *
66
+ * @see {@link mapErr}
67
+ */
68
+ export declare const mapErrAsync: <E, F>(f: (e: E) => F | Promise<F>) => <R, T>(rr: ResultAsyncR<R, T, E>) => ResultAsyncR<R, T, F>;
69
+ /**
70
+ * Async variant of {@link andThen}. The continuation returns a
71
+ * `ResultAsyncR`; its requirements intersect into the chain.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
76
+ * import { andThenAsync } from '@konker.dev/neverthrow-r/async';
77
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
78
+ *
79
+ * const program = pipe(
80
+ * okAsyncR<number>(2),
81
+ * andThenAsync((n) => okAsyncR<string>(`got ${n}`)),
82
+ * );
83
+ * ```
84
+ *
85
+ * @see {@link andThen}
86
+ */
87
+ export declare const andThenAsync: <A, R2, B, E2>(f: (a: A) => ResultAsyncR<R2, B, E2>) => <R1, E1>(rr: ResultAsyncR<R1, A, E1>) => ResultAsyncR<R1 & R2, B, E1 | E2>;
88
+ /**
89
+ * Async variant of {@link orElse}. The recovery returns a `ResultAsyncR`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { errAsyncR, okAsyncR } from '@konker.dev/neverthrow-r/constructors';
94
+ * import { orElseAsync } from '@konker.dev/neverthrow-r/async';
95
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
96
+ *
97
+ * const withFallback = pipe(
98
+ * errAsyncR<string, number>('boom'),
99
+ * orElseAsync(() => okAsyncR<number>(0)),
100
+ * );
101
+ * ```
102
+ *
103
+ * @see {@link orElse}
104
+ */
105
+ export declare const orElseAsync: <E, R2, U, F>(f: (e: E) => ResultAsyncR<R2, U, F>) => <R1, T>(rr: ResultAsyncR<R1, T, E>) => ResultAsyncR<R1 & R2, T | U, F>;
106
+ /**
107
+ * Async variant of {@link match}. Returns a function from environment to a
108
+ * `Promise` of the matched value.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
113
+ * import { matchAsync } from '@konker.dev/neverthrow-r/async';
114
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
115
+ *
116
+ * const rendered = pipe(
117
+ * okAsyncR<number>(42),
118
+ * matchAsync(
119
+ * (n) => `got ${n}`,
120
+ * (e: never) => `error: ${String(e)}`,
121
+ * ),
122
+ * );
123
+ * // rendered(undefined) is Promise<string>
124
+ * ```
125
+ *
126
+ * @see {@link match}
127
+ */
128
+ export declare const matchAsync: <T, E, A, B = A>(okFn: (t: T) => A, errFn: (e: E) => B) => <R>(rr: ResultAsyncR<R, T, E>) => (r: R) => Promise<A | B>;
129
+ /**
130
+ * Async variant of {@link andTee}.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
135
+ * import { andTeeAsync } from '@konker.dev/neverthrow-r/async';
136
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
137
+ *
138
+ * const traced = pipe(okAsyncR<number>(2), andTeeAsync((n) => console.log(n)));
139
+ * ```
140
+ *
141
+ * @see {@link andTee}
142
+ */
143
+ export declare const andTeeAsync: <T>(f: (t: T) => unknown) => <R, E>(rr: ResultAsyncR<R, T, E>) => ResultAsyncR<R, T, E>;
144
+ /**
145
+ * Async variant of {@link orTee}.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * import { errAsyncR } from '@konker.dev/neverthrow-r/constructors';
150
+ * import { orTeeAsync } from '@konker.dev/neverthrow-r/async';
151
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
152
+ *
153
+ * const logged = pipe(errAsyncR<string>('boom'), orTeeAsync((e) => console.error(e)));
154
+ * ```
155
+ *
156
+ * @see {@link orTee}
157
+ */
158
+ export declare const orTeeAsync: <E>(f: (e: E) => unknown) => <R, T>(rr: ResultAsyncR<R, T, E>) => ResultAsyncR<R, T, E>;
159
+ /**
160
+ * Async variant of {@link andThrough}.
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * import { errAsyncR, okAsyncR } from '@konker.dev/neverthrow-r/constructors';
165
+ * import { andThroughAsync } from '@konker.dev/neverthrow-r/async';
166
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
167
+ *
168
+ * const validated = pipe(
169
+ * okAsyncR<number>(2),
170
+ * andThroughAsync((n) =>
171
+ * n > 0 ? okAsyncR<unknown>(undefined) : errAsyncR<string>('non-positive'),
172
+ * ),
173
+ * );
174
+ * ```
175
+ *
176
+ * @see {@link andThrough}
177
+ */
178
+ export declare const andThroughAsync: <T, R2, F>(f: (t: T) => ResultAsyncR<R2, unknown, F>) => <R1, E>(rr: ResultAsyncR<R1, T, E>) => ResultAsyncR<R1 & R2, T, E | F>;
179
+ //# sourceMappingURL=async.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.d.ts","sourceRoot":"","sources":["../src/async.ts"],"names":[],"mappings":"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"}
package/dist/async.js ADDED
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Async combinators over `ResultAsyncR`, mirroring the sync surface from
3
+ * {@link sync} 1:1. Each combinator is the `Async`-suffixed sibling of its
4
+ * sync counterpart; semantics and type signatures match, lifted to
5
+ * `ResultAsyncR`.
6
+ *
7
+ * @remarks
8
+ * Cross-link to the sync module for the full prose on each combinator. The
9
+ * docs here focus on the async-specific shape: each transformer accepts
10
+ * `Promise`-returning functions, and the operand is a `ResultAsyncR`.
11
+ *
12
+ * Reach for this module when the chain is already async (e.g. it started
13
+ * with {@link okAsyncR} or was promoted via {@link bridges}). To enter the
14
+ * async track from a sync chain mid-pipeline, use {@link bridges} instead.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
19
+ * import { andThenAsync, mapAsync } from '@konker.dev/neverthrow-r/async';
20
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
21
+ *
22
+ * const program = pipe(
23
+ * okAsyncR<number>(2),
24
+ * mapAsync(async (n) => n + 1),
25
+ * andThenAsync((n) => okAsyncR<string>(`got ${n}`)),
26
+ * );
27
+ *
28
+ * program(undefined); // ResultAsync resolving to Ok('got 3')
29
+ * ```
30
+ *
31
+ * @module
32
+ */
33
+ /**
34
+ * Async variant of {@link map}. Accepts a sync- or `Promise`-returning
35
+ * transform.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
40
+ * import { mapAsync } from '@konker.dev/neverthrow-r/async';
41
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
42
+ *
43
+ * const doubled = pipe(okAsyncR<number>(2), mapAsync(async (n) => n * 2));
44
+ * ```
45
+ *
46
+ * @see {@link map}
47
+ */
48
+ export const mapAsync = (f) => (rr) => (r) => rr(r).map(f);
49
+ /**
50
+ * Async variant of {@link mapErr}. Accepts a sync- or `Promise`-returning
51
+ * transform.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { errAsyncR } from '@konker.dev/neverthrow-r/constructors';
56
+ * import { mapErrAsync } from '@konker.dev/neverthrow-r/async';
57
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
58
+ *
59
+ * const wrapped = pipe(
60
+ * errAsyncR<string>('boom'),
61
+ * mapErrAsync(async (msg) => ({ tag: 'fail' as const, msg })),
62
+ * );
63
+ * ```
64
+ *
65
+ * @see {@link mapErr}
66
+ */
67
+ export const mapErrAsync = (f) => (rr) => (r) => rr(r).mapErr(f);
68
+ /**
69
+ * Async variant of {@link andThen}. The continuation returns a
70
+ * `ResultAsyncR`; its requirements intersect into the chain.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
75
+ * import { andThenAsync } from '@konker.dev/neverthrow-r/async';
76
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
77
+ *
78
+ * const program = pipe(
79
+ * okAsyncR<number>(2),
80
+ * andThenAsync((n) => okAsyncR<string>(`got ${n}`)),
81
+ * );
82
+ * ```
83
+ *
84
+ * @see {@link andThen}
85
+ */
86
+ export const andThenAsync = (f) => (rr) => (r) => rr(r).andThen((a) => f(a)(r));
87
+ /**
88
+ * Async variant of {@link orElse}. The recovery returns a `ResultAsyncR`.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { errAsyncR, okAsyncR } from '@konker.dev/neverthrow-r/constructors';
93
+ * import { orElseAsync } from '@konker.dev/neverthrow-r/async';
94
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
95
+ *
96
+ * const withFallback = pipe(
97
+ * errAsyncR<string, number>('boom'),
98
+ * orElseAsync(() => okAsyncR<number>(0)),
99
+ * );
100
+ * ```
101
+ *
102
+ * @see {@link orElse}
103
+ */
104
+ export const orElseAsync = (f) => (rr) => (r) => rr(r).orElse((e) => f(e)(r));
105
+ /**
106
+ * Async variant of {@link match}. Returns a function from environment to a
107
+ * `Promise` of the matched value.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
112
+ * import { matchAsync } from '@konker.dev/neverthrow-r/async';
113
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
114
+ *
115
+ * const rendered = pipe(
116
+ * okAsyncR<number>(42),
117
+ * matchAsync(
118
+ * (n) => `got ${n}`,
119
+ * (e: never) => `error: ${String(e)}`,
120
+ * ),
121
+ * );
122
+ * // rendered(undefined) is Promise<string>
123
+ * ```
124
+ *
125
+ * @see {@link match}
126
+ */
127
+ export const matchAsync = (okFn, errFn) => (rr) => async (r) => rr(r).match(okFn, errFn);
128
+ /**
129
+ * Async variant of {@link andTee}.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * import { okAsyncR } from '@konker.dev/neverthrow-r/constructors';
134
+ * import { andTeeAsync } from '@konker.dev/neverthrow-r/async';
135
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
136
+ *
137
+ * const traced = pipe(okAsyncR<number>(2), andTeeAsync((n) => console.log(n)));
138
+ * ```
139
+ *
140
+ * @see {@link andTee}
141
+ */
142
+ export const andTeeAsync = (f) => (rr) => (r) => rr(r).andTee(f);
143
+ /**
144
+ * Async variant of {@link orTee}.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * import { errAsyncR } from '@konker.dev/neverthrow-r/constructors';
149
+ * import { orTeeAsync } from '@konker.dev/neverthrow-r/async';
150
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
151
+ *
152
+ * const logged = pipe(errAsyncR<string>('boom'), orTeeAsync((e) => console.error(e)));
153
+ * ```
154
+ *
155
+ * @see {@link orTee}
156
+ */
157
+ export const orTeeAsync = (f) => (rr) => (r) => rr(r).orTee(f);
158
+ /**
159
+ * Async variant of {@link andThrough}.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * import { errAsyncR, okAsyncR } from '@konker.dev/neverthrow-r/constructors';
164
+ * import { andThroughAsync } from '@konker.dev/neverthrow-r/async';
165
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
166
+ *
167
+ * const validated = pipe(
168
+ * okAsyncR<number>(2),
169
+ * andThroughAsync((n) =>
170
+ * n > 0 ? okAsyncR<unknown>(undefined) : errAsyncR<string>('non-positive'),
171
+ * ),
172
+ * );
173
+ * ```
174
+ *
175
+ * @see {@link andThrough}
176
+ */
177
+ export const andThroughAsync = (f) => (rr) => (r) => rr(r).andThrough((t) => f(t)(r));
178
+ //# sourceMappingURL=async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.js","sourceRoot":"","sources":["../src/async.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,QAAQ,GACnB,CAAO,CAA2B,EAAE,EAAE,CACtC,CAAO,EAAyB,EAAyB,EAAE,CAC3D,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEjB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,CAAO,CAA2B,EAAE,EAAE,CACtC,CAAO,EAAyB,EAAyB,EAAE,CAC3D,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAEpB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,CAAe,CAAoC,EAAE,EAAE,CACvD,CAAS,EAA2B,EAAqC,EAAE,CAC3E,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,CAAc,CAAmC,EAAE,EAAE,CACrD,CAAQ,EAA0B,EAAmC,EAAE,CACvE,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,UAAU,GACrB,CAAiB,IAAiB,EAAE,KAAkB,EAAE,EAAE,CAC1D,CAAI,EAAyB,EAAE,EAAE,CACjC,KAAK,EAAE,CAAI,EAAkB,EAAE,CAC7B,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAE7B;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,CAAI,CAAoB,EAAE,EAAE,CAC5B,CAAO,EAAyB,EAAyB,EAAE,CAC3D,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,UAAU,GACrB,CAAI,CAAoB,EAAE,EAAE,CAC5B,CAAO,EAAyB,EAAyB,EAAE,CAC3D,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnB;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAW,CAAyC,EAAE,EAAE,CACxD,CAAQ,EAA0B,EAAmC,EAAE,CACvE,CAAC,CAAC,EAAE,EAAE,CACJ,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Sync→async bridge operators: take a `ResultR` and return a `ResultAsyncR`,
3
+ * promoting the chain onto the async track mid-pipeline.
4
+ *
5
+ * @remarks
6
+ * Reach for this module when a chain that starts synchronously needs to
7
+ * await — typically an I/O call partway through. Three flavours, mirroring
8
+ * the corresponding sync combinators but lifting the operand into
9
+ * `ResultAsyncR`:
10
+ *
11
+ * - {@link asyncMap} — promote via a `Promise`-returning transform.
12
+ * - {@link asyncAndThen} — promote via a `ResultAsyncR`-returning step.
13
+ * - {@link asyncAndThrough} — promote via a fallible async tee.
14
+ *
15
+ * Every step *after* the bridge must come from {@link async} (the
16
+ * `*Async`-suffixed combinators); there is no async→sync bridge.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { okR } from '@konker.dev/neverthrow-r/constructors';
21
+ * import { mapAsync } from '@konker.dev/neverthrow-r/async';
22
+ * import { asyncMap } from '@konker.dev/neverthrow-r/bridges';
23
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
24
+ *
25
+ * const program = pipe(
26
+ * okR<number>(2),
27
+ * asyncMap(async (n) => n + 1), // sync → async here
28
+ * mapAsync(async (n) => n * 10), // continue async
29
+ * );
30
+ *
31
+ * program(undefined); // ResultAsync resolving to Ok(30)
32
+ * ```
33
+ *
34
+ * @module
35
+ */
36
+ import type { ResultAsyncR, ResultR } from './types.js';
37
+ /**
38
+ * Promotes a `ResultR` to a `ResultAsyncR` by applying a `Promise`-returning
39
+ * transform to the success value.
40
+ *
41
+ * @remarks
42
+ * The sync→async sibling of {@link map}. After this step the chain is async;
43
+ * follow with {@link mapAsync}, {@link andThenAsync}, etc.
44
+ *
45
+ * @typeParam A - The input success type.
46
+ * @typeParam B - The output success type.
47
+ *
48
+ * @param f - `Promise`-returning transform from `A` to `B`.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * import { okR } from '@konker.dev/neverthrow-r/constructors';
53
+ * import { asyncMap } from '@konker.dev/neverthrow-r/bridges';
54
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
55
+ *
56
+ * const program = pipe(okR<number>(2), asyncMap(async (n) => n * 2));
57
+ * program(undefined); // ResultAsync resolving to Ok(4)
58
+ * ```
59
+ *
60
+ * @see {@link map}
61
+ * @see {@link mapAsync}
62
+ */
63
+ export declare const asyncMap: <A, B>(f: (a: A) => Promise<B>) => <R, E>(rr: ResultR<R, A, E>) => ResultAsyncR<R, B, E>;
64
+ /**
65
+ * Promotes a `ResultR` to a `ResultAsyncR` by chaining a
66
+ * `ResultAsyncR`-returning step.
67
+ *
68
+ * @remarks
69
+ * Sync→async sibling of {@link andThen}. The continuation's requirements
70
+ * `R2` are intersected (`R1 & R2`); its error type `E2` is unioned
71
+ * (`E1 | E2`).
72
+ *
73
+ * @typeParam A - The previous step's success type.
74
+ * @typeParam R2 - The continuation's requirements.
75
+ * @typeParam B - The continuation's success type.
76
+ * @typeParam E2 - The continuation's error type.
77
+ *
78
+ * @param f - Function from the previous success value to a `ResultAsyncR`.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * import { okAsyncR, okR } from '@konker.dev/neverthrow-r/constructors';
83
+ * import { asyncAndThen } from '@konker.dev/neverthrow-r/bridges';
84
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
85
+ *
86
+ * const program = pipe(
87
+ * okR<number>(2),
88
+ * asyncAndThen((n) => okAsyncR<string>(`got ${n}`)),
89
+ * );
90
+ *
91
+ * program(undefined); // ResultAsync resolving to Ok('got 2')
92
+ * ```
93
+ *
94
+ * @see {@link andThen}
95
+ * @see {@link andThenAsync}
96
+ */
97
+ export declare const asyncAndThen: <A, R2, B, E2>(f: (a: A) => ResultAsyncR<R2, B, E2>) => <R1, E1>(rr: ResultR<R1, A, E1>) => ResultAsyncR<R1 & R2, B, E1 | E2>;
98
+ /**
99
+ * Promotes a `ResultR` to a `ResultAsyncR` via a fallible async tee that
100
+ * propagates the *original* success value.
101
+ *
102
+ * @remarks
103
+ * Sync→async sibling of {@link andThrough}. The tee step is itself a
104
+ * `ResultAsyncR` that can fail; on success its value is discarded and the
105
+ * chain continues with the original success value.
106
+ *
107
+ * @typeParam T - The success type (preserved through the step on success).
108
+ * @typeParam R2 - The tee's requirements.
109
+ * @typeParam F - The tee's error type.
110
+ *
111
+ * @param f - Function from the success value to a `ResultAsyncR` whose value
112
+ * is ignored on success.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * import { okAsyncR, okR } from '@konker.dev/neverthrow-r/constructors';
117
+ * import { asyncAndThrough } from '@konker.dev/neverthrow-r/bridges';
118
+ * import { pipe } from '@konker.dev/neverthrow-r/pipe';
119
+ *
120
+ * const program = pipe(
121
+ * okR<number>(2),
122
+ * asyncAndThrough((n) => okAsyncR<unknown>(`logged ${n}`)),
123
+ * );
124
+ *
125
+ * program(undefined); // ResultAsync resolving to Ok(2)
126
+ * ```
127
+ *
128
+ * @see {@link andThrough}
129
+ * @see {@link andThroughAsync}
130
+ */
131
+ export declare const asyncAndThrough: <T, R2, F>(f: (t: T) => ResultAsyncR<R2, unknown, F>) => <R1, E>(rr: ResultR<R1, T, E>) => ResultAsyncR<R1 & R2, T, E | F>;
132
+ //# sourceMappingURL=bridges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridges.d.ts","sourceRoot":"","sources":["../src/bridges.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,MAC7B,CAAC,EAAE,CAAC,EAAE,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAE/B,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,YAAY,GACtB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,YAAY,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,MAClD,EAAE,EAAE,EAAE,EAAE,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAG,YAAY,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAE9B,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,eAAe,GACzB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MACnD,EAAE,EAAE,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,YAAY,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAEvB,CAAC"}