@nlozgachev/pipelined 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -375,8 +375,9 @@ var Result;
375
375
  if ((0, Result2.isErr)(data)) f(data.error);
376
376
  return data;
377
377
  };
378
+ Result2.fromPredicate = (pred, onFalse) => (a) => pred(a) ? (0, Result2.ok)(a) : (0, Result2.err)(onFalse(a));
378
379
  Result2.recover = (fallback) => (data) => (0, Result2.isOk)(data) ? data : fallback(data.error);
379
- Result2.recoverUnless = (blockedErr, fallback) => (data) => (0, Result2.isErr)(data) && data.error !== blockedErr ? fallback() : data;
380
+ Result2.recoverUnless = (isBlocked, fallback) => (data) => (0, Result2.isErr)(data) && !isBlocked(data.error) ? fallback() : data;
380
381
  Result2.toMaybe = (data) => (0, Result2.isOk)(data) ? Maybe.some(data.value) : Maybe.none();
381
382
  Result2.ap = (arg) => (data) => (0, Result2.isOk)(data) && (0, Result2.isOk)(arg) ? (0, Result2.ok)(data.value(arg.value)) : (0, Result2.isErr)(data) ? data : arg;
382
383
  })(Result || (Result = {}));
@@ -392,7 +393,6 @@ var Maybe;
392
393
  Maybe2.fromNullable = (value) => value === null || value === void 0 ? (0, Maybe2.none)() : (0, Maybe2.some)(value);
393
394
  Maybe2.toNullable = (data) => (0, Maybe2.isSome)(data) ? data.value : null;
394
395
  Maybe2.toUndefined = (data) => (0, Maybe2.isSome)(data) ? data.value : void 0;
395
- Maybe2.fromUndefined = (value) => value === void 0 ? (0, Maybe2.none)() : (0, Maybe2.some)(value);
396
396
  Maybe2.fromPredicate = (pred) => (a) => pred(a) ? (0, Maybe2.some)(a) : (0, Maybe2.none)();
397
397
  Maybe2.toResult = (onNone) => (data) => (0, Maybe2.isSome)(data) ? Result.ok(data.value) : Result.err(onNone());
398
398
  Maybe2.fromResult = (data) => Result.isOk(data) ? (0, Maybe2.some)(data.value) : (0, Maybe2.none)();
@@ -1445,10 +1445,15 @@ var RemoteData;
1445
1445
  if ((0, RemoteData2.isSuccess)(data)) f(data.value);
1446
1446
  return data;
1447
1447
  };
1448
+ RemoteData2.tapError = (f) => (data) => {
1449
+ if ((0, RemoteData2.isFailure)(data)) f(data.error);
1450
+ return data;
1451
+ };
1448
1452
  RemoteData2.recover = (fallback) => (data) => (0, RemoteData2.isFailure)(data) ? fallback(data.error) : data;
1449
1453
  RemoteData2.toMaybe = (data) => (0, RemoteData2.isSuccess)(data) ? Maybe.some(data.value) : Maybe.none();
1450
1454
  RemoteData2.toResult = (onNotReady) => (data) => (0, RemoteData2.isSuccess)(data) ? Result.ok(data.value) : Result.err((0, RemoteData2.isFailure)(data) ? data.error : onNotReady());
1451
1455
  RemoteData2.fromResult = (data) => Result.isOk(data) ? (0, RemoteData2.success)(data.value) : (0, RemoteData2.failure)(data.error);
1456
+ RemoteData2.fromMaybe = (onNone) => (data) => Maybe.isSome(data) ? (0, RemoteData2.success)(data.value) : (0, RemoteData2.failure)(onNone());
1452
1457
  })(RemoteData || (RemoteData = {}));
1453
1458
 
1454
1459
  // src/Core/Task.ts
