@shirudo/result 0.0.2 → 0.0.4

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/dist/index.mjs CHANGED
@@ -12,6 +12,88 @@ var Pipeable = class {
12
12
  }
13
13
  };
14
14
 
15
+ //#endregion
16
+ //#region src/errors.ts
17
+ const ERR_INVALID_STATE = "ERR_INVALID_STATE";
18
+ const ERR_TASK_YIELD_NOT_RESULT = "ERR_TASK_YIELD_NOT_RESULT";
19
+ const ERR_MATCH_ON_OK = "ERR_MATCH_ON_OK";
20
+ const ERR_UNWRAP_ON_ERR = "ERR_UNWRAP_ON_ERR";
21
+ const ERR_UNWRAP_ERR_ON_OK = "ERR_UNWRAP_ERR_ON_OK";
22
+ const ERR_EXPECT_OK = "ERR_EXPECT_OK";
23
+ const ERR_EXPECT_ERR = "ERR_EXPECT_ERR";
24
+ const formatResultErrorMessage = (code, message, context) => {
25
+ if (context) return `${code}: ${message} (context: ${context})`;
26
+ return `${code}: ${message}`;
27
+ };
28
+ var ResultError = class extends Error {
29
+ code;
30
+ context;
31
+ constructor(message, code, context) {
32
+ super(formatResultErrorMessage(code, message, context));
33
+ this.code = code;
34
+ this.context = context;
35
+ this.name = new.target.name;
36
+ Object.setPrototypeOf(this, new.target.prototype);
37
+ }
38
+ };
39
+ var ResultTypeError = class extends TypeError {
40
+ code;
41
+ context;
42
+ constructor(message, code, context) {
43
+ super(formatResultErrorMessage(code, message, context));
44
+ this.code = code;
45
+ this.context = context;
46
+ this.name = new.target.name;
47
+ Object.setPrototypeOf(this, new.target.prototype);
48
+ }
49
+ };
50
+ const INVALID_RESULT_STATE_MESSAGE = "Unreachable: Result is neither Ok nor Err";
51
+ var InvalidResultStateError = class extends ResultError {
52
+ constructor(context) {
53
+ super(INVALID_RESULT_STATE_MESSAGE, ERR_INVALID_STATE, context);
54
+ }
55
+ };
56
+ var TaskYieldNotResultError = class extends ResultTypeError {
57
+ yieldedValue;
58
+ constructor(yieldedValue) {
59
+ super("task() expected yielded values to be Result. Use `yield*` on a Result.", ERR_TASK_YIELD_NOT_RESULT);
60
+ this.yieldedValue = yieldedValue;
61
+ }
62
+ };
63
+ var MatchOnOkError = class extends ResultTypeError {
64
+ constructor() {
65
+ super("match() can only be called on Err results. Use `if (result.isErr()) { ... }` first.", ERR_MATCH_ON_OK);
66
+ }
67
+ };
68
+ var UnwrapOnErrError = class extends ResultTypeError {
69
+ errorValue;
70
+ constructor(errorValue) {
71
+ super(`Called unwrap() on Err: ${String(errorValue)}`, ERR_UNWRAP_ON_ERR);
72
+ this.errorValue = errorValue;
73
+ }
74
+ };
75
+ var UnwrapErrOnOkError = class extends ResultTypeError {
76
+ okValue;
77
+ constructor(okValue) {
78
+ super(`Called unwrapErr() on Ok: ${String(okValue)}`, ERR_UNWRAP_ERR_ON_OK);
79
+ this.okValue = okValue;
80
+ }
81
+ };
82
+ var ExpectOkError = class extends ResultError {
83
+ expectedMessage;
84
+ constructor(expectedMessage) {
85
+ super(expectedMessage, ERR_EXPECT_OK);
86
+ this.expectedMessage = expectedMessage;
87
+ }
88
+ };
89
+ var ExpectErrError = class extends ResultError {
90
+ expectedMessage;
91
+ constructor(expectedMessage) {
92
+ super(expectedMessage, ERR_EXPECT_ERR);
93
+ this.expectedMessage = expectedMessage;
94
+ }
95
+ };
96
+
15
97
  //#endregion
16
98
  //#region src/core/matcher.ts
