@onrails/result 0.1.4 → 0.3.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 +11 -19
- package/README.md +14 -62
- package/RECIPES.md +12 -25
- package/dist/async-BR3AX0ck.d.cts +326 -0
- package/dist/async-SZ7BEl0g.d.ts +326 -0
- package/dist/compat/neverthrow.cjs +266 -94
- package/dist/compat/neverthrow.cjs.map +1 -1
- package/dist/compat/neverthrow.d.cts +4 -4
- package/dist/compat/neverthrow.d.ts +4 -4
- package/dist/compat/neverthrow.js +263 -91
- package/dist/compat/neverthrow.js.map +1 -1
- package/dist/extra.cjs +2 -25
- package/dist/extra.cjs.map +1 -1
- package/dist/extra.d.cts +7 -19
- package/dist/extra.d.ts +7 -19
- package/dist/extra.js +3 -25
- package/dist/extra.js.map +1 -1
- package/dist/fluent.cjs +55 -29
- package/dist/fluent.cjs.map +1 -1
- package/dist/fluent.d.cts +38 -11
- package/dist/fluent.d.ts +38 -11
- package/dist/fluent.js +55 -29
- package/dist/fluent.js.map +1 -1
- package/dist/index.cjs +290 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -69
- package/dist/index.d.ts +294 -69
- package/dist/index.js +287 -127
- package/dist/index.js.map +1 -1
- package/dist/pipe.cjs.map +1 -1
- package/dist/pipe.d.cts +7 -5
- package/dist/pipe.d.ts +7 -5
- package/dist/pipe.js.map +1 -1
- package/dist/railway.cjs +293 -188
- package/dist/railway.cjs.map +1 -1
- package/dist/railway.d.cts +26 -180
- package/dist/railway.d.ts +26 -180
- package/dist/railway.js +294 -178
- package/dist/railway.js.map +1 -1
- package/dist/try-gen.cjs +1 -1
- package/dist/try-gen.cjs.map +1 -1
- package/dist/try-gen.d.cts +29 -3
- package/dist/try-gen.d.ts +29 -3
- package/dist/try-gen.js +1 -1
- package/dist/try-gen.js.map +1 -1
- package/dist/types-BQ9vv0nD.d.cts +55 -0
- package/dist/types-BQ9vv0nD.d.ts +55 -0
- package/package.json +5 -18
- package/skills/railway-do-notation/SKILL.md +397 -0
- package/skills/result-composition/SKILL.md +323 -0
- package/dist/$.cjs +0 -40
- package/dist/$.cjs.map +0 -1
- package/dist/$.js +0 -36
- package/dist/$.js.map +0 -1
- package/dist/_.d.cts +0 -2
- package/dist/_.d.ts +0 -2
- package/dist/async-CH8Cs8KE.d.cts +0 -161
- package/dist/async-DKISqIBc.d.ts +0 -161
- package/dist/interop.cjs +0 -253
- package/dist/interop.cjs.map +0 -1
- package/dist/interop.d.cts +0 -35
- package/dist/interop.d.ts +0 -35
- package/dist/interop.js +0 -249
- package/dist/interop.js.map +0 -1
- package/dist/types-C2Dp1d5J.d.cts +0 -21
- package/dist/types-C2Dp1d5J.d.ts +0 -21
- package/dist/validation.cjs +0 -53
- package/dist/validation.cjs.map +0 -1
- package/dist/validation.d.cts +0 -72
- package/dist/validation.d.ts +0 -72
- package/dist/validation.js +0 -48
- package/dist/validation.js.map +0 -1
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
// src/internal/dual.ts
|
|
2
|
+
var dual = (arity, body) => {
|
|
3
|
+
const run = body;
|
|
4
|
+
const dispatcher = (...args) => args.length >= arity ? run(...args) : (self) => run(self, ...args);
|
|
5
|
+
return dispatcher;
|
|
6
|
+
};
|
|
7
|
+
|
|
1
8
|
// src/result.ts
|
|
2
9
|
var ok = (value) => ({
|
|
3
10
|
_tag: "Ok",
|
|
@@ -9,25 +16,22 @@ var err = (error) => ({
|
|
|
9
16
|
});
|
|
10
17
|
var isOk = (result) => result._tag === "Ok";
|
|
11
18
|
var isErr = (result) => result._tag === "Err";
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return (result) => flatMapImpl(result, fn);
|
|
29
|
-
}
|
|
30
|
-
var unwrapOr = (result, defaultValue) => isOk(result) ? result.value : defaultValue;
|
|
19
|
+
var map = dual(
|
|
20
|
+
2,
|
|
21
|
+
(result, fn) => isOk(result) ? ok(fn(result.value)) : err(result.error)
|
|
22
|
+
);
|
|
23
|
+
var mapErr = dual(
|
|
24
|
+
2,
|
|
25
|
+
(result, fn) => isErr(result) ? err(fn(result.error)) : ok(result.value)
|
|
26
|
+
);
|
|
27
|
+
var flatMap = dual(
|
|
28
|
+
2,
|
|
29
|
+
(result, fn) => isOk(result) ? fn(result.value) : err(result.error)
|
|
30
|
+
);
|
|
31
|
+
var unwrapOr = dual(
|
|
32
|
+
2,
|
|
33
|
+
(result, defaultValue) => isOk(result) ? result.value : defaultValue
|
|
34
|
+
);
|
|
31
35
|
function trySync(fn, onThrow) {
|
|
32
36
|
return (...args) => {
|
|
33
37
|
try {
|
|
@@ -37,18 +41,6 @@ function trySync(fn, onThrow) {
|
|
|
37
41
|
}
|
|
38
42
|
};
|
|
39
43
|
}
|
|
40
|
-
var combine = (results) => {
|
|
41
|
-
const values = [];
|
|
42
|
-
for (const result of results) {
|
|
43
|
-
if (isErr(result)) return err(result.error);
|
|
44
|
-
values.push(result.value);
|
|
45
|
-
}
|
|
46
|
-
return ok(values);
|
|
47
|
-
};
|
|
48
|
-
var combineTuple = (results) => (
|
|
49
|
-
// Runtime identical to combine; the cast restores per-index tuple types.
|
|
50
|
-
combine(results)
|
|
51
|
-
);
|
|
52
44
|
|
|
53
45
|
// src/types.ts
|
|
54
46
|
var UnexpectedError = class extends Error {
|
|
@@ -61,17 +53,6 @@ var UnexpectedError = class extends Error {
|
|
|
61
53
|
};
|
|
62
54
|
|
|
63
55
|
// src/async.ts
|
|
64
|
-
var liftPromiseResult = async (promise, onDefect) => {
|
|
65
|
-
try {
|
|
66
|
-
const result = await promise;
|
|
67
|
-
if (isErr(result)) {
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
return isResultLike(result.value) ? result.value : result;
|
|
71
|
-
} catch (error) {
|
|
72
|
-
return err(onDefect(error));
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
56
|
var sequenceSettled = (settled) => {
|
|
76
57
|
const values = [];
|
|
77
58
|
for (const result of settled) {
|
|
@@ -88,9 +69,32 @@ var ResultAsync = class _ResultAsync {
|
|
|
88
69
|
}
|
|
89
70
|
run;
|
|
90
71
|
promise = null;
|
|
72
|
+
/**
|
|
73
|
+
* Lifts an already-settled sync {@link Result} into a {@link ResultAsync}.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* const ra = ResultAsync.fromResult(ok(42)); // ResultAsync<number, never>
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
91
80
|
static fromResult(result) {
|
|
92
81
|
return new _ResultAsync(async () => result);
|
|
93
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Wraps a `PromiseLike<T>` that may reject. Rejections pass through `onReject`
|
|
85
|
+
* to become a typed `Err`; resolution becomes `Ok<T>`.
|
|
86
|
+
*
|
|
87
|
+
* @param promise - the promise to wrap
|
|
88
|
+
* @param onReject - maps a rejection reason to the `Err` channel
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const body = ResultAsync.fromPromise(
|
|
93
|
+
* fetch(url).then((r) => r.text()),
|
|
94
|
+
* (e): NetError => ({ kind: "net", cause: String(e) }),
|
|
95
|
+
* );
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
94
98
|
static fromPromise(promise, onReject) {
|
|
95
99
|
return new _ResultAsync(async () => {
|
|
96
100
|
try {
|
|
@@ -100,12 +104,29 @@ var ResultAsync = class _ResultAsync {
|
|
|
100
104
|
}
|
|
101
105
|
});
|
|
102
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Wraps a `PromiseLike<T>` that is **guaranteed not to reject**, skipping the
|
|
109
|
+
* `onReject` mapper. Use only when rejection is provably impossible.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* const now = ResultAsync.fromSafePromise(Promise.resolve(Date.now()));
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
103
116
|
static fromSafePromise(promise) {
|
|
104
117
|
return new _ResultAsync(async () => ok(await promise));
|
|
105
118
|
}
|
|
106
119
|
/**
|
|
107
|
-
* Defers work until {@link resolve}. Unlike {@link fromPromise},
|
|
108
|
-
* until the `ResultAsync` is resolved (e.g. by `combineTuple` /
|
|
120
|
+
* Defers work until {@link resolve}. Unlike {@link fromPromise}, the factory
|
|
121
|
+
* does not run until the `ResultAsync` is resolved (e.g. by `combineTuple` /
|
|
122
|
+
* `combineTupleParallel`). The factory runs at most once — `resolve` memoizes.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const insert = ResultAsync.defer(() => db.orders.insert(row));
|
|
127
|
+
* // nothing has run yet
|
|
128
|
+
* const r = await insert; // factory runs exactly once here
|
|
129
|
+
* ```
|
|
109
130
|
*/
|
|
110
131
|
static defer(fn) {
|
|
111
132
|
return new _ResultAsync(fn);
|
|
@@ -113,14 +134,49 @@ var ResultAsync = class _ResultAsync {
|
|
|
113
134
|
static ok(value) {
|
|
114
135
|
return new _ResultAsync(async () => ok(value));
|
|
115
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Lifts an error into an `Err` async result.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const r = ResultAsync.err({ kind: "not_found" as const });
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
116
145
|
static err(error) {
|
|
117
146
|
return new _ResultAsync(async () => err(error));
|
|
118
147
|
}
|
|
119
|
-
/**
|
|
148
|
+
/**
|
|
149
|
+
* Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a
|
|
150
|
+
* {@link ResultAsync}. A thrown defect is routed through `onDefect`,
|
|
151
|
+
* defaulting to {@link UnexpectedError}. The `Ok` value passes through
|
|
152
|
+
* verbatim — even when it happens to be Result-shaped.
|
|
153
|
+
*
|
|
154
|
+
* @param promise - a promise that already yields a `Result`
|
|
155
|
+
* @param onDefect - maps an unexpected throw to the `Err` channel
|
|
156
|
+
* @see {@link fromAsync} from `@onrails/result`
|
|
157
|
+
*/
|
|
120
158
|
static fromResultPromise(promise, onDefect) {
|
|
121
159
|
const mapDefect = onDefect ?? ((error) => new UnexpectedError("Unexpected async defect", error));
|
|
122
|
-
return new _ResultAsync(() =>
|
|
160
|
+
return new _ResultAsync(async () => {
|
|
161
|
+
try {
|
|
162
|
+
return await promise;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return err(mapDefect(error));
|
|
165
|
+
}
|
|
166
|
+
});
|
|
123
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Combines a homogeneous array of async results into one. Resolves
|
|
170
|
+
* **sequentially** in input order, short-circuiting on the first `Err`.
|
|
171
|
+
* For heterogeneous tuples that preserve per-index types, use
|
|
172
|
+
* {@link combineTuple}; for wall-clock overlap, {@link combineTupleParallel}.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* const all = ResultAsync.combine([loadA(), loadB(), loadC()]);
|
|
177
|
+
* // ResultAsync<Item[], LoadError>
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
124
180
|
static combine(results) {
|
|
125
181
|
return new _ResultAsync(async () => {
|
|
126
182
|
const values = [];
|
|
@@ -134,6 +190,23 @@ var ResultAsync = class _ResultAsync {
|
|
|
134
190
|
return ok(values);
|
|
135
191
|
});
|
|
136
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Heterogeneous async tuple combine — resolves branches **sequentially**
|
|
195
|
+
* (left-to-right), returning the first `Err` in input order. Preserves each
|
|
196
|
+
* branch's `Ok` type by position, so the result destructures type-safely.
|
|
197
|
+
* This is the canonical sequential async combine (replaces the former
|
|
198
|
+
* `sequenceTupleAsync`).
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()] as const);
|
|
203
|
+
* // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>
|
|
204
|
+
* const r = await combined;
|
|
205
|
+
* if (isOk(r)) {
|
|
206
|
+
* const [cfg, catalog] = r.value; // typed per position
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
137
210
|
static combineTuple(results) {
|
|
138
211
|
return _ResultAsync.combine(
|
|
139
212
|
results
|
|
@@ -142,18 +215,55 @@ var ResultAsync = class _ResultAsync {
|
|
|
142
215
|
/**
|
|
143
216
|
* Like {@link combineTuple}, but starts every branch before awaiting (wall-clock
|
|
144
217
|
* parallel for independent IO). On failure, returns the first `Err` in input order.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* // independent IO — overlap them
|
|
222
|
+
* const combined = ResultAsync.combineTupleParallel([
|
|
223
|
+
* loadProfile(id),
|
|
224
|
+
* loadMetrics(id),
|
|
225
|
+
* ] as const);
|
|
226
|
+
* ```
|
|
145
227
|
*/
|
|
146
228
|
static combineTupleParallel(results) {
|
|
147
229
|
return new _ResultAsync(
|
|
148
230
|
async () => sequenceSettled(await Promise.all(results.map((ra) => ra.resolve())))
|
|
149
231
|
);
|
|
150
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Transforms the `Ok` value, passing `Err` through unchanged.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* ResultAsync.ok(2).map((n) => n * 3); // ResultAsync<number> → Ok 6
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
151
241
|
map(fn) {
|
|
152
242
|
return new _ResultAsync(async () => map(await this.resolve(), fn));
|
|
153
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Transforms the `Err` value, passing `Ok` through unchanged — useful for
|
|
246
|
+
* unifying heterogeneous failures into one app-level union.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* load(id).mapErr((e): AppError => ({ kind: "load", cause: e })); // ResultAsync<T, AppError>
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
154
253
|
mapErr(fn) {
|
|
155
254
|
return new _ResultAsync(async () => mapErr(await this.resolve(), fn));
|
|
156
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Canonical bind — chains a step that itself returns a `ResultAsync` or sync
|
|
258
|
+
* `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* authenticate(req)
|
|
263
|
+
* .flatMap((user) => loadProfile(user.id)) // ResultAsync
|
|
264
|
+
* .flatMap((p) => validate(p)); // sync Result also accepted
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
157
267
|
flatMap(fn) {
|
|
158
268
|
return new _ResultAsync(async () => {
|
|
159
269
|
const first = await this.resolve();
|
|
@@ -161,25 +271,31 @@ var ResultAsync = class _ResultAsync {
|
|
|
161
271
|
return first;
|
|
162
272
|
}
|
|
163
273
|
const next = fn(first.value);
|
|
164
|
-
|
|
165
|
-
return next.resolve();
|
|
166
|
-
}
|
|
167
|
-
if (isResultLike(next)) {
|
|
168
|
-
return next;
|
|
169
|
-
}
|
|
170
|
-
return isCompatLike(next) ? next.inner : next;
|
|
274
|
+
return next instanceof _ResultAsync ? next.resolve() : next;
|
|
171
275
|
});
|
|
172
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* neverthrow-compat alias of {@link flatMap}. Kept as the documented compat
|
|
279
|
+
* tier; prefer {@link flatMap} in new code.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* authenticate(req).andThen((user) => loadProfile(user.id));
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
173
286
|
andThen(fn) {
|
|
174
287
|
return this.flatMap(fn);
|
|
175
288
|
}
|
|
176
289
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
290
|
+
* Error-channel bind — runs `fn` only on `Err`, swapping in a recovery
|
|
291
|
+
* `ResultAsync` or sync `Result`. `Ok` passes through. The mirror of
|
|
292
|
+
* {@link flatMap} on the error track.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```ts
|
|
296
|
+
* loadFromCache(id).recover(() => loadFromOrigin(id)); // ResultAsync<T, F>
|
|
297
|
+
* ```
|
|
179
298
|
*/
|
|
180
|
-
chain(fn) {
|
|
181
|
-
return this.flatMap(fn);
|
|
182
|
-
}
|
|
183
299
|
recover(fn) {
|
|
184
300
|
return new _ResultAsync(async () => {
|
|
185
301
|
const first = await this.resolve();
|
|
@@ -190,9 +306,27 @@ var ResultAsync = class _ResultAsync {
|
|
|
190
306
|
return next instanceof _ResultAsync ? next.resolve() : next;
|
|
191
307
|
});
|
|
192
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* neverthrow-compat alias of {@link recover}. Kept as the documented compat
|
|
311
|
+
* tier; prefer {@link recover} in new code.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* loadFromCache(id).orElse(() => loadFromOrigin(id));
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
193
318
|
orElse(fn) {
|
|
194
319
|
return this.recover(fn);
|
|
195
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Runs a side effect on the `Ok` value and passes the result through
|
|
323
|
+
* unchanged; a no-op on `Err`. Mirrors {@link tapErr}.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* saveUser(u).tap((saved) => analytics.track("user_saved", saved.id));
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
196
330
|
tap(fn) {
|
|
197
331
|
return new _ResultAsync(async () => {
|
|
198
332
|
const result = await this.resolve();
|
|
@@ -202,6 +336,15 @@ var ResultAsync = class _ResultAsync {
|
|
|
202
336
|
return result;
|
|
203
337
|
});
|
|
204
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Runs a side effect on the `Err` value and passes the result through
|
|
341
|
+
* unchanged; a no-op on `Ok`. The error-track mirror of {@link tap}.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* saveUser(u).tapErr((e) => logger.warn("save failed", e));
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
205
348
|
tapErr(fn) {
|
|
206
349
|
return new _ResultAsync(async () => {
|
|
207
350
|
const result = await this.resolve();
|
|
@@ -211,28 +354,49 @@ var ResultAsync = class _ResultAsync {
|
|
|
211
354
|
return result;
|
|
212
355
|
});
|
|
213
356
|
}
|
|
214
|
-
unwrapOr(defaultValue) {
|
|
215
|
-
return this.resolve().then((result) => isErr(result) ? defaultValue : result.value);
|
|
216
|
-
}
|
|
217
357
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
358
|
+
* Settles to the `Ok` value, or `defaultValue` if `Err`. Terminal — returns a
|
|
359
|
+
* plain `Promise`, not a `ResultAsync`.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* const profile = await loadProfile(id).unwrapOr(guestProfile);
|
|
364
|
+
* ```
|
|
220
365
|
*/
|
|
221
|
-
|
|
222
|
-
return this.resolve().then((result) =>
|
|
366
|
+
unwrapOr(defaultValue) {
|
|
367
|
+
return this.resolve().then((result) => isErr(result) ? defaultValue : result.value);
|
|
223
368
|
}
|
|
224
369
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
370
|
+
* Terminal collapse — folds both tracks into a single awaited value. Returns
|
|
371
|
+
* a plain `Promise`, settling the carrier exactly once.
|
|
372
|
+
*
|
|
373
|
+
* @param onOk - handles the `Ok` value
|
|
374
|
+
* @param onErr - handles the `Err` value
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```ts
|
|
378
|
+
* const status = await save(row).match(
|
|
379
|
+
* () => 200,
|
|
380
|
+
* (e) => (e.kind === "conflict" ? 409 : 500),
|
|
381
|
+
* );
|
|
382
|
+
* ```
|
|
227
383
|
*/
|
|
228
|
-
isErr() {
|
|
229
|
-
return this.resolve().then((result) => isErr(result));
|
|
230
|
-
}
|
|
231
384
|
match(onOk, onErr) {
|
|
232
385
|
return this.resolve().then(
|
|
233
386
|
(result) => isErr(result) ? onErr(result.error) : onOk(result.value)
|
|
234
387
|
);
|
|
235
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Settles the carrier to a bare sync {@link Result}, memoizing so the
|
|
391
|
+
* underlying factory runs at most once. Prefer `await ra` (the thenable) or
|
|
392
|
+
* {@link match} in app code; use `resolve` when you need the tagged union back.
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```ts
|
|
396
|
+
* const r = await load(id).resolve(); // Result<Data, LoadError>
|
|
397
|
+
* if (isOk(r)) use(r.value);
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
236
400
|
resolve() {
|
|
237
401
|
if (!this.promise) {
|
|
238
402
|
this.promise = this.run();
|
|
@@ -252,12 +416,20 @@ var ResultAsync = class _ResultAsync {
|
|
|
252
416
|
);
|
|
253
417
|
}
|
|
254
418
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
419
|
+
|
|
420
|
+
// src/collections.ts
|
|
421
|
+
var combine = (results) => {
|
|
422
|
+
const values = [];
|
|
423
|
+
for (const result of results) {
|
|
424
|
+
if (isErr(result)) return err(result.error);
|
|
425
|
+
values.push(result.value);
|
|
426
|
+
}
|
|
427
|
+
return ok(values);
|
|
428
|
+
};
|
|
429
|
+
var combineTuple = (results) => (
|
|
430
|
+
// Runtime identical to combine; the cast restores per-index tuple types.
|
|
431
|
+
combine(results)
|
|
432
|
+
);
|
|
261
433
|
|
|
262
434
|
// src/compat/neverthrow.ts
|
|
263
435
|
var CompatResult = class _CompatResult {
|
|
@@ -296,16 +468,10 @@ var CompatResult = class _CompatResult {
|
|
|
296
468
|
return new _CompatResult(flatMap(this.inner, (value) => fn(value).inner));
|
|
297
469
|
}
|
|
298
470
|
asyncAndThen(fn) {
|
|
299
|
-
|
|
300
|
-
return CompatResultAsync.err(this.inner.error);
|
|
301
|
-
}
|
|
302
|
-
return CompatResultAsync.fromInner(coerceToCoreAsync(fn(this.inner.value)));
|
|
471
|
+
return isErr(this.inner) ? CompatResultAsync.err(this.inner.error) : CompatResultAsync.fromInner(coerceToCoreAsync(fn(this.inner.value)));
|
|
303
472
|
}
|
|
304
473
|
orElse(fn) {
|
|
305
|
-
|
|
306
|
-
return new _CompatResult(this.inner);
|
|
307
|
-
}
|
|
308
|
-
return fn(this.inner.error);
|
|
474
|
+
return isOk(this.inner) ? new _CompatResult(this.inner) : fn(this.inner.error);
|
|
309
475
|
}
|
|
310
476
|
match(onOk, onErr) {
|
|
311
477
|
return isOk(this.inner) ? onOk(this.inner.value) : onErr(this.inner.error);
|
|
@@ -396,10 +562,16 @@ var CompatResultAsync = class _CompatResultAsync {
|
|
|
396
562
|
return this.inner.unwrapOr(defaultValue);
|
|
397
563
|
}
|
|
398
564
|
isOk() {
|
|
399
|
-
return this.inner.
|
|
565
|
+
return this.inner.match(
|
|
566
|
+
() => true,
|
|
567
|
+
() => false
|
|
568
|
+
);
|
|
400
569
|
}
|
|
401
570
|
isErr() {
|
|
402
|
-
return this.inner.
|
|
571
|
+
return this.inner.match(
|
|
572
|
+
() => false,
|
|
573
|
+
() => true
|
|
574
|
+
);
|
|
403
575
|
}
|
|
404
576
|
match(onOk, onErr) {
|
|
405
577
|
return this.inner.match(onOk, onErr);
|
|
@@ -440,11 +612,11 @@ function coerceToCore(next) {
|
|
|
440
612
|
return next;
|
|
441
613
|
}
|
|
442
614
|
var coerceToCoreAsync = (next) => next instanceof CompatResultAsync ? next.toCore() : next;
|
|
443
|
-
var
|
|
444
|
-
var
|
|
445
|
-
var
|
|
446
|
-
var
|
|
615
|
+
var okAsync = CompatResultAsync.ok;
|
|
616
|
+
var errAsync = CompatResultAsync.err;
|
|
617
|
+
var fromPromise = CompatResultAsync.fromPromise;
|
|
618
|
+
var fromSafePromise = CompatResultAsync.fromSafePromise;
|
|
447
619
|
|
|
448
|
-
export { CompatResult, CompatResultAsync, Result, CompatResultAsync as ResultAsync, err2 as err,
|
|
620
|
+
export { CompatResult, CompatResultAsync, Result, CompatResultAsync as ResultAsync, err2 as err, errAsync, fromPromise, fromSafePromise, ok2 as ok, okAsync };
|
|
449
621
|
//# sourceMappingURL=neverthrow.js.map
|
|
450
622
|
//# sourceMappingURL=neverthrow.js.map
|