@@ -1457,6 +1462,7 @@ var Task;
1457
1462
  ((Task2) => {
1458
1463
  Task2.resolve = (value) => () => Deferred.fromPromise(Promise.resolve(value));
1459
1464
  Task2.from = (f) => (signal) => Deferred.fromPromise(f(signal));
1465
+ Task2.fromSync = (f) => () => Deferred.fromPromise(Promise.resolve(f()));
1460
1466
  Task2.map = (f) => (data) => (0, Task2.from)((signal) => toPromise(data, signal).then(f));
1461
1467
  Task2.chain = (f) => (data) => (0, Task2.from)((signal) => toPromise(data, signal).then((a) => toPromise(f(a), signal)));
1462
1468
  Task2.ap = (arg) => (data) => (0, Task2.from)(
@@ -1495,13 +1501,14 @@ var Task;
1495
1501
  return run(times);
1496
1502
  });
1497
1503
  Task2.repeatUntil = (options) => (task) => (0, Task2.from)((signal) => {
1498
- const { when: predicate, delay: ms } = options;
1504
+ const { when: predicate, delay: ms, maxAttempts } = options;
1499
1505
  const wait = () => ms !== void 0 && ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
1500
- const run = () => toPromise(task, signal).then((a) => {
1506
+ const run = (attempt) => toPromise(task, signal).then((a) => {
1501
1507
  if (predicate(a)) return a;
1502
- return wait().then(run);
1508
+ if (maxAttempts !== void 0 && attempt >= maxAttempts) return a;
1509
+ return wait().then(() => run(attempt + 1));
1503
1510
  });
1504
- return run();
1511
+ return run(1);
1505
1512
  });
1506
1513
  Task2.race = (tasks) => (0, Task2.from)((signal) => Promise.race(tasks.map((t) => toPromise(t, signal))));
1507
1514
  Task2.sequential = (tasks) => (0, Task2.from)(async (signal) => {
@@ -1532,8 +1539,12 @@ var Task;
1532
1539
  ]);
1533
1540
  });
1534
1541
  Task2.abortable = (factory) => {
1535
- const controller = new AbortController();
1542
+ let currentController = null;
1543
+ const abort = () => currentController?.abort();
1536
1544
  const task = (outerSignal) => {
1545
+ currentController?.abort();
1546
+ currentController = new AbortController();
1547
+ const controller = currentController;
1537
1548
  if (outerSignal) {
1538
1549
  if (outerSignal.aborted) {
1539
1550
  controller.abort(outerSignal.reason);
@@ -1543,7 +1554,7 @@ var Task;
1543
1554
  }
1544
1555
  return Deferred.fromPromise(factory(controller.signal));
1545
1556
  };
1546
- return { task, abort: () => controller.abort() };
1557
+ return { task, abort };
1547
1558
  };
1548
1559
  })(Task || (Task = {}));
1549
1560
 
@@ -1678,6 +1689,7 @@ var Validation;
1678
1689
  });
1679
1690
  Validation2.isValid = (data) => data.kind === "Valid";
1680
1691
  Validation2.isInvalid = (data) => data.kind === "Invalid";
1692
+ Validation2.fromPredicate = (pred, onFalse) => (a) => pred(a) ? (0, Validation2.valid)(a) : (0, Validation2.invalid)(onFalse(a));
1681
1693
  Validation2.map = (f) => (data) => (0, Validation2.isValid)(data) ? (0, Validation2.valid)(f(data.value)) : data;
1682
1694
  Validation2.ap = (arg) => (data) => {
1683
1695
  if ((0, Validation2.isValid)(data) && (0, Validation2.isValid)(arg)) return (0, Validation2.valid)(data.value(arg.value));
@@ -1694,8 +1706,13 @@ var Validation;
1694
1706
  if ((0, Validation2.isValid)(data)) f(data.value);
1695
1707
  return data;
1696
1708
  };
1709
+ Validation2.tapError = (f) => (data) => {
1710
+ if ((0, Validation2.isInvalid)(data)) f(data.errors);
1711
+ return data;
1712
+ };
1697
1713
  Validation2.recover = (fallback) => (data) => (0, Validation2.isValid)(data) ? data : fallback(data.errors);