17
99
  /**
@@ -74,7 +156,7 @@ var ErrMatchBuilder = class ErrMatchBuilder {
74
156
  static fromResult(result, makeErr) {
75
157
  if (result.isOk()) return new ErrMatchBuilder(makeErr, void 0, result);
76
158
  if (result.isErr()) return new ErrMatchBuilder(makeErr, result.error);
77
- throw new Error("Unreachable: Result is neither Ok nor Err");
159
+ throw new InvalidResultStateError("ErrMatchBuilder.fromResult");
78
160
  }
79
161
  when(ctor, handler) {
80
162
  if (this.#resolved) return this;
@@ -142,7 +224,7 @@ function mapBoth(mapOk, mapErr$1) {
142
224
  return (source) => {
143
225
  if (source.isOk()) return ok(mapOk(source.value));
144
226
  if (source.isErr()) return err(mapErr$1(source.error));
145
- throw new Error("Unreachable: Result is neither Ok nor Err");
227
+ throw new InvalidResultStateError("mapBoth");
146
228
  };
147
229
  }
148
230
  /**
@@ -169,7 +251,7 @@ function zipImpl(left, right) {
169
251
  if (left.isErr()) return left;
170
252
  if (right.isErr()) return right;
171
253
  if (left.isOk() && right.isOk()) return ok([left.value, right.value]);
172
- throw new Error("Unreachable: Result is neither Ok nor Err");
254
+ throw new InvalidResultStateError("zip");
173
255
  }
174
256
  function zip(...args) {
175
257
  if (args.length === 1) {
@@ -235,7 +317,7 @@ function match(handlers) {
235
317
  return (source) => {
236
318
  if (source.isOk()) return handlers.ok(source.value);
237
319
  if (source.isErr()) return handlers.err(source.error);
238
- throw new Error("Unreachable: Result is neither Ok nor Err");
320
+ throw new InvalidResultStateError("match");
239
321
  };
240
322
  }
241
323
 
@@ -249,7 +331,7 @@ function recover(defaultValue) {
249
331
  return (source) => {
250
332
  if (source.isOk()) return source;
251
333
  if (source.isErr()) return ok(defaultValue);
252
- throw new Error("Unreachable: Result is neither Ok nor Err");
334
+ throw new InvalidResultStateError("recover");
253
335
  };
254
336
  }
255
337
  /**
@@ -259,7 +341,7 @@ function recoverWith(fn) {
259
341
  return (source) => {
260
342
  if (source.isOk()) return source;
261
343
  if (source.isErr()) return ok(fn(source.error));
262
- throw new Error("Unreachable: Result is neither Ok nor Err");
344
+ throw new InvalidResultStateError("recoverWith");
263
345
  };
264
346
  }
265
347
 
@@ -272,7 +354,7 @@ function recoverWith(fn) {
272
354
  function swap(result) {
273
355
  if (result.isOk()) return err(result.value);
274
356
  if (result.isErr()) return ok(result.error);
275
- throw new Error("Unreachable: Result is neither Ok nor Err");
357
+ throw new InvalidResultStateError("swap");
276
358
  }
277
359
 
278
360
  //#endregion
@@ -303,7 +385,7 @@ function tryMap(project, errorMapper) {
303
385
  if (source.isErr()) return source;
304
386
  try {
305
387
  if (source.isOk()) return ok(project(source.value));
306
- throw new Error("Unreachable: Result is neither Ok nor Err");
388
+ throw new InvalidResultStateError("tryMap");
307
389
  } catch (error) {
308
390
  return err(errorMapper ? errorMapper(error) : error);
309
391
  }
@@ -325,7 +407,7 @@ function collectFirstOk(results) {
325
407
  errors.push(result.error);
326
408
  continue;
327
409
  }
328
- throw new Error("Unreachable: Result is neither Ok nor Err");
410
+ throw new InvalidResultStateError("collectFirstOk");
329
411
  }
330
412
  return err(errors);
331
413
  }
@@ -403,7 +485,7 @@ function matchAsync(handlers) {
403
485
  return async (source) => {
404
486
  if (source.isOk()) return await handlers.ok(source.value);
405
487
  if (source.isErr()) return await handlers.err(source.error);
406
- throw new Error("Unreachable: Result is neither Ok nor Err");
488
+ throw new InvalidResultStateError("matchAsync");
407
489
  };
408
490
  }
409
491
 
@@ -433,7 +515,7 @@ function tryMapAsync(project, errorMapper) {
433
515
  if (source.isErr()) return source;
434
516
  try {
435
517
  if (source.isOk()) return ok(await project(source.value));
436
- throw new Error("Unreachable: Result is neither Ok nor Err");
518
+ throw new InvalidResultStateError("tryMapAsync");
437
519
  } catch (error) {
438
520
  return err(errorMapper ? errorMapper(error) : error);
439
521
  }
@@ -458,7 +540,7 @@ var ResultBase = class extends Pipeable {
458
540
  fold(onOk, onErr) {
459
541
  if (this._tag === "Ok") return onOk(this.value);
460
542
  if (this._tag === "Err") return onErr(this.error);
461
- throw new Error("Unreachable: Result is neither Ok nor Err");
543
+ throw new InvalidResultStateError("Result.fold");
462
544
  }
463
545
  /**
464
546
  * Enables `yield* result` in generators (Do-notation).
@@ -478,7 +560,7 @@ var ResultBase = class extends Pipeable {
478
560
  */
