@nlozgachev/pipelined 0.10.0 → 0.12.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/README.md +9 -3
- package/esm/src/Core/Option.js +2 -1
- package/esm/src/Core/RemoteData.js +5 -5
- package/esm/src/Core/TaskValidation.js +1 -3
- package/esm/src/Core/Tuple.js +112 -0
- package/esm/src/Core/index.js +4 -5
- package/esm/src/{Core → Utils}/Arr.js +95 -23
- package/esm/src/Utils/Dict.js +421 -0
- package/esm/src/Utils/Num.js +124 -0
- package/esm/src/{Core → Utils}/Rec.js +85 -11
- package/esm/src/Utils/Str.js +134 -0
- package/esm/src/Utils/Uniq.js +265 -0
- package/esm/src/Utils/index.js +6 -0
- package/package.json +11 -1
- package/script/src/Core/Option.js +2 -1
- package/script/src/Core/RemoteData.js +5 -5
- package/script/src/Core/TaskValidation.js +1 -3
- package/script/src/Core/Tuple.js +115 -0
- package/script/src/Core/index.js +4 -5
- package/script/src/{Core → Utils}/Arr.js +95 -23
- package/script/src/Utils/Dict.js +424 -0
- package/script/src/Utils/Num.js +127 -0
- package/script/src/{Core → Utils}/Rec.js +85 -11
- package/script/src/Utils/Str.js +137 -0
- package/script/src/Utils/Uniq.js +268 -0
- package/script/src/Utils/index.js +22 -0
- package/types/src/Composition/compose.d.ts.map +1 -1
- package/types/src/Composition/converge.d.ts.map +1 -1
- package/types/src/Composition/curry.d.ts.map +1 -1
- package/types/src/Composition/flow.d.ts.map +1 -1
- package/types/src/Composition/fn.d.ts.map +1 -1
- package/types/src/Composition/juxt.d.ts.map +1 -1
- package/types/src/Composition/memoize.d.ts.map +1 -1
- package/types/src/Composition/not.d.ts.map +1 -1
- package/types/src/Composition/on.d.ts.map +1 -1
- package/types/src/Composition/pipe.d.ts.map +1 -1
- package/types/src/Composition/uncurry.d.ts.map +1 -1
- package/types/src/Core/Deferred.d.ts.map +1 -1
- package/types/src/Core/Lens.d.ts.map +1 -1
- package/types/src/Core/Logged.d.ts.map +1 -1
- package/types/src/Core/Option.d.ts.map +1 -1
- package/types/src/Core/Optional.d.ts.map +1 -1
- package/types/src/Core/Predicate.d.ts.map +1 -1
- package/types/src/Core/Reader.d.ts.map +1 -1
- package/types/src/Core/Refinement.d.ts.map +1 -1
- package/types/src/Core/RemoteData.d.ts.map +1 -1
- package/types/src/Core/Result.d.ts.map +1 -1
- package/types/src/Core/State.d.ts.map +1 -1
- package/types/src/Core/Task.d.ts.map +1 -1
- package/types/src/Core/TaskOption.d.ts.map +1 -1
- package/types/src/Core/TaskResult.d.ts.map +1 -1
- package/types/src/Core/TaskValidation.d.ts.map +1 -1
- package/types/src/Core/These.d.ts.map +1 -1
- package/types/src/Core/Tuple.d.ts +129 -0
- package/types/src/Core/Tuple.d.ts.map +1 -0
- package/types/src/Core/Validation.d.ts.map +1 -1
- package/types/src/Core/index.d.ts +4 -5
- package/types/src/Core/index.d.ts.map +1 -1
- package/types/src/Types/Brand.d.ts.map +1 -1
- package/types/src/Types/NonEmptyList.d.ts.map +1 -1
- package/types/src/{Core → Utils}/Arr.d.ts +25 -3
- package/types/src/Utils/Arr.d.ts.map +1 -0
- package/types/src/Utils/Dict.d.ts +310 -0
- package/types/src/Utils/Dict.d.ts.map +1 -0
- package/types/src/Utils/Num.d.ts +110 -0
- package/types/src/Utils/Num.d.ts.map +1 -0
- package/types/src/{Core → Utils}/Rec.d.ts +39 -1
- package/types/src/Utils/Rec.d.ts.map +1 -0
- package/types/src/Utils/Str.d.ts +128 -0
- package/types/src/Utils/Str.d.ts.map +1 -0
- package/types/src/Utils/Uniq.d.ts +179 -0
- package/types/src/Utils/Uniq.d.ts.map +1 -0
- package/types/src/Utils/index.d.ts +7 -0
- package/types/src/Utils/index.d.ts.map +1 -0
- package/types/src/Core/Arr.d.ts.map +0 -1
- package/types/src/Core/Rec.d.ts.map +0 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Option } from "../Core/Option.js";
|
|
2
|
+
/**
|
|
3
|
+
* String utilities. All transformation functions are data-last and curried so they
|
|
4
|
+
* compose naturally with `pipe`. Safe parsers return `Option` instead of `NaN`.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { Str } from "@nlozgachev/pipelined/utils";
|
|
9
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
10
|
+
*
|
|
11
|
+
* pipe(" Hello, World! ", Str.trim, Str.toLowerCase); // "hello, world!"
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export var Str;
|
|
15
|
+
(function (Str) {
|
|
16
|
+
/**
|
|
17
|
+
* Splits a string by a separator. Data-last: use in `pipe`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
Str.split = (separator) => (s) => s.split(separator);
|
|
25
|
+
/**
|
|
26
|
+
* Removes leading and trailing whitespace from a string.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* pipe(" hello ", Str.trim); // "hello"
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
Str.trim = (s) => s.trim();
|
|
34
|
+
/**
|
|
35
|
+
* Returns `true` when the string contains the given substring.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* pipe("hello world", Str.includes("world")); // true
|
|
40
|
+
* pipe("hello world", Str.includes("xyz")); // false
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
Str.includes = (substring) => (s) => s.includes(substring);
|
|
44
|
+
/**
|
|
45
|
+
* Returns `true` when the string starts with the given prefix.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* pipe("hello world", Str.startsWith("hello")); // true
|
|
50
|
+
* pipe("hello world", Str.startsWith("world")); // false
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
Str.startsWith = (prefix) => (s) => s.startsWith(prefix);
|
|
54
|
+
/**
|
|
55
|
+
* Returns `true` when the string ends with the given suffix.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* pipe("hello world", Str.endsWith("world")); // true
|
|
60
|
+
* pipe("hello world", Str.endsWith("hello")); // false
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
Str.endsWith = (suffix) => (s) => s.endsWith(suffix);
|
|
64
|
+
/**
|
|
65
|
+
* Converts a string to uppercase.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* pipe("hello", Str.toUpperCase); // "HELLO"
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
Str.toUpperCase = (s) => s.toUpperCase();
|
|
73
|
+
/**
|
|
74
|
+
* Converts a string to lowercase.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* pipe("HELLO", Str.toLowerCase); // "hello"
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
Str.toLowerCase = (s) => s.toLowerCase();
|
|
82
|
+
/**
|
|
83
|
+
* Splits a string into lines, normalising `\r\n` and `\r` line endings.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* Str.lines("one\ntwo\nthree"); // ["one", "two", "three"]
|
|
88
|
+
* Str.lines("a\r\nb"); // ["a", "b"]
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
Str.lines = (s) => s.split(/\r?\n|\r/);
|
|
92
|
+
/**
|
|
93
|
+
* Splits a string into words on any whitespace boundary, filtering out empty strings.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* Str.words(" hello world "); // ["hello", "world"]
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
Str.words = (s) => s.trim().split(/\s+/).filter(Boolean);
|
|
101
|
+
/**
|
|
102
|
+
* Safe number parsers that return `Option` instead of `NaN`.
|
|
103
|
+
*/
|
|
104
|
+
Str.parse = {
|
|
105
|
+
/**
|
|
106
|
+
* Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* Str.parse.int("42"); // Some(42)
|
|
111
|
+
* Str.parse.int("3.7"); // Some(3)
|
|
112
|
+
* Str.parse.int("abc"); // None
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
int: (s) => {
|
|
116
|
+
const n = parseInt(s, 10);
|
|
117
|
+
return isNaN(n) ? Option.none() : Option.some(n);
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* Str.parse.float("3.14"); // Some(3.14)
|
|
125
|
+
* Str.parse.float("42"); // Some(42)
|
|
126
|
+
* Str.parse.float("abc"); // None
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
float: (s) => {
|
|
130
|
+
const n = parseFloat(s);
|
|
131
|
+
return isNaN(n) ? Option.none() : Option.some(n);
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
})(Str || (Str = {}));
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional utilities for unique-value collections (`ReadonlySet<A>`). All functions are pure
|
|
3
|
+
* and data-last — they compose naturally with `pipe`.
|
|
4
|
+
*
|
|
5
|
+
* Every "mutating" operation returns a new set; the original is never changed.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Uniq } from "@nlozgachev/pipelined/utils";
|
|
10
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
11
|
+
*
|
|
12
|
+
* const active = pipe(
|
|
13
|
+
* Uniq.fromArray(["alice", "bob", "alice", "carol"]),
|
|
14
|
+
* Uniq.remove("bob"),
|
|
15
|
+
* Uniq.map(name => name.toUpperCase()),
|
|
16
|
+
* );
|
|
17
|
+
* // ReadonlySet { "ALICE", "CAROL" }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export var Uniq;
|
|
21
|
+
(function (Uniq) {
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Constructors
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Creates an empty unique collection.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* Uniq.empty<number>(); // ReadonlySet {}
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
Uniq.empty = () => new globalThis.Set();
|
|
34
|
+
/**
|
|
35
|
+
* Creates a unique collection containing a single item.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* Uniq.singleton(42); // ReadonlySet { 42 }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
Uniq.singleton = (item) => new globalThis.Set([item]);
|
|
43
|
+
/**
|
|
44
|
+
* Creates a unique collection from an array, automatically discarding duplicates.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* Uniq.fromArray([1, 2, 2, 3, 3, 3]); // ReadonlySet { 1, 2, 3 }
|
|
49
|
+
* Uniq.fromArray([]); // ReadonlySet {}
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
Uniq.fromArray = (arr) => new globalThis.Set(arr);
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Query
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
/**
|
|
57
|
+
* Returns `true` if the collection contains the given item.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(2)); // true
|
|
62
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(4)); // false
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
Uniq.has = (item) => (s) => s.has(item);
|
|
66
|
+
/**
|
|
67
|
+
* Returns the number of items in the collection.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* Uniq.size(Uniq.fromArray([1, 2, 3])); // 3
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
Uniq.size = (s) => s.size;
|
|
75
|
+
/**
|
|
76
|
+
* Returns `true` if the collection has no items.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* Uniq.isEmpty(Uniq.empty()); // true
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
Uniq.isEmpty = (s) => s.size === 0;
|
|
84
|
+
/**
|
|
85
|
+
* Returns `true` if every item in `set` also exists in `other`.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
|
|
90
|
+
* pipe(Uniq.fromArray([1, 4]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // false
|
|
91
|
+
* pipe(Uniq.empty<number>(), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
Uniq.isSubsetOf = (other) => (s) => {
|
|
95
|
+
const set = s;
|
|
96
|
+
if (typeof set.isSubsetOf === "function")
|
|
97
|
+
return set.isSubsetOf(other);
|
|
98
|
+
for (const item of s)
|
|
99
|
+
if (!other.has(item))
|
|
100
|
+
return false;
|
|
101
|
+
return true;
|
|
102
|
+
};
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Modification
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
/**
|
|
107
|
+
* Returns a new collection with the item added. If the item is already present, returns the
|
|
108
|
+
* original collection unchanged.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.insert(3)); // ReadonlySet { 1, 2, 3 }
|
|
113
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.insert(2)); // ReadonlySet { 1, 2 } — unchanged
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
Uniq.insert = (item) => (s) => {
|
|
117
|
+
if (s.has(item))
|
|
118
|
+
return s;
|
|
119
|
+
const result = new globalThis.Set(s);
|
|
120
|
+
result.add(item);
|
|
121
|
+
return result;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Returns a new collection with the item removed. If the item is not present, returns the
|
|
125
|
+
* original collection unchanged.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(2)); // ReadonlySet { 1, 3 }
|
|
130
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(4)); // ReadonlySet { 1, 2, 3 } — unchanged
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
Uniq.remove = (item) => (s) => {
|
|
134
|
+
if (!s.has(item))
|
|
135
|
+
return s;
|
|
136
|
+
const result = new globalThis.Set(s);
|
|
137
|
+
result.delete(item);
|
|
138
|
+
return result;
|
|
139
|
+
};
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
// Transform
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
/**
|
|
144
|
+
* Applies `f` to each item, returning a new collection of the results. Duplicate results are
|
|
145
|
+
* automatically merged.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.map(n => n % 3)); // ReadonlySet { 1, 2, 0 }
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
Uniq.map = (f) => (s) => {
|
|
153
|
+
const result = new globalThis.Set();
|
|
154
|
+
for (const item of s) {
|
|
155
|
+
result.add(f(item));
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Returns a new collection containing only the items for which the predicate returns `true`.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4, 5]), Uniq.filter(n => n % 2 === 0));
|
|
165
|
+
* // ReadonlySet { 2, 4 }
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
Uniq.filter = (predicate) => (s) => {
|
|
169
|
+
const result = new globalThis.Set();
|
|
170
|
+
for (const item of s) {
|
|
171
|
+
if (predicate(item))
|
|
172
|
+
result.add(item);
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
};
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Set operations
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
/**
|
|
180
|
+
* Returns a new collection containing all items from both collections.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.union(Uniq.fromArray([2, 3, 4])));
|
|
185
|
+
* // ReadonlySet { 1, 2, 3, 4 }
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
Uniq.union = (other) => (s) => {
|
|
189
|
+
const set = s;
|
|
190
|
+
if (typeof set.union === "function")
|
|
191
|
+
return set.union(other);
|
|
192
|
+
const result = new globalThis.Set(s);
|
|
193
|
+
for (const item of other)
|
|
194
|
+
result.add(item);
|
|
195
|
+
return result;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Returns a new collection containing only the items that appear in both collections.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.intersection(Uniq.fromArray([2, 3, 4])));
|
|
203
|
+
* // ReadonlySet { 2, 3 }
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
Uniq.intersection = (other) => (s) => {
|
|
207
|
+
const set = s;
|
|
208
|
+
if (typeof set.intersection === "function")
|
|
209
|
+
return set.intersection(other);
|
|
210
|
+
const result = new globalThis.Set();
|
|
211
|
+
for (const item of s)
|
|
212
|
+
if (other.has(item))
|
|
213
|
+
result.add(item);
|
|
214
|
+
return result;
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Returns a new collection containing only the items from `set` that do not appear in `other`.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.difference(Uniq.fromArray([2, 4])));
|
|
222
|
+
* // ReadonlySet { 1, 3 }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
Uniq.difference = (other) => (s) => {
|
|
226
|
+
const set = s;
|
|
227
|
+
if (typeof set.difference === "function")
|
|
228
|
+
return set.difference(other);
|
|
229
|
+
const result = new globalThis.Set();
|
|
230
|
+
for (const item of s)
|
|
231
|
+
if (!other.has(item))
|
|
232
|
+
result.add(item);
|
|
233
|
+
return result;
|
|
234
|
+
};
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
// Fold
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
/**
|
|
239
|
+
* Folds the collection into a single value by applying `f` to each item in insertion order.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* Uniq.reduce(0, (acc, n) => acc + n)(Uniq.fromArray([1, 2, 3])); // 6
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
Uniq.reduce = (init, f) => (s) => {
|
|
247
|
+
let acc = init;
|
|
248
|
+
for (const item of s) {
|
|
249
|
+
acc = f(acc, item);
|
|
250
|
+
}
|
|
251
|
+
return acc;
|
|
252
|
+
};
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Convert
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
/**
|
|
257
|
+
* Converts the collection to a readonly array in insertion order.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* Uniq.toArray(Uniq.fromArray([3, 1, 2])); // [3, 1, 2]
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
Uniq.toArray = (s) => [...s];
|
|
265
|
+
})(Uniq || (Uniq = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nlozgachev/pipelined",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Simple functional programming toolkit for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"functional",
|
|
@@ -37,6 +37,16 @@
|
|
|
37
37
|
"default": "./script/src/Core/index.js"
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
|
+
"./utils": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./types/src/Utils/index.d.ts",
|
|
43
|
+
"default": "./esm/src/Utils/index.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./types/src/Utils/index.d.ts",
|
|
47
|
+
"default": "./script/src/Utils/index.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
40
50
|
"./types": {
|
|
41
51
|
"import": {
|
|
42
52
|
"types": "./types/src/Types/index.d.ts",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Option = void 0;
|
|
4
4
|
const Result_js_1 = require("./Result.js");
|
|
5
|
+
const _none = { kind: "None" };
|
|
5
6
|
var Option;
|
|
6
7
|
(function (Option) {
|
|
7
8
|
/**
|
|
@@ -15,7 +16,7 @@ var Option;
|
|
|
15
16
|
/**
|
|
16
17
|
* Creates a None (empty Option).
|
|
17
18
|
*/
|
|
18
|
-
Option.none = () =>
|
|
19
|
+
Option.none = () => _none;
|
|
19
20
|
/**
|
|
20
21
|
* Type guard that checks if a Option is None.
|
|
21
22
|
*/
|
|
@@ -3,16 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RemoteData = void 0;
|
|
4
4
|
const Option_js_1 = require("./Option.js");
|
|
5
5
|
const Result_js_1 = require("./Result.js");
|
|
6
|
+
const _notAsked = { kind: "NotAsked" };
|
|
7
|
+
const _loading = { kind: "Loading" };
|
|
6
8
|
var RemoteData;
|
|
7
9
|
(function (RemoteData) {
|
|
8
10
|
/**
|
|
9
11
|
* Creates a NotAsked RemoteData.
|
|
10
12
|
*/
|
|
11
|
-
RemoteData.notAsked = () =>
|
|
13
|
+
RemoteData.notAsked = () => _notAsked;
|
|
12
14
|
/**
|
|
13
15
|
* Creates a Loading RemoteData.
|
|
14
16
|
*/
|
|
15
|
-
RemoteData.loading = () =>
|
|
17
|
+
RemoteData.loading = () => _loading;
|
|
16
18
|
/**
|
|
17
19
|
* Creates a Failure RemoteData with the given error.
|
|
18
20
|
*/
|
|
@@ -208,7 +210,5 @@ var RemoteData;
|
|
|
208
210
|
* ); // Ok(42)
|
|
209
211
|
* ```
|
|
210
212
|
*/
|
|
211
|
-
RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data)
|
|
212
|
-
? Result_js_1.Result.ok(data.value)
|
|
213
|
-
: Result_js_1.Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
|
|
213
|
+
RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data) ? Result_js_1.Result.ok(data.value) : Result_js_1.Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
|
|
214
214
|
})(RemoteData || (exports.RemoteData = RemoteData = {}));
|
|
@@ -94,9 +94,7 @@ var TaskValidation;
|
|
|
94
94
|
* The fallback receives the accumulated error list so callers can inspect which errors occurred.
|
|
95
95
|
* The fallback can produce a different success type, widening the result to `TaskValidation<E, A | B>`.
|
|
96
96
|
*/
|
|
97
|
-
TaskValidation.recover = (fallback) => (data) => Task_js_1.Task.chain((validation) => Validation_js_1.Validation.isValid(validation)
|
|
98
|
-
? Task_js_1.Task.resolve(validation)
|
|
99
|
-
: fallback(validation.errors))(data);
|
|
97
|
+
TaskValidation.recover = (fallback) => (data) => Task_js_1.Task.chain((validation) => Validation_js_1.Validation.isValid(validation) ? Task_js_1.Task.resolve(validation) : fallback(validation.errors))(data);
|
|
100
98
|
/**
|
|
101
99
|
* Runs two TaskValidations concurrently and combines their results into a tuple.
|
|
102
100
|
* If both are Valid, returns Valid with both values. If either fails, accumulates
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Tuple = void 0;
|
|
4
|
+
var Tuple;
|
|
5
|
+
(function (Tuple) {
|
|
6
|
+
/**
|
|
7
|
+
* Creates a pair from two values.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* Tuple.make("Paris", 2_161_000); // ["Paris", 2161000]
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
Tuple.make = (first, second) => [first, second];
|
|
15
|
+
/**
|
|
16
|
+
* Returns the first value from the pair.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* Tuple.first(Tuple.make("Paris", 2_161_000)); // "Paris"
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
Tuple.first = (tuple) => tuple[0];
|
|
24
|
+
/**
|
|
25
|
+
* Returns the second value from the pair.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* Tuple.second(Tuple.make("Paris", 2_161_000)); // 2161000
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
Tuple.second = (tuple) => tuple[1];
|
|
33
|
+
/**
|
|
34
|
+
* Transforms the first value, leaving the second unchanged.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* pipe(Tuple.make("alice", 42), Tuple.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
Tuple.mapFirst = (f) => (tuple) => [f(tuple[0]), tuple[1]];
|
|
42
|
+
/**
|
|
43
|
+
* Transforms the second value, leaving the first unchanged.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* pipe(Tuple.make("alice", 42), Tuple.mapSecond((n) => n * 2)); // ["alice", 84]
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
Tuple.mapSecond = (f) => (tuple) => [tuple[0], f(tuple[1])];
|
|
51
|
+
/**
|
|
52
|
+
* Transforms both values independently in a single step.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* pipe(
|
|
57
|
+
* Tuple.make("alice", 42),
|
|
58
|
+
* Tuple.mapBoth(
|
|
59
|
+
* (name) => name.toUpperCase(),
|
|
60
|
+
* (score) => score * 2,
|
|
61
|
+
* ),
|
|
62
|
+
* ); // ["ALICE", 84]
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
Tuple.mapBoth = (onFirst, onSecond) => (tuple) => [
|
|
66
|
+
onFirst(tuple[0]),
|
|
67
|
+
onSecond(tuple[1]),
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Applies a binary function to both values, collapsing the pair into a single value.
|
|
71
|
+
* Useful as the final step when consuming a pair in a pipeline.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* pipe(Tuple.make("Alice", 100), Tuple.fold((name, score) => `${name}: ${score}`));
|
|
76
|
+
* // "Alice: 100"
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
Tuple.fold = (f) => (tuple) => f(tuple[0], tuple[1]);
|
|
80
|
+
/**
|
|
81
|
+
* Swaps the two values: `[A, B]` becomes `[B, A]`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* Tuple.swap(Tuple.make("key", 1)); // [1, "key"]
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
Tuple.swap = (tuple) => [tuple[1], tuple[0]];
|
|
89
|
+
/**
|
|
90
|
+
* Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* Tuple.toArray(Tuple.make("hello", 42)); // ["hello", 42]
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
Tuple.toArray = (tuple) => [...tuple];
|
|
98
|
+
/**
|
|
99
|
+
* Runs a side effect with both values without changing the pair.
|
|
100
|
+
* Useful for logging or debugging in the middle of a pipeline.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* pipe(
|
|
105
|
+
* Tuple.make("Paris", 2_161_000),
|
|
106
|
+
* Tuple.tap((city, pop) => console.log(`${city}: ${pop}`)),
|
|
107
|
+
* Tuple.mapSecond((n) => n / 1_000_000),
|
|
108
|
+
* ); // logs "Paris: 2161000", returns ["Paris", 2.161]
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
Tuple.tap = (f) => (tuple) => {
|
|
112
|
+
f(tuple[0], tuple[1]);
|
|
113
|
+
return tuple;
|
|
114
|
+
};
|
|
115
|
+
})(Tuple || (exports.Tuple = Tuple = {}));
|
package/script/src/Core/index.js
CHANGED
|
@@ -14,22 +14,21 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./Arr.js"), exports);
|
|
18
|
-
__exportStar(require("./Logged.js"), exports);
|
|
19
17
|
__exportStar(require("./Deferred.js"), exports);
|
|
20
18
|
__exportStar(require("./Lens.js"), exports);
|
|
19
|
+
__exportStar(require("./Logged.js"), exports);
|
|
21
20
|
__exportStar(require("./Option.js"), exports);
|
|
22
|
-
__exportStar(require("./Reader.js"), exports);
|
|
23
21
|
__exportStar(require("./Optional.js"), exports);
|
|
24
|
-
__exportStar(require("./Rec.js"), exports);
|
|
25
22
|
__exportStar(require("./Predicate.js"), exports);
|
|
23
|
+
__exportStar(require("./Reader.js"), exports);
|
|
26
24
|
__exportStar(require("./Refinement.js"), exports);
|
|
27
25
|
__exportStar(require("./RemoteData.js"), exports);
|
|
28
|
-
__exportStar(require("./State.js"), exports);
|
|
29
26
|
__exportStar(require("./Result.js"), exports);
|
|
27
|
+
__exportStar(require("./State.js"), exports);
|
|
30
28
|
__exportStar(require("./Task.js"), exports);
|
|
31
29
|
__exportStar(require("./TaskOption.js"), exports);
|
|
32
30
|
__exportStar(require("./TaskResult.js"), exports);
|
|
33
31
|
__exportStar(require("./TaskValidation.js"), exports);
|
|
34
32
|
__exportStar(require("./These.js"), exports);
|
|
33
|
+
__exportStar(require("./Tuple.js"), exports);
|
|
35
34
|
__exportStar(require("./Validation.js"), exports);
|