1698
- Validation2.recoverUnless = (blockedErrors, fallback) => (data) => (0, Validation2.isInvalid)(data) && !data.errors.some((err2) => blockedErrors.includes(err2)) ? fallback() : data;
1714
+ Validation2.recoverUnless = (isBlocked, fallback) => (data) => (0, Validation2.isInvalid)(data) && !data.errors.some(isBlocked) ? fallback() : data;
1715
+ Validation2.toResult = (data) => (0, Validation2.isValid)(data) ? Result.ok(data.value) : Result.err(data.errors);
1699
1716
  Validation2.product = (first, second) => {
1700
1717
  if ((0, Validation2.isValid)(first) && (0, Validation2.isValid)(second)) return (0, Validation2.valid)([first.value, second.value]);
1701
1718
  const errors = [
@@ -1869,6 +1886,12 @@ var Arr;
1869
1886
  for (let i = 0; i < n; i++) result[i] = f(data[i]);
1870
1887
  return result;
1871
1888
  };
1889
+ Arr2.mapWithIndex = (f) => (data) => {
1890
+ const n = data.length;
1891
+ const result = new Array(n);
1892
+ for (let i = 0; i < n; i++) result[i] = f(i, data[i]);
1893
+ return result;
1894
+ };
1872
1895
  Arr2.filter = (predicate) => (data) => {
1873
1896
  const n = data.length;
1874
1897
  const result = [];
@@ -2195,7 +2218,13 @@ var Num;
2195
2218
  Num2.add = (b) => (a) => a + b;
2196
2219
  Num2.subtract = (b) => (a) => a - b;
2197
2220
  Num2.multiply = (b) => (a) => a * b;
2198
- Num2.divide = (b) => (a) => a / b;
2221
+ Num2.divide = (b) => (a) => b === 0 ? Maybe.none() : Maybe.some(a / b);
2222
+ Num2.abs = (n) => Math.abs(n);
2223
+ Num2.negate = (n) => -n;
2224
+ Num2.round = (n) => Math.round(n);
2225
+ Num2.floor = (n) => Math.floor(n);
2226
+ Num2.ceil = (n) => Math.ceil(n);
2227
+ Num2.remainder = (divisor) => (n) => divisor === 0 ? Maybe.none() : Maybe.some(n % divisor);
2199
2228
  })(Num || (Num = {}));
2200
2229
 
2201
2230
  // src/Utils/Rec.ts
@@ -2321,6 +2350,12 @@ var Str;
2321
2350
  Str2.toLowerCase = (s) => s.toLowerCase();
2322
2351
  Str2.lines = (s) => s.split(/\r?\n|\r/);
2323
2352
  Str2.words = (s) => s.trim().split(/\s+/).filter(Boolean);
