@nlozgachev/pipelined 0.11.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.
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Uniq = void 0;
4
+ /**
5
+ * Functional utilities for unique-value collections (`ReadonlySet<A>`). All functions are pure
6
+ * and data-last — they compose naturally with `pipe`.
7
+ *
8
+ * Every "mutating" operation returns a new set; the original is never changed.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { Uniq } from "@nlozgachev/pipelined/utils";
13
+ * import { pipe } from "@nlozgachev/pipelined/composition";
14
+ *
15
+ * const active = pipe(
16
+ * Uniq.fromArray(["alice", "bob", "alice", "carol"]),
17
+ * Uniq.remove("bob"),
18
+ * Uniq.map(name => name.toUpperCase()),
19
+ * );
20
+ * // ReadonlySet { "ALICE", "CAROL" }
21
+ * ```
22
+ */
23
+ var Uniq;
24
+ (function (Uniq) {
25
+ // ---------------------------------------------------------------------------
26
+ // Constructors
27
+ // ---------------------------------------------------------------------------
28
+ /**
29
+ * Creates an empty unique collection.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * Uniq.empty<number>(); // ReadonlySet {}
34
+ * ```
35
+ */
36
+ Uniq.empty = () => new globalThis.Set();
37
+ /**
38
+ * Creates a unique collection containing a single item.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * Uniq.singleton(42); // ReadonlySet { 42 }
43
+ * ```
44
+ */
45
+ Uniq.singleton = (item) => new globalThis.Set([item]);
46
+ /**
47
+ * Creates a unique collection from an array, automatically discarding duplicates.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * Uniq.fromArray([1, 2, 2, 3, 3, 3]); // ReadonlySet { 1, 2, 3 }
52
+ * Uniq.fromArray([]); // ReadonlySet {}
53
+ * ```
54
+ */
55
+ Uniq.fromArray = (arr) => new globalThis.Set(arr);
56
+ // ---------------------------------------------------------------------------
57
+ // Query
58
+ // ---------------------------------------------------------------------------
59
+ /**
60
+ * Returns `true` if the collection contains the given item.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(2)); // true
65
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(4)); // false
66
+ * ```
67
+ */
68
+ Uniq.has = (item) => (s) => s.has(item);
69
+ /**
70
+ * Returns the number of items in the collection.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * Uniq.size(Uniq.fromArray([1, 2, 3])); // 3
75
+ * ```
76
+ */
77
+ Uniq.size = (s) => s.size;
78
+ /**
79
+ * Returns `true` if the collection has no items.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * Uniq.isEmpty(Uniq.empty()); // true
84
+ * ```
85
+ */
86
+ Uniq.isEmpty = (s) => s.size === 0;
87
+ /**
88
+ * Returns `true` if every item in `set` also exists in `other`.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * pipe(Uniq.fromArray([1, 2]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
93
+ * pipe(Uniq.fromArray([1, 4]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // false
94
+ * pipe(Uniq.empty<number>(), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
95
+ * ```
96
+ */
97
+ Uniq.isSubsetOf = (other) => (s) => {
98
+ const set = s;
99
+ if (typeof set.isSubsetOf === "function")
100
+ return set.isSubsetOf(other);
101
+ for (const item of s)
102
+ if (!other.has(item))
103
+ return false;
104
+ return true;
105
+ };
106
+ // ---------------------------------------------------------------------------
107
+ // Modification
108
+ // ---------------------------------------------------------------------------
109
+ /**
110
+ * Returns a new collection with the item added. If the item is already present, returns the
111
+ * original collection unchanged.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * pipe(Uniq.fromArray([1, 2]), Uniq.insert(3)); // ReadonlySet { 1, 2, 3 }
116
+ * pipe(Uniq.fromArray([1, 2]), Uniq.insert(2)); // ReadonlySet { 1, 2 } — unchanged
117
+ * ```
118
+ */
119
+ Uniq.insert = (item) => (s) => {
120
+ if (s.has(item))
121
+ return s;
122
+ const result = new globalThis.Set(s);
123
+ result.add(item);
124
+ return result;
125
+ };
126
+ /**
127
+ * Returns a new collection with the item removed. If the item is not present, returns the
128
+ * original collection unchanged.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(2)); // ReadonlySet { 1, 3 }
133
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(4)); // ReadonlySet { 1, 2, 3 } — unchanged
134
+ * ```
135
+ */
136
+ Uniq.remove = (item) => (s) => {
137
+ if (!s.has(item))
138
+ return s;
139
+ const result = new globalThis.Set(s);
140
+ result.delete(item);
141
+ return result;
142
+ };
143
+ // ---------------------------------------------------------------------------
144
+ // Transform
145
+ // ---------------------------------------------------------------------------
146
+ /**
147
+ * Applies `f` to each item, returning a new collection of the results. Duplicate results are
148
+ * automatically merged.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.map(n => n % 3)); // ReadonlySet { 1, 2, 0 }
153
+ * ```
154
+ */
155
+ Uniq.map = (f) => (s) => {
156
+ const result = new globalThis.Set();
157
+ for (const item of s) {
158
+ result.add(f(item));
159
+ }
160
+ return result;
161
+ };
162
+ /**
163
+ * Returns a new collection containing only the items for which the predicate returns `true`.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * pipe(Uniq.fromArray([1, 2, 3, 4, 5]), Uniq.filter(n => n % 2 === 0));
168
+ * // ReadonlySet { 2, 4 }
169
+ * ```
170
+ */
171
+ Uniq.filter = (predicate) => (s) => {
172
+ const result = new globalThis.Set();
173
+ for (const item of s) {
174
+ if (predicate(item))
175
+ result.add(item);
176
+ }
177
+ return result;
178
+ };
179
+ // ---------------------------------------------------------------------------
180
+ // Set operations
181
+ // ---------------------------------------------------------------------------
182
+ /**
183
+ * Returns a new collection containing all items from both collections.
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.union(Uniq.fromArray([2, 3, 4])));
188
+ * // ReadonlySet { 1, 2, 3, 4 }
189
+ * ```
190
+ */
191
+ Uniq.union = (other) => (s) => {
192
+ const set = s;
193
+ if (typeof set.union === "function")
194
+ return set.union(other);
195
+ const result = new globalThis.Set(s);
196
+ for (const item of other)
197
+ result.add(item);
198
+ return result;
199
+ };
200
+ /**
201
+ * Returns a new collection containing only the items that appear in both collections.
202
+ *
203
+ * @example
204
+ * ```ts
205
+ * pipe(Uniq.fromArray([1, 2, 3]), Uniq.intersection(Uniq.fromArray([2, 3, 4])));
206
+ * // ReadonlySet { 2, 3 }
207
+ * ```
208
+ */
209
+ Uniq.intersection = (other) => (s) => {
210
+ const set = s;
211
+ if (typeof set.intersection === "function")
212
+ return set.intersection(other);
213
+ const result = new globalThis.Set();
214
+ for (const item of s)
215
+ if (other.has(item))
216
+ result.add(item);
217
+ return result;
218
+ };
219
+ /**
220
+ * Returns a new collection containing only the items from `set` that do not appear in `other`.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.difference(Uniq.fromArray([2, 4])));
225
+ * // ReadonlySet { 1, 3 }
226
+ * ```
227
+ */
228
+ Uniq.difference = (other) => (s) => {
229
+ const set = s;
230
+ if (typeof set.difference === "function")
231
+ return set.difference(other);
232
+ const result = new globalThis.Set();
233
+ for (const item of s)
234
+ if (!other.has(item))
235
+ result.add(item);
236
+ return result;
237
+ };
238
+ // ---------------------------------------------------------------------------
239
+ // Fold
240
+ // ---------------------------------------------------------------------------
241
+ /**
242
+ * Folds the collection into a single value by applying `f` to each item in insertion order.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * Uniq.reduce(0, (acc, n) => acc + n)(Uniq.fromArray([1, 2, 3])); // 6
247
+ * ```
248
+ */
249
+ Uniq.reduce = (init, f) => (s) => {
250
+ let acc = init;
251
+ for (const item of s) {
252
+ acc = f(acc, item);
253
+ }
254
+ return acc;
255
+ };
256
+ // ---------------------------------------------------------------------------
257
+ // Convert
258
+ // ---------------------------------------------------------------------------
259
+ /**
260
+ * Converts the collection to a readonly array in insertion order.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * Uniq.toArray(Uniq.fromArray([3, 1, 2])); // [3, 1, 2]
265
+ * ```
266
+ */
267
+ Uniq.toArray = (s) => [...s];
268
+ })(Uniq || (exports.Uniq = Uniq = {}));
@@ -18,3 +18,5 @@ __exportStar(require("./Arr.js"), exports);
18
18
  __exportStar(require("./Rec.js"), exports);
