@nicolastoulemont/std 0.1.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/README.md +1 -0
- package/dist/adt/index.d.mts +2 -0
- package/dist/adt/index.mjs +3 -0
- package/dist/adt-DraJkmij.mjs +318 -0
- package/dist/adt-DraJkmij.mjs.map +1 -0
- package/dist/apply-fn.types-CXDoeA7D.d.mts +8 -0
- package/dist/apply-fn.types-CXDoeA7D.d.mts.map +1 -0
- package/dist/brand/index.d.mts +2 -0
- package/dist/brand/index.mjs +3 -0
- package/dist/brand-CTaxGuU9.mjs +165 -0
- package/dist/brand-CTaxGuU9.mjs.map +1 -0
- package/dist/data/index.d.mts +2 -0
- package/dist/data/index.mjs +3 -0
- package/dist/data-DgzWI4R_.mjs +244 -0
- package/dist/data-DgzWI4R_.mjs.map +1 -0
- package/dist/discriminator.types-DCkkrCj4.d.mts +7 -0
- package/dist/discriminator.types-DCkkrCj4.d.mts.map +1 -0
- package/dist/either/index.d.mts +2 -0
- package/dist/either/index.mjs +3 -0
- package/dist/either-CnOBUH7a.mjs +598 -0
- package/dist/either-CnOBUH7a.mjs.map +1 -0
- package/dist/equality/index.d.mts +86 -0
- package/dist/equality/index.d.mts.map +1 -0
- package/dist/equality/index.mjs +3 -0
- package/dist/equality-YMebYwm1.mjs +201 -0
- package/dist/equality-YMebYwm1.mjs.map +1 -0
- package/dist/err/index.d.mts +2 -0
- package/dist/err/index.mjs +3 -0
- package/dist/err-BqQApH9r.mjs +169 -0
- package/dist/err-BqQApH9r.mjs.map +1 -0
- package/dist/flow/index.d.mts +2 -0
- package/dist/flow/index.mjs +3 -0
- package/dist/flow-pRdnqmMY.mjs +21 -0
- package/dist/flow-pRdnqmMY.mjs.map +1 -0
- package/dist/gen/index.d.mts +3 -0
- package/dist/gen/index.mjs +3 -0
- package/dist/gen-YfMC9sDT.mjs +42 -0
- package/dist/gen-YfMC9sDT.mjs.map +1 -0
- package/dist/index-BCrD3pEs.d.mts +222 -0
- package/dist/index-BCrD3pEs.d.mts.map +1 -0
- package/dist/index-BR7takNf.d.mts +186 -0
- package/dist/index-BR7takNf.d.mts.map +1 -0
- package/dist/index-CcPnhWje.d.mts +72 -0
- package/dist/index-CcPnhWje.d.mts.map +1 -0
- package/dist/index-CtJ8Ks9X.d.mts +105 -0
- package/dist/index-CtJ8Ks9X.d.mts.map +1 -0
- package/dist/index-CvGTIg9L.d.mts +211 -0
- package/dist/index-CvGTIg9L.d.mts.map +1 -0
- package/dist/index-DPVT0yK4.d.mts +50 -0
- package/dist/index-DPVT0yK4.d.mts.map +1 -0
- package/dist/index-DgOAEEpu.d.mts +79 -0
- package/dist/index-DgOAEEpu.d.mts.map +1 -0
- package/dist/index-Dtq3kmln.d.mts +394 -0
- package/dist/index-Dtq3kmln.d.mts.map +1 -0
- package/dist/index-bLRqTe5I.d.mts +80 -0
- package/dist/index-bLRqTe5I.d.mts.map +1 -0
- package/dist/index-tkgTLCoq.d.mts +80 -0
- package/dist/index-tkgTLCoq.d.mts.map +1 -0
- package/dist/index-wTrnFgYg.d.mts +57 -0
- package/dist/index-wTrnFgYg.d.mts.map +1 -0
- package/dist/index-yyBTq8Ys.d.mts +79 -0
- package/dist/index-yyBTq8Ys.d.mts.map +1 -0
- package/dist/index.d.mts +135 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +41 -0
- package/dist/index.mjs.map +1 -0
- package/dist/is-promise-BEl3eGZg.mjs +11 -0
- package/dist/is-promise-BEl3eGZg.mjs.map +1 -0
- package/dist/option/index.d.mts +3 -0
- package/dist/option/index.mjs +3 -0
- package/dist/option-CKHDOVea.mjs +410 -0
- package/dist/option-CKHDOVea.mjs.map +1 -0
- package/dist/option.types-D6TYG_i3.d.mts +89 -0
- package/dist/option.types-D6TYG_i3.d.mts.map +1 -0
- package/dist/pipe/index.d.mts +2 -0
- package/dist/pipe/index.mjs +3 -0
- package/dist/pipe-GYxZNkPB.mjs +10 -0
- package/dist/pipe-GYxZNkPB.mjs.map +1 -0
- package/dist/predicate/index.d.mts +2 -0
- package/dist/predicate/index.mjs +3 -0
- package/dist/predicate-B6-EdVgW.mjs +293 -0
- package/dist/predicate-B6-EdVgW.mjs.map +1 -0
- package/dist/result/index.d.mts +3 -0
- package/dist/result/index.mjs +3 -0
- package/dist/result-C5tPWR60.mjs +422 -0
- package/dist/result-C5tPWR60.mjs.map +1 -0
- package/dist/result-D7XJ96pv.mjs +1 -0
- package/dist/result.types-Ce7AEOzj.d.mts +156 -0
- package/dist/result.types-Ce7AEOzj.d.mts.map +1 -0
- package/dist/run/index.d.mts +2 -0
- package/dist/run/index.mjs +3 -0
- package/dist/run-DpXkImo9.mjs +10 -0
- package/dist/run-DpXkImo9.mjs.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import { t as isPromise } from "./is-promise-BEl3eGZg.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/result/result.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create a successful Result.
|
|
6
|
+
*
|
|
7
|
+
* @param value - The success value
|
|
8
|
+
* @returns A Result with ok: true
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* ok(42) // { ok: true, value: 42 }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
const ok = (value) => ({
|
|
16
|
+
ok: true,
|
|
17
|
+
value,
|
|
18
|
+
*[Symbol.iterator]() {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Create an error Result.
|
|
24
|
+
*
|
|
25
|
+
* @param error - The error value
|
|
26
|
+
* @returns A Result with ok: false
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* err('something went wrong') // { ok: false, error: 'something went wrong' }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
const err = (error) => ({
|
|
34
|
+
ok: false,
|
|
35
|
+
error,
|
|
36
|
+
*[Symbol.iterator]() {
|
|
37
|
+
yield error;
|
|
38
|
+
throw new Error("Unreachable: Do should short-circuit on error");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Check if a Result is successful.
|
|
43
|
+
*
|
|
44
|
+
* @param result - The Result to check
|
|
45
|
+
* @returns true if the Result is ok
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const result = ok(42)
|
|
50
|
+
* if (isOk(result)) {
|
|
51
|
+
* console.log(result.value) // TypeScript knows value exists
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
const isOk = (result) => result.ok;
|
|
56
|
+
/**
|
|
57
|
+
* Check if a Result is an error.
|
|
58
|
+
*
|
|
59
|
+
* @param result - The Result to check
|
|
60
|
+
* @returns true if the Result is an error
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const result = err('oops')
|
|
65
|
+
* if (isErr(result)) {
|
|
66
|
+
* console.log(result.error) // TypeScript knows error exists
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
const isErr = (result) => !result.ok;
|
|
71
|
+
/**
|
|
72
|
+
* Transform the success value of a Result.
|
|
73
|
+
* If the Result is an error, it passes through unchanged.
|
|
74
|
+
*
|
|
75
|
+
* Supports both sync and async functions:
|
|
76
|
+
* - Sync fn: returns Result<U, E>
|
|
77
|
+
* - Async fn: returns Promise<Result<U, E>>
|
|
78
|
+
*
|
|
79
|
+
* @param fn - Function to transform the success value
|
|
80
|
+
* @returns A function that takes a Result and returns a new Result
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* // Sync usage
|
|
85
|
+
* pipe(
|
|
86
|
+
* ok(5),
|
|
87
|
+
* map(n => n * 2)
|
|
88
|
+
* ) // { ok: true, value: 10 }
|
|
89
|
+
*
|
|
90
|
+
* // Async usage
|
|
91
|
+
* await pipe(
|
|
92
|
+
* ok(userId),
|
|
93
|
+
* map(async id => await fetchName(id))
|
|
94
|
+
* ) // Promise<Result<string, E>>
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
const map = (fn) => (result) => {
|
|
98
|
+
if (!result.ok) return result;
|
|
99
|
+
const mapped = fn(result.value);
|
|
100
|
+
if (mapped instanceof Promise) return mapped.then(ok);
|
|
101
|
+
return ok(mapped);
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Transform the error value of a Result.
|
|
105
|
+
* If the Result is successful, it passes through unchanged.
|
|
106
|
+
*
|
|
107
|
+
* Supports both sync and async functions:
|
|
108
|
+
* - Sync fn: returns Result<T, F>
|
|
109
|
+
* - Async fn: returns Promise<Result<T, F>>
|
|
110
|
+
*
|
|
111
|
+
* @param fn - Function to transform the error value
|
|
112
|
+
* @returns A function that takes a Result and returns a new Result
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* // Sync usage
|
|
117
|
+
* pipe(
|
|
118
|
+
* err({ code: 404 }),
|
|
119
|
+
* mapErr(e => `Error: ${e.code}`)
|
|
120
|
+
* ) // { ok: false, error: 'Error: 404' }
|
|
121
|
+
*
|
|
122
|
+
* // Async usage
|
|
123
|
+
* await pipe(
|
|
124
|
+
* err(errorCode),
|
|
125
|
+
* mapErr(async code => await translateError(code))
|
|
126
|
+
* ) // Promise<Result<T, string>>
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
const mapErr = (fn) => (result) => {
|
|
130
|
+
if (result.ok) return result;
|
|
131
|
+
const mapped = fn(result.error);
|
|
132
|
+
if (mapped instanceof Promise) return mapped.then(err);
|
|
133
|
+
return err(mapped);
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Chain operations that return Results.
|
|
137
|
+
* If the Result is an error, it passes through unchanged.
|
|
138
|
+
*
|
|
139
|
+
* Supports both sync and async functions:
|
|
140
|
+
* - Sync fn: returns Result<U, E | E2>
|
|
141
|
+
* - Async fn: returns Promise<Result<U, E | E2>>
|
|
142
|
+
*
|
|
143
|
+
* @param fn - Function that takes a value and returns a Result (or Promise<Result>)
|
|
144
|
+
* @returns A function that takes a Result and returns a new Result
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const divide = (a: number, b: number) =>
|
|
149
|
+
* b === 0 ? err('division by zero') : ok(a / b)
|
|
150
|
+
*
|
|
151
|
+
* // Sync usage
|
|
152
|
+
* pipe(
|
|
153
|
+
* ok(10),
|
|
154
|
+
* flatMap(n => divide(n, 2))
|
|
155
|
+
* ) // { ok: true, value: 5 }
|
|
156
|
+
*
|
|
157
|
+
* // Async usage
|
|
158
|
+
* await pipe(
|
|
159
|
+
* ok(userId),
|
|
160
|
+
* flatMap(async id => ok(await fetchUser(id)))
|
|
161
|
+
* ) // Promise<Result<User, E>>
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
const flatMap = (fn) => (result) => result.ok ? fn(result.value) : result;
|
|
165
|
+
/**
|
|
166
|
+
* Perform a side effect on the success value without modifying the Result.
|
|
167
|
+
* Useful for debugging, logging, or other side effects in a pipeline.
|
|
168
|
+
* If the Result is an error, the function is not called.
|
|
169
|
+
*
|
|
170
|
+
* Supports both sync and async functions:
|
|
171
|
+
* - Sync fn: returns Result<T, E>
|
|
172
|
+
* - Async fn: returns Promise<Result<T, E>>
|
|
173
|
+
*
|
|
174
|
+
* @param fn - Function to call with the success value (return value is ignored)
|
|
175
|
+
* @returns A function that takes a Result and returns the same Result
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* // Sync usage
|
|
180
|
+
* pipe(
|
|
181
|
+
* ok(42),
|
|
182
|
+
* tap(console.log), // logs 42
|
|
183
|
+
* map(n => n * 2)
|
|
184
|
+
* ) // { ok: true, value: 84 }
|
|
185
|
+
*
|
|
186
|
+
* // Async usage
|
|
187
|
+
* await pipe(
|
|
188
|
+
* ok(42),
|
|
189
|
+
* tap(async v => await logToServer(v)),
|
|
190
|
+
* map(n => n * 2)
|
|
191
|
+
* ) // Promise<Result<84, E>>
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
const tap = (fn) => (result) => {
|
|
195
|
+
if (!result.ok) return result;
|
|
196
|
+
const sideEffect = fn(result.value);
|
|
197
|
+
if (sideEffect instanceof Promise) return sideEffect.then(() => result);
|
|
198
|
+
return result;
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Recover from an error by providing an alternative Result.
|
|
202
|
+
* If the Result is successful, it passes through unchanged.
|
|
203
|
+
*
|
|
204
|
+
* Supports both sync and async functions:
|
|
205
|
+
* - Sync fn: returns Result<T | U, E2>
|
|
206
|
+
* - Async fn: returns Promise<Result<T | U, E2>>
|
|
207
|
+
*
|
|
208
|
+
* @param fn - Function that takes the error and returns an alternative Result
|
|
209
|
+
* @returns A function that takes a Result and returns a new Result
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* // Sync recovery
|
|
214
|
+
* pipe(
|
|
215
|
+
* err('cache miss'),
|
|
216
|
+
* orElse(() => ok(defaultValue))
|
|
217
|
+
* ) // { ok: true, value: defaultValue }
|
|
218
|
+
*
|
|
219
|
+
* // Async recovery
|
|
220
|
+
* await pipe(
|
|
221
|
+
* err('cache miss'),
|
|
222
|
+
* orElse(async () => ok(await fetchFromAPI()))
|
|
223
|
+
* ) // Promise<Result<T, E2>>
|
|
224
|
+
*
|
|
225
|
+
* // Chain multiple fallbacks
|
|
226
|
+
* pipe(
|
|
227
|
+
* err('not found'),
|
|
228
|
+
* orElse(() => tryCache()),
|
|
229
|
+
* orElse(() => tryAPI()),
|
|
230
|
+
* orElse(() => ok(fallback))
|
|
231
|
+
* )
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
const orElse = (fn) => (result) => result.ok ? result : fn(result.error);
|
|
235
|
+
/**
|
|
236
|
+
* Filter a successful Result based on a predicate.
|
|
237
|
+
* If the predicate returns false, converts the success to an error.
|
|
238
|
+
* If the Result is already an error, it passes through unchanged.
|
|
239
|
+
*
|
|
240
|
+
* @param predicate - Function that returns true to keep the value
|
|
241
|
+
* @param onFail - Function that creates the error when predicate fails
|
|
242
|
+
* @returns A function that takes a Result and returns a new Result
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* pipe(
|
|
247
|
+
* ok(5),
|
|
248
|
+
* filter(n => n > 10, n => `${n} is too small`)
|
|
249
|
+
* ) // { ok: false, error: '5 is too small' }
|
|
250
|
+
*
|
|
251
|
+
* pipe(
|
|
252
|
+
* ok(15),
|
|
253
|
+
* filter(n => n > 10, n => `${n} is too small`)
|
|
254
|
+
* ) // { ok: true, value: 15 }
|
|
255
|
+
*
|
|
256
|
+
* // With complex validation
|
|
257
|
+
* pipe(
|
|
258
|
+
* ok(user),
|
|
259
|
+
* filter(u => u.age >= 18, u => ({ code: 'UNDERAGE', user: u }))
|
|
260
|
+
* )
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
const filter = (predicate, onFail) => (result) => {
|
|
264
|
+
if (!result.ok) return result;
|
|
265
|
+
return predicate(result.value) ? result : err(onFail(result.value));
|
|
266
|
+
};
|
|
267
|
+
function all(results) {
|
|
268
|
+
if (Array.isArray(results)) {
|
|
269
|
+
const values$1 = [];
|
|
270
|
+
for (const result of results) {
|
|
271
|
+
if (!result.ok) return result;
|
|
272
|
+
values$1.push(result.value);
|
|
273
|
+
}
|
|
274
|
+
return ok(values$1);
|
|
275
|
+
}
|
|
276
|
+
const values = {};
|
|
277
|
+
for (const [key, result] of Object.entries(results)) {
|
|
278
|
+
const r = result;
|
|
279
|
+
if (!r.ok) return result;
|
|
280
|
+
values[key] = r.value;
|
|
281
|
+
}
|
|
282
|
+
return ok(values);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Get the success value or a default value.
|
|
286
|
+
*
|
|
287
|
+
* @param defaultValue - Value to return if the Result is an error
|
|
288
|
+
* @returns A function that takes a Result and returns the value or default
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* pipe(ok(42), unwrapOr(0)) // 42
|
|
293
|
+
* pipe(err('oops'), unwrapOr(0)) // 0
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
const unwrapOr = (defaultValue) => (result) => result.ok ? result.value : defaultValue;
|
|
297
|
+
/**
|
|
298
|
+
* Get the success value or compute a value from the error.
|
|
299
|
+
*
|
|
300
|
+
* @param fn - Function to compute a value from the error
|
|
301
|
+
* @returns A function that takes a Result and returns the value or computed value
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* pipe(
|
|
306
|
+
* err({ code: 404 }),
|
|
307
|
+
* unwrapOrElse(e => `Error ${e.code}`)
|
|
308
|
+
* ) // 'Error 404'
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
const unwrapOrElse = (fn) => (result) => result.ok ? result.value : fn(result.error);
|
|
312
|
+
/**
|
|
313
|
+
* Pattern match on a Result, handling both success and error cases.
|
|
314
|
+
*
|
|
315
|
+
* @param handlers - Object with ok and err handlers
|
|
316
|
+
* @returns A function that takes a Result and returns the handler result
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* pipe(
|
|
321
|
+
* ok(42),
|
|
322
|
+
* match({
|
|
323
|
+
* ok: n => `Got ${n}`,
|
|
324
|
+
* err: e => `Error: ${e}`
|
|
325
|
+
* })
|
|
326
|
+
* ) // 'Got 42'
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
const match = (handlers) => (result) => result.ok ? handlers.ok(result.value) : handlers.err(result.error);
|
|
330
|
+
/**
|
|
331
|
+
* Wrap a function that might throw into a Result.
|
|
332
|
+
* Supports both sync and async functions with automatic type inference.
|
|
333
|
+
*
|
|
334
|
+
* - Sync fn: returns Result<T, Error>
|
|
335
|
+
* - Async fn: returns Promise<Result<T, Error>>
|
|
336
|
+
*
|
|
337
|
+
* **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),
|
|
338
|
+
* you should add an explicit return type annotation. This is because TypeScript's
|
|
339
|
+
* conditional types cannot determine if `any` is a Promise or not, resulting in a
|
|
340
|
+
* union type `Promise<Result<unknown, Error>> | Result<any, Error>` that won't work
|
|
341
|
+
* with Result utilities like `isOk` or `isErr`.
|
|
342
|
+
*
|
|
343
|
+
* @param fn - Function that might throw (sync or async)
|
|
344
|
+
* @returns A Result with the return value or the caught error
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* // Sync usage
|
|
349
|
+
* fromTry(() => JSON.parse('{"valid": true}'))
|
|
350
|
+
* // { ok: true, value: { valid: true } }
|
|
351
|
+
*
|
|
352
|
+
* fromTry(() => JSON.parse('not json'))
|
|
353
|
+
* // { ok: false, error: SyntaxError }
|
|
354
|
+
*
|
|
355
|
+
* // When fn returns `any`, add explicit return type:
|
|
356
|
+
* fromTry((): unknown => JSON.parse(input))
|
|
357
|
+
* fromTry((): MyType => JSON.parse(input))
|
|
358
|
+
*
|
|
359
|
+
* // Async usage
|
|
360
|
+
* await fromTry(async () => await fetch('/api/user'))
|
|
361
|
+
* // Promise<Result<Response, Error>>
|
|
362
|
+
*
|
|
363
|
+
* await fromTry(async () => {
|
|
364
|
+
* throw new Error('network error')
|
|
365
|
+
* })
|
|
366
|
+
* // Promise<{ ok: false, error: Error }>
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
const fromTry = (fn) => {
|
|
370
|
+
try {
|
|
371
|
+
const result = fn();
|
|
372
|
+
if (isPromise(result)) return result.then(ok).catch((e) => err(e instanceof Error ? e : new Error(String(e))));
|
|
373
|
+
return ok(result);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Result namespace containing all utility functions for working with Result types.
|
|
380
|
+
*
|
|
381
|
+
* Result represents either success (ok) or failure (err). Use this for operations
|
|
382
|
+
* that can fail with typed errors.
|
|
383
|
+
*
|
|
384
|
+
* @see {@link Option} for presence/absence semantics (no error information)
|
|
385
|
+
* @see {@link Either} for two valid outcomes (not just success/failure)
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```ts
|
|
389
|
+
* import { Result, pipe } from '@repo/std'
|
|
390
|
+
* import type { Result as ResultType } from '@repo/std'
|
|
391
|
+
*
|
|
392
|
+
* const divide = (a: number, b: number): ResultType<number, string> =>
|
|
393
|
+
* b === 0 ? Result.err('division by zero') : Result.ok(a / b)
|
|
394
|
+
*
|
|
395
|
+
* const result = pipe(
|
|
396
|
+
* divide(10, 2),
|
|
397
|
+
* Result.map(n => n * 2),
|
|
398
|
+
* Result.unwrapOr(0)
|
|
399
|
+
* )
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
const Result = {
|
|
403
|
+
ok,
|
|
404
|
+
err,
|
|
405
|
+
isOk,
|
|
406
|
+
isErr,
|
|
407
|
+
map,
|
|
408
|
+
mapErr,
|
|
409
|
+
flatMap,
|
|
410
|
+
tap,
|
|
411
|
+
orElse,
|
|
412
|
+
filter,
|
|
413
|
+
all,
|
|
414
|
+
unwrapOr,
|
|
415
|
+
unwrapOrElse,
|
|
416
|
+
match,
|
|
417
|
+
fromTry
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
//#endregion
|
|
421
|
+
export { err as n, ok as r, Result as t };
|
|
422
|
+
//# sourceMappingURL=result-C5tPWR60.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-C5tPWR60.mjs","names":["values"],"sources":["../src/result/result.ts"],"sourcesContent":["import { isPromise } from \"../shared/is-promise\"\nimport type {\n AllArrayReturn,\n AllObjectReturn,\n FromTryReturn,\n Result as ResultType,\n ResultFlatMap,\n ResultMap,\n ResultMapErr,\n ResultTap,\n ResultOrElse,\n ResultFilter,\n} from \"./result.types\"\n\n// ============================================================================\n// Constructors\n// ============================================================================\n\n/**\n * Create a successful Result.\n *\n * @param value - The success value\n * @returns A Result with ok: true\n *\n * @example\n * ```ts\n * ok(42) // { ok: true, value: 42 }\n * ```\n */\nexport const ok = <T>(value: T): ResultType<T, never> => ({\n ok: true,\n value,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, T, unknown> {\n return value\n },\n})\n\n/**\n * Create an error Result.\n *\n * @param error - The error value\n * @returns A Result with ok: false\n *\n * @example\n * ```ts\n * err('something went wrong') // { ok: false, error: 'something went wrong' }\n * ```\n */\nexport const err = <E>(error: E): ResultType<never, E> => ({\n ok: false,\n error,\n *[Symbol.iterator](): Generator<E, never, unknown> {\n yield error\n throw new Error(\"Unreachable: Do should short-circuit on error\")\n },\n})\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a Result is successful.\n *\n * @param result - The Result to check\n * @returns true if the Result is ok\n *\n * @example\n * ```ts\n * const result = ok(42)\n * if (isOk(result)) {\n * console.log(result.value) // TypeScript knows value exists\n * }\n * ```\n */\nexport const isOk = <T, E>(result: ResultType<T, E>): result is Extract<ResultType<T, E>, { ok: true }> => result.ok\n\n/**\n * Check if a Result is an error.\n *\n * @param result - The Result to check\n * @returns true if the Result is an error\n *\n * @example\n * ```ts\n * const result = err('oops')\n * if (isErr(result)) {\n * console.log(result.error) // TypeScript knows error exists\n * }\n * ```\n */\nexport const isErr = <T, E>(result: ResultType<T, E>): result is Extract<ResultType<T, E>, { ok: false }> => !result.ok\n\n// ============================================================================\n// Transformations (curried for pipe)\n// ============================================================================\n\n/**\n * Transform the success value of a Result.\n * If the Result is an error, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<U, E>\n * - Async fn: returns Promise<Result<U, E>>\n *\n * @param fn - Function to transform the success value\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * ok(5),\n * map(n => n * 2)\n * ) // { ok: true, value: 10 }\n *\n * // Async usage\n * await pipe(\n * ok(userId),\n * map(async id => await fetchName(id))\n * ) // Promise<Result<string, E>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const map: ResultMap = (fn) => (result) => {\n if (!result.ok) return result as any\n const mapped = fn(result.value)\n if (mapped instanceof Promise) {\n return mapped.then(ok) as any\n }\n return ok(mapped) as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Transform the error value of a Result.\n * If the Result is successful, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T, F>\n * - Async fn: returns Promise<Result<T, F>>\n *\n * @param fn - Function to transform the error value\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * err({ code: 404 }),\n * mapErr(e => `Error: ${e.code}`)\n * ) // { ok: false, error: 'Error: 404' }\n *\n * // Async usage\n * await pipe(\n * err(errorCode),\n * mapErr(async code => await translateError(code))\n * ) // Promise<Result<T, string>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const mapErr: ResultMapErr = (fn) => (result) => {\n if (result.ok) return result as any\n const mapped = fn(result.error)\n if (mapped instanceof Promise) {\n return mapped.then(err) as any\n }\n return err(mapped) as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Chain operations that return Results.\n * If the Result is an error, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<U, E | E2>\n * - Async fn: returns Promise<Result<U, E | E2>>\n *\n * @param fn - Function that takes a value and returns a Result (or Promise<Result>)\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * const divide = (a: number, b: number) =>\n * b === 0 ? err('division by zero') : ok(a / b)\n *\n * // Sync usage\n * pipe(\n * ok(10),\n * flatMap(n => divide(n, 2))\n * ) // { ok: true, value: 5 }\n *\n * // Async usage\n * await pipe(\n * ok(userId),\n * flatMap(async id => ok(await fetchUser(id)))\n * ) // Promise<Result<User, E>>\n * ```\n */\n\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const flatMap: ResultFlatMap = (fn) => (result) => (result.ok ? fn(result.value) : result) as any\n\n/**\n * Perform a side effect on the success value without modifying the Result.\n * Useful for debugging, logging, or other side effects in a pipeline.\n * If the Result is an error, the function is not called.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T, E>\n * - Async fn: returns Promise<Result<T, E>>\n *\n * @param fn - Function to call with the success value (return value is ignored)\n * @returns A function that takes a Result and returns the same Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * ok(42),\n * tap(console.log), // logs 42\n * map(n => n * 2)\n * ) // { ok: true, value: 84 }\n *\n * // Async usage\n * await pipe(\n * ok(42),\n * tap(async v => await logToServer(v)),\n * map(n => n * 2)\n * ) // Promise<Result<84, E>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tap: ResultTap = (fn) => (result) => {\n if (!result.ok) return result as any\n const sideEffect = fn(result.value)\n if (sideEffect instanceof Promise) {\n return sideEffect.then(() => result) as any\n }\n return result as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Recover from an error by providing an alternative Result.\n * If the Result is successful, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T | U, E2>\n * - Async fn: returns Promise<Result<T | U, E2>>\n *\n * @param fn - Function that takes the error and returns an alternative Result\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync recovery\n * pipe(\n * err('cache miss'),\n * orElse(() => ok(defaultValue))\n * ) // { ok: true, value: defaultValue }\n *\n * // Async recovery\n * await pipe(\n * err('cache miss'),\n * orElse(async () => ok(await fetchFromAPI()))\n * ) // Promise<Result<T, E2>>\n *\n * // Chain multiple fallbacks\n * pipe(\n * err('not found'),\n * orElse(() => tryCache()),\n * orElse(() => tryAPI()),\n * orElse(() => ok(fallback))\n * )\n * ```\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const orElse: ResultOrElse = (fn) => (result) => (result.ok ? result : fn(result.error)) as any\n\n/**\n * Filter a successful Result based on a predicate.\n * If the predicate returns false, converts the success to an error.\n * If the Result is already an error, it passes through unchanged.\n *\n * @param predicate - Function that returns true to keep the value\n * @param onFail - Function that creates the error when predicate fails\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * pipe(\n * ok(5),\n * filter(n => n > 10, n => `${n} is too small`)\n * ) // { ok: false, error: '5 is too small' }\n *\n * pipe(\n * ok(15),\n * filter(n => n > 10, n => `${n} is too small`)\n * ) // { ok: true, value: 15 }\n *\n * // With complex validation\n * pipe(\n * ok(user),\n * filter(u => u.age >= 18, u => ({ code: 'UNDERAGE', user: u }))\n * )\n * ```\n */\nexport const filter: ResultFilter = (predicate, onFail) => (result) => {\n if (!result.ok) return result\n return predicate(result.value) ? result : err(onFail(result.value))\n}\n\n// ============================================================================\n// Combinators\n// ============================================================================\n\n/**\n * Combine multiple Results into a single Result.\n * Supports both array and object inputs.\n *\n * - If all Results are ok, returns ok with all values\n * - If any Result is an error, returns the first error (short-circuits)\n *\n * @example\n * ```ts\n * // Array form (use `as const` for tuple types) - returns Result<[number, string], E>\n * const [num, str] = pipe(\n * Result.all([parseNumber(input), parseString(other)] as const),\n * Result.unwrapOr([0, ''])\n * )\n *\n * // Object form - returns Result<{ user: User, config: Config }, E>\n * pipe(\n * Result.all({ user: fetchUser(id), config: loadConfig() }),\n * Result.tap(({ user, config }) => console.log(user.name, config.theme))\n * )\n * ```\n */\nexport function all<T extends readonly ResultType<unknown, unknown>[]>(results: T): AllArrayReturn<T>\nexport function all<T extends Record<string, ResultType<unknown, unknown>>>(results: T): AllObjectReturn<T>\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument -- Required for handling union types in overloaded function */\nexport function all(results: any): any {\n if (Array.isArray(results)) {\n const values: unknown[] = []\n for (const result of results) {\n if (!result.ok) return result\n values.push(result.value)\n }\n return ok(values)\n }\n\n const values: Record<string, unknown> = {}\n for (const [key, result] of Object.entries(results)) {\n const r = result as ResultType<unknown, unknown>\n if (!r.ok) return result\n values[key] = r.value\n }\n return ok(values)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument */\n\n// ============================================================================\n// Extraction\n// ============================================================================\n\n/**\n * Get the success value or a default value.\n *\n * @param defaultValue - Value to return if the Result is an error\n * @returns A function that takes a Result and returns the value or default\n *\n * @example\n * ```ts\n * pipe(ok(42), unwrapOr(0)) // 42\n * pipe(err('oops'), unwrapOr(0)) // 0\n * ```\n */\nexport const unwrapOr =\n <T>(defaultValue: T) =>\n <E>(result: ResultType<T, E>): T =>\n result.ok ? result.value : defaultValue\n\n/**\n * Get the success value or compute a value from the error.\n *\n * @param fn - Function to compute a value from the error\n * @returns A function that takes a Result and returns the value or computed value\n *\n * @example\n * ```ts\n * pipe(\n * err({ code: 404 }),\n * unwrapOrElse(e => `Error ${e.code}`)\n * ) // 'Error 404'\n * ```\n */\nexport const unwrapOrElse =\n <E, T>(fn: (error: E) => T) =>\n (result: ResultType<T, E>): T =>\n result.ok ? result.value : fn(result.error)\n\n/**\n * Pattern match on a Result, handling both success and error cases.\n *\n * @param handlers - Object with ok and err handlers\n * @returns A function that takes a Result and returns the handler result\n *\n * @example\n * ```ts\n * pipe(\n * ok(42),\n * match({\n * ok: n => `Got ${n}`,\n * err: e => `Error: ${e}`\n * })\n * ) // 'Got 42'\n * ```\n */\nexport const match =\n <T, E, U>(handlers: { ok: (value: T) => U; err: (error: E) => U }) =>\n (result: ResultType<T, E>): U =>\n result.ok ? handlers.ok(result.value) : handlers.err(result.error)\n\n// ============================================================================\n// Error Boundary\n// ============================================================================\n\n/**\n * Wrap a function that might throw into a Result.\n * Supports both sync and async functions with automatic type inference.\n *\n * - Sync fn: returns Result<T, Error>\n * - Async fn: returns Promise<Result<T, Error>>\n *\n * **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),\n * you should add an explicit return type annotation. This is because TypeScript's\n * conditional types cannot determine if `any` is a Promise or not, resulting in a\n * union type `Promise<Result<unknown, Error>> | Result<any, Error>` that won't work\n * with Result utilities like `isOk` or `isErr`.\n *\n * @param fn - Function that might throw (sync or async)\n * @returns A Result with the return value or the caught error\n *\n * @example\n * ```ts\n * // Sync usage\n * fromTry(() => JSON.parse('{\"valid\": true}'))\n * // { ok: true, value: { valid: true } }\n *\n * fromTry(() => JSON.parse('not json'))\n * // { ok: false, error: SyntaxError }\n *\n * // When fn returns `any`, add explicit return type:\n * fromTry((): unknown => JSON.parse(input))\n * fromTry((): MyType => JSON.parse(input))\n *\n * // Async usage\n * await fromTry(async () => await fetch('/api/user'))\n * // Promise<Result<Response, Error>>\n *\n * await fromTry(async () => {\n * throw new Error('network error')\n * })\n * // Promise<{ ok: false, error: Error }>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-type-assertion -- Required for conditional return type */\nexport const fromTry = <T>(fn: () => T): FromTryReturn<T> => {\n try {\n const result = fn()\n if (isPromise(result)) {\n return result\n .then(ok)\n .catch((e) => err(e instanceof Error ? e : new Error(String(e)))) as unknown as FromTryReturn<T>\n }\n return ok(result) as unknown as FromTryReturn<T>\n } catch (e) {\n return err(e instanceof Error ? e : new Error(String(e))) as unknown as FromTryReturn<T>\n }\n}\n/* oxlint-enable no-explicit-any, no-unsafe-type-assertion */\n\n// ============================================================================\n// Namespace\n// ============================================================================\n\n/**\n * Result namespace containing all utility functions for working with Result types.\n *\n * Result represents either success (ok) or failure (err). Use this for operations\n * that can fail with typed errors.\n *\n * @see {@link Option} for presence/absence semantics (no error information)\n * @see {@link Either} for two valid outcomes (not just success/failure)\n *\n * @example\n * ```ts\n * import { Result, pipe } from '@repo/std'\n * import type { Result as ResultType } from '@repo/std'\n *\n * const divide = (a: number, b: number): ResultType<number, string> =>\n * b === 0 ? Result.err('division by zero') : Result.ok(a / b)\n *\n * const result = pipe(\n * divide(10, 2),\n * Result.map(n => n * 2),\n * Result.unwrapOr(0)\n * )\n * ```\n */\nexport const Result = {\n ok,\n err,\n isOk,\n isErr,\n map,\n mapErr,\n flatMap,\n tap,\n orElse,\n filter,\n all,\n unwrapOr,\n unwrapOrElse,\n match,\n fromTry,\n} as const\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//#region src/gen/gen.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The yieldable protocol - any type that can be yielded in a gen computation.
|
|
4
|
+
* Implements Symbol.iterator to allow `yield*` extraction of values.
|
|
5
|
+
*
|
|
6
|
+
* @template A - The success value type
|
|
7
|
+
* @template E - The error type (yielded on failure)
|
|
8
|
+
*/
|
|
9
|
+
type Yieldable<A, E> = {
|
|
10
|
+
[Symbol.iterator](): Generator<E, A, unknown>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Extract the success type from a Yieldable.
|
|
14
|
+
*/
|
|
15
|
+
type YieldableValue<T> = T extends Yieldable<infer A, unknown> ? A : never;
|
|
16
|
+
/**
|
|
17
|
+
* Extract the error type from a Yieldable.
|
|
18
|
+
*/
|
|
19
|
+
type YieldableError<T> = T extends Yieldable<unknown, infer E> ? E : never;
|
|
20
|
+
/**
|
|
21
|
+
* Sync computation - returned when using a sync generator with gen.
|
|
22
|
+
* The run() method returns Result directly (no Promise).
|
|
23
|
+
* Implements Yieldable so it can be nested in other gen computations.
|
|
24
|
+
*
|
|
25
|
+
* @template A - The success value type
|
|
26
|
+
* @template E - The error type
|
|
27
|
+
*/
|
|
28
|
+
type SyncComputation<A, E> = Yieldable<A, E> & {
|
|
29
|
+
/**
|
|
30
|
+
* Execute the computation synchronously.
|
|
31
|
+
* @returns Result<A, E> directly (no Promise)
|
|
32
|
+
*/
|
|
33
|
+
run(): Result<A, E>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Async computation - returned when using an async generator with gen.
|
|
37
|
+
* The run() method returns Promise<Result>.
|
|
38
|
+
* Does NOT implement Yieldable - cannot be yielded in sync context.
|
|
39
|
+
*
|
|
40
|
+
* @template A - The success value type
|
|
41
|
+
* @template E - The error type
|
|
42
|
+
*/
|
|
43
|
+
type AsyncComputation<A, E> = {
|
|
44
|
+
/**
|
|
45
|
+
* Execute the computation asynchronously.
|
|
46
|
+
* @returns Promise<Result<A, E>>
|
|
47
|
+
*/
|
|
48
|
+
run(): Promise<Result<A, E>>;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Union type for any computation (sync or async).
|
|
52
|
+
*/
|
|
53
|
+
type Computation<A, E> = SyncComputation<A, E> | AsyncComputation<A, E>;
|
|
54
|
+
/**
|
|
55
|
+
* Sync generator type for gen.
|
|
56
|
+
* Yields errors of type E, returns value of type A.
|
|
57
|
+
*/
|
|
58
|
+
type GenGenerator<A, E> = Generator<E, A, unknown>;
|
|
59
|
+
/**
|
|
60
|
+
* Async generator type for gen.
|
|
61
|
+
* Yields errors of type E, returns value of type A.
|
|
62
|
+
*/
|
|
63
|
+
type AsyncGenGenerator<A, E> = AsyncGenerator<E, A, unknown>;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/result/result.types.d.ts
|
|
66
|
+
/**
|
|
67
|
+
* A discriminated union representing either a successful result or an error.
|
|
68
|
+
* Compatible with ts-pattern for exhaustive matching.
|
|
69
|
+
* Implements Yieldable protocol for use in Do computations with yield*.
|
|
70
|
+
*/
|
|
71
|
+
type Result<T, E> = Yieldable<T, E> & ({
|
|
72
|
+
readonly ok: true;
|
|
73
|
+
readonly value: T;
|
|
74
|
+
} | {
|
|
75
|
+
readonly ok: false;
|
|
76
|
+
readonly error: E;
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Compute the return type of `fromTry` based on whether fn returns a Promise.
|
|
80
|
+
* - If fn returns Promise<T>, result is Promise<Result<T, Error>>
|
|
81
|
+
* - If fn returns T, result is Result<T, Error>
|
|
82
|
+
*/
|
|
83
|
+
type FromTryReturn<T> = T extends Promise<infer U> ? Promise<Result<U, Error>> : Result<T, Error>;
|
|
84
|
+
/**
|
|
85
|
+
* Extract the success type from a Result.
|
|
86
|
+
* Uses structural matching to extract the value type from the ok branch.
|
|
87
|
+
*/
|
|
88
|
+
type ResultValue<R> = R extends {
|
|
89
|
+
readonly ok: true;
|
|
90
|
+
readonly value: infer T;
|
|
91
|
+
} ? T : never;
|
|
92
|
+
/**
|
|
93
|
+
* Extract the error type from a Result.
|
|
94
|
+
* Uses structural matching to extract the error type from the err branch.
|
|
95
|
+
*/
|
|
96
|
+
type ResultError<R> = R extends {
|
|
97
|
+
readonly ok: false;
|
|
98
|
+
readonly error: infer E;
|
|
99
|
+
} ? E : never;
|
|
100
|
+
/**
|
|
101
|
+
* Compute return type for `all` with array input.
|
|
102
|
+
* Preserves tuple structure and extracts value types from each position.
|
|
103
|
+
*/
|
|
104
|
+
type AllArrayReturn<T extends readonly Result<unknown, unknown>[]> = Result<{ -readonly [K in keyof T]: ResultValue<T[K]> }, ResultError<T[number]>>;
|
|
105
|
+
/**
|
|
106
|
+
* Compute return type for `all` with object input.
|
|
107
|
+
* Preserves object structure and extracts value types from each key.
|
|
108
|
+
*/
|
|
109
|
+
type AllObjectReturn<T extends Record<string, Result<unknown, unknown>>> = Result<{ -readonly [K in keyof T]: ResultValue<T[K]> }, ResultError<T[keyof T]>>;
|
|
110
|
+
/**
|
|
111
|
+
* Interface for flatMap - using method syntax improves generic inference in pipe chains.
|
|
112
|
+
* Note: Async overload must come first for proper overload resolution.
|
|
113
|
+
*/
|
|
114
|
+
type ResultFlatMap = {
|
|
115
|
+
<A, B, E2$1>(fn: (value: A) => Promise<Result<B, E2$1>>): <E>(result: Result<A, E>) => Promise<Result<B, E | E2$1>>;
|
|
116
|
+
<A, B, E2$1>(fn: (value: A) => Result<B, E2$1>): <E>(result: Result<A, E>) => Result<B, E | E2$1>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Interface for map function.
|
|
120
|
+
* Note: Async overload must come first for proper overload resolution.
|
|
121
|
+
*/
|
|
122
|
+
type ResultMap = {
|
|
123
|
+
<A, B>(fn: (value: A) => Promise<B>): <E>(result: Result<A, E>) => Promise<Result<B, E>>;
|
|
124
|
+
<A, B>(fn: (value: A) => B): <E>(result: Result<A, E>) => Result<B, E>;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Interface for mapErr function.
|
|
128
|
+
* Note: Async overload must come first for proper overload resolution.
|
|
129
|
+
*/
|
|
130
|
+
type ResultMapErr = {
|
|
131
|
+
<E1, E2$1>(fn: (error: E1) => Promise<E2$1>): <A>(result: Result<A, E1>) => Promise<Result<A, E2$1>>;
|
|
132
|
+
<E1, E2$1>(fn: (error: E1) => E2$1): <A>(result: Result<A, E1>) => Result<A, E2$1>;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Interface for tap function.
|
|
136
|
+
*/
|
|
137
|
+
type ResultTap = {
|
|
138
|
+
<A, R>(fn: (value: A) => R): <E>(result: Result<A, E>) => R extends Promise<unknown> ? Promise<Result<A, E>> : Result<A, E>;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Interface for orElse function.
|
|
142
|
+
* Note: Async overload must come first for proper overload resolution.
|
|
143
|
+
*/
|
|
144
|
+
type ResultOrElse = {
|
|
145
|
+
<E1, A2, E2$1>(fn: (error: E1) => Promise<Result<A2, E2$1>>): <A>(result: Result<A, E1>) => Promise<Result<A | A2, E2$1>>;
|
|
146
|
+
<E1, A2, E2$1>(fn: (error: E1) => Result<A2, E2$1>): <A>(result: Result<A, E1>) => Result<A | A2, E2$1>;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Interface for filter function.
|
|
150
|
+
*/
|
|
151
|
+
type ResultFilter = {
|
|
152
|
+
<A, E2$1>(predicate: (value: A) => boolean, onFail: (value: A) => E2$1): <E>(result: Result<A, E>) => Result<A, E | E2$1>;
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
export { YieldableError as _, ResultFilter as a, ResultMapErr as c, AsyncComputation as d, AsyncGenGenerator as f, Yieldable as g, SyncComputation as h, Result as i, ResultOrElse as l, GenGenerator as m, AllObjectReturn as n, ResultFlatMap as o, Computation as p, FromTryReturn as r, ResultMap as s, AllArrayReturn as t, ResultTap as u, YieldableValue as v };
|
|
156
|
+
//# sourceMappingURL=result.types-Ce7AEOzj.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.types-Ce7AEOzj.d.mts","names":[],"sources":["../src/gen/gen.types.ts","../src/result/result.types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-DpXkImo9.mjs","names":[],"sources":["../src/run/run.ts"],"sourcesContent":["import { gen } from \"../gen\"\nimport type { Result as ResultType } from \"../result/result.types\"\n\n/**\n * Convenience wrapper around Do() that executes the computation immediately\n * and returns the Result directly.\n *\n * Use this when you want inline execution without storing the computation.\n * For deferred execution, use Do() directly.\n *\n * @see {@link Do} for deferred/composable computations\n *\n * @example\n * ```typescript\n * // Sync computation\n * const result = run(function* () {\n * const a = yield* divide(10, 2)\n * const b = yield* divide(a, 2)\n * return b\n * }) // Result<number, \"DivisionByZero\">\n *\n * // Async computation\n * const user = await run(async function* () {\n * const data = yield* await fetchUser(1)\n * return data.name\n * }) // Promise<Result<string, \"NotFound\">>\n *\n * // Type accumulation\n * const result = run(function* () {\n * const a = yield* divide(10, 2) // \"DivisionByZero\"\n * const b = yield* findUser(a) // \"NotFound\"\n * return b.name\n * }) // Result<string, \"DivisionByZero\" | \"NotFound\">\n * ```\n */\n\n/**\n * Execute a sync generator computation immediately.\n *\n * @template A - The success value type\n * @template E - The error type (union of all yielded error types)\n * @param generatorFn - A function returning a sync generator\n * @returns Result<A, E> directly\n */\nexport function run<A, E>(generatorFn: () => Generator<E, A, unknown>): ResultType<A, E>\n\n/**\n * Execute an async generator computation immediately.\n *\n * @template A - The success value type\n * @template E - The error type (union of all yielded error types)\n * @param generatorFn - A function returning an async generator\n * @returns Promise<Result<A, E>>\n */\nexport function run<A, E>(generatorFn: () => AsyncGenerator<E, A, unknown>): Promise<ResultType<A, E>>\n// Implementation\n/* oxlint-disable no-explicit-any, no-unsafe-type-assertion, no-unsafe-return, no-unsafe-argument -- Required for overloaded function implementation */\nexport function run<A, E>(\n generatorFn: (() => Generator<E, A, unknown>) | (() => AsyncGenerator<E, A, unknown>),\n): ResultType<A, E> | Promise<ResultType<A, E>> {\n const computation = gen(generatorFn as any)\n return computation.run() as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-type-assertion, no-unsafe-return */\n"],"mappings":";;;AAyDA,SAAgB,IACd,aAC8C;AAE9C,QADoB,IAAI,YAAmB,CACxB,KAAK"}
|