2353
+ Str2.isEmpty = (s) => s.length === 0;
2354
+ Str2.isBlank = (s) => s.trim().length === 0;
2355
+ Str2.length = (s) => s.length;
2356
+ Str2.slice = (start, end) => (s) => s.slice(start, end);
2357
+ Str2.padStart = (maxLength, fillString) => (s) => s.padStart(maxLength, fillString);
2358
+ Str2.padEnd = (maxLength, fillString) => (s) => s.padEnd(maxLength, fillString);
2324
2359
  Str2.parse = {
2325
2360
  /**
2326
2361
  * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
package/dist/index.mjs CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  These,
45
45
  Tuple,
46
46
  Validation
47
- } from "./chunk-NTISCH7Z.mjs";
47
+ } from "./chunk-QJS6D6MW.mjs";
48
48
  import {
49
49
  Arr,
50
50
  Dict,
@@ -52,13 +52,13 @@ import {
52
52
  Rec,
53
53
  Str,
54
54
  Uniq
55
- } from "./chunk-6H373E63.mjs";
55
+ } from "./chunk-CA3VE4YD.mjs";
56
56
  import {
57
57
  Deferred,
58
58
  Maybe,
59
59
  Result,
60
60
  Task
61
- } from "./chunk-Z3DYYR43.mjs";
61
+ } from "./chunk-7JF44HJH.mjs";
62
62
  import {
63
63
  Brand
64
64
  } from "./chunk-BYWKZLHM.mjs";
package/dist/utils.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { M as Maybe, R as Result, T as Task } from './Task-BoqaFsUR.mjs';
1
+ import { M as Maybe, R as Result, T as Task } from './Task-BZT0wedE.mjs';
2
2
  import { N as NonEmptyList } from './NonEmptyList-BlGFjor5.mjs';
3
3
 
4
4
  /**
@@ -93,6 +93,18 @@ declare namespace Arr {
93
93
  * ```
94
94
  */
95
95
  const map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
96
+ /**
97
+ * Transforms each element using both its value and its zero-based index.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * pipe(
102
+ * ["a", "b", "c"],
103
+ * Arr.mapWithIndex((i, s) => ({ position: i + 1, value: s }))
104
+ * ); // [{ position: 1, value: "a" }, { position: 2, value: "b" }, { position: 3, value: "c" }]
105
+ * ```
106
+ */
107
+ const mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
96
108
  /**
97
109
  * Filters elements that satisfy the predicate.
98
110
  *
@@ -846,15 +858,78 @@ declare namespace Num {
846
858
  */
847
859
  const multiply: (b: number) => (a: number) => number;
848
860
  /**
849
- * Divides a number by `b`. Data-last: `divide(b)(a)` = `a / b`.
861
+ * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
862
+ *
863
+ * @example
864
+ * ```ts
865
+ * pipe(20, Num.divide(4)); // Some(5)
866
+ * pipe(5, Num.divide(0)); // None
867
+ * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
868
+ * ```
869
+ */
870
+ const divide: (b: number) => (a: number) => Maybe<number>;
871
+ /**
872
+ * Returns the absolute value of a number.
873
+ *
874
+ * @example
875
+ * ```ts
876
+ * pipe(-5, Num.abs); // 5
877
+ * pipe(5, Num.abs); // 5
878
+ * ```
879
+ */
880
+ const abs: (n: number) => number;
881
+ /**
882
+ * Negates a number (arithmetic negation).
883
+ *
884
+ * @example
885
+ * ```ts
886
+ * pipe(5, Num.negate); // -5
887
+ * pipe(-5, Num.negate); // 5
888
+ * ```
889
+ */
890
+ const negate: (n: number) => number;
891
+ /**
892
+ * Rounds a number to the nearest integer.
893
+ *
894
+ * @example
895
+ * ```ts
896
+ * pipe(3.5, Num.round); // 4
897
+ * pipe(3.4, Num.round); // 3
898
+ * ```
899
+ */
900
+ const round: (n: number) => number;
901
+ /**
902
+ * Rounds a number down to the nearest integer.
903
+ *
904
+ * @example
905
+ * ```ts
906
+ * pipe(3.9, Num.floor); // 3
907
+ * pipe(-3.2, Num.floor); // -4
908
+ * ```
909
+ */
910
+ const floor: (n: number) => number;
911
+ /**
912
+ * Rounds a number up to the nearest integer.
850
913
  *
851
914
  * @example
852
915
  * ```ts
853
- * pipe(20, Num.divide(4)); // 5
854
- * pipe([10, 20, 30], Arr.map(Num.divide(10))); // [1, 2, 3]
916
+ * pipe(3.1, Num.ceil); // 4
917
+ * pipe(-3.9, Num.ceil); // -3
855
918
  * ```
856
919
  */
857
- const divide: (b: number) => (a: number) => number;
920
+ const ceil: (n: number) => number;
921
+ /**
922
+ * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
923
+ * Data-last: `remainder(divisor)(a)` = `a % divisor`.
924
+ *
925
+ * @example
926
+ * ```ts
927
+ * pipe(10, Num.remainder(3)); // Some(1)
928
+ * pipe(5, Num.remainder(0)); // None
929
+ * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
930
+ * ```
931
+ */
932
+ const remainder: (divisor: number) => (n: number) => Maybe<number>;
858
933
  }
859
934
 
860
935
  /**
@@ -1133,6 +1208,66 @@ declare namespace Str {
1133
1208
  * ```
1134
1209
  */
1135
1210
  const words: (s: string) => readonly string[];
