@satoshibits/functional 1.0.2
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 +242 -0
- package/dist/array-utils.d.mts +317 -0
- package/dist/array-utils.d.mts.map +1 -0
- package/dist/array-utils.mjs +370 -0
- package/dist/array-utils.mjs.map +1 -0
- package/dist/composition.d.mts +603 -0
- package/dist/composition.d.mts.map +1 -0
- package/dist/composition.mjs +516 -0
- package/dist/composition.mjs.map +1 -0
- package/dist/object-utils.d.mts +267 -0
- package/dist/object-utils.d.mts.map +1 -0
- package/dist/object-utils.mjs +258 -0
- package/dist/object-utils.mjs.map +1 -0
- package/dist/option.d.mts +622 -0
- package/dist/option.d.mts.map +1 -0
- package/dist/option.mjs +637 -0
- package/dist/option.mjs.map +1 -0
- package/dist/performance.d.mts +265 -0
- package/dist/performance.d.mts.map +1 -0
- package/dist/performance.mjs +453 -0
- package/dist/performance.mjs.map +1 -0
- package/dist/pipeline.d.mts +431 -0
- package/dist/pipeline.d.mts.map +1 -0
- package/dist/pipeline.mjs +460 -0
- package/dist/pipeline.mjs.map +1 -0
- package/dist/predicates.d.mts +722 -0
- package/dist/predicates.d.mts.map +1 -0
- package/dist/predicates.mjs +802 -0
- package/dist/predicates.mjs.map +1 -0
- package/dist/reader-result.d.mts +422 -0
- package/dist/reader-result.d.mts.map +1 -0
- package/dist/reader-result.mjs +758 -0
- package/dist/reader-result.mjs.map +1 -0
- package/dist/result.d.mts +684 -0
- package/dist/result.d.mts.map +1 -0
- package/dist/result.mjs +814 -0
- package/dist/result.mjs.map +1 -0
- package/dist/types.d.mts +439 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +191 -0
- package/dist/types.mjs.map +1 -0
- package/dist/validation.d.mts +622 -0
- package/dist/validation.d.mts.map +1 -0
- package/dist/validation.mjs +852 -0
- package/dist/validation.mjs.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module composition
|
|
3
|
+
* @description Core functional composition utilities using TypeScript 4.0+ variadic tuple types.
|
|
4
|
+
* Provides type-safe function composition with automatic type inference
|
|
5
|
+
* for pipelines of any length. All functions follow functional programming principles,
|
|
6
|
+
* supporting both synchronous and asynchronous composition patterns.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { pipe, flow, compose, tap, pipeAsync } from './composition.mts';
|
|
11
|
+
*
|
|
12
|
+
* // pipe - execute functions with an initial value
|
|
13
|
+
* const result = pipe(
|
|
14
|
+
* 5,
|
|
15
|
+
* x => x * 2,
|
|
16
|
+
* x => x + 1,
|
|
17
|
+
* x => `Result: ${x}`
|
|
18
|
+
* );
|
|
19
|
+
* // => "Result: 11"
|
|
20
|
+
*
|
|
21
|
+
* // flow - create reusable pipelines
|
|
22
|
+
* const processUser = flow(
|
|
23
|
+
* (user: User) => ({ ...user, name: user.name.trim() }),
|
|
24
|
+
* user => ({ ...user, name: user.name.toUpperCase() }),
|
|
25
|
+
* user => ({ ...user, isActive: true })
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* // compose - right-to-left composition
|
|
29
|
+
* const calculate = compose(
|
|
30
|
+
* Math.round,
|
|
31
|
+
* Math.sqrt,
|
|
32
|
+
* Math.abs
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* // async composition
|
|
36
|
+
* const fetchAndProcess = pipeAsync(
|
|
37
|
+
* async (id: string) => fetchUser(id),
|
|
38
|
+
* async (user: User) => enrichUser(user),
|
|
39
|
+
* async (enriched: EnrichedUser) => saveUser(enriched)
|
|
40
|
+
* );
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @category Core
|
|
44
|
+
* @since 2025-07-03
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* Pipe - applies a series of functions from left to right.
|
|
48
|
+
* @description Executes a sequence of functions in order, passing the result of each function
|
|
49
|
+
* as the argument to the next. The first argument is the initial value, followed by functions
|
|
50
|
+
* that transform the value step by step. Supports up to 6 transformations with full type inference.
|
|
51
|
+
*
|
|
52
|
+
* @template A - Type of the initial value
|
|
53
|
+
* @template B,C,D,E,F,G - Types of intermediate and final values through the pipeline
|
|
54
|
+
* @param {A} value - The initial value to transform
|
|
55
|
+
* @param {...Function} fns - Functions to apply in sequence
|
|
56
|
+
* @returns {*} The final transformed value
|
|
57
|
+
*
|
|
58
|
+
* @category Core
|
|
59
|
+
* @example
|
|
60
|
+
* // Basic transformation pipeline
|
|
61
|
+
* const result = pipe(
|
|
62
|
+
* 5,
|
|
63
|
+
* x => x * 2,
|
|
64
|
+
* x => x + 1,
|
|
65
|
+
* x => `Result: ${x}`
|
|
66
|
+
* );
|
|
67
|
+
* // => "Result: 11"
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Complex data transformation
|
|
71
|
+
* const user = { name: 'john', age: 25 };
|
|
72
|
+
* const formatted = pipe(
|
|
73
|
+
* user,
|
|
74
|
+
* u => ({ ...u, name: u.name.toUpperCase() }),
|
|
75
|
+
* u => ({ ...u, ageGroup: u.age >= 18 ? 'adult' : 'minor' }),
|
|
76
|
+
* u => `${u.name} (${u.ageGroup})`
|
|
77
|
+
* );
|
|
78
|
+
* // => "JOHN (adult)"
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Working with arrays
|
|
82
|
+
* const doubled = pipe(
|
|
83
|
+
* [1, 2, 3, 4, 5],
|
|
84
|
+
* arr => arr.map(x => x * 2),
|
|
85
|
+
* arr => arr.filter(x => x > 5),
|
|
86
|
+
* arr => arr.reduce((sum, x) => sum + x, 0)
|
|
87
|
+
* );
|
|
88
|
+
* // => 18 (6 + 8 + 10)
|
|
89
|
+
*
|
|
90
|
+
* @see flow - Create a reusable pipeline function
|
|
91
|
+
* @see compose - Right-to-left composition
|
|
92
|
+
* @since 2025-07-03
|
|
93
|
+
*/
|
|
94
|
+
export declare function pipe<A>(value: A): A;
|
|
95
|
+
export declare function pipe<A, B>(value: A, fn1: (a: A) => B): B;
|
|
96
|
+
export declare function pipe<A, B, C>(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C;
|
|
97
|
+
export declare function pipe<A, B, C, D>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): D;
|
|
98
|
+
export declare function pipe<A, B, C, D, E>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): E;
|
|
99
|
+
export declare function pipe<A, B, C, D, E, F>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): F;
|
|
100
|
+
export declare function pipe<A, B, C, D, E, F, G>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F, fn6: (f: F) => G): G;
|
|
101
|
+
/**
|
|
102
|
+
* Flow - compose functions without an initial value.
|
|
103
|
+
* Creates a reusable pipeline function that can be called multiple times
|
|
104
|
+
* with different inputs.
|
|
105
|
+
*
|
|
106
|
+
* @category Core
|
|
107
|
+
* @example
|
|
108
|
+
* // Create a reusable pipeline
|
|
109
|
+
* const processUser = flow(
|
|
110
|
+
* (user: { name: string; age: number }) => ({ ...user, name: user.name.trim() }),
|
|
111
|
+
* user => ({ ...user, name: user.name.toUpperCase() }),
|
|
112
|
+
* user => ({ ...user, isAdult: user.age >= 18 })
|
|
113
|
+
* );
|
|
114
|
+
*
|
|
115
|
+
* processUser({ name: ' john ', age: 25 });
|
|
116
|
+
* // => { name: 'JOHN', age: 25, isAdult: true }
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // String processing pipeline
|
|
120
|
+
* const slugify = flow(
|
|
121
|
+
* (str: string) => str.toLowerCase(),
|
|
122
|
+
* str => str.trim(),
|
|
123
|
+
* str => str.replace(/\s+/g, '-'),
|
|
124
|
+
* str => str.replace(/[^a-z0-9-]/g, '')
|
|
125
|
+
* );
|
|
126
|
+
*
|
|
127
|
+
* slugify('Hello World!'); // => 'hello-world'
|
|
128
|
+
* slugify(' TypeScript 4.0 '); // => 'typescript-40'
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Data validation pipeline
|
|
132
|
+
* const validateAndTransform = flow(
|
|
133
|
+
* (data: unknown) => data as { name?: string; email?: string },
|
|
134
|
+
* data => {
|
|
135
|
+
* if (!data.name) throw new Error('Name is required');
|
|
136
|
+
* if (!data.email) throw new Error('Email is required');
|
|
137
|
+
* return data as { name: string; email: string };
|
|
138
|
+
* },
|
|
139
|
+
* data => ({
|
|
140
|
+
* ...data,
|
|
141
|
+
* name: data.name.trim(),
|
|
142
|
+
* email: data.email.toLowerCase()
|
|
143
|
+
* })
|
|
144
|
+
* );
|
|
145
|
+
*
|
|
146
|
+
* @see pipe - Apply functions with an initial value
|
|
147
|
+
* @see compose - Right-to-left composition
|
|
148
|
+
*/
|
|
149
|
+
export declare function flow<A, B>(fn1: (a: A) => B): (a: A) => B;
|
|
150
|
+
export declare function flow<A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (a: A) => C;
|
|
151
|
+
export declare function flow<A, B, C, D>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): (a: A) => D;
|
|
152
|
+
export declare function flow<A, B, C, D, E>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E): (a: A) => E;
|
|
153
|
+
export declare function flow<A, B, C, D, E, F>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D, fn4: (d: D) => E, fn5: (e: E) => F): (a: A) => F;
|
|
154
|
+
export declare function flow<Args extends unknown[], B>(fn1: (...args: Args) => B): (...args: Args) => B;
|
|
155
|
+
export declare function flow<Args extends unknown[], B, C>(fn1: (...args: Args) => B, fn2: (b: B) => C): (...args: Args) => C;
|
|
156
|
+
export declare function flow<Args extends unknown[], B, C, D>(fn1: (...args: Args) => B, fn2: (b: B) => C, fn3: (c: C) => D): (...args: Args) => D;
|
|
157
|
+
/**
|
|
158
|
+
* Identity function - returns its input unchanged.
|
|
159
|
+
* @description A function that returns its argument without any modification.
|
|
160
|
+
* Useful as a default or placeholder in pipelines, for filtering truthy values,
|
|
161
|
+
* or when conditional transformations are needed.
|
|
162
|
+
*
|
|
163
|
+
* @template T - The type of the input and output
|
|
164
|
+
* @param {T} x - The value to return unchanged
|
|
165
|
+
* @returns {T} The same value that was passed in
|
|
166
|
+
*
|
|
167
|
+
* @category Utilities
|
|
168
|
+
* @example
|
|
169
|
+
* // As a default transformation
|
|
170
|
+
* const transform = shouldTransform ? (x: number) => x * 2 : identity;
|
|
171
|
+
* [1, 2, 3].map(transform); // => [1, 2, 3] or [2, 4, 6]
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* // Filtering out falsy values while preserving types
|
|
175
|
+
* const values = [1, null, 2, undefined, 3];
|
|
176
|
+
* const nonNull = values.filter(identity); // => [1, 2, 3]
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* // As a placeholder in conditional pipelines
|
|
180
|
+
* const pipeline = flow(
|
|
181
|
+
* validateInput,
|
|
182
|
+
* shouldNormalize ? normalizeData : identity,
|
|
183
|
+
* saveToDatabase
|
|
184
|
+
* );
|
|
185
|
+
*
|
|
186
|
+
* @see constant - Create a function that always returns the same value
|
|
187
|
+
* @since 2025-07-03
|
|
188
|
+
*/
|
|
189
|
+
export declare const identity: <T>(x: T) => T;
|
|
190
|
+
/**
|
|
191
|
+
* Constant function - creates a function that always returns the same value.
|
|
192
|
+
* @description Returns a function that ignores its arguments and always returns the specified value.
|
|
193
|
+
* Useful for providing default values, mocking in tests, or replacing complex logic with fixed results.
|
|
194
|
+
*
|
|
195
|
+
* @template T - The type of the constant value
|
|
196
|
+
* @param {T} x - The value to always return
|
|
197
|
+
* @returns {() => T} A function that always returns the constant value
|
|
198
|
+
*
|
|
199
|
+
* @category Utilities
|
|
200
|
+
* @example
|
|
201
|
+
* // Default value provider
|
|
202
|
+
* const getDefault = constant({ status: 'pending', count: 0 });
|
|
203
|
+
* const status = userStatus || getDefault();
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* // Mock functions in tests
|
|
207
|
+
* const mockUserService = {
|
|
208
|
+
* getCurrentUser: constant({ id: 1, name: 'Test User' }),
|
|
209
|
+
* isAuthenticated: constant(true)
|
|
210
|
+
* };
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* // Replacing conditional logic
|
|
214
|
+
* const getDiscount = isPremium
|
|
215
|
+
* ? calculatePremiumDiscount
|
|
216
|
+
* : constant(0);
|
|
217
|
+
*
|
|
218
|
+
* @see identity - Return the input unchanged
|
|
219
|
+
* @since 2025-07-03
|
|
220
|
+
*/
|
|
221
|
+
export declare const constant: <T>(x: T) => () => T;
|
|
222
|
+
/**
|
|
223
|
+
* Compose - right-to-left function composition (opposite of flow).
|
|
224
|
+
* For those who prefer mathematical composition order where (f ∘ g)(x) = f(g(x)).
|
|
225
|
+
*
|
|
226
|
+
* @category Core
|
|
227
|
+
* @example
|
|
228
|
+
* // Mathematical style composition
|
|
229
|
+
* const addThenDouble = compose(
|
|
230
|
+
* (x: number) => x * 2, // second
|
|
231
|
+
* (x: number) => x + 1 // first
|
|
232
|
+
* );
|
|
233
|
+
* addThenDouble(5); // => 12 ((5 + 1) * 2)
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* // Reading right-to-left
|
|
237
|
+
* const processData = compose(
|
|
238
|
+
* JSON.stringify, // 3. Convert to JSON
|
|
239
|
+
* addTimestamp, // 2. Add metadata
|
|
240
|
+
* validateData // 1. Validate first
|
|
241
|
+
* );
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* // Equivalent to nested function calls
|
|
245
|
+
* const traditional = (x: number) => Math.round(Math.sqrt(Math.abs(x)));
|
|
246
|
+
* const composed = compose(Math.round, Math.sqrt, Math.abs);
|
|
247
|
+
* // Both produce the same result
|
|
248
|
+
*
|
|
249
|
+
* @see flow - Left-to-right composition
|
|
250
|
+
* @see pipe - Apply functions with an initial value
|
|
251
|
+
*/
|
|
252
|
+
export declare function compose<A, B>(fn1: (a: A) => B): (a: A) => B;
|
|
253
|
+
export declare function compose<A, B, C>(fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => C;
|
|
254
|
+
export declare function compose<A, B, C, D>(fn3: (c: C) => D, fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => D;
|
|
255
|
+
export declare function compose<A, B, C, D, E>(fn4: (d: D) => E, fn3: (c: C) => D, fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => E;
|
|
256
|
+
export declare function compose<Args extends unknown[], B>(fn1: (...args: Args) => B): (...args: Args) => B;
|
|
257
|
+
export declare function compose<Args extends unknown[], B, C>(fn2: (b: B) => C, fn1: (...args: Args) => B): (...args: Args) => C;
|
|
258
|
+
export declare function compose<Args extends unknown[], B, C, D>(fn3: (c: C) => D, fn2: (b: B) => C, fn1: (...args: Args) => B): (...args: Args) => D;
|
|
259
|
+
/**
|
|
260
|
+
* Tap - execute a side effect without changing the value.
|
|
261
|
+
* @description Executes a function for its side effects while passing the input value through unchanged.
|
|
262
|
+
* Useful for debugging, logging, or triggering external actions in pipelines without breaking the flow.
|
|
263
|
+
* The side effect function receives the value but its return value is ignored.
|
|
264
|
+
*
|
|
265
|
+
* @template T - The type of the value being passed through
|
|
266
|
+
* @param {function(T): void} fn - Function to execute for side effects
|
|
267
|
+
* @returns {function(T): T} A function that executes the side effect and returns the input
|
|
268
|
+
*
|
|
269
|
+
* @category Side Effects
|
|
270
|
+
* @example
|
|
271
|
+
* // Debugging pipeline steps
|
|
272
|
+
* const result = pipe(
|
|
273
|
+
* { name: 'John', age: 30 },
|
|
274
|
+
* tap(console.log), // Log initial value
|
|
275
|
+
* user => ({ ...user, age: user.age + 1 }),
|
|
276
|
+
* tap(user => console.log('After increment:', user)),
|
|
277
|
+
* user => ({ ...user, status: 'active' })
|
|
278
|
+
* );
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* // Triggering side effects
|
|
282
|
+
* const saveUser = pipe(
|
|
283
|
+
* validateUser,
|
|
284
|
+
* tap(user => analytics.track('user_validated', { id: user.id })),
|
|
285
|
+
* normalizeUser,
|
|
286
|
+
* tap(user => cache.set(user.id, user)),
|
|
287
|
+
* saveToDatabase
|
|
288
|
+
* );
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* // Conditional debugging
|
|
292
|
+
* const debug = process.env.DEBUG === 'true';
|
|
293
|
+
* const pipeline = flow(
|
|
294
|
+
* parseData,
|
|
295
|
+
* debug ? tap(data => console.log('Parsed:', data)) : identity,
|
|
296
|
+
* transformData
|
|
297
|
+
* );
|
|
298
|
+
*
|
|
299
|
+
* @see identity - Pass through without side effects
|
|
300
|
+
* @since 2025-07-03
|
|
301
|
+
*/
|
|
302
|
+
export declare const tap: <T>(fn: (x: T) => void) => (x: T) => T;
|
|
303
|
+
/**
|
|
304
|
+
* Currying utility - converts a function of multiple arguments into a sequence of functions.
|
|
305
|
+
* Each function takes a single argument and returns another function until all arguments are provided.
|
|
306
|
+
*
|
|
307
|
+
* @category Function Transformation
|
|
308
|
+
* @example
|
|
309
|
+
* // Basic currying
|
|
310
|
+
* const add = (a: number, b: number) => a + b;
|
|
311
|
+
* const curriedAdd = curry(add);
|
|
312
|
+
* const add5 = curriedAdd(5);
|
|
313
|
+
* add5(3); // => 8
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* // Building reusable functions
|
|
317
|
+
* const multiply = curry((factor: number, value: number) => value * factor);
|
|
318
|
+
* const double = multiply(2);
|
|
319
|
+
* const triple = multiply(3);
|
|
320
|
+
*
|
|
321
|
+
* [1, 2, 3].map(double); // => [2, 4, 6]
|
|
322
|
+
* [1, 2, 3].map(triple); // => [3, 6, 9]
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* // Configuration functions
|
|
326
|
+
* const createLogger = curry((level: string, category: string, message: string) =>
|
|
327
|
+
* console.log(`[${level}] ${category}: ${message}`)
|
|
328
|
+
* );
|
|
329
|
+
*
|
|
330
|
+
* const errorLogger = createLogger('ERROR');
|
|
331
|
+
* const authErrorLogger = errorLogger('AUTH');
|
|
332
|
+
* authErrorLogger('Invalid credentials'); // => "[ERROR] AUTH: Invalid credentials"
|
|
333
|
+
*
|
|
334
|
+
* @see partial - Fix some arguments of a function
|
|
335
|
+
* @see flip - Reverse argument order
|
|
336
|
+
*/
|
|
337
|
+
export declare const curry: <A, B, C>(fn: (a: A, b: B) => C) => (a: A) => (b: B) => C;
|
|
338
|
+
/**
|
|
339
|
+
* Partial application - fixes some arguments of a function.
|
|
340
|
+
* Returns a new function that takes the remaining arguments.
|
|
341
|
+
*
|
|
342
|
+
* @category Function Transformation
|
|
343
|
+
* @example
|
|
344
|
+
* // Partially apply configuration
|
|
345
|
+
* const greet = (greeting: string, name: string) => `${greeting}, ${name}!`;
|
|
346
|
+
* const sayHello = partial(greet, 'Hello');
|
|
347
|
+
* sayHello('World'); // => "Hello, World!"
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* // Creating specialized functions
|
|
351
|
+
* const fetchAPI = (method: string, endpoint: string, body?: unknown) =>
|
|
352
|
+
* fetch(endpoint, { method, body: JSON.stringify(body) });
|
|
353
|
+
*
|
|
354
|
+
* const postAPI = partial(fetchAPI, 'POST');
|
|
355
|
+
* const getAPI = partial(fetchAPI, 'GET');
|
|
356
|
+
*
|
|
357
|
+
* postAPI('/users', { name: 'John' });
|
|
358
|
+
* getAPI('/users');
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* // Event handler specialization
|
|
362
|
+
* const logEvent = (category: string, action: string, label: string) =>
|
|
363
|
+
* analytics.track({ category, action, label });
|
|
364
|
+
*
|
|
365
|
+
* const logUserAction = partial(logEvent, 'USER');
|
|
366
|
+
* const logButtonClick = partial(logUserAction, 'CLICK');
|
|
367
|
+
*
|
|
368
|
+
* logButtonClick('submit-form'); // Logs: { category: 'USER', action: 'CLICK', label: 'submit-form' }
|
|
369
|
+
*
|
|
370
|
+
* @see curry - Convert to single-argument functions
|
|
371
|
+
* @see flip - Reverse argument order
|
|
372
|
+
*/
|
|
373
|
+
export declare const partial: <A extends unknown[], B, C>(fn: (...args: [...A, B]) => C, ...args: A) => (lastArg: B) => C;
|
|
374
|
+
/**
|
|
375
|
+
* Flip - reverses the order of arguments for a binary function.
|
|
376
|
+
* Useful when you need to adapt a function to work with different argument orders.
|
|
377
|
+
*
|
|
378
|
+
* @category Function Transformation
|
|
379
|
+
* @example
|
|
380
|
+
* // Basic flip
|
|
381
|
+
* const divide = (a: number, b: number) => a / b;
|
|
382
|
+
* const divideBy = flip(divide);
|
|
383
|
+
* divideBy(2, 10); // => 5 (10 / 2)
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* // Adapting functions for composition
|
|
387
|
+
* const concat = (a: string, b: string) => a + b;
|
|
388
|
+
* const prepend = flip(concat);
|
|
389
|
+
*
|
|
390
|
+
* const addPrefix = prepend('PREFIX_');
|
|
391
|
+
* addPrefix('value'); // => "valuePREFIX_"
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* // Working with collections
|
|
395
|
+
* const has = (obj: Record<string, unknown>, key: string) => key in obj;
|
|
396
|
+
* const hasKey = flip(has);
|
|
397
|
+
*
|
|
398
|
+
* const users = [{ name: 'John' }, { name: 'Jane', admin: true }];
|
|
399
|
+
* users.filter(hasKey('admin')); // => [{ name: 'Jane', admin: true }]
|
|
400
|
+
*
|
|
401
|
+
* @see curry - Convert to single-argument functions
|
|
402
|
+
* @see partial - Fix some arguments
|
|
403
|
+
*/
|
|
404
|
+
export declare const flip: <A, B, C>(fn: (a: A, b: B) => C) => (b: B, a: A) => C;
|
|
405
|
+
/**
|
|
406
|
+
* Memoization - caches function results based on arguments.
|
|
407
|
+
* Improves performance for expensive pure functions by storing previously computed results.
|
|
408
|
+
*
|
|
409
|
+
* @category Performance
|
|
410
|
+
* @example
|
|
411
|
+
* // Memoize expensive calculations
|
|
412
|
+
* const fibonacci = memoize((n: number): number => {
|
|
413
|
+
* if (n <= 1) return n;
|
|
414
|
+
* return fibonacci(n - 1) + fibonacci(n - 2);
|
|
415
|
+
* });
|
|
416
|
+
*
|
|
417
|
+
* fibonacci(40); // First call: slow
|
|
418
|
+
* fibonacci(40); // Second call: instant (cached)
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* // Custom cache key generation
|
|
422
|
+
* const processUser = memoize(
|
|
423
|
+
* async (userId: string, options: { includeDetails: boolean }) => {
|
|
424
|
+
* const user = await fetchUser(userId);
|
|
425
|
+
* return options.includeDetails
|
|
426
|
+
* ? { ...user, details: await fetchUserDetails(userId) }
|
|
427
|
+
* : user;
|
|
428
|
+
* },
|
|
429
|
+
* (userId, options) => `${userId}-${options.includeDetails}`
|
|
430
|
+
* );
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* // Memoizing API calls
|
|
434
|
+
* const fetchProductData = memoize(async (productId: string) => {
|
|
435
|
+
* const response = await fetch(`/api/products/${productId}`);
|
|
436
|
+
* return response.json();
|
|
437
|
+
* });
|
|
438
|
+
*
|
|
439
|
+
* // Multiple components can call this without duplicate requests
|
|
440
|
+
* await fetchProductData('123'); // Makes API call
|
|
441
|
+
* await fetchProductData('123'); // Returns cached result
|
|
442
|
+
*
|
|
443
|
+
* @see identity - For functions that don't need memoization
|
|
444
|
+
*/
|
|
445
|
+
export declare const memoize: <Args extends unknown[], Return>(fn: (...args: Args) => Return, getKey?: (...args: Args) => string) => ((...args: Args) => Return);
|
|
446
|
+
/**
|
|
447
|
+
* Compose async functions from right to left.
|
|
448
|
+
* Allows composition of Promise-returning functions in mathematical order.
|
|
449
|
+
* Now supports any number of async functions.
|
|
450
|
+
*
|
|
451
|
+
* @category Async
|
|
452
|
+
* @example
|
|
453
|
+
* // Async data processing pipeline
|
|
454
|
+
* const processData = composeAsync(
|
|
455
|
+
* async (data: ProcessedData) => saveToDatabase(data), // 3. Save
|
|
456
|
+
* async (data: ValidatedData) => transformData(data), // 2. Transform
|
|
457
|
+
* async (data: RawData) => validateData(data) // 1. Validate
|
|
458
|
+
* );
|
|
459
|
+
*
|
|
460
|
+
* const result = await processData(rawData);
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* // API call composition with multiple steps
|
|
464
|
+
* const fetchUserWithPosts = composeAsync(
|
|
465
|
+
* async (enriched: EnrichedUser) => logActivity(enriched), // 5. Log
|
|
466
|
+
* async (userData: UserWithMetadata) => enrichWithMetadata(userData),// 4. Enrich
|
|
467
|
+
* async (userWithPerms: UserWithPerms) => addPreferences(userWithPerms), // 3. Add prefs
|
|
468
|
+
* async (userWithPosts: UserWithPosts) => addPermissions(userWithPosts), // 2. Add perms
|
|
469
|
+
* async (user: User) => ({ ...user, posts: await fetchUserPosts(user.id) }), // 1. Add posts
|
|
470
|
+
* async (userId: string) => fetchUser(userId) // 0. Fetch user
|
|
471
|
+
* );
|
|
472
|
+
*
|
|
473
|
+
* const enrichedUser = await fetchUserWithPosts('123');
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* // Error handling in async composition
|
|
477
|
+
* const safeProcessData = composeAsync(
|
|
478
|
+
* async (result: ProcessResult) => logSuccess(result),
|
|
479
|
+
* async (data: ValidData) => processData(data).catch(err => {
|
|
480
|
+
* console.error('Processing failed:', err);
|
|
481
|
+
* throw err;
|
|
482
|
+
* }),
|
|
483
|
+
* async (raw: unknown) => validateData(raw)
|
|
484
|
+
* );
|
|
485
|
+
*
|
|
486
|
+
* @see pipeAsync - Left-to-right async composition
|
|
487
|
+
* @see compose - Synchronous right-to-left composition
|
|
488
|
+
* @since 2025-07-03
|
|
489
|
+
*/
|
|
490
|
+
export declare function composeAsync<A, B>(f1: (a: A) => Promise<B>): (a: A) => Promise<B>;
|
|
491
|
+
export declare function composeAsync<A, B, C>(f2: (b: B) => Promise<C>, f1: (a: A) => Promise<B>): (a: A) => Promise<C>;
|
|
492
|
+
export declare function composeAsync<A, B, C, D>(f3: (c: C) => Promise<D>, f2: (b: B) => Promise<C>, f1: (a: A) => Promise<B>): (a: A) => Promise<D>;
|
|
493
|
+
export declare function composeAsync<A, B, C, D, E>(f4: (d: D) => Promise<E>, f3: (c: C) => Promise<D>, f2: (b: B) => Promise<C>, f1: (a: A) => Promise<B>): (a: A) => Promise<E>;
|
|
494
|
+
export declare function composeAsync<A, B, C, D, E, F>(f5: (e: E) => Promise<F>, f4: (d: D) => Promise<E>, f3: (c: C) => Promise<D>, f2: (b: B) => Promise<C>, f1: (a: A) => Promise<B>): (a: A) => Promise<F>;
|
|
495
|
+
/**
|
|
496
|
+
* Pipe async functions from left to right.
|
|
497
|
+
* Natural reading order for async function composition.
|
|
498
|
+
* Now supports any number of async functions.
|
|
499
|
+
*
|
|
500
|
+
* @category Async
|
|
501
|
+
* @example
|
|
502
|
+
* // Sequential async operations
|
|
503
|
+
* const uploadAndProcess = pipeAsync(
|
|
504
|
+
* async (file: File) => uploadFile(file), // 1. Upload
|
|
505
|
+
* async (url: string) => processImage(url), // 2. Process
|
|
506
|
+
* async (processed: ProcessedImage) => notify(processed) // 3. Notify
|
|
507
|
+
* );
|
|
508
|
+
*
|
|
509
|
+
* const result = await uploadAndProcess(imageFile);
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* // API data enrichment with multiple steps
|
|
513
|
+
* const enrichUser = pipeAsync(
|
|
514
|
+
* async (userId: string) => fetchUser(userId),
|
|
515
|
+
* async (user: User) => ({
|
|
516
|
+
* ...user,
|
|
517
|
+
* permissions: await fetchPermissions(user.roleId)
|
|
518
|
+
* }),
|
|
519
|
+
* async (user: UserWithPerms) => ({
|
|
520
|
+
* ...user,
|
|
521
|
+
* preferences: await fetchPreferences(user.id)
|
|
522
|
+
* }),
|
|
523
|
+
* async (user: UserWithPrefs) => ({
|
|
524
|
+
* ...user,
|
|
525
|
+
* analytics: await fetchAnalytics(user.id)
|
|
526
|
+
* }),
|
|
527
|
+
* async (user: FullUser) => cacheUser(user)
|
|
528
|
+
* );
|
|
529
|
+
*
|
|
530
|
+
* const fullUser = await enrichUser('123');
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* // Error handling in async pipelines
|
|
534
|
+
* const processOrder = pipeAsync(
|
|
535
|
+
* async (orderId: string) => fetchOrder(orderId),
|
|
536
|
+
* async (order: Order) => validateOrder(order),
|
|
537
|
+
* async (validOrder: ValidOrder) => processPayment(validOrder),
|
|
538
|
+
* async (paidOrder: PaidOrder) => shipOrder(paidOrder),
|
|
539
|
+
* async (shippedOrder: ShippedOrder) => sendConfirmation(shippedOrder)
|
|
540
|
+
* );
|
|
541
|
+
*
|
|
542
|
+
* try {
|
|
543
|
+
* await processOrder('ORDER-123');
|
|
544
|
+
* } catch (error) {
|
|
545
|
+
* console.error('Order processing failed:', error);
|
|
546
|
+
* }
|
|
547
|
+
*
|
|
548
|
+
* @see composeAsync - Right-to-left async composition
|
|
549
|
+
* @see pipe - Synchronous left-to-right composition
|
|
550
|
+
* @since 2025-07-03
|
|
551
|
+
*/
|
|
552
|
+
export declare function pipeAsync<A, B>(f1: (a: A) => Promise<B>): (a: A) => Promise<B>;
|
|
553
|
+
export declare function pipeAsync<A, B, C>(f1: (a: A) => Promise<B>, f2: (b: B) => Promise<C>): (a: A) => Promise<C>;
|
|
554
|
+
export declare function pipeAsync<A, B, C, D>(f1: (a: A) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>): (a: A) => Promise<D>;
|
|
555
|
+
export declare function pipeAsync<A, B, C, D, E>(f1: (a: A) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>, f4: (d: D) => Promise<E>): (a: A) => Promise<E>;
|
|
556
|
+
export declare function pipeAsync<A, B, C, D, E, F>(f1: (a: A) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>, f4: (d: D) => Promise<E>, f5: (e: E) => Promise<F>): (a: A) => Promise<F>;
|
|
557
|
+
/**
|
|
558
|
+
* Sequential execution of async functions.
|
|
559
|
+
* @description Executes an array of async functions in order, waiting for each to complete before starting the next.
|
|
560
|
+
* Collects and returns all results in an array. Unlike Promise.all, this ensures sequential execution
|
|
561
|
+
* which is useful when operations depend on each other or when you need to limit concurrency.
|
|
562
|
+
*
|
|
563
|
+
* @template T - The type of values returned by the async functions
|
|
564
|
+
* @param {Array<() => Promise<T>>} fns - Array of async functions to execute
|
|
565
|
+
* @returns {Promise<T[]>} Promise resolving to array of all results in order
|
|
566
|
+
*
|
|
567
|
+
* @category Async
|
|
568
|
+
* @example
|
|
569
|
+
* // Execute initialization steps in order
|
|
570
|
+
* const initSteps = [
|
|
571
|
+
* async () => connectDatabase(),
|
|
572
|
+
* async () => loadConfiguration(),
|
|
573
|
+
* async () => startServer()
|
|
574
|
+
* ];
|
|
575
|
+
*
|
|
576
|
+
* const results = await sequence(initSteps);
|
|
577
|
+
* // All steps completed in order
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* // Data fetching sequence
|
|
581
|
+
* const fetchOperations = userIds.map(id =>
|
|
582
|
+
* async () => fetchUserData(id)
|
|
583
|
+
* );
|
|
584
|
+
*
|
|
585
|
+
* const allUserData = await sequence(fetchOperations);
|
|
586
|
+
* // Fetches users one by one, not in parallel
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* // Cleanup operations
|
|
590
|
+
* const cleanup = sequence([
|
|
591
|
+
* async () => closeConnections(),
|
|
592
|
+
* async () => flushCache(),
|
|
593
|
+
* async () => logShutdown()
|
|
594
|
+
* ]);
|
|
595
|
+
*
|
|
596
|
+
* process.on('SIGTERM', () => cleanup());
|
|
597
|
+
*
|
|
598
|
+
* @see Promise.all - For parallel execution
|
|
599
|
+
* @see pipeAsync - For composing async functions
|
|
600
|
+
* @since 2025-07-03
|
|
601
|
+
*/
|
|
602
|
+
export declare const sequence: <T>(fns: (() => Promise<T>)[]) => Promise<T[]>;
|
|
603
|
+
//# sourceMappingURL=composition.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composition.d.mts","sourceRoot":"","sources":["../src/composition.mts"],"names":[],"mappings":"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"}
|