19
19
  __exportStar(require("./Num.js"), exports);
20
20
  __exportStar(require("./Str.js"), exports);
21
+ __exportStar(require("./Dict.js"), exports);
22
+ __exportStar(require("./Uniq.js"), exports);
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Tuple<A, B> represents a pair of two values that are always both present.
3
+ * It is a typed alias for `readonly [A, B]`.
4
+ *
5
+ * Use Tuple when two values always travel together through a pipeline and you
6
+ * want to transform either or both sides without destructuring.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { Tuple } from "@nlozgachev/pipelined/core";
11
+ * import { pipe } from "@nlozgachev/pipelined/composition";
12
+ *
13
+ * const entry = Tuple.make("alice", 42);
14
+ *
15
+ * pipe(
16
+ * entry,
17
+ * Tuple.mapFirst((name) => name.toUpperCase()),
18
+ * Tuple.mapSecond((score) => score * 2),
19
+ * Tuple.fold((name, score) => `${name}: ${score}`),
20
+ * ); // "ALICE: 84"
21
+ * ```
22
+ */
23
+ export type Tuple<A, B> = readonly [A, B];
24
+ export declare namespace Tuple {
25
+ /**
26
+ * Creates a pair from two values.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * Tuple.make("Paris", 2_161_000); // ["Paris", 2161000]
31
+ * ```
32
+ */
33
+ const make: <A, B>(first: A, second: B) => Tuple<A, B>;
34
+ /**
35
+ * Returns the first value from the pair.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * Tuple.first(Tuple.make("Paris", 2_161_000)); // "Paris"
40
+ * ```
41
+ */
42
+ const first: <A, B>(tuple: Tuple<A, B>) => A;
43
+ /**
44
+ * Returns the second value from the pair.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * Tuple.second(Tuple.make("Paris", 2_161_000)); // 2161000
49
+ * ```
50
+ */
51
+ const second: <A, B>(tuple: Tuple<A, B>) => B;
52
+ /**
53
+ * Transforms the first value, leaving the second unchanged.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * pipe(Tuple.make("alice", 42), Tuple.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
58
+ * ```
59
+ */
60
+ const mapFirst: <A, C>(f: (a: A) => C) => <B>(tuple: Tuple<A, B>) => Tuple<C, B>;
61
+ /**
62
+ * Transforms the second value, leaving the first unchanged.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * pipe(Tuple.make("alice", 42), Tuple.mapSecond((n) => n * 2)); // ["alice", 84]
67
+ * ```
68
+ */
69
+ const mapSecond: <B, D>(f: (b: B) => D) => <A>(tuple: Tuple<A, B>) => Tuple<A, D>;
70
+ /**
71
+ * Transforms both values independently in a single step.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * pipe(
76
+ * Tuple.make("alice", 42),
77
+ * Tuple.mapBoth(
78
+ * (name) => name.toUpperCase(),
79
+ * (score) => score * 2,
80
+ * ),
81
+ * ); // ["ALICE", 84]
82
+ * ```
83
+ */
84
+ const mapBoth: <A, C, B, D>(onFirst: (a: A) => C, onSecond: (b: B) => D) => (tuple: Tuple<A, B>) => Tuple<C, D>;
85
+ /**
86
+ * Applies a binary function to both values, collapsing the pair into a single value.
87
+ * Useful as the final step when consuming a pair in a pipeline.
88
+ *
89
+ * @example
90
+ * ```ts
91
+ * pipe(Tuple.make("Alice", 100), Tuple.fold((name, score) => `${name}: ${score}`));
92
+ * // "Alice: 100"
93
+ * ```
94
+ */
95
+ const fold: <A, B, C>(f: (a: A, b: B) => C) => (tuple: Tuple<A, B>) => C;
96
+ /**
97
+ * Swaps the two values: `[A, B]` becomes `[B, A]`.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * Tuple.swap(Tuple.make("key", 1)); // [1, "key"]
102
+ * ```
103
+ */
104
+ const swap: <A, B>(tuple: Tuple<A, B>) => Tuple<B, A>;
105
+ /**
106
+ * Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * Tuple.toArray(Tuple.make("hello", 42)); // ["hello", 42]
111
+ * ```
112
+ */
113
+ const toArray: <A, B>(tuple: Tuple<A, B>) => readonly (A | B)[];
114
+ /**
115
+ * Runs a side effect with both values without changing the pair.
116
+ * Useful for logging or debugging in the middle of a pipeline.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * pipe(
121
+ * Tuple.make("Paris", 2_161_000),
122
+ * Tuple.tap((city, pop) => console.log(`${city}: ${pop}`)),
123
+ * Tuple.mapSecond((n) => n / 1_000_000),
124
+ * ); // logs "Paris: 2161000", returns ["Paris", 2.161]
125
+ * ```
126
+ */
127
+ const tap: <A, B>(f: (a: A, b: B) => void) => (tuple: Tuple<A, B>) => Tuple<A, B>;
128
+ }
129
+ //# sourceMappingURL=Tuple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tuple.d.ts","sourceRoot":"","sources":["../../../src/src/Core/Tuple.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE1C,yBAAiB,KAAK,CAAC;IACtB;;;;;;;OAOG;IACI,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAoB,CAAC;IAEhF;;;;;;;OAOG;IACI,MAAM,KAAK,GAAI,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAAa,CAAC;IAE/D;;;;;;;OAOG;IACI,MAAM,MAAM,GAAI,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAAa,CAAC;IAEhE;;;;;;;OAOG;IACI,MAAM,QAAQ,GAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAA4B,CAAC;IAElH;;;;;;;OAOG;IACI,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAA4B,CAAC;IAEnH;;;;;;;;;;;;;OAaG;IACI,MAAM,OAAO,GAClB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAG5F,CAAC;IAEH;;;;;;;;;OASG;IACI,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAA0B,CAAC;IAExG;;;;;;;OAOG;IACI,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAyB,CAAC;IAEpF;;;;;;;OAOG;IACI,MAAM,OAAO,GAAI,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAgB,CAAC;IAEpF;;;;;;;;;;;;OAYG;IACI,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAGrF,CAAC;CACF"}
@@ -1,18 +1,19 @@
1
- export * from "./Logged.js";
2
1
  export * from "./Deferred.js";
3
2
  export * from "./Lens.js";
3
+ export * from "./Logged.js";
4
4
  export * from "./Option.js";
5
- export * from "./Reader.js";
6
5
  export * from "./Optional.js";
7
6
  export * from "./Predicate.js";
7
+ export * from "./Reader.js";
8
8
  export * from "./Refinement.js";
9
9
  export * from "./RemoteData.js";
10
- export * from "./State.js";
11
10
  export * from "./Result.js";
11
+ export * from "./State.js";
12
12
  export * from "./Task.js";
13
13
  export * from "./TaskOption.js";
14
14
  export * from "./TaskResult.js";
15
15
  export * from "./TaskValidation.js";
16
16
  export * from "./These.js";
17
+ export * from "./Tuple.js";
17
18
  export * from "./Validation.js";
18
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/Core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/Core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}