1211
+ /**
1212
+ * Returns `true` when the string is empty.
1213
+ *
1214
+ * @example
1215
+ * ```ts
1216
+ * pipe("", Str.isEmpty); // true
1217
+ * pipe("hi", Str.isEmpty); // false
1218
+ * ```
1219
+ */
1220
+ const isEmpty: (s: string) => boolean;
1221
+ /**
1222
+ * Returns `true` when the string is empty or contains only whitespace.
1223
+ *
1224
+ * @example
1225
+ * ```ts
1226
+ * pipe(" ", Str.isBlank); // true
1227
+ * pipe("hi", Str.isBlank); // false
1228
+ * ```
1229
+ */
1230
+ const isBlank: (s: string) => boolean;
1231
+ /**
1232
+ * Returns the length of the string.
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * pipe("hello", Str.length); // 5
1237
+ * pipe("", Str.length); // 0
1238
+ * ```
1239
+ */
1240
+ const length: (s: string) => number;
1241
+ /**
1242
+ * Extracts a substring between two indices. Data-last: use in `pipe`.
1243
+ *
1244
+ * @example
1245
+ * ```ts
1246
+ * pipe("hello", Str.slice(1, 3)); // "el"
1247
+ * pipe("hello", Str.slice(2)); // "llo"
1248
+ * ```
1249
+ */
1250
+ const slice: (start: number, end?: number) => (s: string) => string;
1251
+ /**
1252
+ * Pads the start of a string to a specified length. Data-last: use in `pipe`.
1253
+ *
1254
+ * @example
1255
+ * ```ts
1256
+ * pipe("5", Str.padStart(3, "0")); // "005"
1257
+ * pipe("hi", Str.padStart(5)); // " hi"
1258
+ * ```
1259
+ */
1260
+ const padStart: (maxLength: number, fillString?: string) => (s: string) => string;
1261
+ /**
1262
+ * Pads the end of a string to a specified length. Data-last: use in `pipe`.
1263
+ *
1264
+ * @example
1265
+ * ```ts
1266
+ * pipe("hi", Str.padEnd(5, ".")); // "hi..."
1267
+ * pipe("hi", Str.padEnd(5)); // "hi "
1268
+ * ```
1269
+ */
1270
+ const padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
1136
1271
  /**
1137
1272
  * Safe number parsers that return `Maybe` instead of `NaN`.
1138
1273
  */
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { M as Maybe, R as Result, T as Task } from './Task-7brqoQrb.js';
1
+ import { M as Maybe, R as Result, T as Task } from './Task-BW66NsGR.js';
2
2
  import { N as NonEmptyList } from './NonEmptyList-BlGFjor5.js';
3
3
 
4
4
  /**
@@ -93,6 +93,18 @@ declare namespace Arr {
93
93
  * ```
94
94
  */
95
95
  const map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
96
+ /**
97
+ * Transforms each element using both its value and its zero-based index.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * pipe(
102
+ * ["a", "b", "c"],
103
+ * Arr.mapWithIndex((i, s) => ({ position: i + 1, value: s }))
104
+ * ); // [{ position: 1, value: "a" }, { position: 2, value: "b" }, { position: 3, value: "c" }]
105
+ * ```
106
+ */
107
+ const mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
96
108
  /**
97
109
  * Filters elements that satisfy the predicate.
98
110
  *
@@ -846,15 +858,78 @@ declare namespace Num {
846
858
  */
847
859
  const multiply: (b: number) => (a: number) => number;
