@shirudo/result 0.0.1 → 0.0.3
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 +99 -1
- package/dist/index.cjs +487 -942
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +390 -807
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +390 -807
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +485 -942
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -10
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/pipeable.ts
|
|
1
|
+
//#region src/core/pipeable.ts
|
|
2
2
|
var Pipeable = class {
|
|
3
3
|
pipe(...ops) {
|
|
4
4
|
let ret = this;
|
|
@@ -13,19 +13,13 @@ var Pipeable = class {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
//#endregion
|
|
16
|
-
//#region src/
|
|
17
|
-
function isResult(value) {
|
|
18
|
-
return typeof value === "object" && value !== null && "isOk" in value && typeof value.isOk === "function" && "isErr" in value && typeof value.isErr === "function";
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/matcher.ts
|
|
16
|
+
//#region src/core/matcher.ts
|
|
23
17
|
/**
|
|
24
|
-
* Matcher
|
|
18
|
+
* Matcher für Err-Values (liefert einen beliebigen Return-Type, z.B. string messages).
|
|
25
19
|
*
|
|
26
20
|
* - `.when(Ctor, handler)` matched via `instanceof`
|
|
27
|
-
* - `.whenGuard(guard, handler)` matched via
|
|
28
|
-
* - `.run()`
|
|
21
|
+
* - `.whenGuard(guard, handler)` matched via Type-Guard
|
|
22
|
+
* - `.run()` ist nur erlaubt, wenn alle Error-Cases behandelt wurden (`E` wurde zu `never` reduziert)
|
|
29
23
|
*/
|
|
30
24
|
var ErrorMatchBuilder = class ErrorMatchBuilder {
|
|
31
25
|
#error;
|
|
@@ -57,12 +51,15 @@ var ErrorMatchBuilder = class ErrorMatchBuilder {
|
|
|
57
51
|
throw this.#error;
|
|
58
52
|
}
|
|
59
53
|
};
|
|
54
|
+
function isResult$1(value) {
|
|
55
|
+
return typeof value === "object" && value !== null && "isOk" in value && typeof value.isOk === "function" && "isErr" in value && typeof value.isErr === "function";
|
|
56
|
+
}
|
|
60
57
|
/**
|
|
61
|
-
* Matcher
|
|
58
|
+
* Matcher für `Result`-Errors, der immer wieder ein `Result` zurückgibt.
|
|
62
59
|
*
|
|
63
|
-
*
|
|
64
|
-
* -
|
|
65
|
-
* -
|
|
60
|
+
* Handler dürfen:
|
|
61
|
+
* - ein `Result` zurückgeben (wird direkt returned)
|
|
62
|
+
* - einen Error-Wert zurückgeben (wird automatisch zu `Err(error)` gewrappt)
|
|
66
63
|
*/
|
|
67
64
|
var ErrMatchBuilder = class ErrMatchBuilder {
|
|
68
65
|
#makeErr;
|
|
@@ -83,7 +80,7 @@ var ErrMatchBuilder = class ErrMatchBuilder {
|
|
|
83
80
|
if (this.#resolved) return this;
|
|
84
81
|
if (this.#error instanceof ctor) {
|
|
85
82
|
const out = handler(this.#error);
|
|
86
|
-
const resolved = isResult(out) ? out : this.#makeErr(out);
|
|
83
|
+
const resolved = isResult$1(out) ? out : this.#makeErr(out);
|
|
87
84
|
return new ErrMatchBuilder(this.#makeErr, this.#error, resolved);
|
|
88
85
|
}
|
|
89
86
|
return this;
|
|
@@ -93,7 +90,7 @@ var ErrMatchBuilder = class ErrMatchBuilder {
|
|
|
93
90
|
const error = this.#error;
|
|
94
91
|
if (guard(error)) {
|
|
95
92
|
const out = handler(error);
|
|
96
|
-
const resolved = isResult(out) ? out : this.#makeErr(out);
|
|
93
|
+
const resolved = isResult$1(out) ? out : this.#makeErr(out);
|
|
97
94
|
return new ErrMatchBuilder(this.#makeErr, this.#error, resolved);
|
|
98
95
|
}
|
|
99
96
|
return this;
|
|
@@ -101,688 +98,19 @@ var ErrMatchBuilder = class ErrMatchBuilder {
|
|
|
101
98
|
otherwise(handler) {
|
|
102
99
|
if (this.#resolved) return this.#resolved;
|
|
103
100
|
const out = handler(this.#error);
|
|
104
|
-
return isResult(out) ? out : this.#makeErr(out);
|
|
101
|
+
return isResult$1(out) ? out : this.#makeErr(out);
|
|
105
102
|
}
|
|
106
103
|
run() {
|
|
107
104
|
if (this.#resolved) return this.#resolved;
|
|
108
105
|
throw this.#error;
|
|
109
106
|
}
|
|
110
107
|
};
|
|
111
|
-
/**
|
|
112
|
-
* Universal matcher for `Result` (Ok + Err in a single chain).
|
|
113
|
-
*
|
|
114
|
-
* - `.err(Ctor, handler)` matched via `instanceof`
|
|
115
|
-
* - `.errVal(value, handler)` matched via `Object.is`
|
|
116
|
-
* - `.ok(handler)` defines the success branch
|
|
117
|
-
* - `.run()` is only allowed after `.ok()` is set
|
|
118
|
-
*
|
|
119
|
-
* Lazy: if the Result is `Ok`, Err cases are not evaluated in `.run()`.
|
|
120
|
-
*/
|
|
121
|
-
var ResultMatchBuilder = class ResultMatchBuilder {
|
|
122
|
-
#result;
|
|
123
|
-
#errCases;
|
|
124
|
-
#okHandler;
|
|
125
|
-
constructor(result, errCases = [], okHandler) {
|
|
126
|
-
this.#result = result;
|
|
127
|
-
this.#errCases = Object.freeze([...errCases]);
|
|
128
|
-
this.#okHandler = okHandler;
|
|
129
|
-
Object.freeze(this);
|
|
130
|
-
}
|
|
131
|
-
static fromResult(result) {
|
|
132
|
-
return new ResultMatchBuilder(result);
|
|
133
|
-
}
|
|
134
|
-
err(ctor, handler) {
|
|
135
|
-
return new ResultMatchBuilder(this.#result, [...this.#errCases, {
|
|
136
|
-
kind: "ctor",
|
|
137
|
-
ctor,
|
|
138
|
-
handler
|
|
139
|
-
}], this.#okHandler);
|
|
140
|
-
}
|
|
141
|
-
errVal(value, handler) {
|
|
142
|
-
return new ResultMatchBuilder(this.#result, [...this.#errCases, {
|
|
143
|
-
kind: "val",
|
|
144
|
-
value,
|
|
145
|
-
handler
|
|
146
|
-
}], this.#okHandler);
|
|
147
|
-
}
|
|
148
|
-
ok(handler) {
|
|
149
|
-
return new ResultMatchBuilder(this.#result, this.#errCases, handler);
|
|
150
|
-
}
|
|
151
|
-
run() {
|
|
152
|
-
const result = this.#result;
|
|
153
|
-
if (result.isOk()) {
|
|
154
|
-
const okHandler = this.#okHandler;
|
|
155
|
-
if (!okHandler) throw new Error("ResultMatchBuilder.run() requires an ok() handler.");
|
|
156
|
-
return okHandler(result.value);
|
|
157
|
-
}
|
|
158
|
-
if (result.isErr()) {
|
|
159
|
-
const error = result.error;
|
|
160
|
-
for (const c of this.#errCases) {
|
|
161
|
-
if (c.kind === "ctor") {
|
|
162
|
-
if (error instanceof c.ctor) return c.handler(error);
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
if (Object.is(error, c.value)) return c.handler(error);
|
|
166
|
-
}
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
//#endregion
|
|
174
|
-
//#region src/conversions/fromNullable.ts
|
|
175
|
-
/**
|
|
176
|
-
* Converts `null | undefined` to `Err`, everything else to `Ok`.
|
|
177
|
-
*
|
|
178
|
-
* **Type Safety**: The type assertion `as NonNullable<T>` is safe,
|
|
179
|
-
* as the runtime check guarantees that the value is not null/undefined.
|
|
180
|
-
*
|
|
181
|
-
* @param value The value to check
|
|
182
|
-
* @param error The error to use if value is null/undefined
|
|
183
|
-
* @returns An Ok Result with the NonNullable value, or an Err Result with the error
|
|
184
|
-
*
|
|
185
|
-
* @example
|
|
186
|
-
* ```ts
|
|
187
|
-
* fromNullable(user, 'User not found')
|
|
188
|
-
* // Ok(user) or Err('User not found')
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
function fromNullable(value, error) {
|
|
192
|
-
if (value === null || value === void 0) return Result.err(error);
|
|
193
|
-
return Result.ok(value);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
//#endregion
|
|
197
|
-
//#region src/conversions/fromPromise.ts
|
|
198
|
-
async function fromPromise(promise, errorMapper) {
|
|
199
|
-
try {
|
|
200
|
-
const value = await promise;
|
|
201
|
-
return Result.ok(value);
|
|
202
|
-
} catch (error) {
|
|
203
|
-
try {
|
|
204
|
-
return Result.err(errorMapper ? errorMapper(error) : error);
|
|
205
|
-
} catch (mapperError) {
|
|
206
|
-
return Result.err(mapperError);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
//#endregion
|
|
212
|
-
//#region src/conversions/try.ts
|
|
213
|
-
/**
|
|
214
|
-
* Executes a function and catches exceptions.
|
|
215
|
-
*
|
|
216
|
-
* @param fn The function to execute
|
|
217
|
-
* @returns An Ok Result with the return value, or an Err Result with the caught exception
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* ```ts
|
|
221
|
-
* const result = tryFn(() => JSON.parse(input));
|
|
222
|
-
* // Ok(parsed) or Err(SyntaxError)
|
|
223
|
-
* ```
|
|
224
|
-
*/
|
|
225
|
-
function tryFn(fn) {
|
|
226
|
-
try {
|
|
227
|
-
return Result.ok(fn());
|
|
228
|
-
} catch (error) {
|
|
229
|
-
return Result.err(error);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
//#endregion
|
|
234
|
-
//#region src/conversions/toPromise.ts
|
|
235
|
-
/**
|
|
236
|
-
* Converts a Result to a Promise.
|
|
237
|
-
* Ok → resolves with the value, Err → rejects with the error
|
|
238
|
-
*
|
|
239
|
-
* @param result The Result to convert
|
|
240
|
-
* @returns A Promise that resolves with the value if Ok, or rejects with the error if Err
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* ```ts
|
|
244
|
-
* const result = ok(42);
|
|
245
|
-
* const promise = toPromise(result);
|
|
246
|
-
* const value = await promise; // 42
|
|
247
|
-
* ```
|
|
248
|
-
*/
|
|
249
|
-
function toPromise(result) {
|
|
250
|
-
if (result.isOk()) return Promise.resolve(result.value);
|
|
251
|
-
return Promise.reject(result.error);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
//#endregion
|
|
255
|
-
//#region src/conversions/toNullable.ts
|
|
256
|
-
/**
|
|
257
|
-
* Converts a Result to `T | null`.
|
|
258
|
-
* Ok → returns the value, Err → returns null
|
|
259
|
-
*
|
|
260
|
-
* @param result The Result to convert
|
|
261
|
-
* @returns The value if Ok, or null if Err
|
|
262
|
-
*
|
|
263
|
-
* @example
|
|
264
|
-
* ```ts
|
|
265
|
-
* const result = ok(42);
|
|
266
|
-
* const value = toNullable(result); // 42
|
|
267
|
-
*
|
|
268
|
-
* const errResult = err('error');
|
|
269
|
-
* const nullValue = toNullable(errResult); // null
|
|
270
|
-
* ```
|
|
271
|
-
*/
|
|
272
|
-
function toNullable(result) {
|
|
273
|
-
if (result.isOk()) return result.value;
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
//#endregion
|
|
278
|
-
//#region src/result.ts
|
|
279
|
-
var Result = class Result extends Pipeable {
|
|
280
|
-
#state;
|
|
281
|
-
constructor(state) {
|
|
282
|
-
super();
|
|
283
|
-
Object.freeze(state);
|
|
284
|
-
this.#state = state;
|
|
285
|
-
Object.freeze(this);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Creates an Ok Result with the given value.
|
|
289
|
-
*
|
|
290
|
-
* **Note**: `null` and `undefined` are allowed as values.
|
|
291
|
-
* If you want to convert `null`/`undefined` to an Err, use `fromNullable()`.
|
|
292
|
-
*
|
|
293
|
-
* @param value The value for the Ok Result
|
|
294
|
-
* @returns An Ok Result with the given value
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* ```ts
|
|
298
|
-
* const result = Result.ok(42);
|
|
299
|
-
* const nullResult = Result.ok(null); // Allowed!
|
|
300
|
-
* ```
|
|
301
|
-
*/
|
|
302
|
-
static ok(value) {
|
|
303
|
-
return new Result({
|
|
304
|
-
_tag: "Ok",
|
|
305
|
-
value
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Creates an Err Result with the given error.
|
|
310
|
-
*
|
|
311
|
-
* **Note**: `null` and `undefined` are allowed as errors.
|
|
312
|
-
*
|
|
313
|
-
* @param error The error for the Err Result
|
|
314
|
-
* @returns An Err Result with the given error
|
|
315
|
-
*
|
|
316
|
-
* @example
|
|
317
|
-
* ```ts
|
|
318
|
-
* const result = Result.err('error message');
|
|
319
|
-
* const nullError = Result.err(null); // Allowed!
|
|
320
|
-
* ```
|
|
321
|
-
*/
|
|
322
|
-
static err(error) {
|
|
323
|
-
return new Result({
|
|
324
|
-
_tag: "Err",
|
|
325
|
-
error
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Converts `null | undefined` to `Err`, everything else to `Ok`.
|
|
330
|
-
*
|
|
331
|
-
* **Type Safety**: The type assertion `as NonNullable<T>` is safe,
|
|
332
|
-
* as the runtime check guarantees that the value is not null/undefined.
|
|
333
|
-
*
|
|
334
|
-
* @param value The value to check
|
|
335
|
-
* @param error The error to use if value is null/undefined
|
|
336
|
-
* @returns An Ok Result with the NonNullable value, or an Err Result with the error
|
|
337
|
-
*
|
|
338
|
-
* @example
|
|
339
|
-
* ```ts
|
|
340
|
-
* Result.fromNullable(user, 'User not found')
|
|
341
|
-
* // Ok(user) or Err('User not found')
|
|
342
|
-
* ```
|
|
343
|
-
*/
|
|
344
|
-
static fromNullable(value, error) {
|
|
345
|
-
return fromNullable(value, error);
|
|
346
|
-
}
|
|
347
|
-
static fromPromise(promise, errorMapper) {
|
|
348
|
-
return fromPromise(promise, errorMapper);
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Executes a function and catches exceptions.
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* ```ts
|
|
355
|
-
* const result = Result.try(() => JSON.parse(input));
|
|
356
|
-
* // Ok(parsed) or Err(SyntaxError)
|
|
357
|
-
* ```
|
|
358
|
-
*/
|
|
359
|
-
static try(fn) {
|
|
360
|
-
return tryFn(fn);
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* Checks if the Result is Ok.
|
|
364
|
-
*
|
|
365
|
-
* @returns `true` if the Result is Ok (and narrows the type)
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* ```ts
|
|
369
|
-
* if (result.isOk()) {
|
|
370
|
-
* const value: T = result.value; // TypeScript knows that value is defined
|
|
371
|
-
* }
|
|
372
|
-
* ```
|
|
373
|
-
*/
|
|
374
|
-
isOk() {
|
|
375
|
-
return this.#state._tag === "Ok";
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Checks if the Result is Err.
|
|
379
|
-
*
|
|
380
|
-
* @returns `true` if the Result is Err (and narrows the type)
|
|
381
|
-
*
|
|
382
|
-
* @example
|
|
383
|
-
* ```ts
|
|
384
|
-
* if (result.isErr()) {
|
|
385
|
-
* const error: E = result.error; // TypeScript knows that error is defined
|
|
386
|
-
* }
|
|
387
|
-
* ```
|
|
388
|
-
*/
|
|
389
|
-
isErr() {
|
|
390
|
-
return this.#state._tag === "Err";
|
|
391
|
-
}
|
|
392
|
-
get value() {
|
|
393
|
-
return this.#state._tag === "Ok" ? this.#state.value : void 0;
|
|
394
|
-
}
|
|
395
|
-
get error() {
|
|
396
|
-
return this.#state._tag === "Err" ? this.#state.error : void 0;
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Returns the value, guaranteed to be defined after `isOk()` check.
|
|
400
|
-
* This method provides better type narrowing than the `value` getter.
|
|
401
|
-
*
|
|
402
|
-
* ⚠️ **Warning**: This method throws an Error if called on an Err result.
|
|
403
|
-
* Use this method only after a type guard (`if (result.isOk())`).
|
|
404
|
-
* For a safer alternative with a custom message, use `expect()`.
|
|
405
|
-
*
|
|
406
|
-
* @throws {Error} If called on an Err result
|
|
407
|
-
*
|
|
408
|
-
* @example
|
|
409
|
-
* ```ts
|
|
410
|
-
* if (result.isOk()) {
|
|
411
|
-
* const value = result.unwrap(); // Type is T, not T | undefined
|
|
412
|
-
* }
|
|
413
|
-
* ```
|
|
414
|
-
*/
|
|
415
|
-
unwrap() {
|
|
416
|
-
if (this.#state._tag === "Ok") return this.#state.value;
|
|
417
|
-
const errorStr = (() => {
|
|
418
|
-
try {
|
|
419
|
-
const error = this.#state.error;
|
|
420
|
-
if (error === null) return "null";
|
|
421
|
-
if (error === void 0) return "undefined";
|
|
422
|
-
if (typeof error === "string") return error;
|
|
423
|
-
if (error instanceof Error) return error.message;
|
|
424
|
-
if (typeof error === "object" && "toString" in error) try {
|
|
425
|
-
return String(error);
|
|
426
|
-
} catch {
|
|
427
|
-
return "[unstringifiable error]";
|
|
428
|
-
}
|
|
429
|
-
return String(error);
|
|
430
|
-
} catch {
|
|
431
|
-
return "[unstringifiable error]";
|
|
432
|
-
}
|
|
433
|
-
})();
|
|
434
|
-
throw new Error(`Called unwrap() on Err: ${errorStr}`);
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Returns the error, guaranteed to be defined after `isErr()` check.
|
|
438
|
-
* This method provides better type narrowing than the `error` getter.
|
|
439
|
-
*
|
|
440
|
-
* ⚠️ **Warning**: This method throws an Error if called on an Ok result.
|
|
441
|
-
* Use this method only after a type guard (`if (result.isErr())`).
|
|
442
|
-
* For a safer alternative with a custom message, use `expectErr()`.
|
|
443
|
-
*
|
|
444
|
-
* @throws {Error} If called on an Ok result
|
|
445
|
-
*
|
|
446
|
-
* @example
|
|
447
|
-
* ```ts
|
|
448
|
-
* if (result.isErr()) {
|
|
449
|
-
* const error = result.unwrapErr(); // Type is E, not E | undefined
|
|
450
|
-
* }
|
|
451
|
-
* ```
|
|
452
|
-
*/
|
|
453
|
-
unwrapErr() {
|
|
454
|
-
if (this.#state._tag === "Err") return this.#state.error;
|
|
455
|
-
const valueStr = (() => {
|
|
456
|
-
try {
|
|
457
|
-
const value = this.#state.value;
|
|
458
|
-
if (value === null) return "null";
|
|
459
|
-
if (value === void 0) return "undefined";
|
|
460
|
-
if (typeof value === "string") return value;
|
|
461
|
-
if (value instanceof Error) return value.message;
|
|
462
|
-
if (typeof value === "object" && "toString" in value) try {
|
|
463
|
-
return String(value);
|
|
464
|
-
} catch {
|
|
465
|
-
return "[unstringifiable value]";
|
|
466
|
-
}
|
|
467
|
-
return String(value);
|
|
468
|
-
} catch {
|
|
469
|
-
return "[unstringifiable value]";
|
|
470
|
-
}
|
|
471
|
-
})();
|
|
472
|
-
throw new Error(`Called unwrapErr() on Ok: ${valueStr}`);
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Returns the value with a custom error message if the result is Err.
|
|
476
|
-
* Similar to `unwrap()`, but allows you to provide a custom error message.
|
|
477
|
-
*
|
|
478
|
-
* ⚠️ **Warning**: This method throws an Error if called on an Err result.
|
|
479
|
-
* Use this method only if you are sure the Result is Ok,
|
|
480
|
-
* or if you need a meaningful error message.
|
|
481
|
-
*
|
|
482
|
-
* @param message Custom error message to throw if result is Err
|
|
483
|
-
* @returns The value if result is Ok
|
|
484
|
-
* @throws {Error} If called on an Err result with the provided message
|
|
485
|
-
*
|
|
486
|
-
* @example
|
|
487
|
-
* ```ts
|
|
488
|
-
* const result = fetchUser(id);
|
|
489
|
-
* const user = result.expect('User should exist'); // Throws with custom message if Err
|
|
490
|
-
* ```
|
|
491
|
-
*/
|
|
492
|
-
expect(message) {
|
|
493
|
-
if (this.#state._tag === "Ok") return this.#state.value;
|
|
494
|
-
throw new Error(message);
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Returns the error with a custom error message if the result is Ok.
|
|
498
|
-
* Similar to `unwrapErr()`, but allows you to provide a custom error message.
|
|
499
|
-
*
|
|
500
|
-
* ⚠️ **Warning**: This method throws an Error if called on an Ok result.
|
|
501
|
-
* Use this method only if you are sure the Result is Err,
|
|
502
|
-
* or if you need a meaningful error message.
|
|
503
|
-
*
|
|
504
|
-
* @param message Custom error message to throw if result is Ok
|
|
505
|
-
* @returns The error if result is Err
|
|
506
|
-
* @throws {Error} If called on an Ok result with the provided message
|
|
507
|
-
*
|
|
508
|
-
* @example
|
|
509
|
-
* ```ts
|
|
510
|
-
* const result = validateInput(input);
|
|
511
|
-
* if (result.isErr()) {
|
|
512
|
-
* const error = result.expectErr('Validation should have failed'); // Throws if Ok
|
|
513
|
-
* }
|
|
514
|
-
* ```
|
|
515
|
-
*/
|
|
516
|
-
expectErr(message) {
|
|
517
|
-
if (this.#state._tag === "Err") return this.#state.error;
|
|
518
|
-
throw new Error(message);
|
|
519
|
-
}
|
|
520
|
-
unwrapOr(defaultValue) {
|
|
521
|
-
return this.#state._tag === "Ok" ? this.#state.value : defaultValue;
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Converts the Result to a Promise.
|
|
525
|
-
* Ok → resolves with the value, Err → rejects with the error
|
|
526
|
-
*
|
|
527
|
-
* This instance method delegates to the standalone `toPromise()` function.
|
|
528
|
-
*
|
|
529
|
-
* @returns A Promise that resolves with the value if Ok, or rejects with the error if Err
|
|
530
|
-
*
|
|
531
|
-
* @example
|
|
532
|
-
* ```ts
|
|
533
|
-
* const result = ok(42);
|
|
534
|
-
* const promise = result.toPromise();
|
|
535
|
-
* const value = await promise; // 42
|
|
536
|
-
*
|
|
537
|
-
* const errResult = err('error');
|
|
538
|
-
* try {
|
|
539
|
-
* await errResult.toPromise();
|
|
540
|
-
* } catch (error) {
|
|
541
|
-
* console.log(error); // 'error'
|
|
542
|
-
* }
|
|
543
|
-
* ```
|
|
544
|
-
*/
|
|
545
|
-
toPromise() {
|
|
546
|
-
return toPromise(this);
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Converts the Result to `T | null`.
|
|
550
|
-
* Ok → returns the value, Err → returns null
|
|
551
|
-
*
|
|
552
|
-
* This instance method delegates to the standalone `toNullable()` function.
|
|
553
|
-
*
|
|
554
|
-
* @returns The value if Ok, or null if Err
|
|
555
|
-
*
|
|
556
|
-
* @example
|
|
557
|
-
* ```ts
|
|
558
|
-
* const result = ok(42);
|
|
559
|
-
* const value = result.toNullable(); // 42
|
|
560
|
-
*
|
|
561
|
-
* const errResult = err('error');
|
|
562
|
-
* const nullValue = errResult.toNullable(); // null
|
|
563
|
-
* ```
|
|
564
|
-
*/
|
|
565
|
-
toNullable() {
|
|
566
|
-
return toNullable(this);
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Enables `yield* result` in generators (Do-notation).
|
|
570
|
-
*
|
|
571
|
-
* The iterator yields the `Result` itself; the runner (see `task`) decides:
|
|
572
|
-
* - Ok → sends back the Ok value (`next(value)`), `yield*` yields `T`
|
|
573
|
-
* - Err → aborts and returns the Err Result
|
|
574
|
-
*/
|
|
575
|
-
*[Symbol.iterator]() {
|
|
576
|
-
return yield this;
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Universal pattern matcher for Ok + Err cases.
|
|
580
|
-
*
|
|
581
|
-
* Use this to exhaustively match on both success and error cases with type-based
|
|
582
|
-
* and value-based pattern matching.
|
|
583
|
-
*
|
|
584
|
-
* @example
|
|
585
|
-
* ```ts
|
|
586
|
-
* const message = result
|
|
587
|
-
* .match()
|
|
588
|
-
* .err(NetworkError, e => `Network: ${e.message}`)
|
|
589
|
-
* .err(ValidationError, e => `Validation: ${e.message}`)
|
|
590
|
-
* .ok(val => `Success: ${val}`)
|
|
591
|
-
* .run();
|
|
592
|
-
* ```
|
|
593
|
-
*/
|
|
594
|
-
match() {
|
|
595
|
-
return ResultMatchBuilder.fromResult(this);
|
|
596
|
-
}
|
|
597
|
-
matchErr() {
|
|
598
|
-
if (this.isErr()) return new ErrorMatchBuilder(this.error);
|
|
599
|
-
throw new Error("matchErr() can only be called on Err results. Use `if (result.isErr()) { ... }` first.");
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Matches on the Err value, but normalizes every branch to a `Result`:
|
|
603
|
-
* - Handlers may return a `Result` (returned directly)
|
|
604
|
-
* - or an error value (wrapped to `Err(error)`)
|
|
605
|
-
*/
|
|
606
|
-
matchErrResult() {
|
|
607
|
-
const makeErr = (error) => Result.err(error);
|
|
608
|
-
return ErrMatchBuilder.fromResult(this, makeErr);
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* @deprecated Use `.match()` instead. Will be removed in next major version.
|
|
612
|
-
*/
|
|
613
|
-
pattern() {
|
|
614
|
-
return this.match();
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* @deprecated Use `.match()` instead. Will be removed in next major version.
|
|
618
|
-
*/
|
|
619
|
-
switch() {
|
|
620
|
-
return this.match();
|
|
621
|
-
}
|
|
622
|
-
/**
|
|
623
|
-
* Folds the Result into a single value by applying one of two functions.
|
|
624
|
-
*
|
|
625
|
-
* This is a direct method equivalent to the `match` pipe operator.
|
|
626
|
-
* Use this when you want to handle both Ok and Err cases and return a single value.
|
|
627
|
-
*
|
|
628
|
-
* @param onOk Function to apply if the Result is Ok
|
|
629
|
-
* @param onErr Function to apply if the Result is Err
|
|
630
|
-
* @returns The result of applying the appropriate function
|
|
631
|
-
*
|
|
632
|
-
* @example
|
|
633
|
-
* ```ts
|
|
634
|
-
* const result = ok(42);
|
|
635
|
-
* const message = result.fold(
|
|
636
|
-
* val => `Success: ${val}`,
|
|
637
|
-
* err => `Error: ${err}`
|
|
638
|
-
* );
|
|
639
|
-
* // message = "Success: 42"
|
|
640
|
-
* ```
|
|
641
|
-
*
|
|
642
|
-
* @example
|
|
643
|
-
* ```ts
|
|
644
|
-
* // Works with discriminated unions
|
|
645
|
-
* const result: Result<string, number> = err(404);
|
|
646
|
-
* const response = result.fold(
|
|
647
|
-
* data => ({ success: true as const, data }),
|
|
648
|
-
* code => ({ success: false as const, code })
|
|
649
|
-
* );
|
|
650
|
-
* // response: { success: true; data: string } | { success: false; code: number }
|
|
651
|
-
* ```
|
|
652
|
-
*/
|
|
653
|
-
fold(onOk, onErr) {
|
|
654
|
-
if (this.isOk()) return onOk(this.value);
|
|
655
|
-
if (this.isErr()) return onErr(this.error);
|
|
656
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
657
|
-
}
|
|
658
|
-
/**
|
|
659
|
-
* Returns the Result as a discriminated union (`{ _tag: 'Ok', value } | { _tag: 'Err', error }`).
|
|
660
|
-
* Useful for libraries like `ts-pattern` that match on plain object unions.
|
|
661
|
-
*/
|
|
662
|
-
toUnion() {
|
|
663
|
-
return this.#state;
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* Serializes the Result into a simple object format.
|
|
667
|
-
* Preserves the original types.
|
|
668
|
-
*/
|
|
669
|
-
serialize() {
|
|
670
|
-
if (this.#state._tag === "Ok") return {
|
|
671
|
-
isSuccess: true,
|
|
672
|
-
data: this.#state.value
|
|
673
|
-
};
|
|
674
|
-
return {
|
|
675
|
-
isSuccess: false,
|
|
676
|
-
error: this.#state.error
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Serializes the Result into a user-friendly format.
|
|
681
|
-
* Converts errors to readable strings.
|
|
682
|
-
*/
|
|
683
|
-
toUserFriendly() {
|
|
684
|
-
if (this.#state._tag === "Ok") return {
|
|
685
|
-
isSuccess: true,
|
|
686
|
-
data: this.#state.value
|
|
687
|
-
};
|
|
688
|
-
const error = this.#state.error;
|
|
689
|
-
const toSafeString = (value) => {
|
|
690
|
-
try {
|
|
691
|
-
return String(value);
|
|
692
|
-
} catch {
|
|
693
|
-
return "[Unstringifiable error]";
|
|
694
|
-
}
|
|
695
|
-
};
|
|
696
|
-
return {
|
|
697
|
-
isSuccess: false,
|
|
698
|
-
error: (() => {
|
|
699
|
-
if (error && typeof error === "object" && "message" in error) {
|
|
700
|
-
const message = error.message;
|
|
701
|
-
return typeof message === "string" ? message : toSafeString(error);
|
|
702
|
-
}
|
|
703
|
-
return toSafeString(error);
|
|
704
|
-
})()
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
const ok = Result.ok;
|
|
709
|
-
const err = Result.err;
|
|
710
|
-
/**
|
|
711
|
-
* Helper for conditional Result creation.
|
|
712
|
-
* Avoids type inference issues with ternary operators.
|
|
713
|
-
*
|
|
714
|
-
* @example
|
|
715
|
-
* ```ts
|
|
716
|
-
* const result = okIf(value > 5, value, 'too small');
|
|
717
|
-
* // instead of: value > 5 ? ok(value) : err('too small')
|
|
718
|
-
* ```
|
|
719
|
-
*/
|
|
720
|
-
function okIf(condition, okValue, errValue) {
|
|
721
|
-
return condition ? ok(okValue) : err(errValue);
|
|
722
|
-
}
|
|
723
|
-
/**
|
|
724
|
-
* Helper for conditional Result creation with lazy evaluation.
|
|
725
|
-
* Evaluates values only when they are needed.
|
|
726
|
-
*
|
|
727
|
-
* @example
|
|
728
|
-
* ```ts
|
|
729
|
-
* const result = okIfLazy(
|
|
730
|
-
* value > 5,
|
|
731
|
-
* () => expensiveComputation(value),
|
|
732
|
-
* () => 'too small'
|
|
733
|
-
* );
|
|
734
|
-
* ```
|
|
735
|
-
*/
|
|
736
|
-
function okIfLazy(condition, okFn, errFn) {
|
|
737
|
-
return condition ? ok(okFn()) : err(errFn());
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
//#endregion
|
|
741
|
-
//#region src/gen.ts
|
|
742
|
-
async function task(makeGenerator, onThrow) {
|
|
743
|
-
const iterator = makeGenerator();
|
|
744
|
-
let input = void 0;
|
|
745
|
-
while (true) {
|
|
746
|
-
let step;
|
|
747
|
-
try {
|
|
748
|
-
step = await iterator.next(input);
|
|
749
|
-
} catch (caught) {
|
|
750
|
-
if (!onThrow) throw caught;
|
|
751
|
-
return err(onThrow(caught));
|
|
752
|
-
}
|
|
753
|
-
if (step.done) try {
|
|
754
|
-
const awaited = await step.value;
|
|
755
|
-
if (isResult(awaited)) return awaited;
|
|
756
|
-
return ok(awaited);
|
|
757
|
-
} catch (caught) {
|
|
758
|
-
if (!onThrow) throw caught;
|
|
759
|
-
return err(onThrow(caught));
|
|
760
|
-
}
|
|
761
|
-
const yielded = step.value;
|
|
762
|
-
if (!isResult(yielded)) throw new TypeError("task() expected yielded values to be Result. Use `yield*` on a Result.");
|
|
763
|
-
if (yielded.isOk()) {
|
|
764
|
-
input = yielded.value;
|
|
765
|
-
continue;
|
|
766
|
-
}
|
|
767
|
-
if (yielded.isErr()) {
|
|
768
|
-
try {
|
|
769
|
-
if (typeof iterator.return === "function") await iterator.return(void 0);
|
|
770
|
-
} catch (caught) {
|
|
771
|
-
if (!onThrow) throw caught;
|
|
772
|
-
return err(onThrow(caught));
|
|
773
|
-
}
|
|
774
|
-
return yielded;
|
|
775
|
-
}
|
|
776
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
const gen = task;
|
|
780
108
|
|
|
781
109
|
//#endregion
|
|
782
|
-
//#region src/
|
|
110
|
+
//#region src/core/map.ts
|
|
783
111
|
/**
|
|
784
|
-
*
|
|
785
|
-
*
|
|
112
|
+
* Transformiert den Wert (Ok-Fall).
|
|
113
|
+
* Entspricht Rust `map`.
|
|
786
114
|
*/
|
|
787
115
|
function map(project) {
|
|
788
116
|
return (source) => {
|
|
@@ -792,10 +120,10 @@ function map(project) {
|
|
|
792
120
|
}
|
|
793
121
|
|
|
794
122
|
//#endregion
|
|
795
|
-
//#region src/
|
|
123
|
+
//#region src/core/mapErr.ts
|
|
796
124
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
125
|
+
* Transformiert den Fehler (Err-Fall).
|
|
126
|
+
* Entspricht Rust `map_err`.
|
|
799
127
|
*/
|
|
800
128
|
function mapErr(project) {
|
|
801
129
|
return (source) => {
|
|
@@ -805,10 +133,10 @@ function mapErr(project) {
|
|
|
805
133
|
}
|
|
806
134
|
|
|
807
135
|
//#endregion
|
|
808
|
-
//#region src/
|
|
136
|
+
//#region src/core/mapBoth.ts
|
|
809
137
|
/**
|
|
810
|
-
*
|
|
811
|
-
*
|
|
138
|
+
* Transformiert sowohl den Ok-Wert als auch den Err-Fehler.
|
|
139
|
+
* Entspricht FP `bimap` / `mapBoth`.
|
|
812
140
|
*/
|
|
813
141
|
function mapBoth(mapOk, mapErr$1) {
|
|
814
142
|
return (source) => {
|
|
@@ -818,15 +146,15 @@ function mapBoth(mapOk, mapErr$1) {
|
|
|
818
146
|
};
|
|
819
147
|
}
|
|
820
148
|
/**
|
|
821
|
-
* Alias
|
|
149
|
+
* Alias für `mapBoth`.
|
|
822
150
|
*/
|
|
823
151
|
const bimap = mapBoth;
|
|
824
152
|
|
|
825
153
|
//#endregion
|
|
826
|
-
//#region src/
|
|
154
|
+
//#region src/core/flatMap.ts
|
|
827
155
|
/**
|
|
828
|
-
*
|
|
829
|
-
*
|
|
156
|
+
* Verkettet eine weitere Operation, die ein Result zurückgibt.
|
|
157
|
+
* Entspricht Rust `and_then` oder JS `flatMap`.
|
|
830
158
|
*/
|
|
831
159
|
function flatMap(project) {
|
|
832
160
|
return (source) => {
|
|
@@ -836,10 +164,42 @@ function flatMap(project) {
|
|
|
836
164
|
}
|
|
837
165
|
|
|
838
166
|
//#endregion
|
|
839
|
-
//#region src/
|
|
167
|
+
//#region src/core/zip.ts
|
|
168
|
+
function zipImpl(left, right) {
|
|
169
|
+
if (left.isErr()) return left;
|
|
170
|
+
if (right.isErr()) return right;
|
|
171
|
+
if (left.isOk() && right.isOk()) return ok([left.value, right.value]);
|
|
172
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
173
|
+
}
|
|
174
|
+
function zip(...args) {
|
|
175
|
+
if (args.length === 1) {
|
|
176
|
+
const right$1 = args[0];
|
|
177
|
+
return (left$1) => zipImpl(left$1, right$1);
|
|
178
|
+
}
|
|
179
|
+
const [left, right] = args;
|
|
180
|
+
return zipImpl(left, right);
|
|
181
|
+
}
|
|
182
|
+
function combineImpl(left, right) {
|
|
183
|
+
if (left.isOk() && right.isOk()) return ok([left.value, right.value]);
|
|
184
|
+
const errors = [];
|
|
185
|
+
if (left.isErr()) errors.push(left.error);
|
|
186
|
+
if (right.isErr()) errors.push(right.error);
|
|
187
|
+
return err(errors);
|
|
188
|
+
}
|
|
189
|
+
function combine(...args) {
|
|
190
|
+
if (args.length === 1) {
|
|
191
|
+
const right$1 = args[0];
|
|
192
|
+
return (left$1) => combineImpl(left$1, right$1);
|
|
193
|
+
}
|
|
194
|
+
const [left, right] = args;
|
|
195
|
+
return combineImpl(left, right);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/core/tap.ts
|
|
840
200
|
/**
|
|
841
|
-
*
|
|
842
|
-
*
|
|
201
|
+
* Führt einen Seiteneffekt aus (Logging, Debugging), ohne das Result zu ändern.
|
|
202
|
+
* Entspricht Rust `inspect` / `inspect_err`.
|
|
843
203
|
*/
|
|
844
204
|
function tap(observer) {
|
|
845
205
|
return (source) => {
|
|
@@ -850,10 +210,10 @@ function tap(observer) {
|
|
|
850
210
|
}
|
|
851
211
|
|
|
852
212
|
//#endregion
|
|
853
|
-
//#region src/
|
|
213
|
+
//#region src/core/filter.ts
|
|
854
214
|
/**
|
|
855
|
-
*
|
|
856
|
-
*
|
|
215
|
+
* Prüft eine Bedingung. Wenn falsch, wird das Result zu Err.
|
|
216
|
+
* Entspricht Rust `filter` (teilweise).
|
|
857
217
|
*/
|
|
858
218
|
function filter(predicate, errorFn) {
|
|
859
219
|
return (source) => {
|
|
@@ -866,31 +226,61 @@ function filter(predicate, errorFn) {
|
|
|
866
226
|
}
|
|
867
227
|
|
|
868
228
|
//#endregion
|
|
869
|
-
//#region src/
|
|
229
|
+
//#region src/core/match.ts
|
|
870
230
|
/**
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*
|
|
874
|
-
* This is the pipe operator equivalent of the `.fold()` instance method.
|
|
231
|
+
* Löst das Result auf. Das Ende der Pipe.
|
|
232
|
+
* Entspricht Rust `match`.
|
|
875
233
|
*/
|
|
876
|
-
function
|
|
234
|
+
function match(handlers) {
|
|
877
235
|
return (source) => {
|
|
878
236
|
if (source.isOk()) return handlers.ok(source.value);
|
|
879
237
|
if (source.isErr()) return handlers.err(source.error);
|
|
880
238
|
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
881
239
|
};
|
|
882
240
|
}
|
|
241
|
+
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/core/recover.ts
|
|
244
|
+
/**
|
|
245
|
+
* Recover: wandelt Err in Ok(defaultValue) um.
|
|
246
|
+
* Ergebnis ist garantiert Ok → Error-Typ wird `never`.
|
|
247
|
+
*/
|
|
248
|
+
function recover(defaultValue) {
|
|
249
|
+
return (source) => {
|
|
250
|
+
if (source.isOk()) return source;
|
|
251
|
+
if (source.isErr()) return ok(defaultValue);
|
|
252
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
253
|
+
};
|
|
254
|
+
}
|
|
883
255
|
/**
|
|
884
|
-
*
|
|
256
|
+
* Wie `recover`, aber berechnet den Default-Wert anhand des Errors.
|
|
885
257
|
*/
|
|
886
|
-
|
|
258
|
+
function recoverWith(fn) {
|
|
259
|
+
return (source) => {
|
|
260
|
+
if (source.isOk()) return source;
|
|
261
|
+
if (source.isErr()) return ok(fn(source.error));
|
|
262
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
263
|
+
};
|
|
264
|
+
}
|
|
887
265
|
|
|
888
266
|
//#endregion
|
|
889
|
-
//#region src/
|
|
267
|
+
//#region src/core/swap.ts
|
|
890
268
|
/**
|
|
891
|
-
*
|
|
892
|
-
*
|
|
893
|
-
|
|
269
|
+
* Tauscht Ok und Err.
|
|
270
|
+
* Result<T, E> → Result<E, T>
|
|
271
|
+
*/
|
|
272
|
+
function swap(result) {
|
|
273
|
+
if (result.isOk()) return err(result.value);
|
|
274
|
+
if (result.isErr()) return ok(result.error);
|
|
275
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/core/tryCatch.ts
|
|
280
|
+
/**
|
|
281
|
+
* Führt eine Funktion aus und fängt Exceptions ab.
|
|
282
|
+
* Wandelt Exceptions in Result<E> um.
|
|
283
|
+
* Entspricht Rust `Result::from` für fallible Operationen.
|
|
894
284
|
*/
|
|
895
285
|
function tryCatch(fn, errorMapper) {
|
|
896
286
|
return (source) => {
|
|
@@ -904,9 +294,9 @@ function tryCatch(fn, errorMapper) {
|
|
|
904
294
|
}
|
|
905
295
|
|
|
906
296
|
//#endregion
|
|
907
|
-
//#region src/
|
|
297
|
+
//#region src/core/tryMap.ts
|
|
908
298
|
/**
|
|
909
|
-
*
|
|
299
|
+
* Wie `map`, aber fängt Exceptions ab und wandelt sie in Err um.
|
|
910
300
|
*/
|
|
911
301
|
function tryMap(project, errorMapper) {
|
|
912
302
|
return (source) => {
|
|
@@ -921,33 +311,29 @@ function tryMap(project, errorMapper) {
|
|
|
921
311
|
}
|
|
922
312
|
|
|
923
313
|
//#endregion
|
|
924
|
-
//#region src/
|
|
925
|
-
/**
|
|
926
|
-
* Recover: turns Err into Ok(defaultValue).
|
|
927
|
-
* Result is guaranteed Ok → error type becomes `never`.
|
|
928
|
-
*/
|
|
929
|
-
function recover(defaultValue) {
|
|
930
|
-
return (source) => {
|
|
931
|
-
if (source.isOk()) return source;
|
|
932
|
-
if (source.isErr()) return ok(defaultValue);
|
|
933
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
934
|
-
};
|
|
935
|
-
}
|
|
314
|
+
//#region src/core/collectFirstOk.ts
|
|
936
315
|
/**
|
|
937
|
-
*
|
|
316
|
+
* Parse a set of `Result`s, short-circuits when an input value is `Ok`.
|
|
317
|
+
* If no `Ok` is found, returns an `Err` containing the collected error values.
|
|
318
|
+
* Useful for "try multiple approaches until one works" patterns.
|
|
938
319
|
*/
|
|
939
|
-
function
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
if (
|
|
320
|
+
function collectFirstOk(results) {
|
|
321
|
+
const errors = [];
|
|
322
|
+
for (const result of results) {
|
|
323
|
+
if (result.isOk()) return ok(result.value);
|
|
324
|
+
if (result.isErr()) {
|
|
325
|
+
errors.push(result.error);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
943
328
|
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
944
|
-
}
|
|
329
|
+
}
|
|
330
|
+
return err(errors);
|
|
945
331
|
}
|
|
946
332
|
|
|
947
333
|
//#endregion
|
|
948
|
-
//#region src/
|
|
334
|
+
//#region src/core/mapAsync.ts
|
|
949
335
|
/**
|
|
950
|
-
* Async
|
|
336
|
+
* Async-Version von map.
|
|
951
337
|
*/
|
|
952
338
|
function mapAsync(project) {
|
|
953
339
|
return async (source) => {
|
|
@@ -957,9 +343,9 @@ function mapAsync(project) {
|
|
|
957
343
|
}
|
|
958
344
|
|
|
959
345
|
//#endregion
|
|
960
|
-
//#region src/
|
|
346
|
+
//#region src/core/mapErrAsync.ts
|
|
961
347
|
/**
|
|
962
|
-
* Async
|
|
348
|
+
* Async-Version von mapErr.
|
|
963
349
|
*/
|
|
964
350
|
function mapErrAsync(project) {
|
|
965
351
|
return async (source) => {
|
|
@@ -969,10 +355,9 @@ function mapErrAsync(project) {
|
|
|
969
355
|
}
|
|
970
356
|
|
|
971
357
|
//#endregion
|
|
972
|
-
//#region src/
|
|
358
|
+
//#region src/core/flatMapAsync.ts
|
|
973
359
|
/**
|
|
974
|
-
* Async
|
|
975
|
-
* Allows different error types in the projected Result.
|
|
360
|
+
* Async-Version von flatMap.
|
|
976
361
|
*/
|
|
977
362
|
function flatMapAsync(project) {
|
|
978
363
|
return async (source) => {
|
|
@@ -982,9 +367,9 @@ function flatMapAsync(project) {
|
|
|
982
367
|
}
|
|
983
368
|
|
|
984
369
|
//#endregion
|
|
985
|
-
//#region src/
|
|
370
|
+
//#region src/core/tapAsync.ts
|
|
986
371
|
/**
|
|
987
|
-
* Async
|
|
372
|
+
* Async-Version von tap.
|
|
988
373
|
*/
|
|
989
374
|
function tapAsync(observer) {
|
|
990
375
|
return async (source) => {
|
|
@@ -995,9 +380,9 @@ function tapAsync(observer) {
|
|
|
995
380
|
}
|
|
996
381
|
|
|
997
382
|
//#endregion
|
|
998
|
-
//#region src/
|
|
383
|
+
//#region src/core/filterAsync.ts
|
|
999
384
|
/**
|
|
1000
|
-
* Async
|
|
385
|
+
* Async-Version von filter.
|
|
1001
386
|
*/
|
|
1002
387
|
function filterAsync(predicate, errorFn) {
|
|
1003
388
|
return async (source) => {
|
|
@@ -1010,29 +395,22 @@ function filterAsync(predicate, errorFn) {
|
|
|
1010
395
|
}
|
|
1011
396
|
|
|
1012
397
|
//#endregion
|
|
1013
|
-
//#region src/
|
|
398
|
+
//#region src/core/matchAsync.ts
|
|
1014
399
|
/**
|
|
1015
|
-
* Async
|
|
1016
|
-
* The end of the pipe.
|
|
1017
|
-
*
|
|
1018
|
-
* This is the async pipe operator equivalent of the `.fold()` instance method.
|
|
400
|
+
* Async-Version von match.
|
|
1019
401
|
*/
|
|
1020
|
-
function
|
|
402
|
+
function matchAsync(handlers) {
|
|
1021
403
|
return async (source) => {
|
|
1022
404
|
if (source.isOk()) return await handlers.ok(source.value);
|
|
1023
405
|
if (source.isErr()) return await handlers.err(source.error);
|
|
1024
406
|
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
1025
407
|
};
|
|
1026
408
|
}
|
|
1027
|
-
/**
|
|
1028
|
-
* @deprecated Use `foldAsync` instead. Will be removed in next major version.
|
|
1029
|
-
*/
|
|
1030
|
-
const matchAsync = foldAsync;
|
|
1031
409
|
|
|
1032
410
|
//#endregion
|
|
1033
|
-
//#region src/
|
|
411
|
+
//#region src/core/tryCatchAsync.ts
|
|
1034
412
|
/**
|
|
1035
|
-
* Async
|
|
413
|
+
* Async-Version von tryCatch.
|
|
1036
414
|
*/
|
|
1037
415
|
function tryCatchAsync(fn, errorMapper) {
|
|
1038
416
|
return async (source) => {
|
|
@@ -1046,9 +424,9 @@ function tryCatchAsync(fn, errorMapper) {
|
|
|
1046
424
|
}
|
|
1047
425
|
|
|
1048
426
|
//#endregion
|
|
1049
|
-
//#region src/
|
|
427
|
+
//#region src/core/tryMapAsync.ts
|
|
1050
428
|
/**
|
|
1051
|
-
* Async
|
|
429
|
+
* Async-Version von tryMap.
|
|
1052
430
|
*/
|
|
1053
431
|
function tryMapAsync(project, errorMapper) {
|
|
1054
432
|
return async (source) => {
|
|
@@ -1063,10 +441,234 @@ function tryMapAsync(project, errorMapper) {
|
|
|
1063
441
|
}
|
|
1064
442
|
|
|
1065
443
|
//#endregion
|
|
1066
|
-
//#region src/
|
|
444
|
+
//#region src/core/result.ts
|
|
445
|
+
var ResultBase = class extends Pipeable {
|
|
446
|
+
isOk() {
|
|
447
|
+
return this._tag === "Ok";
|
|
448
|
+
}
|
|
449
|
+
isErr() {
|
|
450
|
+
return this._tag === "Err";
|
|
451
|
+
}
|
|
452
|
+
unwrapOr(defaultValue) {
|
|
453
|
+
return this._tag === "Ok" ? this.value : defaultValue;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Folds the Result into a single value by applying one of two functions.
|
|
457
|
+
*/
|
|
458
|
+
fold(onOk, onErr) {
|
|
459
|
+
if (this._tag === "Ok") return onOk(this.value);
|
|
460
|
+
if (this._tag === "Err") return onErr(this.error);
|
|
461
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Enables `yield* result` in generators (Do-notation).
|
|
465
|
+
*
|
|
466
|
+
* The iterator yields the `Result` itself; the runner (see `task`) decides:
|
|
467
|
+
* - Ok → sends back the Ok value (`next(value)`), `yield*` yields `T`
|
|
468
|
+
* - Err → aborts and returns the Err Result
|
|
469
|
+
*/
|
|
470
|
+
*[Symbol.iterator]() {
|
|
471
|
+
return yield this;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Matcht auf den Err-Wert via `.when(...)` Kette.
|
|
475
|
+
*
|
|
476
|
+
* Hinweis: aus Type-Safety-Gründen ist `.match()` nur auf einem bereits zu `Err` verengten Result aufrufbar,
|
|
477
|
+
* z.B. innerhalb von `if (result.isErr()) { ... }`.
|
|
478
|
+
*/
|
|
479
|
+
match() {
|
|
480
|
+
if (this._tag === "Err") return new ErrorMatchBuilder(this.error);
|
|
481
|
+
throw new Error("match() can only be called on Err results. Use `if (result.isErr()) { ... }` first.");
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Matcht auf den Err-Wert, aber normalisiert jeden Branch zu einem `Result`:
|
|
485
|
+
* - Handler dürfen ein `Result` zurückgeben (wird direkt returned)
|
|
486
|
+
* - oder einen Error-Wert (wird zu `Err(error)` gewrappt)
|
|
487
|
+
*/
|
|
488
|
+
matchErr() {
|
|
489
|
+
const makeErr = (error) => err(error);
|
|
490
|
+
return ErrMatchBuilder.fromResult(this, makeErr);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Serialisiert das Result in ein einfaches Objekt-Format.
|
|
494
|
+
* Behält die ursprünglichen Typen bei.
|
|
495
|
+
*/
|
|
496
|
+
serialize() {
|
|
497
|
+
if (this._tag === "Ok") return {
|
|
498
|
+
isSuccess: true,
|
|
499
|
+
data: this.value
|
|
500
|
+
};
|
|
501
|
+
return {
|
|
502
|
+
isSuccess: false,
|
|
503
|
+
error: this.error
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Serialisiert das Result in ein user-friendly Format.
|
|
508
|
+
* Konvertiert Errors zu lesbaren Strings.
|
|
509
|
+
*/
|
|
510
|
+
toUserFriendly() {
|
|
511
|
+
if (this._tag === "Ok") return {
|
|
512
|
+
isSuccess: true,
|
|
513
|
+
data: this.value
|
|
514
|
+
};
|
|
515
|
+
const error = this.error;
|
|
516
|
+
return {
|
|
517
|
+
isSuccess: false,
|
|
518
|
+
error: error && typeof error === "object" && "message" in error ? error.message : String(error)
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
var Ok = class extends ResultBase {
|
|
523
|
+
_tag = "Ok";
|
|
524
|
+
value;
|
|
525
|
+
error = void 0;
|
|
526
|
+
constructor(value) {
|
|
527
|
+
super();
|
|
528
|
+
this.value = value;
|
|
529
|
+
Object.freeze(this);
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
var Err = class extends ResultBase {
|
|
533
|
+
_tag = "Err";
|
|
534
|
+
value = void 0;
|
|
535
|
+
error;
|
|
536
|
+
constructor(error) {
|
|
537
|
+
super();
|
|
538
|
+
this.error = error;
|
|
539
|
+
Object.freeze(this);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
function ok(value) {
|
|
543
|
+
return new Ok(value);
|
|
544
|
+
}
|
|
545
|
+
function err(error) {
|
|
546
|
+
return new Err(error);
|
|
547
|
+
}
|
|
548
|
+
function okIf(condition, okValue, errValue) {
|
|
549
|
+
return condition ? ok(okValue) : err(errValue);
|
|
550
|
+
}
|
|
551
|
+
function okIfLazy(condition, okFn, errFn) {
|
|
552
|
+
return condition ? ok(okFn()) : err(errFn());
|
|
553
|
+
}
|
|
554
|
+
function fromNullable(value, error) {
|
|
555
|
+
if (value === null || value === void 0) return err(error);
|
|
556
|
+
return ok(value);
|
|
557
|
+
}
|
|
558
|
+
async function fromPromise(promise, errorMapper) {
|
|
559
|
+
try {
|
|
560
|
+
return ok(await promise);
|
|
561
|
+
} catch (error) {
|
|
562
|
+
try {
|
|
563
|
+
return err(errorMapper ? errorMapper(error) : error);
|
|
564
|
+
} catch (mapperError) {
|
|
565
|
+
return err(mapperError);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function tryFn(fn) {
|
|
570
|
+
try {
|
|
571
|
+
return ok(fn());
|
|
572
|
+
} catch (error) {
|
|
573
|
+
return err(error);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
const Result = {
|
|
577
|
+
ok,
|
|
578
|
+
err,
|
|
579
|
+
fromNullable,
|
|
580
|
+
fromPromise,
|
|
581
|
+
try: tryFn
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
//#endregion
|
|
585
|
+
//#region src/core/isResult.ts
|
|
586
|
+
/**
|
|
587
|
+
* Checks whether a value is a Result.
|
|
588
|
+
* Pure function alternative for runtime checks.
|
|
589
|
+
*/
|
|
590
|
+
function isResult(value) {
|
|
591
|
+
return typeof value === "object" && value !== null && "isOk" in value && typeof value.isOk === "function" && "isErr" in value && typeof value.isErr === "function";
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/gen.ts
|
|
596
|
+
async function task(makeGenerator, onThrow) {
|
|
597
|
+
const iterator = makeGenerator();
|
|
598
|
+
let input = void 0;
|
|
599
|
+
while (true) {
|
|
600
|
+
let step;
|
|
601
|
+
try {
|
|
602
|
+
step = await iterator.next(input);
|
|
603
|
+
} catch (caught) {
|
|
604
|
+
if (!onThrow) throw caught;
|
|
605
|
+
return err(onThrow(caught));
|
|
606
|
+
}
|
|
607
|
+
if (step.done) try {
|
|
608
|
+
const awaited = await step.value;
|
|
609
|
+
if (isResult(awaited)) return awaited;
|
|
610
|
+
return ok(awaited);
|
|
611
|
+
} catch (caught) {
|
|
612
|
+
if (!onThrow) throw caught;
|
|
613
|
+
return err(onThrow(caught));
|
|
614
|
+
}
|
|
615
|
+
const yielded = step.value;
|
|
616
|
+
if (!isResult(yielded)) throw new TypeError("task() expected yielded values to be Result. Use `yield*` on a Result.");
|
|
617
|
+
if (yielded.isOk()) {
|
|
618
|
+
input = yielded.value;
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
if (yielded.isErr()) {
|
|
622
|
+
try {
|
|
623
|
+
if (typeof iterator.return === "function") await iterator.return(void 0);
|
|
624
|
+
} catch (caught) {
|
|
625
|
+
if (!onThrow) throw caught;
|
|
626
|
+
return err(onThrow(caught));
|
|
627
|
+
}
|
|
628
|
+
return yielded;
|
|
629
|
+
}
|
|
630
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const gen = task;
|
|
634
|
+
|
|
635
|
+
//#endregion
|
|
636
|
+
//#region src/core/fold.ts
|
|
637
|
+
/**
|
|
638
|
+
* Folds the Result into a single value by applying one of two functions.
|
|
639
|
+
* The end of the pipe.
|
|
640
|
+
*
|
|
641
|
+
* This is the pipe operator equivalent of the `.fold()` instance method.
|
|
642
|
+
*/
|
|
643
|
+
function fold(handlers) {
|
|
644
|
+
return (source) => {
|
|
645
|
+
if (source.isOk()) return handlers.ok(source.value);
|
|
646
|
+
if (source.isErr()) return handlers.err(source.error);
|
|
647
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
//#endregion
|
|
652
|
+
//#region src/core/foldAsync.ts
|
|
653
|
+
/**
|
|
654
|
+
* Async version of `fold`. Folds the Result into a single value asynchronously.
|
|
655
|
+
* The end of the pipe.
|
|
656
|
+
*
|
|
657
|
+
* This is the async pipe operator equivalent of the `.fold()` instance method.
|
|
658
|
+
*/
|
|
659
|
+
function foldAsync(handlers) {
|
|
660
|
+
return async (source) => {
|
|
661
|
+
if (source.isOk()) return await handlers.ok(source.value);
|
|
662
|
+
if (source.isErr()) return await handlers.err(source.error);
|
|
663
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region src/core/unwrap.ts
|
|
1067
669
|
/**
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
670
|
+
* Gibt den Wert zurück oder wirft einen Error.
|
|
671
|
+
* Entspricht Rust `unwrap`.
|
|
1070
672
|
*/
|
|
1071
673
|
function unwrap(result) {
|
|
1072
674
|
if (result.isOk()) return result.value;
|
|
@@ -1075,10 +677,10 @@ function unwrap(result) {
|
|
|
1075
677
|
}
|
|
1076
678
|
|
|
1077
679
|
//#endregion
|
|
1078
|
-
//#region src/
|
|
680
|
+
//#region src/core/unwrapOr.ts
|
|
1079
681
|
/**
|
|
1080
|
-
*
|
|
1081
|
-
* Pure function
|
|
682
|
+
* Gibt den Wert zurück oder einen Default-Wert.
|
|
683
|
+
* Pure function Alternative zur Instanz-Methode.
|
|
1082
684
|
*/
|
|
1083
685
|
function unwrapOr(result, defaultValue) {
|
|
1084
686
|
if (result.isOk()) return result.value;
|
|
@@ -1086,10 +688,10 @@ function unwrapOr(result, defaultValue) {
|
|
|
1086
688
|
}
|
|
1087
689
|
|
|
1088
690
|
//#endregion
|
|
1089
|
-
//#region src/
|
|
691
|
+
//#region src/core/unwrapOrElse.ts
|
|
1090
692
|
/**
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
693
|
+
* Gibt den Wert zurück oder berechnet einen Default-Wert mit einer Funktion.
|
|
694
|
+
* Entspricht Rust `unwrap_or_else`.
|
|
1093
695
|
*/
|
|
1094
696
|
function unwrapOrElse(result, fn) {
|
|
1095
697
|
if (result.isOk()) return result.value;
|
|
@@ -1098,20 +700,20 @@ function unwrapOrElse(result, fn) {
|
|
|
1098
700
|
}
|
|
1099
701
|
|
|
1100
702
|
//#endregion
|
|
1101
|
-
//#region src/
|
|
703
|
+
//#region src/core/unwrapOrDefault.ts
|
|
1102
704
|
/**
|
|
1103
|
-
* Alias
|
|
1104
|
-
*
|
|
705
|
+
* Alias für `unwrapOr`.
|
|
706
|
+
* Entspricht Rust `unwrap_or_default` (mit explizitem Default-Wert).
|
|
1105
707
|
*/
|
|
1106
708
|
function unwrapOrDefault(result, defaultValue) {
|
|
1107
709
|
return unwrapOr(result, defaultValue);
|
|
1108
710
|
}
|
|
1109
711
|
|
|
1110
712
|
//#endregion
|
|
1111
|
-
//#region src/
|
|
713
|
+
//#region src/core/unwrapOrThrow.ts
|
|
1112
714
|
/**
|
|
1113
|
-
*
|
|
1114
|
-
*
|
|
715
|
+
* Gibt den Wert zurück oder wirft den originalen Err-Wert (nicht gewrappt).
|
|
716
|
+
* Nützlich um `Error`-Instanzen inkl. Stacktrace zu erhalten.
|
|
1115
717
|
*/
|
|
1116
718
|
function unwrapOrThrow(result) {
|
|
1117
719
|
if (result.isOk()) return result.value;
|
|
@@ -1120,10 +722,10 @@ function unwrapOrThrow(result) {
|
|
|
1120
722
|
}
|
|
1121
723
|
|
|
1122
724
|
//#endregion
|
|
1123
|
-
//#region src/
|
|
725
|
+
//#region src/core/unwrapErr.ts
|
|
1124
726
|
/**
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
727
|
+
* Gibt den Fehler zurück oder wirft einen Error.
|
|
728
|
+
* Entspricht Rust `unwrap_err`.
|
|
1127
729
|
*/
|
|
1128
730
|
function unwrapErr(result) {
|
|
1129
731
|
if (result.isErr()) return result.error;
|
|
@@ -1132,10 +734,10 @@ function unwrapErr(result) {
|
|
|
1132
734
|
}
|
|
1133
735
|
|
|
1134
736
|
//#endregion
|
|
1135
|
-
//#region src/
|
|
737
|
+
//#region src/core/expectResult.ts
|
|
1136
738
|
/**
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
739
|
+
* Gibt den Wert zurück oder wirft einen Error mit custom Nachricht.
|
|
740
|
+
* Entspricht Rust `expect`.
|
|
1139
741
|
*/
|
|
1140
742
|
function expectResult(result, message) {
|
|
1141
743
|
if (result.isOk()) return result.value;
|
|
@@ -1143,10 +745,10 @@ function expectResult(result, message) {
|
|
|
1143
745
|
}
|
|
1144
746
|
|
|
1145
747
|
//#endregion
|
|
1146
|
-
//#region src/
|
|
748
|
+
//#region src/core/expectErr.ts
|
|
1147
749
|
/**
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
750
|
+
* Gibt den Fehler zurück oder wirft einen Error mit custom Nachricht.
|
|
751
|
+
* Entspricht Rust `expect_err`.
|
|
1150
752
|
*/
|
|
1151
753
|
function expectErr(result, message) {
|
|
1152
754
|
if (result.isErr()) return result.error;
|
|
@@ -1154,30 +756,30 @@ function expectErr(result, message) {
|
|
|
1154
756
|
}
|
|
1155
757
|
|
|
1156
758
|
//#endregion
|
|
1157
|
-
//#region src/
|
|
759
|
+
//#region src/core/and.ts
|
|
1158
760
|
/**
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
761
|
+
* Kombiniert zwei Results. Gibt den zweiten zurück nur wenn erster Ok ist.
|
|
762
|
+
* Entspricht Rust `and`.
|
|
1161
763
|
*/
|
|
1162
764
|
function and(result, other) {
|
|
1163
765
|
return result.isOk() ? other : result;
|
|
1164
766
|
}
|
|
1165
767
|
|
|
1166
768
|
//#endregion
|
|
1167
|
-
//#region src/
|
|
769
|
+
//#region src/core/or.ts
|
|
1168
770
|
/**
|
|
1169
|
-
* Fallback
|
|
1170
|
-
*
|
|
771
|
+
* Fallback zu einem anderen Result wenn erster Err ist.
|
|
772
|
+
* Entspricht Rust `or`.
|
|
1171
773
|
*/
|
|
1172
774
|
function or(result, other) {
|
|
1173
775
|
return result.isOk() ? result : other;
|
|
1174
776
|
}
|
|
1175
777
|
|
|
1176
778
|
//#endregion
|
|
1177
|
-
//#region src/
|
|
779
|
+
//#region src/core/orElse.ts
|
|
1178
780
|
/**
|
|
1179
|
-
* Fallback
|
|
1180
|
-
*
|
|
781
|
+
* Fallback mit einer Funktion die ein Result zurückgibt.
|
|
782
|
+
* Entspricht Rust `or_else`.
|
|
1181
783
|
*/
|
|
1182
784
|
function orElse(result, fn) {
|
|
1183
785
|
if (result.isOk()) return result;
|
|
@@ -1186,10 +788,10 @@ function orElse(result, fn) {
|
|
|
1186
788
|
}
|
|
1187
789
|
|
|
1188
790
|
//#endregion
|
|
1189
|
-
//#region src/
|
|
791
|
+
//#region src/core/mapOr.ts
|
|
1190
792
|
/**
|
|
1191
|
-
*
|
|
1192
|
-
*
|
|
793
|
+
* Transformiert den Wert oder gibt einen Default-Wert zurück.
|
|
794
|
+
* Entspricht Rust `map_or`.
|
|
1193
795
|
*/
|
|
1194
796
|
function mapOr(result, defaultValue, fn) {
|
|
1195
797
|
if (result.isOk()) return fn(result.value);
|
|
@@ -1197,10 +799,10 @@ function mapOr(result, defaultValue, fn) {
|
|
|
1197
799
|
}
|
|
1198
800
|
|
|
1199
801
|
//#endregion
|
|
1200
|
-
//#region src/
|
|
802
|
+
//#region src/core/mapOrElse.ts
|
|
1201
803
|
/**
|
|
1202
|
-
*
|
|
1203
|
-
*
|
|
804
|
+
* Transformiert den Wert oder berechnet einen Default-Wert mit einer Funktion.
|
|
805
|
+
* Entspricht Rust `map_or_else`.
|
|
1204
806
|
*/
|
|
1205
807
|
function mapOrElse(result, defaultFn, fn) {
|
|
1206
808
|
if (result.isOk()) return fn(result.value);
|
|
@@ -1209,55 +811,11 @@ function mapOrElse(result, defaultFn, fn) {
|
|
|
1209
811
|
}
|
|
1210
812
|
|
|
1211
813
|
//#endregion
|
|
1212
|
-
//#region src/
|
|
1213
|
-
function zipImpl(left, right) {
|
|
1214
|
-
if (left.isErr()) return left;
|
|
1215
|
-
if (right.isErr()) return right;
|
|
1216
|
-
if (left.isOk() && right.isOk()) return ok([left.value, right.value]);
|
|
1217
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
1218
|
-
}
|
|
1219
|
-
function zip(...args) {
|
|
1220
|
-
if (args.length === 1) {
|
|
1221
|
-
const right$1 = args[0];
|
|
1222
|
-
return (left$1) => zipImpl(left$1, right$1);
|
|
1223
|
-
}
|
|
1224
|
-
const [left, right] = args;
|
|
1225
|
-
return zipImpl(left, right);
|
|
1226
|
-
}
|
|
1227
|
-
function combineImpl(left, right) {
|
|
1228
|
-
if (left.isOk() && right.isOk()) return ok([left.value, right.value]);
|
|
1229
|
-
const errors = [];
|
|
1230
|
-
if (left.isErr()) errors.push(left.error);
|
|
1231
|
-
if (right.isErr()) errors.push(right.error);
|
|
1232
|
-
return err(errors);
|
|
1233
|
-
}
|
|
1234
|
-
function combine(...args) {
|
|
1235
|
-
if (args.length === 1) {
|
|
1236
|
-
const right$1 = args[0];
|
|
1237
|
-
return (left$1) => combineImpl(left$1, right$1);
|
|
1238
|
-
}
|
|
1239
|
-
const [left, right] = args;
|
|
1240
|
-
return combineImpl(left, right);
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
//#endregion
|
|
1244
|
-
//#region src/combinators/swap.ts
|
|
1245
|
-
/**
|
|
1246
|
-
* Swaps Ok and Err.
|
|
1247
|
-
* Result<T, E> → Result<E, T>
|
|
1248
|
-
*/
|
|
1249
|
-
function swap(result) {
|
|
1250
|
-
if (result.isOk()) return err(result.value);
|
|
1251
|
-
if (result.isErr()) return ok(result.error);
|
|
1252
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
//#endregion
|
|
1256
|
-
//#region src/collections/sequence.ts
|
|
814
|
+
//#region src/core/sequence.ts
|
|
1257
815
|
/**
|
|
1258
|
-
*
|
|
1259
|
-
* Short-circuits
|
|
1260
|
-
*
|
|
816
|
+
* Kombiniert eine Liste von Results zu einem Result einer Liste.
|
|
817
|
+
* Short-circuits beim ersten Err.
|
|
818
|
+
* Analog zu Rust `collect::<Result<Vec<_>, _>>()`.
|
|
1261
819
|
*/
|
|
1262
820
|
function sequence(results) {
|
|
1263
821
|
const values = [];
|
|
@@ -1272,23 +830,23 @@ function sequence(results) {
|
|
|
1272
830
|
return ok(values);
|
|
1273
831
|
}
|
|
1274
832
|
/**
|
|
1275
|
-
* Alias
|
|
833
|
+
* Alias für `sequence`.
|
|
1276
834
|
*/
|
|
1277
835
|
function all(results) {
|
|
1278
836
|
return sequence(results);
|
|
1279
837
|
}
|
|
1280
838
|
|
|
1281
839
|
//#endregion
|
|
1282
|
-
//#region src/
|
|
840
|
+
//#region src/core/sequenceRecord.ts
|
|
1283
841
|
/**
|
|
1284
|
-
*
|
|
1285
|
-
* Short-circuits
|
|
842
|
+
* Wie `sequence`, aber für Records/Objekte.
|
|
843
|
+
* Short-circuits beim ersten Err.
|
|
1286
844
|
*/
|
|
1287
845
|
function sequenceRecord(record) {
|
|
1288
846
|
const out = {};
|
|
1289
847
|
for (const key of Object.keys(record)) {
|
|
1290
848
|
const result = record[key];
|
|
1291
|
-
if (!result)
|
|
849
|
+
if (!result) continue;
|
|
1292
850
|
if (result.isOk()) {
|
|
1293
851
|
out[key] = result.value;
|
|
1294
852
|
continue;
|
|
@@ -1300,33 +858,13 @@ function sequenceRecord(record) {
|
|
|
1300
858
|
}
|
|
1301
859
|
|
|
1302
860
|
//#endregion
|
|
1303
|
-
//#region src/
|
|
1304
|
-
/**
|
|
1305
|
-
* Parse a set of `Result`s, short-circuits when an input value is `Ok`.
|
|
1306
|
-
* If no `Ok` is found, returns an `Err` containing the collected error values.
|
|
1307
|
-
* Useful for "try multiple approaches until one works" patterns.
|
|
1308
|
-
*/
|
|
1309
|
-
function collectFirstOk(results) {
|
|
1310
|
-
const errors = [];
|
|
1311
|
-
for (const result of results) {
|
|
1312
|
-
if (result.isOk()) return ok(result.value);
|
|
1313
|
-
if (result.isErr()) {
|
|
1314
|
-
errors.push(result.error);
|
|
1315
|
-
continue;
|
|
1316
|
-
}
|
|
1317
|
-
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
1318
|
-
}
|
|
1319
|
-
return err(errors);
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
//#endregion
|
|
1323
|
-
//#region src/collections/collectFirstOkAsync.ts
|
|
861
|
+
//#region src/core/collectFirstOkAsync.ts
|
|
1324
862
|
/**
|
|
1325
|
-
* Async
|
|
863
|
+
* Async-Version von collectFirstOk.
|
|
1326
864
|
*
|
|
1327
|
-
* -
|
|
1328
|
-
* -
|
|
1329
|
-
* -
|
|
865
|
+
* - Nimmt entweder bereits gestartete Promises oder "Thunks" (`() => Awaitable<Result<...>>`).
|
|
866
|
+
* - Verarbeitet die Inputs strikt sequentiell (wie `for ... of` + `await`).
|
|
867
|
+
* - Gibt das erste `Ok` zurück und sammelt alle Errors wenn kein `Ok` gefunden wird.
|
|
1330
868
|
*/
|
|
1331
869
|
async function collectFirstOkAsync(inputs) {
|
|
1332
870
|
const errors = [];
|
|
@@ -1345,61 +883,43 @@ async function collectFirstOkAsync(inputs) {
|
|
|
1345
883
|
}
|
|
1346
884
|
|
|
1347
885
|
//#endregion
|
|
1348
|
-
//#region src/
|
|
886
|
+
//#region src/core/collectFirstOkParallelAsync.ts
|
|
1349
887
|
/**
|
|
1350
|
-
* Parallel
|
|
888
|
+
* Parallel-Variante von `collectFirstOkAsync`.
|
|
1351
889
|
*
|
|
1352
|
-
* -
|
|
1353
|
-
* -
|
|
1354
|
-
* -
|
|
1355
|
-
* -
|
|
890
|
+
* - Startet alle Inputs sofort (Promises oder Thunks).
|
|
891
|
+
* - Gibt das erste `Ok` zurück, sobald es verfügbar ist.
|
|
892
|
+
* - Wenn kein `Ok` gefunden wird, gibt ein `Err` mit allen Error-Werten (in Input-Reihenfolge) zurück.
|
|
893
|
+
* - Rejections werden als `ErrValue` behandelt (`caught as ErrValue`).
|
|
894
|
+
* - Wenn mehrere Inputs ein `Ok` liefern, gewinnt das zuerst abgeschlossene Ergebnis.
|
|
895
|
+
* Bei gleichzeitiger Completion gewinnt das zuerst beobachtete Ergebnis.
|
|
896
|
+
* - Wenn kein `Ok` kommt und mindestens ein Input nie settled, bleibt das Promise offen.
|
|
1356
897
|
*/
|
|
1357
|
-
async function
|
|
898
|
+
async function collectFirstOkParallelAsync(inputs) {
|
|
1358
899
|
if (inputs.length === 0) return err([]);
|
|
1359
|
-
const
|
|
1360
|
-
const
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
if (
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
if (remaining === 0) {
|
|
1374
|
-
done = true;
|
|
1375
|
-
finishAllErr();
|
|
1376
|
-
}
|
|
1377
|
-
};
|
|
1378
|
-
inputs.forEach((input, index) => {
|
|
1379
|
-
Promise.resolve().then(() => typeof input === "function" ? input() : input).then((result) => {
|
|
1380
|
-
if (done) return;
|
|
1381
|
-
if (result.isOk()) {
|
|
1382
|
-
done = true;
|
|
1383
|
-
resolve(ok(result.value));
|
|
1384
|
-
return;
|
|
1385
|
-
}
|
|
1386
|
-
if (result.isErr()) {
|
|
1387
|
-
settleError(index, result.error);
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
settleError(index, /* @__PURE__ */ new Error("Unreachable: Result is neither Ok nor Err"));
|
|
1391
|
-
}).catch((caught) => {
|
|
1392
|
-
settleError(index, caught);
|
|
1393
|
-
});
|
|
1394
|
-
});
|
|
900
|
+
const started = inputs.map((input) => typeof input === "function" ? Promise.resolve().then(input) : input);
|
|
901
|
+
const firstOk = new Promise((resolve) => {
|
|
902
|
+
for (const promise of started) promise.then((result) => {
|
|
903
|
+
if (result.isOk()) resolve(ok(result.value));
|
|
904
|
+
}).catch(() => {});
|
|
905
|
+
});
|
|
906
|
+
const allErrors = Promise.allSettled(started).then((settled) => {
|
|
907
|
+
const errors = [];
|
|
908
|
+
for (const entry of settled) if (entry.status === "fulfilled") {
|
|
909
|
+
const result = entry.value;
|
|
910
|
+
if (result.isErr()) errors.push(result.error);
|
|
911
|
+
else if (!result.isOk()) errors.push(/* @__PURE__ */ new Error("Unreachable: Result is neither Ok nor Err"));
|
|
912
|
+
} else errors.push(entry.reason);
|
|
913
|
+
return err(errors);
|
|
1395
914
|
});
|
|
915
|
+
return Promise.race([firstOk, allErrors]);
|
|
1396
916
|
}
|
|
1397
917
|
|
|
1398
918
|
//#endregion
|
|
1399
|
-
//#region src/
|
|
919
|
+
//#region src/core/collectAllErrors.ts
|
|
1400
920
|
/**
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
921
|
+
* Kombiniert eine Liste von Results.
|
|
922
|
+
* Gibt Ok(values) nur zurück wenn alle Ok sind, sonst Err([errors]).
|
|
1403
923
|
*/
|
|
1404
924
|
function collectAllErrors(results) {
|
|
1405
925
|
const values = [];
|
|
@@ -1419,9 +939,9 @@ function collectAllErrors(results) {
|
|
|
1419
939
|
}
|
|
1420
940
|
|
|
1421
941
|
//#endregion
|
|
1422
|
-
//#region src/
|
|
942
|
+
//#region src/core/partition.ts
|
|
1423
943
|
/**
|
|
1424
|
-
*
|
|
944
|
+
* Partitioniert Results in Ok-Werte und Err-Fehler.
|
|
1425
945
|
*/
|
|
1426
946
|
function partition(results) {
|
|
1427
947
|
const oks = [];
|
|
@@ -1441,7 +961,7 @@ function partition(results) {
|
|
|
1441
961
|
}
|
|
1442
962
|
|
|
1443
963
|
//#endregion
|
|
1444
|
-
//#region src/
|
|
964
|
+
//#region src/core/flatten.ts
|
|
1445
965
|
/**
|
|
1446
966
|
* Flacht ein nested Result ab.
|
|
1447
967
|
* Result<Result<T, E>, E> → Result<T, E>
|
|
@@ -1453,30 +973,53 @@ function flatten(result) {
|
|
|
1453
973
|
}
|
|
1454
974
|
|
|
1455
975
|
//#endregion
|
|
1456
|
-
//#region src/
|
|
976
|
+
//#region src/core/toPromise.ts
|
|
977
|
+
/**
|
|
978
|
+
* Konvertiert ein Result zu einem Promise.
|
|
979
|
+
* Ok → resolve(value), Err → reject(error)
|
|
980
|
+
*/
|
|
981
|
+
function toPromise(result) {
|
|
982
|
+
if (result.isOk()) return Promise.resolve(result.value);
|
|
983
|
+
if (result.isErr()) return Promise.reject(result.error);
|
|
984
|
+
throw new Error("Unreachable: Result is neither Ok nor Err");
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
//#endregion
|
|
988
|
+
//#region src/core/toNullable.ts
|
|
989
|
+
/**
|
|
990
|
+
* Konvertiert ein Result zu `T | null`.
|
|
991
|
+
* Ok → value, Err → null
|
|
992
|
+
*/
|
|
993
|
+
function toNullable(result) {
|
|
994
|
+
if (result.isOk()) return result.value;
|
|
995
|
+
return null;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
//#endregion
|
|
999
|
+
//#region src/core/isOk.ts
|
|
1457
1000
|
/**
|
|
1458
|
-
*
|
|
1459
|
-
* Pure function
|
|
1001
|
+
* Prüft ob ein Result Ok ist.
|
|
1002
|
+
* Pure function Alternative zur Instanz-Methode.
|
|
1460
1003
|
*/
|
|
1461
1004
|
function isOk(result) {
|
|
1462
1005
|
return result.isOk();
|
|
1463
1006
|
}
|
|
1464
1007
|
|
|
1465
1008
|
//#endregion
|
|
1466
|
-
//#region src/
|
|
1009
|
+
//#region src/core/isErr.ts
|
|
1467
1010
|
/**
|
|
1468
|
-
*
|
|
1469
|
-
* Pure function
|
|
1011
|
+
* Prüft ob ein Result Err ist.
|
|
1012
|
+
* Pure function Alternative zur Instanz-Methode.
|
|
1470
1013
|
*/
|
|
1471
1014
|
function isErr(result) {
|
|
1472
1015
|
return result.isErr();
|
|
1473
1016
|
}
|
|
1474
1017
|
|
|
1475
1018
|
//#endregion
|
|
1476
|
-
//#region src/
|
|
1019
|
+
//#region src/core/contains.ts
|
|
1477
1020
|
/**
|
|
1478
|
-
*
|
|
1479
|
-
*
|
|
1021
|
+
* Prüft ob das Result einen bestimmten Wert enthält.
|
|
1022
|
+
* Entspricht Rust `contains`.
|
|
1480
1023
|
*/
|
|
1481
1024
|
function contains(result, value) {
|
|
1482
1025
|
if (!result.isOk()) return false;
|
|
@@ -1484,10 +1027,10 @@ function contains(result, value) {
|
|
|
1484
1027
|
}
|
|
1485
1028
|
|
|
1486
1029
|
//#endregion
|
|
1487
|
-
//#region src/
|
|
1030
|
+
//#region src/core/containsErr.ts
|
|
1488
1031
|
/**
|
|
1489
|
-
*
|
|
1490
|
-
*
|
|
1032
|
+
* Prüft ob das Result einen bestimmten Fehler enthält.
|
|
1033
|
+
* Analog zu `contains` für den Err-Fall.
|
|
1491
1034
|
*/
|
|
1492
1035
|
function containsErr(result, error) {
|
|
1493
1036
|
if (!result.isErr()) return false;
|
|
@@ -1495,5 +1038,5 @@ function containsErr(result, error) {
|
|
|
1495
1038
|
}
|
|
1496
1039
|
|
|
1497
1040
|
//#endregion
|
|
1498
|
-
export { Result, all, and, bimap, collectAllErrors, collectFirstOk, collectFirstOkAsync,
|
|
1041
|
+
export { Err, Ok, Result, all, and, bimap, collectAllErrors, collectFirstOk, collectFirstOkAsync, collectFirstOkParallelAsync, combine, contains, containsErr, err, expectErr, expectResult, filter, filterAsync, flatMap, flatMapAsync, flatten, fold, foldAsync, fromNullable, fromPromise, gen, isErr, isOk, isResult, map, mapAsync, mapBoth, mapErr, mapErrAsync, mapOr, mapOrElse, match, matchAsync, ok, okIf, okIfLazy, or, orElse, partition, recover, recoverWith, sequence, sequenceRecord, swap, tap, tapAsync, task, toNullable, toPromise, tryCatch, tryCatchAsync, tryFn, tryMap, tryMapAsync, unwrap, unwrapErr, unwrapOr, unwrapOrDefault, unwrapOrElse, unwrapOrThrow, zip };
|
|
1499
1042
|
//# sourceMappingURL=index.mjs.map
|