@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.
Files changed (46) hide show
  1. package/README.md +242 -0
  2. package/dist/array-utils.d.mts +317 -0
  3. package/dist/array-utils.d.mts.map +1 -0
  4. package/dist/array-utils.mjs +370 -0
  5. package/dist/array-utils.mjs.map +1 -0
  6. package/dist/composition.d.mts +603 -0
  7. package/dist/composition.d.mts.map +1 -0
  8. package/dist/composition.mjs +516 -0
  9. package/dist/composition.mjs.map +1 -0
  10. package/dist/object-utils.d.mts +267 -0
  11. package/dist/object-utils.d.mts.map +1 -0
  12. package/dist/object-utils.mjs +258 -0
  13. package/dist/object-utils.mjs.map +1 -0
  14. package/dist/option.d.mts +622 -0
  15. package/dist/option.d.mts.map +1 -0
  16. package/dist/option.mjs +637 -0
  17. package/dist/option.mjs.map +1 -0
  18. package/dist/performance.d.mts +265 -0
  19. package/dist/performance.d.mts.map +1 -0
  20. package/dist/performance.mjs +453 -0
  21. package/dist/performance.mjs.map +1 -0
  22. package/dist/pipeline.d.mts +431 -0
  23. package/dist/pipeline.d.mts.map +1 -0
  24. package/dist/pipeline.mjs +460 -0
  25. package/dist/pipeline.mjs.map +1 -0
  26. package/dist/predicates.d.mts +722 -0
  27. package/dist/predicates.d.mts.map +1 -0
  28. package/dist/predicates.mjs +802 -0
  29. package/dist/predicates.mjs.map +1 -0
  30. package/dist/reader-result.d.mts +422 -0
  31. package/dist/reader-result.d.mts.map +1 -0
  32. package/dist/reader-result.mjs +758 -0
  33. package/dist/reader-result.mjs.map +1 -0
  34. package/dist/result.d.mts +684 -0
  35. package/dist/result.d.mts.map +1 -0
  36. package/dist/result.mjs +814 -0
  37. package/dist/result.mjs.map +1 -0
  38. package/dist/types.d.mts +439 -0
  39. package/dist/types.d.mts.map +1 -0
  40. package/dist/types.mjs +191 -0
  41. package/dist/types.mjs.map +1 -0
  42. package/dist/validation.d.mts +622 -0
  43. package/dist/validation.d.mts.map +1 -0
  44. package/dist/validation.mjs +852 -0
  45. package/dist/validation.mjs.map +1 -0
  46. package/package.json +46 -0
