@nlozgachev/pipelined 0.7.0 → 0.9.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.
Files changed (37) hide show
  1. package/esm/src/Core/Arr.js +36 -1
  2. package/esm/src/Core/Deferred.js +8 -4
  3. package/esm/src/Core/Logged.js +4 -4
  4. package/esm/src/Core/Option.js +6 -5
  5. package/esm/src/Core/RemoteData.js +6 -4
  6. package/esm/src/Core/Result.js +8 -6
  7. package/esm/src/Core/These.js +10 -10
  8. package/esm/src/Core/Validation.js +36 -42
  9. package/package.json +1 -1
  10. package/script/src/Core/Arr.js +36 -1
  11. package/script/src/Core/Deferred.js +8 -4
  12. package/script/src/Core/Logged.js +4 -4
  13. package/script/src/Core/Option.js +6 -5
  14. package/script/src/Core/RemoteData.js +6 -4
  15. package/script/src/Core/Result.js +8 -6
  16. package/script/src/Core/These.js +10 -10
  17. package/script/src/Core/Validation.js +36 -42
  18. package/types/src/Core/Arr.d.ts +27 -1
  19. package/types/src/Core/Arr.d.ts.map +1 -1
  20. package/types/src/Core/Deferred.d.ts.map +1 -1
  21. package/types/src/Core/Logged.d.ts +4 -4
  22. package/types/src/Core/Option.d.ts +5 -4
  23. package/types/src/Core/Option.d.ts.map +1 -1
  24. package/types/src/Core/RemoteData.d.ts +5 -3
  25. package/types/src/Core/RemoteData.d.ts.map +1 -1
  26. package/types/src/Core/Result.d.ts +8 -6
  27. package/types/src/Core/Result.d.ts.map +1 -1
  28. package/types/src/Core/TaskOption.d.ts +1 -1
  29. package/types/src/Core/TaskOption.d.ts.map +1 -1
  30. package/types/src/Core/TaskResult.d.ts +1 -1
  31. package/types/src/Core/TaskResult.d.ts.map +1 -1
  32. package/types/src/Core/TaskValidation.d.ts +1 -1
  33. package/types/src/Core/TaskValidation.d.ts.map +1 -1
  34. package/types/src/Core/These.d.ts +10 -10
  35. package/types/src/Core/These.d.ts.map +1 -1
  36. package/types/src/Core/Validation.d.ts +22 -36
  37. package/types/src/Core/Validation.d.ts.map +1 -1
@@ -227,7 +227,7 @@ export var Arr;
227
227
  * pipe([1, 2], Arr.zipWith((a, b) => a + b, ["a", "b"])); // ["1a", "2b"]
228
228
  * ```
229
229
  */
230
- Arr.zipWith = (f, other) => (data) => {
230
+ Arr.zipWith = (f) => (other) => (data) => {
231
231
  const len = Math.min(data.length, other.length);
232
232
  const result = [];
233
233
  for (let i = 0; i < len; i++) {
@@ -376,6 +376,41 @@ export var Arr;
376
376
  * Collects an array of Tasks into a Task of array. Runs in parallel.
377
377
  */
378
378
  Arr.sequenceTask = (data) => Arr.traverseTask((a) => a)(data);
379
+ /**
380
+ * Maps each element to a TaskResult and runs them sequentially.
381
+ * Returns the first Err encountered, or Ok of all results if all succeed.
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * const validate = (n: number): TaskResult<string, number> =>
386
+ * n > 0 ? TaskResult.ok(n) : TaskResult.err("non-positive");
387
+ *
388
+ * pipe(
389
+ * [1, 2, 3],
390
+ * Arr.traverseTaskResult(validate)
391
+ * )(); // Deferred<Ok([1, 2, 3])>
392
+ *
393
+ * pipe(
394
+ * [1, -1, 3],
395
+ * Arr.traverseTaskResult(validate)
396
+ * )(); // Deferred<Err("non-positive")>
397
+ * ```
398
+ */
399
+ Arr.traverseTaskResult = (f) => (data) => Task.from(async () => {
400
+ const result = [];
401
+ for (const a of data) {
402
+ const r = await Deferred.toPromise(f(a)());
403
+ if (Result.isErr(r))
404
+ return r;
405
+ result.push(r.value);
406
+ }
407
+ return Result.ok(result);
408
+ });
409
+ /**
410
+ * Collects an array of TaskResults into a TaskResult of array.
411
+ * Returns the first Err if any element is Err, runs sequentially.
412
+ */
413
+ Arr.sequenceTaskResult = (data) => Arr.traverseTaskResult((a) => a)(data);
379
414
  /**
380
415
  * Returns true if the array is non-empty (type guard).
381
416
  */
