onlyfuncs 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ import * as Result from '../result/index.js';
2
+
3
+
4
+ /**
5
+ * Collects Ok values or combines every Err in a finite iterable.
6
+ * Continues after Err, combining errors left to right from the first error.
7
+ * A single error needs no combination; empty input returns Ok([]).
8
+ * Iteration and combiner exceptions propagate.
9
+ *
10
+ * @template E
11
+ * @param {import("../semigroup/index.js").Semigroup<E>} semigroup - Combines error payloads.
12
+ * @returns {<A>(results: Iterable<import("../result/index.js").Result<A, E>>) =>
13
+ * import("../result/index.js").Result<A[], E>}
14
+ * A function collecting values or accumulated errors.
15
+ * @example
16
+ * all(Semigroup.array)([Result.err(["Name required"]), Result.ok(3), Result.err(["Age required"])]);
17
+ * // { type: "err", error: ["Name required", "Age required"] }
18
+ */
19
+ export const all = (semigroup) => (results) => {
20
+ const outputs = [];
21
+
22
+ let errors;
23
+ let hasErrors = false;
24
+
25
+ for (const result of results) {
26
+ if (Result.isOk(result)) {
27
+ outputs.push(result.value);
28
+ continue;
29
+ }
30
+
31
+ errors = hasErrors
32
+ ? semigroup.combine(errors, result.error)
33
+ : result.error;
34
+
35
+
36
+ hasErrors = true;
37
+ }
38
+
39
+ return hasErrors ? Result.err(errors) : Result.ok(outputs);
40
+ }
41
+
42
+
43
+ /**
44
+ * Validates every element synchronously, collecting Ok values or combining all errors.
45
+ * Continues after Err, combining errors left to right from the first error.
46
+ * Empty input returns Ok([]). Throws stop iteration and propagate without becoming Err.
47
+ *
48
+ * @template A, B, E
49
+ * @param {Object} options - The validation function and error combination operation.
50
+ * @param {import("../semigroup/index.js").Semigroup<E>} options.semigroup - Combines error payloads.
51
+ * @param {(value: A) => import("../result/index.js").Result<B, E>} options.transform -
52
+ * Validates each element.
53
+ * @returns {(values: Iterable<A>) => import("../result/index.js").Result<B[], E>}
54
+ * A function validating a finite iterable.
55
+ * @example
56
+ * const validate = traverse({
57
+ * semigroup: Semigroup.array,
58
+ * transform: n => n > 0 ? Result.ok(n) : Result.err(["Not positive"]),
59
+ * });
60
+ * validate([1, 0, -1]); // { type: "err", error: ["Not positive", "Not positive"] }
61
+ */
62
+ export const traverse = ( { semigroup, transform }) => (values) => {
63
+ const outputs = [];
64
+
65
+ let errors;
66
+ let hasErrors = false;
67
+
68
+ for (const value of values) {
69
+ const result = transform(value);
70
+
71
+ if (Result.isOk(result)) {
72
+ outputs.push(result.value);
73
+ continue;
74
+ }
75
+
76
+ errors = hasErrors
77
+ ? semigroup.combine(errors, result.error)
78
+ : result.error;
79
+
80
+ hasErrors = true;
81
+ }
82
+
83
+ return hasErrors ? Result.err(errors) : Result.ok(outputs);
84
+ }
85
+
86
+
87
+ /**
88
+ * Combines two Ok values, or combines their errors when both are Err.
89
+ * With just one Err, returns that same Result. Calls only the relevant combiner;
90
+ * callback exceptions propagate.
91
+ *
92
+ * @template A, B, C, E
93
+ * @param {Object} options - Operations for combining successes and errors.
94
+ * @param {import("../semigroup/index.js").Semigroup<E>} options.semigroup -
95
+ * Combines two error payloads.
96
+ * @param {(left: A, right: B) => C} options.combine - Combines the left and right successful values.
97
+ * @returns {(
98
+ * left: import("../result/index.js").Result<A, E>,
99
+ * right: import("../result/index.js").Result<B, E>
100
+ * ) => import("../result/index.js").Result<C, E>}
101
+ * A function combining two Results.
102
+ * @example
103
+ * const add = zipWith({ semigroup: Semigroup.array, combine: (left, right) => left + right });
104
+ * add(Result.ok(2), Result.ok(3)); // { type: "ok", value: 5 }
105
+ * add(Result.err(["Left missing"]), Result.err(["Right missing"]));
106
+ * // { type: "err", error: ["Left missing", "Right missing"] }
107
+ */
108
+ export const zipWith = ({ semigroup, combine }) => (left, right) => {
109
+ if (Result.isOk(left) && Result.isOk(right)) {
110
+ return Result.ok(combine(left.value, right.value));
111
+ }
112
+
113
+ if (Result.isErr(left)) {
114
+ if (Result.isErr(right)) {
115
+ return Result.err(semigroup.combine(left.error, right.error));
116
+ }
117
+
118
+ return left;
119
+ }
120
+
121
+ return right;
122
+ }