848
860
  /**
849
- * Divides a number by `b`. Data-last: `divide(b)(a)` = `a / b`.
861
+ * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
862
+ *
863
+ * @example
864
+ * ```ts
865
+ * pipe(20, Num.divide(4)); // Some(5)
866
+ * pipe(5, Num.divide(0)); // None
867
+ * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
868
+ * ```
869
+ */
870
+ const divide: (b: number) => (a: number) => Maybe<number>;
871
+ /**
872
+ * Returns the absolute value of a number.
873
+ *
874
+ * @example
875
+ * ```ts
876
+ * pipe(-5, Num.abs); // 5
877
+ * pipe(5, Num.abs); // 5
878
+ * ```
879
+ */
880
+ const abs: (n: number) => number;
881
+ /**
882
+ * Negates a number (arithmetic negation).
883
+ *
884
+ * @example
885
+ * ```ts
886
+ * pipe(5, Num.negate); // -5
887
+ * pipe(-5, Num.negate); // 5
888
+ * ```
889
+ */
890
+ const negate: (n: number) => number;
891
+ /**
892
+ * Rounds a number to the nearest integer.
893
+ *
894
+ * @example
895
+ * ```ts
896
+ * pipe(3.5, Num.round); // 4
897
+ * pipe(3.4, Num.round); // 3
898
+ * ```
899
+ */
900
+ const round: (n: number) => number;
901
+ /**
902
+ * Rounds a number down to the nearest integer.
903
+ *
904
+ * @example
905
+ * ```ts
906
+ * pipe(3.9, Num.floor); // 3
907
+ * pipe(-3.2, Num.floor); // -4
908
+ * ```
909
+ */
910
+ const floor: (n: number) => number;
911
+ /**
912
+ * Rounds a number up to the nearest integer.
850
913
  *
851
914
  * @example
852
915
  * ```ts
853
- * pipe(20, Num.divide(4)); // 5
854
- * pipe([10, 20, 30], Arr.map(Num.divide(10))); // [1, 2, 3]
916
+ * pipe(3.1, Num.ceil); // 4
917
+ * pipe(-3.9, Num.ceil); // -3
855
918
  * ```
856
919
  */
857
- const divide: (b: number) => (a: number) => number;
920
+ const ceil: (n: number) => number;
921
+ /**
922
+ * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
923
+ * Data-last: `remainder(divisor)(a)` = `a % divisor`.
924
+ *
925
+ * @example
926
+ * ```ts
927
+ * pipe(10, Num.remainder(3)); // Some(1)
928
+ * pipe(5, Num.remainder(0)); // None
929
+ * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
930
+ * ```
931
+ */
932
+ const remainder: (divisor: number) => (n: number) => Maybe<number>;
858
933
  }
859
934
 
860
935
  /**
@@ -1133,6 +1208,66 @@ declare namespace Str {
1133
1208
  * ```
1134
1209
  */
1135
1210
  const words: (s: string) => readonly string[];
1211
+ /**
1212
+ * Returns `true` when the string is empty.
1213
+ *
1214
+ * @example
1215
+ * ```ts
1216
+ * pipe("", Str.isEmpty); // true
1217
+ * pipe("hi", Str.isEmpty); // false
1218
+ * ```
1219
+ */
1220
+ const isEmpty: (s: string) => boolean;
1221
+ /**
1222
+ * Returns `true` when the string is empty or contains only whitespace.
1223
+ *
1224
+ * @example
1225
+ * ```ts
1226
+ * pipe(" ", Str.isBlank); // true
1227
+ * pipe("hi", Str.isBlank); // false
1228
+ * ```
1229
+ */
1230
+ const isBlank: (s: string) => boolean;
1231
+ /**
1232
+ * Returns the length of the string.
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * pipe("hello", Str.length); // 5
1237
+ * pipe("", Str.length); // 0
1238
+ * ```
1239
+ */
1240
+ const length: (s: string) => number;
1241
+ /**
1242
+ * Extracts a substring between two indices. Data-last: use in `pipe`.
1243
+ *
1244
+ * @example
1245
+ * ```ts
1246
+ * pipe("hello", Str.slice(1, 3)); // "el"
1247
+ * pipe("hello", Str.slice(2)); // "llo"
1248
+ * ```
1249
+ */
1250
+ const slice: (start: number, end?: number) => (s: string) => string;
1251
+ /**
1252
+ * Pads the start of a string to a specified length. Data-last: use in `pipe`.
1253
+ *
1254
+ * @example
1255
+ * ```ts
1256
+ * pipe("5", Str.padStart(3, "0")); // "005"
1257
+ * pipe("hi", Str.padStart(5)); // " hi"
1258
+ * ```
1259
+ */
1260
+ const padStart: (maxLength: number, fillString?: string) => (s: string) => string;
1261
+ /**
1262
+ * Pads the end of a string to a specified length. Data-last: use in `pipe`.
1263
+ *
1264
+ * @example
1265
+ * ```ts
1266
+ * pipe("hi", Str.padEnd(5, ".")); // "hi..."
1267
+ * pipe("hi", Str.padEnd(5)); // "hi "
1268
+ * ```
1269
+ */
1270
+ const padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
1136
1271
  /**
1137
1272
  * Safe number parsers that return `Maybe` instead of `NaN`.
1138
1273
  */