@@ -1,3 +1,4 @@
1
+ const _store = new WeakMap();
1
2
  export var Deferred;
2
3
  (function (Deferred) {
3
4
  /**
@@ -10,9 +11,11 @@ export var Deferred;
10
11
  * const value = await d; // "hello"
11
12
  * ```
12
13
  */
13
- Deferred.fromPromise = (p) => ({
14
- then: ((f) => p.then(f)),
15
- });
14
+ Deferred.fromPromise = (p) => {
15
+ const d = ({ then: ((f) => p.then(f)) });
16
+ _store.set(d, p);
17
+ return d;
18
+ };
16
19
  /**
17
20
  * Converts a `Deferred` back into a `Promise`.
18
21
  *
@@ -22,5 +25,6 @@ export var Deferred;
22
25
  * // p is Promise<42>
23
26
  * ```
24
27
  */
25
- Deferred.toPromise = (d) => new Promise((resolve) => d.then(resolve));
28
+ Deferred.toPromise = (d) => _store.get(d) ??
29
+ new Promise((resolve) => d.then(resolve));
26
30
  })(Deferred || (Deferred = {}));
@@ -25,7 +25,7 @@ export var Logged;
25
25
  * @example
26
26
  * ```ts
27
27
  * pipe(
28
- * Logged.of<string, number>(5),
28
+ * Logged.make<string, number>(5),
29
29
  * Logged.map(n => n * 2),
30
30
  * ); // { value: 10, log: [] }
31
31
  * ```
@@ -44,7 +44,7 @@ export var Logged;
44
44
  * @example
45
45
  * ```ts
46
46
  * const result = pipe(
47
- * Logged.of<string, number>(1),
47
+ * Logged.make<string, number>(1),
48
48
  * Logged.chain(n => pipe(Logged.tell("step"), Logged.map(() => n + 1))),
49
49
  * Logged.chain(n => pipe(Logged.tell("done"), Logged.map(() => n * 10))),
50
50
  * );
@@ -83,7 +83,7 @@ export var Logged;
83
83
  * @example
84
84
  * ```ts
85
85
  * pipe(
86
- * Logged.of<string, number>(42),
86
+ * Logged.make<string, number>(42),
87
87
  * Logged.tap(n => console.log("value:", n)),
88
88
  * );
89
89
  * ```
@@ -99,7 +99,7 @@ export var Logged;
99
99
  * @example
100
100
  * ```ts
101
101
  * const result = pipe(
102
- * Logged.of<string, number>(1),
102
+ * Logged.make<string, number>(1),
103
103
  * Logged.chain(n => pipe(Logged.tell("incremented"), Logged.map(() => n + 1))),
104
104
  * );
105
105
  *
@@ -128,16 +128,17 @@ export var Option;
128
128
  Option.match = (cases) => (data) => Option.isSome(data) ? cases.some(data.value) : cases.none();
129
129
  /**
130
130
  * Returns the value inside an Option, or a default value if None.
131
+ * The default is a thunk `() => B` — evaluated only when the Option is None.
131
132
  * The default can be a different type, widening the result to `A | B`.
132
133
  *
133
134
  * @example
134
135
  * ```ts
135
- * pipe(Option.some(5), Option.getOrElse(0)); // 5
136
- * pipe(Option.none(), Option.getOrElse(0)); // 0
137
- * pipe(Option.none<string>(), Option.getOrElse(null)); // null — typed as string | null
136
+ * pipe(Option.some(5), Option.getOrElse(() => 0)); // 5
137
+ * pipe(Option.none(), Option.getOrElse(() => 0)); // 0
138
+ * pipe(Option.none<string>(), Option.getOrElse(() => null)); // null — typed as string | null
138
139
  * ```
139
140
  */