@@ -0,0 +1,431 @@
1
+ /**
2
+ * @module pipeline
3
+ * @description A fluent, chainable API for function composition that maintains state.
4
+ * Unlike pure functional composition, Pipeline provides an object-oriented
5
+ * interface for building complex data transformations with method chaining.
6
+ * Combines the benefits of functional programming with familiar OOP patterns.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { Pipeline } from './pipeline.mts';
11
+ *
12
+ * // basic transformations
13
+ * const result = Pipeline.of(5)
14
+ * .map(x => x * 2)
15
+ * .map(x => x + 1)
16
+ * .value();
17
+ * // => 11
18
+ *
19
+ * // async transformations
20
+ * const userData = await Pipeline.of('user123')
21
+ * .mapAsync(id => fetchUser(id))
22
+ * .then(p => p.map(user => user.email))
23
+ * .then(p => p.value());
24
+ *
25
+ * // error handling
26
+ * const validated = Pipeline.of(input)
27
+ * .filter(x => x > 0, 'Must be positive')
28
+ * .map(result => result.success ? result.data * 2 : result)
29
+ * .value();
30
+ * ```
31
+ *
32
+ * @category Core
33
+ * @since 2025-07-03
34
+ */
35
+ /**
36
+ * Pipeline builder for fluent function composition.
37
+ * Provides a stateful, chainable interface for applying transformations
38
+ * to a value. Unlike pure functional composition, Pipeline maintains
39
+ * internal state and offers a familiar object-oriented API.
40
+ *
41
+ * @category Core
42
+ * @example
43
+ * // Basic transformation pipeline
44
+ * const result = Pipeline.of(5)
45
+ * .map(x => x * 2)
46
+ * .map(x => x + 1)
47
+ * .map(x => `Result: ${x}`)
48
+ * .value();
49
+ * // => "Result: 11"
50
+ *
51
+ * @example
52
+ * // Complex data transformation
53
+ * const userPipeline = Pipeline.of({ name: 'john doe', age: 30 })
54
+ * .map(user => ({ ...user, name: user.name.toUpperCase() }))
55
+ * .tap(user => console.log('Processing:', user.name))
56
+ * .map(user => ({ ...user, ageGroup: user.age >= 18 ? 'adult' : 'minor' }))
57
+ * .value();
58
+ * // => { name: 'JOHN DOE', age: 30, ageGroup: 'adult' }
59
+ *
60
+ * @example
61
+ * // Error handling with filter
62
+ * const processNumber = (n: number) => Pipeline.of(n)
63
+ * .filter(x => x > 0, 'Number must be positive')
64
+ * .map(result => {
65
+ * if (!result.success) return result;
66
+ * return { success: true as const, data: Math.sqrt(result.data) };
67
+ * })
68
+ * .value();
69
+ *
70
+ * processNumber(16); // => { success: true, data: 4 }
71
+ * processNumber(-4); // => { success: false, error: 'Number must be positive' }
72
+ */
73
+ export declare class Pipeline<T> {
74
+ private readonly _value;
75
+ /**
76
+ * Creates a new Pipeline instance with the given value.
77
+ * Use Pipeline.of() for a more functional approach.
78
+ *
79
+ * @private
80
+ */
81
+ constructor(_value: T);
82
+ /**
83
+ * Apply a synchronous transformation.
84
+ * @description Transforms the current value using the provided function.
85
+ * Returns a new Pipeline containing the transformed value.
86
+ *
87
+ * @template U - The type of the transformed value
88
+ * @param {function(T): U} fn - Function to transform the value
89
+ * @returns {Pipeline<U>} A new Pipeline with the transformed value
90
+ *
91
+ * @category Transformation
92
+ * @example
93
+ * const doubled = Pipeline.of(5)
94
+ * .map(x => x * 2)
95
+ * .value();
96
+ * // => 10
97
+ *
98
+ * @example
99
+ * // Chaining transformations
100
+ * const result = Pipeline.of('hello')
101
+ * .map(s => s.toUpperCase())
102
+ * .map(s => s.split(''))
103
+ * .map(arr => arr.reverse())
104
+ * .map(arr => arr.join(''))
105
+ * .value();
106
+ * // => 'OLLEH'
107
+ *
108
+ * @see mapAsync - Transform with async function
109
+ * @see flatMap - Transform and flatten
110
+ * @since 2025-07-03
111
+ */
112
+ map<U>(fn: (value: T) => U): Pipeline<U>;
113
+ /**
114
+ * Apply an asynchronous transformation.
115
+ * @description Transforms the current value using an async function.
116
+ * Returns a Promise that resolves to a new Pipeline with the transformed value.
117
+ *
118
+ * @template U - The type of the transformed value
119
+ * @param {function(T): Promise<U>} fn - Async function to transform the value
120
+ * @returns {Promise<Pipeline<U>>} Promise resolving to a new Pipeline
121
+ *
122
+ * @category Async
123
+ * @example
124
+ * const userData = await Pipeline.of(123)
125
+ * .mapAsync(async (id) => {
126
+ * const response = await fetch(`/api/users/${id}`);
127
+ * return response.json();
128
+ * })
129
+ * .then(p => p.value());
130
+ *
131
+ * @example
132
+ * // Chaining async operations
133
+ * const result = await Pipeline.of('user@example.com')
134
+ * .mapAsync(email => fetchUserByEmail(email))
135
+ * .then(p => p.mapAsync(user => fetchUserPosts(user.id)))
136
+ * .then(p => p.map(posts => posts.length))
137
+ * .then(p => p.value());
138
+ * // => number of posts
139
+ */
140
+ mapAsync<U>(fn: (value: T) => Promise<U>): Promise<Pipeline<U>>;
141
+ /**
142
+ * Apply a transformation that might fail.
143
+ * Handles functions that return Result types.
144
+ *
145
+ * @category Error Handling
146
+ * @example
147
+ * const safeDivide = (n: number, divisor: number) =>
148
+ * divisor === 0
149
+ * ? { success: false as const, error: 'Division by zero' }
150
+ * : { success: true as const, data: n / divisor };
151
+ *
152
+ * const result = Pipeline.of(10)
153
+ * .flatMap(n => safeDivide(n, 2))
154
+ * .value();
155
+ * // => { success: true, data: 5 }
156
+ *
157
+ * @example
158
+ * // Chaining fallible operations
159
+ * const process = Pipeline.of('{"name": "John"}')
160
+ * .flatMap(str => {
161
+ * try {
162
+ * return { success: true as const, data: JSON.parse(str) };
163
+ * } catch {
164
+ * return { success: false as const, error: 'Invalid JSON' };
165
+ * }
166
+ * })
167
+ * .map(result => {
168
+ * if (!result.success) return result;
169
+ * return { success: true as const, data: result.data.name };
170
+ * })
171
+ * .value();
172
+ * // => { success: true, data: 'John' }
173
+ */
174
+ flatMap<U, E>(fn: (value: T) => {
175
+ success: true;
176
+ data: U;
177
+ } | {
178
+ success: false;
179
+ error: E;
180
+ }): Pipeline<{
181
+ success: true;
182
+ data: U;
183
+ } | {
184
+ success: false;
185
+ error: E;
186
+ }>;
187
+ /**
188
+ * Filter the pipeline based on a predicate.
189
+ * Converts the value to a Result type based on the predicate.
190
+ *
191
+ * @category Filtering
192
+ * @example
193
+ * const result = Pipeline.of(5)
194
+ * .filter(x => x > 0, 'Must be positive')
195
+ * .value();
196
+ * // => { success: true, data: 5 }
197
+ *
198
+ * @example
199
+ * // Validation pipeline
200
+ * const validateUser = (user: any) => Pipeline.of(user)
201
+ * .filter(u => u.name, 'Name is required')
202
+ * .map(result => {
203
+ * if (!result.success) return result;
204
+ * return Pipeline.of(result.data)
205
+ * .filter(u => u.age >= 18, 'Must be 18 or older')
206
+ * .value();
207
+ * })
208
+ * .value();
209
+ *
210
+ * validateUser({ name: 'John', age: 20 }); // => { success: true, data: {...} }
211
+ * validateUser({ name: '', age: 20 }); // => { success: false, error: 'Name is required' }
212
+ */
213
+ filter<E>(predicate: (value: T) => boolean, error: E): Pipeline<{
214
+ success: true;
215
+ data: T;
216
+ } | {
217
+ success: false;
218
+ error: E;
219
+ }>;
220
+ /**
221
+ * Execute a side effect without changing the value.
222
+ * Useful for logging, debugging, or triggering external actions.
223
+ *
224
+ * @category Side Effects
225
+ * @example
226
+ * const result = Pipeline.of([1, 2, 3, 4, 5])
227
+ * .tap(arr => console.log('Original:', arr))
228
+ * .map(arr => arr.filter(x => x % 2 === 0))
229
+ * .tap(arr => console.log('Filtered:', arr))
230
+ * .map(arr => arr.reduce((a, b) => a + b, 0))
231
+ * .tap(sum => console.log('Sum:', sum))
232
+ * .value();
233
+ * // Logs: Original: [1,2,3,4,5], Filtered: [2,4], Sum: 6
234
+ * // Returns: 6
235
+ *
236
+ * @example
237
+ * // Analytics tracking
238
+ * const processOrder = Pipeline.of(order)
239
+ * .tap(o => analytics.track('order_started', { orderId: o.id }))
240
+ * .map(o => applyDiscount(o))
241
+ * .tap(o => analytics.track('discount_applied', { amount: o.discount }))
242
+ * .map(o => calculateTax(o))
243
+ * .tap(o => analytics.track('order_completed', { total: o.total }))
244
+ * .value();
245
+ */
246
+ tap(fn: (value: T) => void): Pipeline<T>;
247
+ /**
248
+ * Execute an async side effect without changing the value.
249
+ * Useful for async logging, API calls, or other async side effects.
250
+ *
251
+ * @category Async
252
+ * @example
253
+ * const saveUser = await Pipeline.of(userData)
254
+ * .tapAsync(async (user) => {
255
+ * await logToAnalytics('user_created', user);
256
+ * })
257
+ * .then(p => p.tapAsync(async (user) => {
258
+ * await sendWelcomeEmail(user.email);
259
+ * }))
260
+ * .then(p => p.value());
261
+ *
262
+ * @example
263
+ * // Progress tracking
264
+ * const processLargeFile = await Pipeline.of(file)
265
+ * .tapAsync(f => updateProgress(0))
266
+ * .then(p => p.mapAsync(f => readFile(f)))
267
+ * .then(p => p.tapAsync(_ => updateProgress(33)))
268
+ * .then(p => p.mapAsync(content => parseContent(content)))
269
+ * .then(p => p.tapAsync(_ => updateProgress(66)))
270
+ * .then(p => p.mapAsync(data => saveToDatabase(data)))
271
+ * .then(p => p.tapAsync(_ => updateProgress(100)))
272
+ * .then(p => p.value());
273
+ */
274
+ tapAsync(fn: (value: T) => Promise<void>): Promise<Pipeline<T>>;
275
+ /**
276
+ * Get the final value from the pipeline.
277
+ * Extracts the transformed value, ending the pipeline chain.
278
+ *
279
+ * @category Extraction
280
+ * @example
281
+ * const result = Pipeline.of(10)
282
+ * .map(x => x * 2)
283
+ * .map(x => x + 5)
284
+ * .value();
285
+ * // => 25
286
+ */
287
+ value(): T;
288
+ /**
289
+ * Create a new pipeline with the given value.
290
+ * Factory method for creating Pipeline instances.
291
+ *
292
+ * @category Creation
293
+ * @example
294
+ * const pipeline = Pipeline.of(42);
295
+ *
296
+ * @example
297
+ * // With complex initial values
298
+ * const userPipeline = Pipeline.of({
299
+ * id: 123,
300
+ * name: 'John Doe',
301
+ * email: 'john@example.com'
302
+ * });
303
+ */
304
+ static of<T>(value: T): Pipeline<T>;
305
+ /**
306
+ * Apply a function to the pipeline value and return the result.
307
+ * Useful for conditional transformations or extracting values.
308
+ *
309
+ * @category Advanced
310
+ * @example
311
+ * const discount = Pipeline.of(100)
312
+ * .apply(price =>
313
+ * price > 50
314
+ * ? Pipeline.of(price * 0.9) // 10% discount
315
+ * : Pipeline.of(price)
316
+ * )
317
+ * .value();
318
+ * // => 90
319
+ *
320
+ * @example
321
+ * // Conditional branching
322
+ * const processUser = (user: User) => Pipeline.of(user)
323
+ * .apply(u => {
324
+ * if (u.type === 'premium') {
325
+ * return Pipeline.of(u)
326
+ * .map(u => ({ ...u, benefits: ['ad-free', 'priority-support'] }))
327
+ * .map(u => ({ ...u, discount: 0.2 }));
328
+ * } else {
329
+ * return Pipeline.of(u)
330
+ * .map(u => ({ ...u, benefits: [] }))
331
+ * .map(u => ({ ...u, discount: 0 }));
332
+ * }
333
+ * })
334
+ * .value();
335
+ */
336
+ apply<U>(fn: (value: T) => Pipeline<U>): Pipeline<U>;
337
+ /**
338
+ * Combine two pipelines using a binary function.
339
+ * Useful for merging results from multiple pipelines.
340
+ *
341
+ * @category Advanced
342
+ * @example
343
+ * const pipeline1 = Pipeline.of(5);
344
+ * const pipeline2 = Pipeline.of(3);
345
+ *
346
+ * const sum = pipeline1
347
+ * .combine(pipeline2, (a, b) => a + b)
348
+ * .value();
349
+ * // => 8
350
+ *
351
+ * @example
352
+ * // Combining user data
353
+ * const userPipeline = Pipeline.of({ id: 1, name: 'John' });
354
+ * const preferencesPipeline = Pipeline.of({ theme: 'dark', lang: 'en' });
355
+ *
356
+ * const completeUser = userPipeline
357
+ * .combine(preferencesPipeline, (user, prefs) => ({
358
+ * ...user,
359
+ * preferences: prefs
360
+ * }))
361
+ * .value();
362
+ * // => { id: 1, name: 'John', preferences: { theme: 'dark', lang: 'en' } }
363
+ */
364
+ combine<U, R>(other: Pipeline<U>, fn: (a: T, b: U) => R): Pipeline<R>;
365
+ /**
366
+ * Execute a pipeline of async operations and return the final value directly.
367
+ * Eliminates the need for chaining .then() calls for async transformations.
368
+ * This is a more ergonomic alternative to chaining mapAsync calls.
369
+ *
370
+ * @category Async
371
+ * @example
372
+ * // Instead of this verbose approach:
373
+ * const result = await Pipeline.of('user@example.com')
374
+ * .mapAsync(fetchUserByEmail)
375
+ * .then(p => p.mapAsync(fetchUserPosts))
376
+ * .then(p => p.map(posts => posts.length))
377
+ * .then(p => p.value());
378
+ *
379
+ * // Use pipeAsync for cleaner async pipelines:
380
+ * const result = await Pipeline.of('user@example.com')
381
+ * .pipeAsync(
382
+ * fetchUserByEmail,
383
+ * fetchUserPosts,
384
+ * async (posts) => posts.length
385
+ * );
386
+ * // => number of posts
387
+ *
388
+ * @example
389
+ * // Complex async data enrichment
390
+ * const enrichedUser = await Pipeline.of('123')
391
+ * .pipeAsync(
392
+ * async (id) => fetchUser(id),
393
+ * async (user) => ({
394
+ * ...user,
395
+ * permissions: await fetchPermissions(user.roleId)
396
+ * }),
397
+ * async (user) => ({
398
+ * ...user,
399
+ * preferences: await fetchPreferences(user.id)
400
+ * }),
401
+ * async (user) => ({
402
+ * ...user,
403
+ * analytics: await fetchAnalytics(user.id)
404
+ * })
405
+ * );
406
+ *
407
+ * @example
408
+ * // Error handling in async pipelines
409
+ * try {
410
+ * const order = await Pipeline.of('ORDER-123')
411
+ * .pipeAsync(
412
+ * fetchOrder,
413
+ * validateOrder,
414
+ * processPayment,
415
+ * shipOrder,
416
+ * sendConfirmation
417
+ * );
418
+ * console.log('Order processed:', order);
419
+ * } catch (error) {
420
+ * console.error('Order processing failed:', error);
421
+ * }
422
+ *
423
+ * @since 2025-07-03
424
+ */
425
+ pipeAsync<B>(f1: (a: T) => Promise<B>): Promise<B>;
426
+ pipeAsync<B, C>(f1: (a: T) => Promise<B>, f2: (b: B) => Promise<C>): Promise<C>;
427
+ pipeAsync<B, C, D>(f1: (a: T) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>): Promise<D>;
428
+ pipeAsync<B, C, D, E>(f1: (a: T) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>, f4: (d: D) => Promise<E>): Promise<E>;
429
+ pipeAsync<B, C, D, E, F>(f1: (a: T) => Promise<B>, f2: (b: B) => Promise<C>, f3: (c: C) => Promise<D>, f4: (d: D) => Promise<E>, f5: (e: E) => Promise<F>): Promise<F>;
430
+ }
431
+ //# sourceMappingURL=pipeline.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.mts","sourceRoot":"","sources":["../src/pipeline.mts"],"names":[],"mappings":"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"}