package/dist/utils.js CHANGED
@@ -67,8 +67,9 @@ var Result;
67
67
  if ((0, Result2.isErr)(data)) f(data.error);
68
68
  return data;
69
69
  };
70
+ Result2.fromPredicate = (pred, onFalse) => (a) => pred(a) ? (0, Result2.ok)(a) : (0, Result2.err)(onFalse(a));
70
71
  Result2.recover = (fallback) => (data) => (0, Result2.isOk)(data) ? data : fallback(data.error);
71
- Result2.recoverUnless = (blockedErr, fallback) => (data) => (0, Result2.isErr)(data) && data.error !== blockedErr ? fallback() : data;
72
+ Result2.recoverUnless = (isBlocked, fallback) => (data) => (0, Result2.isErr)(data) && !isBlocked(data.error) ? fallback() : data;
72
73
  Result2.toMaybe = (data) => (0, Result2.isOk)(data) ? Maybe.some(data.value) : Maybe.none();
73
74
  Result2.ap = (arg) => (data) => (0, Result2.isOk)(data) && (0, Result2.isOk)(arg) ? (0, Result2.ok)(data.value(arg.value)) : (0, Result2.isErr)(data) ? data : arg;
74
75
  })(Result || (Result = {}));
@@ -84,7 +85,6 @@ var Maybe;
84
85
  Maybe2.fromNullable = (value) => value === null || value === void 0 ? (0, Maybe2.none)() : (0, Maybe2.some)(value);
85
86
  Maybe2.toNullable = (data) => (0, Maybe2.isSome)(data) ? data.value : null;
86
87
  Maybe2.toUndefined = (data) => (0, Maybe2.isSome)(data) ? data.value : void 0;
87
- Maybe2.fromUndefined = (value) => value === void 0 ? (0, Maybe2.none)() : (0, Maybe2.some)(value);
88
88
  Maybe2.fromPredicate = (pred) => (a) => pred(a) ? (0, Maybe2.some)(a) : (0, Maybe2.none)();
89
89
  Maybe2.toResult = (onNone) => (data) => (0, Maybe2.isSome)(data) ? Result.ok(data.value) : Result.err(onNone());
90
90
  Maybe2.fromResult = (data) => Result.isOk(data) ? (0, Maybe2.some)(data.value) : (0, Maybe2.none)();
@@ -108,6 +108,7 @@ var Task;
108
108
  ((Task2) => {
109
109
  Task2.resolve = (value) => () => Deferred.fromPromise(Promise.resolve(value));
110
110
  Task2.from = (f) => (signal) => Deferred.fromPromise(f(signal));
111
+ Task2.fromSync = (f) => () => Deferred.fromPromise(Promise.resolve(f()));
111
112
  Task2.map = (f) => (data) => (0, Task2.from)((signal) => toPromise(data, signal).then(f));
112
113
  Task2.chain = (f) => (data) => (0, Task2.from)((signal) => toPromise(data, signal).then((a) => toPromise(f(a), signal)));
113
114
  Task2.ap = (arg) => (data) => (0, Task2.from)(
@@ -146,13 +147,14 @@ var Task;
146
147
  return run(times);
147
148
  });
148
149
  Task2.repeatUntil = (options) => (task) => (0, Task2.from)((signal) => {
149
- const { when: predicate, delay: ms } = options;
150
+ const { when: predicate, delay: ms, maxAttempts } = options;
150
151
  const wait = () => ms !== void 0 && ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
151
- const run = () => toPromise(task, signal).then((a) => {
152
+ const run = (attempt) => toPromise(task, signal).then((a) => {
152
153
  if (predicate(a)) return a;
153
- return wait().then(run);
154
+ if (maxAttempts !== void 0 && attempt >= maxAttempts) return a;
155
+ return wait().then(() => run(attempt + 1));
154
156
  });
155
- return run();
157
+ return run(1);
156
158
  });
157
159
  Task2.race = (tasks) => (0, Task2.from)((signal) => Promise.race(tasks.map((t) => toPromise(t, signal))));
158
160
  Task2.sequential = (tasks) => (0, Task2.from)(async (signal) => {
@@ -183,8 +185,12 @@ var Task;
183
185
  ]);
184
186
  });
185
187
  Task2.abortable = (factory) => {
186
- const controller = new AbortController();
188
+ let currentController = null;
189
+ const abort = () => currentController?.abort();
187
190
  const task = (outerSignal) => {
191
+ currentController?.abort();
192
+ currentController = new AbortController();
193
+ const controller = currentController;
188
194
  if (outerSignal) {
189
195
  if (outerSignal.aborted) {
190
196
  controller.abort(outerSignal.reason);
@@ -194,7 +200,7 @@ var Task;
194
200
  }
195
201
  return Deferred.fromPromise(factory(controller.signal));
196
202
  };
197
- return { task, abort: () => controller.abort() };
203
+ return { task, abort };
198
204
  };
199
205
  })(Task || (Task = {}));