140
- Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue;
141
+ Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue();
141
142
  /**
142
143
  * Executes a side effect on the value without changing the Option.
143
144
  * Useful for logging or debugging.
@@ -166,7 +167,7 @@ export var Option;
166
167
  * pipe(Option.some(2), Option.filter(n => n > 3)); // None
167
168
  * ```
168
169
  */
169
- Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.none();
170
+ Option.filter = (predicate) => (data) => Option.isSome(data) ? (predicate(data.value) ? data : Option.none()) : data;
170
171
  /**
171
172
  * Recovers from a None by providing a fallback Option.
172
173
  * The fallback can produce a different type, widening the result to `Option<A | B>`.
@@ -1,3 +1,5 @@
1
+ import { Option } from "./Option.js";
2
+ import { Result } from "./Result.js";
1
3
  export var RemoteData;
2
4
  (function (RemoteData) {
3
5
  /**
@@ -162,7 +164,7 @@ export var RemoteData;
162
164
  * pipe(RemoteData.loading<string, number>(), RemoteData.getOrElse(null)); // null — typed as number | null
163
165
  * ```
164
166
  */
165
- RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue;
167
+ RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue();
166
168
  /**
167
169
  * Executes a side effect on the success value without changing the RemoteData.
168
170
  *
@@ -189,7 +191,7 @@ export var RemoteData;
189
191
  * Converts a RemoteData to an Option.
190
192
  * Success becomes Some, all other states become None.
191
193
  */
192
- RemoteData.toOption = (data) => RemoteData.isSuccess(data) ? { kind: "Some", value: data.value } : { kind: "None" };
194
+ RemoteData.toOption = (data) => RemoteData.isSuccess(data) ? Option.some(data.value) : Option.none();
193
195
  /**
194
196
  * Converts a RemoteData to a Result.
195
197
  * Success becomes Ok, Failure becomes Err.
@@ -204,6 +206,6 @@ export var RemoteData;
204
206
  * ```
205
207
  */
206
208
  RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data)
207
- ? { kind: "Ok", value: data.value }
208
- : { kind: "Error", error: RemoteData.isFailure(data) ? data.error : onNotReady() };
209
+ ? Result.ok(data.value)
210
+ : Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
209
211
  })(RemoteData || (RemoteData = {}));
@@ -1,3 +1,4 @@
1
+ import { Option } from "./Option.js";
1
2
  export var Result;