479
561
  match() {
480
562
  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.");
563
+ throw new MatchOnOkError();
482
564
  }
483
565
  /**
484
566
  * Matcht auf den Err-Wert, aber normalisiert jeden Branch zu einem `Result`:
@@ -613,7 +695,7 @@ async function task(makeGenerator, onThrow) {
613
695
  return err(onThrow(caught));
614
696
  }
615
697
  const yielded = step.value;
616
- if (!isResult(yielded)) throw new TypeError("task() expected yielded values to be Result. Use `yield*` on a Result.");
698
+ if (!isResult(yielded)) throw new TaskYieldNotResultError(yielded);
617
699
  if (yielded.isOk()) {
618
700
  input = yielded.value;
619
701
  continue;
@@ -627,7 +709,7 @@ async function task(makeGenerator, onThrow) {
627
709
  }
628
710
  return yielded;
629
711
  }
630
- throw new Error("Unreachable: Result is neither Ok nor Err");
712
+ throw new InvalidResultStateError("task");
631
713
  }
632
714
  }
633
715
  const gen = task;
@@ -644,7 +726,7 @@ function fold(handlers) {
644
726
  return (source) => {
645
727
  if (source.isOk()) return handlers.ok(source.value);
646
728
  if (source.isErr()) return handlers.err(source.error);
647
- throw new Error("Unreachable: Result is neither Ok nor Err");
729
+ throw new InvalidResultStateError("fold");
648
730
  };
649
731
  }
650
732
 
@@ -660,7 +742,7 @@ function foldAsync(handlers) {
660
742
  return async (source) => {
661
743
  if (source.isOk()) return await handlers.ok(source.value);
662
744
  if (source.isErr()) return await handlers.err(source.error);
663
- throw new Error("Unreachable: Result is neither Ok nor Err");
745
+ throw new InvalidResultStateError("foldAsync");
664
746
  };
665
747
  }
666
748
 
@@ -672,8 +754,8 @@ function foldAsync(handlers) {
672
754
  */
673
755
  function unwrap(result) {
674
756
  if (result.isOk()) return result.value;
675
- if (result.isErr()) throw new Error(`Called unwrap() on Err: ${String(result.error)}`);
676
- throw new Error("Unreachable: Result is neither Ok nor Err");
757
+ if (result.isErr()) throw new UnwrapOnErrError(result.error);
758
+ throw new InvalidResultStateError("unwrap");
677
759
  }
678
760
 
679
761
  //#endregion