200
206
 
@@ -228,6 +234,12 @@ var Arr;
228
234
  for (let i = 0; i < n; i++) result[i] = f(data[i]);
229
235
  return result;
230
236
  };
237
+ Arr2.mapWithIndex = (f) => (data) => {
238
+ const n = data.length;
239
+ const result = new Array(n);
240
+ for (let i = 0; i < n; i++) result[i] = f(i, data[i]);
241
+ return result;
242
+ };
231
243
  Arr2.filter = (predicate) => (data) => {
232
244
  const n = data.length;
233
245
  const result = [];
@@ -554,7 +566,13 @@ var Num;
554
566
  Num2.add = (b) => (a) => a + b;
555
567
  Num2.subtract = (b) => (a) => a - b;
556
568
  Num2.multiply = (b) => (a) => a * b;
557
- Num2.divide = (b) => (a) => a / b;
569
+ Num2.divide = (b) => (a) => b === 0 ? Maybe.none() : Maybe.some(a / b);
570
+ Num2.abs = (n) => Math.abs(n);
571
+ Num2.negate = (n) => -n;
572
+ Num2.round = (n) => Math.round(n);
573
+ Num2.floor = (n) => Math.floor(n);
574
+ Num2.ceil = (n) => Math.ceil(n);
575
+ Num2.remainder = (divisor) => (n) => divisor === 0 ? Maybe.none() : Maybe.some(n % divisor);
558
576
  })(Num || (Num = {}));
559
577
 
560
578
  // src/Utils/Rec.ts
@@ -680,6 +698,12 @@ var Str;
680
698
  Str2.toLowerCase = (s) => s.toLowerCase();
681
699
  Str2.lines = (s) => s.split(/\r?\n|\r/);
682
700
  Str2.words = (s) => s.trim().split(/\s+/).filter(Boolean);
701
+ Str2.isEmpty = (s) => s.length === 0;
702
+ Str2.isBlank = (s) => s.trim().length === 0;
703
+ Str2.length = (s) => s.length;
704
+ Str2.slice = (start, end) => (s) => s.slice(start, end);
705
+ Str2.padStart = (maxLength, fillString) => (s) => s.padStart(maxLength, fillString);
706
+ Str2.padEnd = (maxLength, fillString) => (s) => s.padEnd(maxLength, fillString);
683
707
  Str2.parse = {
684
708
  /**
685
709
  * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
package/dist/utils.mjs CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  Rec,
6
6
  Str,
7
7
  Uniq
8
- } from "./chunk-6H373E63.mjs";
9
- import "./chunk-Z3DYYR43.mjs";
8
+ } from "./chunk-CA3VE4YD.mjs";
9
+ import "./chunk-7JF44HJH.mjs";
10
10
  import "./chunk-DBIC62UV.mjs";
11
11
  export {
12
12
  Arr,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nlozgachev/pipelined",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Opinionated functional abstractions for TypeScript",
5
5
  "license": "BSD-3-Clause",
6
6
  "homepage": "https://pipelined.lozgachev.dev",