2
3
  (function (Result) {
3
4
  /**
@@ -102,16 +103,17 @@ export var Result;
102
103
  Result.match = (cases) => (data) => Result.isOk(data) ? cases.ok(data.value) : cases.err(data.error);
103
104
  /**
104
105
  * Returns the success value or a default value if the Result is an error.
106
+ * The default is a thunk `() => B` — evaluated only when the Result is Err.
105
107
  * The default can be a different type, widening the result to `A | B`.
106
108
  *
107
109
  * @example
108
110
  * ```ts
109
- * pipe(Result.ok(5), Result.getOrElse(0)); // 5
110
- * pipe(Result.err("error"), Result.getOrElse(0)); // 0
111
- * pipe(Result.err("error"), Result.getOrElse(null)); // null — typed as number | null
111
+ * pipe(Result.ok(5), Result.getOrElse(() => 0)); // 5
112
+ * pipe(Result.err("error"), Result.getOrElse(() => 0)); // 0
113
+ * pipe(Result.err("error"), Result.getOrElse(() => null)); // null — typed as number | null
112
114
  * ```
113
115
  */
114
- Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue;
116
+ Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue();
115
117
  /**
116
118
  * Executes a side effect on the success value without changing the Result.
117
119
  * Useful for logging or debugging.
@@ -134,7 +136,7 @@ export var Result;
134
136
  * Recovers from an error by providing a fallback Result.
135
137
  * The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
136
138
  */
137
- Result.recover = (fallback) => (data) => Result.isOk(data) ? data : fallback();
139
+ Result.recover = (fallback) => (data) => Result.isOk(data) ? data : fallback(data.error);
138
140
  /**
139
141
  * Recovers from an error unless it matches the blocked error.
140
142
  * The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
@@ -150,7 +152,7 @@ export var Result;
150
152
  * Result.toOption(Result.err("oops")); // None
151
153
  * ```
152
154
  */
153
- Result.toOption = (data) => Result.isOk(data) ? { kind: "Some", value: data.value } : { kind: "None" };
155
+ Result.toOption = (data) => Result.isOk(data) ? Option.some(data.value) : Option.none();
154
156
  /**
155
157
  * Applies a function wrapped in an Result to a value wrapped in an Result.
156
158
  *
@@ -188,26 +188,26 @@ export var These;
188
188
  *
189
189
  * @example
190
190
  * ```ts
191
- * pipe(These.first(5), These.getFirstOrElse(0)); // 5
192
- * pipe(These.both(5, "warn"), These.getFirstOrElse(0)); // 5
193
- * pipe(These.second("warn"), These.getFirstOrElse(0)); // 0
194
- * pipe(These.second("warn"), These.getFirstOrElse(null)); // null — typed as number | null
191
+ * pipe(These.first(5), These.getFirstOrElse(() => 0)); // 5
192
+ * pipe(These.both(5, "warn"), These.getFirstOrElse(() => 0)); // 5
193
+ * pipe(These.second("warn"), These.getFirstOrElse(() => 0)); // 0
194
+ * pipe(These.second("warn"), These.getFirstOrElse(() => null)); // null — typed as number | null
195
195
  * ```
196
196
  */
197
- These.getFirstOrElse = (defaultValue) => (data) => These.hasFirst(data) ? data.first : defaultValue;
197
+ These.getFirstOrElse = (defaultValue) => (data) => These.hasFirst(data) ? data.first : defaultValue();
198
198
  /**
199
199
  * Returns the second value, or a default if the These has no second value.
200
200
  * The default can be a different type, widening the result to `B | D`.
201
201
  *
202
202
  * @example
203
203
  * ```ts
204
- * pipe(These.second("warn"), These.getSecondOrElse("none")); // "warn"
205
- * pipe(These.both(5, "warn"), These.getSecondOrElse("none")); // "warn"
206
- * pipe(These.first(5), These.getSecondOrElse("none")); // "none"
207
- * pipe(These.first(5), These.getSecondOrElse(null)); // null — typed as string | null
204
+ * pipe(These.second("warn"), These.getSecondOrElse(() => "none")); // "warn"
205
+ * pipe(These.both(5, "warn"), These.getSecondOrElse(() => "none")); // "warn"
206
+ * pipe(These.first(5), These.getSecondOrElse(() => "none")); // "none"
207
+ * pipe(These.first(5), These.getSecondOrElse(() => null)); // null — typed as string | null
208
208
  * ```
209
209
  */
210
- These.getSecondOrElse = (defaultValue) => (data) => These.hasSecond(data) ? data.second : defaultValue;
210
+ These.getSecondOrElse = (defaultValue) => (data) => These.hasSecond(data) ? data.second : defaultValue();
211
211
  /**
212
212
  * Executes a side effect on the first value without changing the These.
213
213
  * Useful for logging or debugging.
@@ -1,4 +1,3 @@
1
- import { isNonEmptyList } from "../Types/NonEmptyList.js";
2
1
  export var Validation;
3
2
  (function (Validation) {
4
3
  /**
@@ -55,22 +54,6 @@ export var Validation;
55
54
  * ```
56
55
  */
57
56
  Validation.map = (f) => (data) => Validation.isValid(data) ? Validation.valid(f(data.value)) : data;
58
- /**
59
- * Chains Validation computations. If the first is Valid, passes the value to f.
60
- * If the first is Invalid, propagates the errors.
61
- *
62
- * Note: chain short-circuits on first error. Use `ap` to accumulate errors.
63
- *
64
- * @example
65
- * ```ts
66
- * const validatePositive = (n: number): Validation<string, number> =>
67
- * n > 0 ? Validation.valid(n) : Validation.invalid("Must be positive");
68
- *
69
- * pipe(Validation.valid(5), Validation.chain(validatePositive)); // Valid(5)
70
- * pipe(Validation.valid(-1), Validation.chain(validatePositive)); // Invalid(["Must be positive"])
71
- * ```
72
- */
73
- Validation.chain = (f) => (data) => Validation.isValid(data) ? f(data.value) : data;
74
57
  /**
75
58
  * Applies a function wrapped in a Validation to a value wrapped in a Validation.
76
59
  * Accumulates errors from both sides.
@@ -98,7 +81,7 @@ export var Validation;
98
81
  ...(Validation.isInvalid(data) ? data.errors : []),
99
82
  ...(Validation.isInvalid(arg) ? arg.errors : []),
100
83
  ];
101
- return isNonEmptyList(errors) ? Validation.invalidAll(errors) : Validation.valid(data);
84
+ return Validation.invalidAll(errors);
102
85
  };
103
86
  /**
104
87
  * Extracts the value from a Validation by providing handlers for both cases.
@@ -141,7 +124,7 @@ export var Validation;
141
124
  * pipe(Validation.invalid("oops"), Validation.getOrElse(null)); // null — typed as number | null
142
125
  * ```
143
126
  */
144
- Validation.getOrElse = (defaultValue) => (data) => Validation.isValid(data) ? data.value : defaultValue;
127
+ Validation.getOrElse = (defaultValue) => (data) => Validation.isValid(data) ? data.value : defaultValue();
145
128
  /**
146
129
  * Executes a side effect on the success value without changing the Validation.
147
130
  *
@@ -161,9 +144,10 @@ export var Validation;
161
144
  };
162
145
  /**
163
146
  * Recovers from an Invalid state by providing a fallback Validation.
147
+ * The fallback receives the accumulated error list so callers can inspect which errors occurred.
164
148
  * The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
165
149
  */
166
- Validation.recover = (fallback) => (data) => Validation.isValid(data) ? data : fallback();
150
+ Validation.recover = (fallback) => (data) => Validation.isValid(data) ? data : fallback(data.errors);
167
151
  /**
168
152
  * Recovers from an Invalid state unless the errors contain any of the blocked errors.
169
153
  * The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
@@ -173,46 +157,56 @@ export var Validation;
173
157
  ? fallback()
174
158
  : data;
175
159
  /**
176
- * Combines two Validation instances, accumulating errors from both.
177
- * If both are Valid, returns the second valid value.
178
- * If either is Invalid, combines their errors into a single Invalid.
160
+ * Combines two independent Validation instances into a tuple.
161
+ * If both are Valid, returns Valid with both values as a tuple.
162
+ * If either is Invalid, accumulates errors from both sides.
179
163
  *
180
164
  * @example
181
165
  * ```ts
182
- * Validation.combine(
183
- * Validation.invalid("Error 1"),
184
- * Validation.invalid("Error 2")
185
- * ); // Invalid(["Error 1", "Error 2"])
186
- *
187
- * Validation.combine(
188
- * Validation.valid("a"),
189
- * Validation.valid("b")
190
- * ); // Valid("b")
166
+ * Validation.product(
167
+ * Validation.valid("alice"),
168
+ * Validation.valid(30)
169
+ * ); // Valid(["alice", 30])
170
+ *
171
+ * Validation.product(
172
+ * Validation.invalid("Name required"),
173
+ * Validation.invalid("Age must be >= 0")
174
+ * ); // Invalid(["Name required", "Age must be >= 0"])
191
175
  * ```
192
176
  */
193
- Validation.combine = (first, second) => {
194
- if (Validation.isValid(first) && Validation.isValid(second)) {
195
- return second;
196
- }
177
+ Validation.product = (first, second) => {
178
+ if (Validation.isValid(first) && Validation.isValid(second))
179
+ return Validation.valid([first.value, second.value]);
197
180
  const errors = [
198
181
  ...(Validation.isInvalid(first) ? first.errors : []),
199
182
  ...(Validation.isInvalid(second) ? second.errors : []),
200
183
  ];
201
- return isNonEmptyList(errors) ? Validation.invalidAll(errors) : second;
184
+ return Validation.invalidAll(errors);
202
185
  };
203
186
  /**
204
- * Combines multiple Validation instances, accumulating all errors.
205
- * If all are Valid, returns the last valid value.
206
- * Returns undefined for an empty array.
187
+ * Combines a non-empty list of Validation instances, accumulating all errors.
188
+ * If all are Valid, returns Valid with all values collected into an array.
189
+ * If any are Invalid, returns Invalid with all accumulated errors.
207
190
  *
208
191
  * @example
209
192
  * ```ts
210
- * Validation.combineAll([
193
+ * Validation.productAll([
211
194
  * validateName(name),
212
195
  * validateEmail(email),
213
196
  * validateAge(age)
214
197
  * ]);
198
+ * // Valid([name, email, age]) or Invalid([...all errors])
215
199
  * ```
216
200
  */
217
- Validation.combineAll = (data) => data.length === 0 ? undefined : data.reduce((acc, v) => Validation.combine(acc, v));
201
+ Validation.productAll = (data) => {
202
+ const values = [];
203
+ const errors = [];
204
+ for (const v of data) {
205
+ if (Validation.isValid(v))
206
+ values.push(v.value);
207
+ else
208
+ errors.push(...v.errors);
209
+ }
210
+ return errors.length > 0 ? Validation.invalidAll(errors) : Validation.valid(values);
211
+ };
218
212
  })(Validation || (Validation = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nlozgachev/pipelined",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Simple functional programming toolkit for TypeScript",
5
5
  "keywords": [
6
6
  "functional",
@@ -230,7 +230,7 @@ var Arr;
230
230
  * pipe([1, 2], Arr.zipWith((a, b) => a + b, ["a", "b"])); // ["1a", "2b"]
231
231
  * ```
232
232
  */
233
- Arr.zipWith = (f, other) => (data) => {
233
+ Arr.zipWith = (f) => (other) => (data) => {
234
234
  const len = Math.min(data.length, other.length);
235
235
  const result = [];
236
236
  for (let i = 0; i < len; i++) {
@@ -379,6 +379,41 @@ var Arr;
379
379
  * Collects an array of Tasks into a Task of array. Runs in parallel.
380
380
  */
381
381
  Arr.sequenceTask = (data) => Arr.traverseTask((a) => a)(data);
382
+ /**
383
+ * Maps each element to a TaskResult and runs them sequentially.
384
+ * Returns the first Err encountered, or Ok of all results if all succeed.
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * const validate = (n: number): TaskResult<string, number> =>
389
+ * n > 0 ? TaskResult.ok(n) : TaskResult.err("non-positive");
390
+ *
391
+ * pipe(
392
+ * [1, 2, 3],
393
+ * Arr.traverseTaskResult(validate)
394
+ * )(); // Deferred<Ok([1, 2, 3])>
395
+ *
396
+ * pipe(
397
+ * [1, -1, 3],
398
+ * Arr.traverseTaskResult(validate)
399
+ * )(); // Deferred<Err("non-positive")>
400
+ * ```
401
+ */
402
+ Arr.traverseTaskResult = (f) => (data) => Task_js_1.Task.from(async () => {
403
+ const result = [];
404
+ for (const a of data) {
405
+ const r = await Deferred_js_1.Deferred.toPromise(f(a)());
406
+ if (Result_js_1.Result.isErr(r))
407
+ return r;
408
+ result.push(r.value);
409
+ }
410
+ return Result_js_1.Result.ok(result);
411
+ });
412
+ /**
413
+ * Collects an array of TaskResults into a TaskResult of array.
414
+ * Returns the first Err if any element is Err, runs sequentially.
415
+ */
416
+ Arr.sequenceTaskResult = (data) => Arr.traverseTaskResult((a) => a)(data);
382
417
  /**
383
418
  * Returns true if the array is non-empty (type guard).
384
419
  */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Deferred = void 0;
4
+ const _store = new WeakMap();
4
5
  var Deferred;
5
6
  (function (Deferred) {
6
7
  /**
@@ -13,9 +14,11 @@ var Deferred;
13
14
  * const value = await d; // "hello"
14
15
  * ```
15
16
  */
16
- Deferred.fromPromise = (p) => ({
17
- then: ((f) => p.then(f)),
18
- });
17
+ Deferred.fromPromise = (p) => {
18
+ const d = ({ then: ((f) => p.then(f)) });
19
+ _store.set(d, p);
20
+ return d;
21
+ };
19
22
  /**
20
23
  * Converts a `Deferred` back into a `Promise`.
21
24
  *
@@ -25,5 +28,6 @@ var Deferred;
25
28
  * // p is Promise<42>
26
29
  * ```
27
30
  */
28
- Deferred.toPromise = (d) => new Promise((resolve) => d.then(resolve));
31
+ Deferred.toPromise = (d) => _store.get(d) ??
32
+ new Promise((resolve) => d.then(resolve));
29
33
  })(Deferred || (exports.Deferred = Deferred = {}));
@@ -28,7 +28,7 @@ var Logged;
28
28
  * @example
29
29
  * ```ts
30
30
  * pipe(
31
- * Logged.of<string, number>(5),
31
+ * Logged.make<string, number>(5),
32
32
  * Logged.map(n => n * 2),
33
33
  * ); // { value: 10, log: [] }
34
34
  * ```
@@ -47,7 +47,7 @@ var Logged;
47
47
  * @example
48
48
  * ```ts
49
49
  * const result = pipe(
50
- * Logged.of<string, number>(1),
50
+ * Logged.make<string, number>(1),
51
51
  * Logged.chain(n => pipe(Logged.tell("step"), Logged.map(() => n + 1))),
52
52
  * Logged.chain(n => pipe(Logged.tell("done"), Logged.map(() => n * 10))),
53
53
  * );
@@ -86,7 +86,7 @@ var Logged;
86
86
  * @example
87
87
  * ```ts
88
88
  * pipe(
89
- * Logged.of<string, number>(42),
89
+ * Logged.make<string, number>(42),
90
90
  * Logged.tap(n => console.log("value:", n)),
91
91
  * );
92
92
  * ```
@@ -102,7 +102,7 @@ var Logged;
102
102
  * @example
103
103
  * ```ts
104
104
  * const result = pipe(
105
- * Logged.of<string, number>(1),
105
+ * Logged.make<string, number>(1),
106
106
  * Logged.chain(n => pipe(Logged.tell("incremented"), Logged.map(() => n + 1))),
107
107
  * );
108
108
  *
@@ -131,16 +131,17 @@ var Option;
131
131
  Option.match = (cases) => (data) => Option.isSome(data) ? cases.some(data.value) : cases.none();
132
132
  /**
133
133
  * Returns the value inside an Option, or a default value if None.
134
+ * The default is a thunk `() => B` — evaluated only when the Option is None.
134
135
  * The default can be a different type, widening the result to `A | B`.
135
136
  *
136
137
  * @example
137
138
  * ```ts
138
- * pipe(Option.some(5), Option.getOrElse(0)); // 5
139
- * pipe(Option.none(), Option.getOrElse(0)); // 0
140
- * pipe(Option.none<string>(), Option.getOrElse(null)); // null — typed as string | null
139
+ * pipe(Option.some(5), Option.getOrElse(() => 0)); // 5
140
+ * pipe(Option.none(), Option.getOrElse(() => 0)); // 0
141
+ * pipe(Option.none<string>(), Option.getOrElse(() => null)); // null — typed as string | null
141
142
  * ```
142
143
  */
143
- Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue;
144
+ Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue();
144
145
  /**
145
146
  * Executes a side effect on the value without changing the Option.
146
147
  * Useful for logging or debugging.
@@ -169,7 +170,7 @@ var Option;
169
170
  * pipe(Option.some(2), Option.filter(n => n > 3)); // None
170
171
  * ```
171
172
  */
172
- Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.none();
173
+ Option.filter = (predicate) => (data) => Option.isSome(data) ? (predicate(data.value) ? data : Option.none()) : data;
173
174
  /**
174
175
  * Recovers from a None by providing a fallback Option.
175
176
  * The fallback can produce a different type, widening the result to `Option<A | B>`.
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RemoteData = void 0;
4
+ const Option_js_1 = require("./Option.js");
5
+ const Result_js_1 = require("./Result.js");
4
6
  var RemoteData;
5
7
  (function (RemoteData) {
6
8
  /**
@@ -165,7 +167,7 @@ var RemoteData;
165
167
  * pipe(RemoteData.loading<string, number>(), RemoteData.getOrElse(null)); // null — typed as number | null
166
168
  * ```
167
169
  */
168
- RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue;
170
+ RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue();
169
171
  /**
170
172
  * Executes a side effect on the success value without changing the RemoteData.
171
173
  *
@@ -192,7 +194,7 @@ var RemoteData;
192
194
  * Converts a RemoteData to an Option.
193
195
  * Success becomes Some, all other states become None.
194
196
  */
195
- RemoteData.toOption = (data) => RemoteData.isSuccess(data) ? { kind: "Some", value: data.value } : { kind: "None" };
197
+ RemoteData.toOption = (data) => RemoteData.isSuccess(data) ? Option_js_1.Option.some(data.value) : Option_js_1.Option.none();
196
198
  /**
197
199
  * Converts a RemoteData to a Result.
198
200
  * Success becomes Ok, Failure becomes Err.
@@ -207,6 +209,6 @@ var RemoteData;
207
209
  * ```
208
210
  */
209
211
  RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data)
210
- ? { kind: "Ok", value: data.value }
211
- : { kind: "Error", error: RemoteData.isFailure(data) ? data.error : onNotReady() };
212
+ ? Result_js_1.Result.ok(data.value)
213
+ : Result_js_1.Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
212
214
  })(RemoteData || (exports.RemoteData = RemoteData = {}));
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Result = void 0;
4
+ const Option_js_1 = require("./Option.js");
4
5
  var Result;
5
6
  (function (Result) {
6
7
  /**
@@ -105,16 +106,17 @@ var Result;
105
106
  Result.match = (cases) => (data) => Result.isOk(data) ? cases.ok(data.value) : cases.err(data.error);
106
107
  /**
107
108
  * Returns the success value or a default value if the Result is an error.
109
+ * The default is a thunk `() => B` — evaluated only when the Result is Err.
108
110
  * The default can be a different type, widening the result to `A | B`.
109
111
  *
110
112
  * @example
111
113
  * ```ts
112
- * pipe(Result.ok(5), Result.getOrElse(0)); // 5
113
- * pipe(Result.err("error"), Result.getOrElse(0)); // 0
114
- * pipe(Result.err("error"), Result.getOrElse(null)); // null — typed as number | null
114
+ * pipe(Result.ok(5), Result.getOrElse(() => 0)); // 5
115
+ * pipe(Result.err("error"), Result.getOrElse(() => 0)); // 0
116
+ * pipe(Result.err("error"), Result.getOrElse(() => null)); // null — typed as number | null
115
117
  * ```
116
118
  */
117
- Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue;
119
+ Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue();
118
120
  /**
119
121
  * Executes a side effect on the success value without changing the Result.
120
122
  * Useful for logging or debugging.
@@ -137,7 +139,7 @@ var Result;
137
139
  * Recovers from an error by providing a fallback Result.
138
140
  * The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
139
141
  */
140
- Result.recover = (fallback) => (data) => Result.isOk(data) ? data : fallback();
142
+ Result.recover = (fallback) => (data) => Result.isOk(data) ? data : fallback(data.error);
141
143
  /**
142
144
  * Recovers from an error unless it matches the blocked error.
143
145
  * The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
@@ -153,7 +155,7 @@ var Result;
153
155
  * Result.toOption(Result.err("oops")); // None
154
156
  * ```
155
157
  */
156
- Result.toOption = (data) => Result.isOk(data) ? { kind: "Some", value: data.value } : { kind: "None" };
158
+ Result.toOption = (data) => Result.isOk(data) ? Option_js_1.Option.some(data.value) : Option_js_1.Option.none();
157
159
  /**
158
160
  * Applies a function wrapped in an Result to a value wrapped in an Result.
159
161
  *