@@ -696,7 +778,7 @@ function unwrapOr(result, defaultValue) {
696
778
  function unwrapOrElse(result, fn) {
697
779
  if (result.isOk()) return result.value;
698
780
  if (result.isErr()) return fn(result.error);
699
- throw new Error("Unreachable: Result is neither Ok nor Err");
781
+ throw new InvalidResultStateError("unwrapOrElse");
700
782
  }
701
783
 
702
784
  //#endregion
@@ -718,7 +800,7 @@ function unwrapOrDefault(result, defaultValue) {
718
800
  function unwrapOrThrow(result) {
719
801
  if (result.isOk()) return result.value;
720
802
  if (result.isErr()) throw result.error;
721
- throw new Error("Unreachable: Result is neither Ok nor Err");
803
+ throw new InvalidResultStateError("unwrapOrThrow");
722
804
  }
723
805
 
724
806
  //#endregion
@@ -729,8 +811,8 @@ function unwrapOrThrow(result) {
729
811
  */
730
812
  function unwrapErr(result) {
731
813
  if (result.isErr()) return result.error;
732
- if (result.isOk()) throw new Error(`Called unwrapErr() on Ok: ${String(result.value)}`);
733
- throw new Error("Unreachable: Result is neither Ok nor Err");
814
+ if (result.isOk()) throw new UnwrapErrOnOkError(result.value);
815
+ throw new InvalidResultStateError("unwrapErr");
734
816
  }
735
817
 
736
818
  //#endregion
@@ -741,7 +823,7 @@ function unwrapErr(result) {
741
823
  */
742
824
  function expectResult(result, message) {
743
825
  if (result.isOk()) return result.value;
744
- throw new Error(message);
826
+ throw new ExpectOkError(message);
745
827
  }
746
828
 
747
829
  //#endregion
@@ -752,7 +834,7 @@ function expectResult(result, message) {
752
834
  */
753
835
  function expectErr(result, message) {
754
836
  if (result.isErr()) return result.error;
755
- throw new Error(message);
837
+ throw new ExpectErrError(message);
756
838
  }
757
839
 
758
840
  //#endregion
@@ -784,7 +866,7 @@ function or(result, other) {
784
866
  function orElse(result, fn) {
785
867
  if (result.isOk()) return result;
786
868
  if (result.isErr()) return fn(result.error);
787
- throw new Error("Unreachable: Result is neither Ok nor Err");
869
+ throw new InvalidResultStateError("orElse");
788
870
  }
789
871
 
790
872
  //#endregion
@@ -807,7 +889,7 @@ function mapOr(result, defaultValue, fn) {
807
889
  function mapOrElse(result, defaultFn, fn) {
808
890
  if (result.isOk()) return fn(result.value);
809
891
  if (result.isErr()) return defaultFn(result.error);
810
- throw new Error("Unreachable: Result is neither Ok nor Err");
892
+ throw new InvalidResultStateError("mapOrElse");
811
893
  }
812
894
 
813
895
  //#endregion
@@ -825,7 +907,7 @@ function sequence(results) {
825
907
  continue;
826
908
  }
827
909
  if (result.isErr()) return result;
828
- throw new Error("Unreachable: Result is neither Ok nor Err");
910
+ throw new InvalidResultStateError("sequence");
829
911
  }
830
912
  return ok(values);
831
913
  }
@@ -852,7 +934,7 @@ function sequenceRecord(record) {
852
934
  continue;
853
935
  }
854
936
  if (result.isErr()) return result;
855
- throw new Error("Unreachable: Result is neither Ok nor Err");
937
+ throw new InvalidResultStateError("sequenceRecord");
856
938
  }
857
939
  return ok(out);
858
940
  }
@@ -875,7 +957,7 @@ async function collectFirstOkAsync(inputs) {
875
957
  errors.push(result.error);
876
958
  continue;
877
959
  }
878
- throw new Error("Unreachable: Result is neither Ok nor Err");
960
+ throw new InvalidResultStateError("collectFirstOkAsync");
879
961
  } catch (error) {
880
962
  errors.push(error);
881
963
  }
@@ -883,53 +965,36 @@ async function collectFirstOkAsync(inputs) {
883
965
  }
884
966
 
885
967
  //#endregion
886
- //#region src/core/collectFirstOkRaceAsync.ts
968
+ //#region src/core/collectFirstOkParallelAsync.ts
887
969
  /**
888
- * Parallel/Race-Variante von `collectFirstOkAsync`.
970
+ * Parallel-Variante von `collectFirstOkAsync`.
889
971
  *
890
972
  * - Startet alle Inputs sofort (Promises oder Thunks).
891
973
  * - Gibt das erste `Ok` zurück, sobald es verfügbar ist.
892
974
  * - Wenn kein `Ok` gefunden wird, gibt ein `Err` mit allen Error-Werten (in Input-Reihenfolge) zurück.
975
+ * - Rejections werden als `ErrValue` behandelt (`caught as ErrValue`).
976
+ * - Wenn mehrere Inputs ein `Ok` liefern, gewinnt das zuerst abgeschlossene Ergebnis.
977
+ * Bei gleichzeitiger Completion gewinnt das zuerst beobachtete Ergebnis.
978
+ * - Wenn kein `Ok` kommt und mindestens ein Input nie settled, bleibt das Promise offen.
893
979
  */
894
- async function collectFirstOkRaceAsync(inputs) {
980
+ async function collectFirstOkParallelAsync(inputs) {
895
981
  if (inputs.length === 0) return err([]);
896
- const UNSET = Symbol("unset");
897
- const errorsByIndex = Array(inputs.length).fill(UNSET);
898
- return new Promise((resolve) => {
899
- let done = false;
900
- let remaining = inputs.length;
901
- const finishAllErr = () => {
902
- const errors = [];
903
- for (const entry of errorsByIndex) if (entry !== UNSET) errors.push(entry);
904
- resolve(err(errors));
905
- };
906
- const settleError = (index, errorValue) => {
907
- if (done) return;
908
- errorsByIndex[index] = errorValue;
909
- remaining -= 1;
910
- if (remaining === 0) {
911
- done = true;
912
- finishAllErr();
913
- }
914
- };
915
- inputs.forEach((input, index) => {
916
- Promise.resolve().then(() => typeof input === "function" ? input() : input).then((result) => {
917
- if (done) return;
918
- if (result.isOk()) {
919
- done = true;
920
- resolve(ok(result.value));
921
- return;
922
- }
923
- if (result.isErr()) {
924
- settleError(index, result.error);
925
- return;
926
- }
927
- settleError(index, /* @__PURE__ */ new Error("Unreachable: Result is neither Ok nor Err"));
928
- }).catch((caught) => {
929
- settleError(index, caught);
930
- });
931
- });
982
+ const started = inputs.map((input) => typeof input === "function" ? Promise.resolve().then(input) : input);
983
+ const firstOk = new Promise((resolve) => {
984
+ for (const promise of started) promise.then((result) => {
985
+ if (result.isOk()) resolve(ok(result.value));
986
+ }).catch(() => {});
987
+ });
988
+ const allErrors = Promise.allSettled(started).then((settled) => {
989
+ const errors = [];
990
+ for (const entry of settled) if (entry.status === "fulfilled") {
991
+ const result = entry.value;
992
+ if (result.isErr()) errors.push(result.error);
993
+ else if (!result.isOk()) errors.push(new InvalidResultStateError("collectFirstOkParallelAsync"));
994
+ } else errors.push(entry.reason);
995
+ return err(errors);
932
996
  });
997
+ return Promise.race([firstOk, allErrors]);
933
998
  }
934
999
 
935
1000
  //#endregion
@@ -950,7 +1015,7 @@ function collectAllErrors(results) {
950
1015
  errors.push(result.error);
951
1016
  continue;
952
1017
  }
953
- throw new Error("Unreachable: Result is neither Ok nor Err");
1018
+ throw new InvalidResultStateError("collectAllErrors");
954
1019
  }
955
1020
  return errors.length === 0 ? ok(values) : err(errors);
956
1021
  }
@@ -972,7 +1037,7 @@ function partition(results) {
972
1037
  errs.push(result.error);
973
1038
  continue;
974
1039
  }
975
- throw new Error("Unreachable: Result is neither Ok nor Err");
1040
+ throw new InvalidResultStateError("partition");
976
1041
  }
977
1042
  return [oks, errs];
978
1043
  }
@@ -998,7 +1063,7 @@ function flatten(result) {
998
1063
  function toPromise(result) {
999
1064
  if (result.isOk()) return Promise.resolve(result.value);
1000
1065
  if (result.isErr()) return Promise.reject(result.error);
1001
- throw new Error("Unreachable: Result is neither Ok nor Err");
1066
+ throw new InvalidResultStateError("toPromise");
1002
1067
  }
1003
1068
 
1004
1069
  //#endregion
@@ -1055,5 +1120,5 @@ function containsErr(result, error) {
1055
1120
  }
1056
1121
 
1057
1122
  //#endregion
1058
- export { Err, Ok, Result, all, and, bimap, collectAllErrors, collectFirstOk, collectFirstOkAsync, collectFirstOkRaceAsync, 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 };
1123
+ export { ERR_EXPECT_ERR, ERR_EXPECT_OK, ERR_INVALID_STATE, ERR_MATCH_ON_OK, ERR_TASK_YIELD_NOT_RESULT, ERR_UNWRAP_ERR_ON_OK, ERR_UNWRAP_ON_ERR, Err, ExpectErrError, ExpectOkError, InvalidResultStateError, MatchOnOkError, Ok, Result, ResultError, ResultTypeError, TaskYieldNotResultError, UnwrapErrOnOkError, UnwrapOnErrError, 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 };
1059
1124
  //# sourceMappingURL=index.mjs.map