@railway-ts/pipelines 0.1.7 → 0.1.8
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 +129 -70
- package/dist/composition/index.cjs +22 -0
- package/dist/composition/index.cjs.map +1 -1
- package/dist/composition/index.d.cts +89 -3
- package/dist/composition/index.d.ts +89 -3
- package/dist/composition/index.mjs +21 -1
- package/dist/composition/index.mjs.map +1 -1
- package/dist/option/index.cjs +43 -19
- package/dist/option/index.cjs.map +1 -1
- package/dist/option/index.d.cts +1 -1
- package/dist/option/index.d.ts +1 -1
- package/dist/option/index.mjs +40 -20
- package/dist/option/index.mjs.map +1 -1
- package/dist/result/index.cjs +70 -33
- package/dist/result/index.cjs.map +1 -1
- package/dist/result/index.d.cts +1032 -1
- package/dist/result/index.d.ts +1032 -1
- package/dist/result/index.mjs +63 -33
- package/dist/result/index.mjs.map +1 -1
- package/dist/schema/index.cjs +180 -45
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +628 -1550
- package/dist/schema/index.d.ts +628 -1550
- package/dist/schema/index.mjs +176 -45
- package/dist/schema/index.mjs.map +1 -1
- package/package.json +3 -11
- package/dist/index-BdfKTZ7O.d.cts +0 -799
- package/dist/index-BdfKTZ7O.d.ts +0 -799
- package/dist/index.cjs +0 -1149
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.mjs +0 -1041
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Railway-oriented programming for TypeScript. Result and Option types that don't suck.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Small, focused API surface. Errors propagate automatically, you handle them once at the end.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -14,11 +14,53 @@ bun add @railway-ts/pipelines # or npm, pnpm, yarn
|
|
|
14
14
|
|
|
15
15
|
Requires TypeScript 5.0+ and Node.js 18+.
|
|
16
16
|
|
|
17
|
-
## Quick
|
|
17
|
+
## Quick Example
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
20
|
import { pipe } from '@railway-ts/pipelines/composition';
|
|
21
|
-
import { ok,
|
|
21
|
+
import { ok, err, mapWith, match } from '@railway-ts/pipelines/result';
|
|
22
|
+
|
|
23
|
+
const divide = (a: number, b: number) =>
|
|
24
|
+
b === 0 ? err('div by zero') : ok(a / b);
|
|
25
|
+
|
|
26
|
+
const result = pipe(
|
|
27
|
+
divide(10, 2),
|
|
28
|
+
mapWith((x) => x * 3),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
match(result, {
|
|
32
|
+
ok: (value) => console.log(value), // 15
|
|
33
|
+
err: (error) => console.error(error),
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Documentation
|
|
38
|
+
|
|
39
|
+
-> **[Getting Started](docs/GETTING_STARTED.md)** - Guided walkthrough from first principles to full pipelines
|
|
40
|
+
-> **[Recipes](docs/RECIPES.md)** - Point-free composition, error recovery, async pipelines, validation patterns
|
|
41
|
+
-> **[Advanced](docs/ADVANCED.md)** - Symbol branding, type inference, implementation details
|
|
42
|
+
-> **[Examples](examples/)** - Working code you can run
|
|
43
|
+
|
|
44
|
+
For a complete real-world pipeline, see the [Launch Decision Pipeline](docs/RECIPES.md#full-example-launch-decision-pipeline) -- validates input, fetches weather data, and makes a GO/NO-GO decision.
|
|
45
|
+
|
|
46
|
+
## What's Included
|
|
47
|
+
|
|
48
|
+
- **Result\<T, E\>** -- typed success/failure with map, flatMap, match, and recovery
|
|
49
|
+
- **Option\<T\>** -- nullable handling without null checks
|
|
50
|
+
- **Schema validation** -- parse unknown data, accumulate all errors, infer TypeScript types
|
|
51
|
+
- **Composition** -- `pipe`, `flow`, `pipeAsync`, `flowAsync`, `curry`
|
|
52
|
+
- **Async** -- sync-preserving overloads, parallel field validation, seamless sync/async mixing
|
|
53
|
+
- **Standard Schema v1** -- `toStandardSchema()` for tRPC, TanStack Form, React Hook Form, and other consumers
|
|
54
|
+
|
|
55
|
+
## Two Styles
|
|
56
|
+
|
|
57
|
+
Same task, two approaches -- use whichever fits your codebase.
|
|
58
|
+
|
|
59
|
+
**Pipeline-first** -- keep validation and computation as separate pipeline steps:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { pipeAsync } from '@railway-ts/pipelines/composition';
|
|
63
|
+
import { mapWith, match } from '@railway-ts/pipelines/result';
|
|
22
64
|
import {
|
|
23
65
|
validate,
|
|
24
66
|
object,
|
|
@@ -36,8 +78,11 @@ const schema = object({
|
|
|
36
78
|
y: required(chain(parseNumber(), min(1))),
|
|
37
79
|
});
|
|
38
80
|
|
|
39
|
-
async function compute(input: unknown)
|
|
40
|
-
const result = await
|
|
81
|
+
async function compute(input: unknown) {
|
|
82
|
+
const result = await pipeAsync(
|
|
83
|
+
validate(input, schema),
|
|
84
|
+
mapWith(({ x, y }) => x / y),
|
|
85
|
+
);
|
|
41
86
|
|
|
42
87
|
return match<number, ValidationError[], ValidationResult<number>>(result, {
|
|
43
88
|
ok: (value) => ({ valid: true, data: value }),
|
|
@@ -45,40 +90,51 @@ async function compute(input: unknown): Promise<ValidationResult<number>> {
|
|
|
45
90
|
});
|
|
46
91
|
}
|
|
47
92
|
|
|
48
|
-
await compute({ x: 10, y: 2 }).then(console.log); // { valid: true, data: 5 }
|
|
93
|
+
await compute({ x: '10', y: '2' }).then(console.log); // { valid: true, data: 5 }
|
|
49
94
|
```
|
|
50
95
|
|
|
51
|
-
**
|
|
52
|
-
|
|
53
|
-
## Documentation
|
|
54
|
-
|
|
55
|
-
→ **[Getting Started](GETTING_STARTED.md)** - Your first pipeline
|
|
56
|
-
→ **[Recipes](docs/RECIPES.md)** - Common patterns (point-free composition, async, validation)
|
|
57
|
-
→ **[Advanced](docs/ADVANCED.md)** - Symbol branding, tuple preservation, type inference
|
|
58
|
-
→ **[Examples](examples/)** - Working code you can run
|
|
96
|
+
**Schema-first** -- fold the transform into the schema, get the result in one call:
|
|
59
97
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
98
|
+
```typescript
|
|
99
|
+
import {
|
|
100
|
+
validateAndFormatResult,
|
|
101
|
+
object,
|
|
102
|
+
required,
|
|
103
|
+
chain,
|
|
104
|
+
parseNumber,
|
|
105
|
+
min,
|
|
106
|
+
transform,
|
|
107
|
+
} from '@railway-ts/pipelines/schema';
|
|
63
108
|
|
|
64
|
-
|
|
109
|
+
const schema = chain(
|
|
110
|
+
object({
|
|
111
|
+
x: required(chain(parseNumber(), min(0))),
|
|
112
|
+
y: required(chain(parseNumber(), min(1))),
|
|
113
|
+
}),
|
|
114
|
+
transform(({ x, y }) => x / y),
|
|
115
|
+
);
|
|
65
116
|
|
|
66
|
-
|
|
117
|
+
const result = validateAndFormatResult({ x: '10', y: '2' }, schema);
|
|
118
|
+
console.log(result); // { valid: true, data: 5 }
|
|
119
|
+
```
|
|
67
120
|
|
|
68
|
-
**
|
|
121
|
+
**The pattern:** Validate at boundaries, chain operations, branch once at the end. Errors propagate automatically.
|
|
69
122
|
|
|
70
123
|
## API Reference
|
|
71
124
|
|
|
72
125
|
### Option
|
|
73
126
|
|
|
74
|
-
Handle nullable values without `if (x
|
|
127
|
+
Handle nullable values without `if (x !== null)` everywhere.
|
|
75
128
|
|
|
76
129
|
```typescript
|
|
77
130
|
import { pipe } from '@railway-ts/pipelines/composition';
|
|
78
|
-
import { some,
|
|
131
|
+
import { some, mapWith, match } from '@railway-ts/pipelines/option';
|
|
79
132
|
|
|
80
133
|
const user = some({ name: 'Alice', age: 25 });
|
|
81
|
-
const name = pipe(
|
|
134
|
+
const name = pipe(
|
|
135
|
+
user,
|
|
136
|
+
mapWith((u) => u.name),
|
|
137
|
+
);
|
|
82
138
|
|
|
83
139
|
match(name, {
|
|
84
140
|
some: (n) => console.log(n),
|
|
@@ -86,11 +142,12 @@ match(name, {
|
|
|
86
142
|
}); // Output: Alice
|
|
87
143
|
```
|
|
88
144
|
|
|
89
|
-
**Core:** `some`, `none`, `isSome`, `isNone`
|
|
90
|
-
**Transform:** `map`, `flatMap`, `bimap`, `filter`, `tap`
|
|
91
|
-
**
|
|
92
|
-
**
|
|
93
|
-
**
|
|
145
|
+
**Core:** `some`, `none`, `isSome`, `isNone`
|
|
146
|
+
**Transform:** `map`, `flatMap`, `bimap`, `filter`, `tap`
|
|
147
|
+
**Curried:** `mapWith`, `flatMapWith`, `filterWith`, `tapWith`
|
|
148
|
+
**Unwrap:** `unwrap`, `unwrapOr`, `unwrapOrElse`
|
|
149
|
+
**Combine:** `combine`
|
|
150
|
+
**Convert:** `fromNullable`, `mapToResult`
|
|
94
151
|
**Branch:** `match`
|
|
95
152
|
|
|
96
153
|
### Result
|
|
@@ -99,11 +156,14 @@ Explicit error handling. No exceptions, no try-catch pyramids.
|
|
|
99
156
|
|
|
100
157
|
```typescript
|
|
101
158
|
import { pipe } from '@railway-ts/pipelines/composition';
|
|
102
|
-
import { ok, err,
|
|
159
|
+
import { ok, err, mapWith, match } from '@railway-ts/pipelines/result';
|
|
103
160
|
|
|
104
161
|
const divide = (a: number, b: number) => (b === 0 ? err('div by zero') : ok(a / b));
|
|
105
162
|
|
|
106
|
-
const result = pipe(
|
|
163
|
+
const result = pipe(
|
|
164
|
+
divide(10, 2),
|
|
165
|
+
mapWith((x) => x * 3),
|
|
166
|
+
);
|
|
107
167
|
|
|
108
168
|
match(result, {
|
|
109
169
|
ok: (value) => console.log(value),
|
|
@@ -111,18 +171,21 @@ match(result, {
|
|
|
111
171
|
}); // Output: 15
|
|
112
172
|
```
|
|
113
173
|
|
|
114
|
-
**Core:** `ok`, `err`, `isOk`, `isErr`
|
|
115
|
-
**Transform:** `map`, `mapErr`, `flatMap`, `bimap`, `filter`, `tap`, `tapErr`
|
|
116
|
-
**
|
|
117
|
-
**
|
|
118
|
-
**
|
|
119
|
-
**
|
|
174
|
+
**Core:** `ok`, `err`, `isOk`, `isErr`
|
|
175
|
+
**Transform:** `map`, `mapErr`, `flatMap`, `bimap`, `filter`, `tap`, `tapErr`
|
|
176
|
+
**Curried:** `mapWith`, `flatMapWith`, `mapErrWith`, `filterWith`, `tapWith`, `tapErrWith`
|
|
177
|
+
**Recovery:** `orElse`, `orElseWith`
|
|
178
|
+
**Unwrap:** `unwrap`, `unwrapOr`, `unwrapOrElse`
|
|
179
|
+
**Combine:** `combine`, `combineAll`
|
|
180
|
+
**Convert:** `fromTry`, `fromTryWithError`, `fromPromise`, `fromPromiseWithError`, `toPromise`, `mapToOption`
|
|
120
181
|
**Branch:** `match`
|
|
121
182
|
|
|
122
183
|
### Schema
|
|
123
184
|
|
|
124
185
|
Parse untrusted data into typed values. Accumulates all validation errors.
|
|
125
186
|
|
|
187
|
+
> **Standard Schema v1 compliant** — use `toStandardSchema()` for interop with tRPC, TanStack Form, React Hook Form, and other Standard Schema consumers. See [Recipes → Standard Schema Interop](docs/RECIPES.md#standard-schema-interop).
|
|
188
|
+
|
|
126
189
|
```typescript
|
|
127
190
|
import {
|
|
128
191
|
validate,
|
|
@@ -150,23 +213,29 @@ const result = validate(input, userSchema);
|
|
|
150
213
|
// Result<User, ValidationError[]>
|
|
151
214
|
```
|
|
152
215
|
|
|
153
|
-
**Primitives:** `string`, `number`, `boolean`, `date`, `bigint`
|
|
154
|
-
**Parsers:** `parseNumber`, `
|
|
155
|
-
**Structures:** `object`, `array`, `tuple`, `tupleOf`
|
|
156
|
-
**Unions:** `union`, `discriminatedUnion`, `literal`
|
|
157
|
-
**Modifiers:** `required`, `optional`, `nullable`, `emptyAsOptional`
|
|
158
|
-
**String Constraints:** `minLength`, `maxLength`, `pattern`, `nonEmpty`, `email`, `phoneNumber`
|
|
159
|
-
**Number Constraints:** `min`, `max`, `integer`, `finite`, `between`
|
|
160
|
-
**
|
|
161
|
-
**
|
|
162
|
-
**
|
|
216
|
+
**Primitives:** `string`, `number`, `boolean`, `date`, `bigint`
|
|
217
|
+
**Parsers:** `parseNumber`, `parseString`, `parseBool`, `parseBigInt`, `parseDate`, `parseISODate`, `parseJSON`, `parseURL`, `parseEnum`
|
|
218
|
+
**Structures:** `object`, `array`, `tuple`, `tupleOf`
|
|
219
|
+
**Unions:** `union`, `discriminatedUnion`, `literal`
|
|
220
|
+
**Modifiers:** `required`, `optional`, `nullable`, `emptyAsOptional`
|
|
221
|
+
**String Constraints:** `minLength`, `maxLength`, `pattern`, `nonEmpty`, `email`, `phoneNumber`
|
|
222
|
+
**Number Constraints:** `min`, `max`, `integer`, `finite`, `between`, `positive`, `negative`, `nonZero`, `divisibleBy`, `precision`
|
|
223
|
+
**Date Constraints:** `dateRange`, `pastDate`, `futureDate`, `todayOrFuture`
|
|
224
|
+
**Enums:** `stringEnum`, `enumValue`, `oneOf`
|
|
225
|
+
**Boolean Constraints:** `matches`
|
|
226
|
+
**Array Constraints:** `minItems`, `maxItems`, `notEmpty`, `unique`
|
|
227
|
+
**Combinators:** `chain`, `transform`, `refine`
|
|
228
|
+
**Cross-field:** `refineAt`, `refineAtAsync`
|
|
229
|
+
**Async:** `chainAsync`, `refineAsync`, `refineAtAsync`
|
|
230
|
+
**Utilities:** `validate`, `validateAndFormatResult`, `formatErrors`, `toStandardSchema`, `ROOT_ERROR_KEY`
|
|
231
|
+
**Types:** `Validator`, `AsyncValidator`, `MaybeAsyncValidator`, `Schema`, `SyncSchema`, `InferSchemaType`, `ValidatorMapOutput`, `ValidationError`, `ValidationResult`, `StandardSchemaV1`
|
|
163
232
|
|
|
164
233
|
### Composition
|
|
165
234
|
|
|
166
235
|
Build pipelines. No nested function calls.
|
|
167
236
|
|
|
168
237
|
```typescript
|
|
169
|
-
import { pipe, flow,
|
|
238
|
+
import { pipe, flow, pipeAsync, flowAsync } from '@railway-ts/pipelines/composition';
|
|
170
239
|
|
|
171
240
|
// Immediate execution
|
|
172
241
|
const result = pipe(
|
|
@@ -175,34 +244,24 @@ const result = pipe(
|
|
|
175
244
|
(x) => x + 1,
|
|
176
245
|
); // 11
|
|
177
246
|
|
|
178
|
-
//
|
|
247
|
+
// Reusable pipeline
|
|
179
248
|
const process = flow(
|
|
180
249
|
(x: number) => x * 2,
|
|
181
250
|
(x) => x + 1,
|
|
182
251
|
);
|
|
183
252
|
process(5); // 11
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**Functions:** `pipe`, `flow`, `curry`, `uncurry`, `tupled`, `untupled`
|
|
187
253
|
|
|
188
|
-
|
|
254
|
+
// Async pipeline (awaits each step)
|
|
255
|
+
const data = await pipeAsync(userId, fetchUser, validateUser, enrichProfile);
|
|
189
256
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
import { some, none, map } from '@railway-ts/pipelines/option';
|
|
194
|
-
import { ok, err, flatMap } from '@railway-ts/pipelines/result';
|
|
195
|
-
import { pipe, flow } from '@railway-ts/pipelines/composition';
|
|
196
|
-
import { string, number, validate } from '@railway-ts/pipelines/schema';
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Root imports (adds type suffixes)
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
import { mapOption, mapResult, pipe, ok, validate } from '@railway-ts/pipelines';
|
|
257
|
+
// Reusable async pipeline
|
|
258
|
+
const processOrder = flowAsync(validateOrder, chargePayment, createShipment);
|
|
259
|
+
await processOrder(orderInput);
|
|
203
260
|
```
|
|
204
261
|
|
|
205
|
-
|
|
262
|
+
**Sync:** `pipe`, `flow`, `curry`, `uncurry`, `tupled`, `untupled`
|
|
263
|
+
**Async:** `pipeAsync`, `flowAsync`
|
|
264
|
+
**Types:** `MaybeAsync`
|
|
206
265
|
|
|
207
266
|
## Examples
|
|
208
267
|
|
|
@@ -217,10 +276,10 @@ bun run examples/index.ts
|
|
|
217
276
|
|
|
218
277
|
**What's in there:**
|
|
219
278
|
|
|
220
|
-
- `option/` - Nullable handling patterns
|
|
221
|
-
- `result/` - Error handling patterns
|
|
222
|
-
- `schema/` - Validation (basic, unions, tuples)
|
|
223
|
-
- `composition/` - Function composition
|
|
279
|
+
- `option/` - Nullable handling patterns, curried helpers
|
|
280
|
+
- `result/` - Error handling patterns, curried helpers, recovery
|
|
281
|
+
- `schema/` - Validation (basic, unions, tuples, async validation)
|
|
282
|
+
- `composition/` - Function composition (sync and async)
|
|
224
283
|
- `complete-pipelines/` - Full examples with validation + async + logic
|
|
225
284
|
|
|
226
285
|
Start with `examples/complete-pipelines/async-launch.ts` for a real-world pattern.
|
|
@@ -24,6 +24,26 @@ function flow(...fns) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
// src/composition/pipe-async.ts
|
|
28
|
+
async function pipeAsync(a, ...fns) {
|
|
29
|
+
let result = await a;
|
|
30
|
+
for (const fn of fns) {
|
|
31
|
+
result = await fn(result);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/composition/flow-async.ts
|
|
37
|
+
function flowAsync(first, ...fns) {
|
|
38
|
+
return async (...args) => {
|
|
39
|
+
let result = await first(...args);
|
|
40
|
+
for (const fn of fns) {
|
|
41
|
+
result = await fn(result);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
27
47
|
// src/composition/curry.ts
|
|
28
48
|
function curry(fn) {
|
|
29
49
|
const arity = fn.length;
|
|
@@ -64,7 +84,9 @@ function untupled(fn) {
|
|
|
64
84
|
|
|
65
85
|
exports.curry = curry;
|
|
66
86
|
exports.flow = flow;
|
|
87
|
+
exports.flowAsync = flowAsync;
|
|
67
88
|
exports.pipe = pipe;
|
|
89
|
+
exports.pipeAsync = pipeAsync;
|
|
68
90
|
exports.tupled = tupled;
|
|
69
91
|
exports.uncurry = uncurry;
|
|
70
92
|
exports.untupled = untupled;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/composition/pipe.ts","../../src/composition/flow.ts","../../src/composition/curry.ts","../../src/composition/uncurry.ts","../../src/composition/tupled.ts","../../src/composition/untupled.ts"],"names":[],"mappings":";;;AA8GO,SAAS,IAAA,CAAK,UAAmB,GAAA,EAAiC;AACvE,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,MAAA,GAAS,GAAG,MAAM,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,MAAA;AACT;;;ACkBO,SAAS,QAAQ,GAAA,EAA+D;AACrF,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAI,CAAC,CAAA;AAAA,EACd;AAEA,EAAA,MAAM,CAAC,KAAA,EAAO,GAAG,IAAI,CAAA,GAAI,GAAA;AACzB,EAAA,OAAO,IAAI,IAAA,KAA6B;AACtC,IAAA,IAAI,MAAA,GAAS,KAAA,CAAM,GAAG,IAAI,CAAA;AAC1B,IAAA,KAAA,MAAW,MAAM,IAAA,EAAM;AACrB,MAAA,MAAA,GAAS,GAAG,MAAM,CAAA;AAAA,IACpB;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;;;AC9FO,SAAS,MAAiC,EAAA,EAAwB;AACvE,EAAA,MAAM,QAAQ,EAAA,CAAG,MAAA;AAEjB,EAAA,OAAO,SAAS,WAAW,IAAA,EAA0B;AACnD,IAAA,IAAI,IAAA,CAAK,UAAU,KAAA,EAAO;AACxB,MAAA,OAAQ,EAAA,CAAuB,GAAG,IAAI,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,YAAa,QAAA,EAA8B;AAChD,MAAA,OAAO,OAAA,CAAQ,GAAG,IAAA,EAAM,GAAG,QAAQ,CAAA;AAAA,IACrC,CAAA;AAAA,EACF,CAAA;AACF;;;ACPO,SAAS,QAAQ,EAAA,EAAsB;AAC5C,EAAA,OAAO,SAAS,aAAa,IAAA,EAA0B;AAErD,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAA,GAAU,OAA2B,GAAG,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;;;ACbO,SAAS,OAAkC,EAAA,EAAqC;AACrF,EAAA,OAAO,SAAS,SAAS,IAAA,EAA0B;AACjD,IAAA,OAAO,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,EACnB,CAAA;AACF;;;ACPO,SAAS,SAAoC,EAAA,EAAwB;AAC1E,EAAA,OAAO,SAAS,cAAc,IAAA,EAA0B;AACtD,IAAA,OAAO,GAAG,IAAI,CAAA;AAAA,EAChB,CAAA;AACF","file":"index.cjs","sourcesContent":["type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Pipes a value through a series of functions, from left to right.\n * Each function receives the output of the previous function.\n * Unlike flow, pipe immediately executes the functions with the provided initial value.\n *\n * @example\n * // Basic usage\n * const result = pipe(\n * 5,\n * (n) => n * 2, // 10\n * (n) => n + 1, // 11\n * (n) => n.toString() // \"11\"\n * );\n * // result: \"11\"\n *\n * @example\n * // With Option\n * import { some, mapOption } from \"@railway-ts/pipelines/option\";\n *\n * const optionResult = pipe(\n * some(5),\n * (o) => mapOption(o, (n) => n * 2),\n * (o) => mapOption(o, (n) => n.toString())\n * );\n * // optionResult: Option<string> containing \"10\"\n *\n * @example\n * // With Result\n * import { ok, mapResult } from \"@railway-ts/pipelines/result\";\n *\n * const resultValue = pipe(\n * ok(5),\n * (r) => mapResult(r, (n) => n * 2),\n * (r) => mapResult(r, (n) => n.toString())\n * );\n * // resultValue: Result<string, never> containing \"10\"\n *\n * @param a - The initial value to pipe through the functions\n * @param ab - The first function to apply to the initial value\n * @param functions - Additional functions to apply in sequence\n * @returns The final result after applying all functions\n */\n\nexport function pipe<A, B>(a: A, ab: (this: void, a: A) => B): B;\nexport function pipe<A, B, C>(a: A, ab: (this: void, a: A) => B, bc: (this: void, b: B) => C): C;\nexport function pipe<A, B, C, D>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n): D;\nexport function pipe<A, B, C, D, E>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n): I;\nexport function pipe<A, B, C, D, E, F, G, H, I, J>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n): J;\nexport function pipe(value: unknown, ...fns: UnknownFunction[]): unknown {\n let result = value;\n for (const fn of fns) {\n result = fn(result);\n }\n return result;\n}\n","type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Creates a new function that is the composition of the provided functions, applied from left to right.\n * Unlike pipe, flow doesn't immediately execute the functions but returns a new function that,\n * when called, will run the composed functions in sequence.\n *\n * @example\n * // Basic usage\n * const processNumber = flow(\n * (n: number) => n * 2,\n * (n) => n + 1,\n * (n) => n.toString()\n * );\n *\n * const result = processNumber(5); // \"11\"\n *\n * @example\n * // With multiple arguments\n * const formatName = flow(\n * (first: string, last: string) => `${first} ${last}`,\n * (name) => name.toUpperCase()\n * );\n *\n * const name = formatName(\"John\", \"Doe\"); // \"JOHN DOE\"\n *\n * @example\n * // With Option type\n * import { some, none, mapOption, flatMapOption, type Option } from \"@railway-ts/pipelines/option\";\n *\n * const safeParseInt = (radix: number) => (str: string): Option<number> => {\n * const n = Number.parseInt(str, radix);\n * return Number.isNaN(n) ? none() : some(n);\n * };\n *\n * const processString = flow(\n * (s: string) => some(s),\n * (o) => mapOption(o, (s) => s + \"0\"),\n * (o) => flatMapOption(o, safeParseInt(10))\n * );\n *\n * const option = processString(\"42\"); // Option<number> containing 420\n *\n * @example\n * // With Result type\n * import { ok, err, flatMapResult } from \"@railway-ts/pipelines/result\";\n *\n * const validatePositive = (n: number) => (n > 0 ? ok(n) : err(\"Not positive\"));\n *\n * const validateNumber = flow(\n * (n: number) => ok(n),\n * (r) => flatMapResult(r, validatePositive),\n * (r) => flatMapResult(r, (n) => ok(n * 2))\n * );\n *\n * const result = validateNumber(5); // Result<number, string> containing 10\n *\n * @param ab - The first function in the composition\n * @param functions - Additional functions to compose in sequence\n * @returns A new function that applies all the composed functions in sequence\n */\nexport function flow<A extends unknown[], B>(ab: (this: void, ...a: A) => B): (...a: A) => B;\nexport function flow<A extends unknown[], B, C>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n): (...a: A) => C;\nexport function flow<A extends unknown[], B, C, D>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n): (...a: A) => D;\nexport function flow<A extends unknown[], B, C, D, E>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n): (...a: A) => E;\nexport function flow<A extends unknown[], B, C, D, E, F>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n): (...a: A) => F;\nexport function flow<A extends unknown[], B, C, D, E, F, G>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n): (...a: A) => G;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n): (...a: A) => H;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n): (...a: A) => I;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I, J>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n): (...a: A) => J;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n jk: (this: void, j: J) => K,\n): (...a: A) => K;\nexport function flow(...fns: [UnknownFunction, ...UnknownFunction[]]): UnknownFunction {\n if (fns.length === 1) {\n return fns[0];\n }\n\n const [first, ...rest] = fns;\n return (...args: unknown[]): unknown => {\n let result = first(...args);\n for (const fn of rest) {\n result = fn(result);\n }\n return result;\n };\n}\n","type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Curries a multi-parameter function into a sequence of unary functions.\n * Enables partial application at any depth and composes cleanly with `pipe`.\n *\n * Note: This curry is unary-only at each step to ensure compatibility with `pipe` and `flow`.\n *\n * @example\n * // Basic (2-arity)\n * const add = (a: number, b: number) => a + b;\n * const add5 = curry(add)(5);\n * add5(3); // 8\n *\n * @example\n * // 3-arity and partial application\n * const multiply = (a: number, b: number, c: number) => a * b * c;\n * const curriedMultiply = curry(multiply);\n * curriedMultiply(2)(3)(4); // 24\n *\n * @example\n * // With pipe\n * import { pipe } from \"@/utils\";\n * const divide = (divisor: number, dividend: number) => dividend / divisor;\n * const result = pipe(100, curry(divide)(2), (n) => n + 1); // 51\n *\n * @example\n * // With Result validators\n * import { ok, err, flatMapResult, type Result } from \"@/index\";\n * const between = (min: number, max: number, n: number): Result<number, string> =>\n * n >= min && n <= max ? ok(n) : err(`Value must be between ${min} and ${max}`);\n * const validateAge = curry(between)(0)(120);\n * pipe(ok(25), (r) => flatMapResult(r, validateAge)); // ok(25)\n *\n * @param fn - The multi-argument function to transform into a unary curried chain\n * @returns A curried function that takes one argument at each application step\n */\n\n// 2-arity\nexport function curry<A, B, R>(fn: (a: A, b: B) => R): (a: A) => (b: B) => R;\n\n// 3-arity\nexport function curry<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (a: A) => (b: B) => (c: C) => R;\n\n// 4-arity\nexport function curry<A, B, C, D, R>(fn: (a: A, b: B, c: C, d: D) => R): (a: A) => (b: B) => (c: C) => (d: D) => R;\n\n// 5-arity\nexport function curry<A, B, C, D, E, R>(\n fn: (a: A, b: B, c: C, d: D, e: E) => R,\n): (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R;\n\n// Implementation\nexport function curry<T extends UnknownFunction>(fn: T): UnknownFunction {\n const arity = fn.length;\n\n return function curried(...args: unknown[]): unknown {\n if (args.length >= arity) {\n return (fn as UnknownFunction)(...args);\n }\n\n return function (...nextArgs: unknown[]): unknown {\n return curried(...args, ...nextArgs);\n };\n };\n}\n","type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Uncurries a curried unary function chain back into a multi-argument function.\n * Inverse of `curry`. Useful when calling curried APIs with positional arguments.\n *\n * Note: Expects strictly unary nesting (the shape produced by `curry`).\n *\n * @example\n * // 2-arity\n * const addCurried = (a: number) => (b: number) => a + b;\n * const add = uncurry(addCurried);\n * add(5, 3); // 8\n *\n * @example\n * // 3-arity\n * const multiplyCurried = (a: number) => (b: number) => (c: number) => a * b * c;\n * const multiply = uncurry(multiplyCurried);\n * multiply(2, 3, 4); // 24\n *\n * @example\n * // Round-trip with curry\n * import { curry } from \"@railway-ts/pipelines\";\n * const divide = (divisor: number, dividend: number) => dividend / divisor;\n * const divideCurried = curry(divide);\n * const divideUncurried = uncurry(divideCurried);\n * divideUncurried(2, 100); // 50\n *\n * @param fn - A curried unary function chain (e.g., a => b => c => r)\n * @returns A multi-argument function equivalent to applying the curried chain in sequence\n */\n\n// Overloads ordered from most specific (5-arity) to least specific (2-arity)\n// This ensures TypeScript matches the correct overload\n\n// 5-arity\nexport function uncurry<A, B, C, D, E, R>(\n fn: (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R,\n): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// 5-arity\nexport function uncurry<A, B, C, D, E, R>(\n fn: (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R,\n): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// 4-arity\nexport function uncurry<A, B, C, D, R>(fn: (a: A) => (b: B) => (c: C) => (d: D) => R): (a: A, b: B, c: C, d: D) => R;\n\n// 3-arity\nexport function uncurry<A, B, C, R>(fn: (a: A) => (b: B) => (c: C) => R): (a: A, b: B, c: C) => R;\n\n// 2-arity\nexport function uncurry<A, B, R>(fn: (a: A) => (b: B) => R): (a: A, b: B) => R;\n\n// 1-arity (identity - technically not curried, but allows for consistent API)\nexport function uncurry<A, R>(fn: (a: A) => R): (a: A) => R;\n\n// Implementation - looser types allow overloads to work correctly\nexport function uncurry(fn: unknown): unknown {\n return function uncurried(...args: unknown[]): unknown {\n // Apply arguments sequentially to the curried function chain\n let result = fn;\n\n for (const arg of args) {\n result = (result as UnknownFunction)(arg);\n }\n\n return result;\n };\n}\n","type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Transforms a multi-argument function into one that accepts a single tuple argument.\n * This makes multi-arg functions composable in `pipe`/`flow` when your data is a tuple.\n *\n * @example\n * // Basic\n * const add = (a: number, b: number) => a + b;\n * const tupledAdd = tupled(add);\n * tupledAdd([5, 3]); // 8\n *\n * @example\n * // With pipe (tuple input)\n * import { pipe } from \"@/utils\";\n * const distance = (x: number, y: number) => Math.hypot(x, y);\n * pipe([3, 4] as [number, number], tupled(distance)); // 5\n *\n * @example\n * // With Result\n * import { ok, err, flatMapResult, mapResult, type Result } from \"@railway-ts/pipelines/result\";\n * const divide = (dividend: number, divisor: number): Result<number, string> =>\n * divisor === 0 ? err(\"Division by zero\") : ok(dividend / divisor);\n * const tupledDivide = tupled(divide);\n * pipe(ok<[number, number], string>([10, 2]),\n * (r) => flatMapResult(r, tupledDivide),\n * (r) => mapResult(r, (n) => n * 2)\n * ); // ok(10)\n *\n * @example\n * // With Option\n * import { some, none, flatMapOption, type Option } from \"@railway-ts/pipelines/option\";\n * const safeParse = (str: string, radix: number): Option<number> => {\n * const n = Number.parseInt(str, radix);\n * return Number.isNaN(n) ? none() : some(n);\n * };\n * const tupledParse = tupled(safeParse);\n * flatMapOption(some([\"FF\", 16] as [string, number]), tupledParse); // some(255)\n *\n * @param fn - A function taking positional arguments to be adapted to a single tuple argument\n * @returns A function that takes a tuple and applies it to `fn` as positional args\n */\n\n// 2-arity\nexport function tupled<A, B, R>(fn: (a: A, b: B) => R): (args: [A, B]) => R;\n\n// 3-arity\nexport function tupled<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (args: [A, B, C]) => R;\n\n// 4-arity\nexport function tupled<A, B, C, D, R>(fn: (a: A, b: B, c: C, d: D) => R): (args: [A, B, C, D]) => R;\n\n// 5-arity\nexport function tupled<A, B, C, D, E, R>(fn: (a: A, b: B, c: C, d: D, e: E) => R): (args: [A, B, C, D, E]) => R;\n\n// Implementation\nexport function tupled<T extends UnknownFunction>(fn: T): (args: unknown[]) => unknown {\n return function tupledFn(args: unknown[]): unknown {\n return fn(...args);\n };\n}\n","type UnknownFunction = (...params: unknown[]) => unknown;\n\n/**\n * Transforms a function that accepts a tuple into a multi-argument function.\n * Inverse of `tupled`. Useful when callers have positional arguments but your core API uses tuples.\n *\n * @example\n * // Basic\n * const tupledAdd = ([a, b]: [number, number]) => a + b;\n * const add = untupled(tupledAdd);\n * add(5, 3); // 8\n *\n * @example\n * // 3-arity\n * const sum3Tupled = ([a, b, c]: [number, number, number]) => a + b + c;\n * const sum3 = untupled(sum3Tupled);\n * sum3(1, 2, 3); // 6\n *\n * @example\n * // With Result\n * import { ok, err, flatMapResult, type Result } from \"@railway-ts/pipelines/result\";\n * const validateRange = ([min, max, value]: [number, number, number]): Result<number, string> =>\n * value >= min && value <= max ? ok(value) : err(`Value ${value} not between ${min} and ${max}`);\n * const validate = untupled(validateRange);\n * flatMapResult(ok(50), (n) => validate(0, 100, n)); // ok(50)\n *\n * @example\n * // With Option\n * import { some, none, type Option } from \"@railway-ts/pipelines/option\";\n * const parsePair = ([x, y]: [string, string]): Option<number> => {\n * const a = Number(x), b = Number(y);\n * return Number.isNaN(a) || Number.isNaN(b) ? none() : some(a + b);\n * };\n * const parse = untupled(parsePair);\n * parse(\"2\", \"3\"); // some(5)\n *\n * @param fn - A function that accepts a tuple of arguments\n * @returns A function that accepts the same arguments positionally\n */\n\n// 2-arity\nexport function untupled<A, B, R>(fn: (args: [A, B]) => R): (a: A, b: B) => R;\n\n// 3-arity\nexport function untupled<A, B, C, R>(fn: (args: [A, B, C]) => R): (a: A, b: B, c: C) => R;\n\n// 4-arity\nexport function untupled<A, B, C, D, R>(fn: (args: [A, B, C, D]) => R): (a: A, b: B, c: C, d: D) => R;\n\n// 5-arity\nexport function untupled<A, B, C, D, E, R>(fn: (args: [A, B, C, D, E]) => R): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// Implementation\nexport function untupled<T extends UnknownFunction>(fn: T): UnknownFunction {\n return function untupledFn(...args: unknown[]): unknown {\n return fn(args);\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/composition/pipe.ts","../../src/composition/flow.ts","../../src/composition/pipe-async.ts","../../src/composition/flow-async.ts","../../src/composition/curry.ts","../../src/composition/uncurry.ts","../../src/composition/tupled.ts","../../src/composition/untupled.ts"],"names":[],"mappings":";;;AA8GO,SAAS,IAAA,CAAK,UAAmB,GAAA,EAAiC;AACvE,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,MAAA,GAAS,GAAG,MAAM,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,MAAA;AACT;;;ACkBO,SAAS,QAAQ,GAAA,EAA+D;AACrF,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAI,CAAC,CAAA;AAAA,EACd;AAEA,EAAA,MAAM,CAAC,KAAA,EAAO,GAAG,IAAI,CAAA,GAAI,GAAA;AACzB,EAAA,OAAO,IAAI,IAAA,KAA6B;AACtC,IAAA,IAAI,MAAA,GAAS,KAAA,CAAM,GAAG,IAAI,CAAA;AAC1B,IAAA,KAAA,MAAW,MAAM,IAAA,EAAM;AACrB,MAAA,MAAA,GAAS,GAAG,MAAM,CAAA;AAAA,IACpB;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;;;AC5CA,eAAsB,SAAA,CAAU,MAAe,GAAA,EAA0C;AACvF,EAAA,IAAI,SAAS,MAAM,CAAA;AACnB,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,MAAA,GAAS,MAAM,GAAG,MAAM,CAAA;AAAA,EAC1B;AACA,EAAA,OAAO,MAAA;AACT;;;ACHO,SAAS,SAAA,CACd,UACG,GAAA,EACuC;AAC1C,EAAA,OAAO,UAAU,IAAA,KAAoB;AACnC,IAAA,IAAI,MAAA,GAAS,MAAM,KAAA,CAAM,GAAG,IAAI,CAAA;AAChC,IAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,MAAA,MAAA,GAAS,MAAM,GAAG,MAAM,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;;;AChEO,SAAS,MAAiC,EAAA,EAAwB;AACvE,EAAA,MAAM,QAAQ,EAAA,CAAG,MAAA;AAEjB,EAAA,OAAO,SAAS,WAAW,IAAA,EAA0B;AACnD,IAAA,IAAI,IAAA,CAAK,UAAU,KAAA,EAAO;AACxB,MAAA,OAAQ,EAAA,CAAuB,GAAG,IAAI,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,YAAa,QAAA,EAA8B;AAChD,MAAA,OAAO,OAAA,CAAQ,GAAG,IAAA,EAAM,GAAG,QAAQ,CAAA;AAAA,IACrC,CAAA;AAAA,EACF,CAAA;AACF;;;ACPO,SAAS,QAAQ,EAAA,EAAsB;AAC5C,EAAA,OAAO,SAAS,aAAa,IAAA,EAA0B;AAErD,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAA,GAAU,OAA2B,GAAG,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;;;ACbO,SAAS,OAAkC,EAAA,EAAqC;AACrF,EAAA,OAAO,SAAS,SAAS,IAAA,EAA0B;AACjD,IAAA,OAAO,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,EACnB,CAAA;AACF;;;ACPO,SAAS,SAAoC,EAAA,EAAwB;AAC1E,EAAA,OAAO,SAAS,cAAc,IAAA,EAA0B;AACtD,IAAA,OAAO,GAAG,IAAI,CAAA;AAAA,EAChB,CAAA;AACF","file":"index.cjs","sourcesContent":["import type { UnknownFunction } from './types';\n\n/**\n * Pipes a value through a series of functions, from left to right.\n * Each function receives the output of the previous function.\n * Unlike flow, pipe immediately executes the functions with the provided initial value.\n *\n * @example\n * // Basic usage\n * const result = pipe(\n * 5,\n * (n) => n * 2, // 10\n * (n) => n + 1, // 11\n * (n) => n.toString() // \"11\"\n * );\n * // result: \"11\"\n *\n * @example\n * // With Option\n * import { some, mapOption } from \"@railway-ts/pipelines/option\";\n *\n * const optionResult = pipe(\n * some(5),\n * (o) => mapOption(o, (n) => n * 2),\n * (o) => mapOption(o, (n) => n.toString())\n * );\n * // optionResult: Option<string> containing \"10\"\n *\n * @example\n * // With Result\n * import { ok, mapResult } from \"@railway-ts/pipelines/result\";\n *\n * const resultValue = pipe(\n * ok(5),\n * (r) => mapResult(r, (n) => n * 2),\n * (r) => mapResult(r, (n) => n.toString())\n * );\n * // resultValue: Result<string, never> containing \"10\"\n *\n * @param a - The initial value to pipe through the functions\n * @param ab - The first function to apply to the initial value\n * @param functions - Additional functions to apply in sequence\n * @returns The final result after applying all functions\n */\n\nexport function pipe<A, B>(a: A, ab: (this: void, a: A) => B): B;\nexport function pipe<A, B, C>(a: A, ab: (this: void, a: A) => B, bc: (this: void, b: B) => C): C;\nexport function pipe<A, B, C, D>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n): D;\nexport function pipe<A, B, C, D, E>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n): I;\nexport function pipe<A, B, C, D, E, F, G, H, I, J>(\n a: A,\n ab: (this: void, a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n): J;\nexport function pipe(value: unknown, ...fns: UnknownFunction[]): unknown {\n let result = value;\n for (const fn of fns) {\n result = fn(result);\n }\n return result;\n}\n","import type { UnknownFunction } from './types';\n\n/**\n * Creates a new function that is the composition of the provided functions, applied from left to right.\n * Unlike pipe, flow doesn't immediately execute the functions but returns a new function that,\n * when called, will run the composed functions in sequence.\n *\n * @example\n * // Basic usage\n * const processNumber = flow(\n * (n: number) => n * 2,\n * (n) => n + 1,\n * (n) => n.toString()\n * );\n *\n * const result = processNumber(5); // \"11\"\n *\n * @example\n * // With multiple arguments\n * const formatName = flow(\n * (first: string, last: string) => `${first} ${last}`,\n * (name) => name.toUpperCase()\n * );\n *\n * const name = formatName(\"John\", \"Doe\"); // \"JOHN DOE\"\n *\n * @example\n * // With Option type\n * import { some, none, mapOption, flatMapOption, type Option } from \"@railway-ts/pipelines/option\";\n *\n * const safeParseInt = (radix: number) => (str: string): Option<number> => {\n * const n = Number.parseInt(str, radix);\n * return Number.isNaN(n) ? none() : some(n);\n * };\n *\n * const processString = flow(\n * (s: string) => some(s),\n * (o) => mapOption(o, (s) => s + \"0\"),\n * (o) => flatMapOption(o, safeParseInt(10))\n * );\n *\n * const option = processString(\"42\"); // Option<number> containing 420\n *\n * @example\n * // With Result type\n * import { ok, err, flatMapResult } from \"@railway-ts/pipelines/result\";\n *\n * const validatePositive = (n: number) => (n > 0 ? ok(n) : err(\"Not positive\"));\n *\n * const validateNumber = flow(\n * (n: number) => ok(n),\n * (r) => flatMapResult(r, validatePositive),\n * (r) => flatMapResult(r, (n) => ok(n * 2))\n * );\n *\n * const result = validateNumber(5); // Result<number, string> containing 10\n *\n * @param ab - The first function in the composition\n * @param functions - Additional functions to compose in sequence\n * @returns A new function that applies all the composed functions in sequence\n */\nexport function flow<A extends unknown[], B>(ab: (this: void, ...a: A) => B): (...a: A) => B;\nexport function flow<A extends unknown[], B, C>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n): (...a: A) => C;\nexport function flow<A extends unknown[], B, C, D>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n): (...a: A) => D;\nexport function flow<A extends unknown[], B, C, D, E>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n): (...a: A) => E;\nexport function flow<A extends unknown[], B, C, D, E, F>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n): (...a: A) => F;\nexport function flow<A extends unknown[], B, C, D, E, F, G>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n): (...a: A) => G;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n): (...a: A) => H;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n): (...a: A) => I;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I, J>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n): (...a: A) => J;\nexport function flow<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(\n ab: (this: void, ...a: A) => B,\n bc: (this: void, b: B) => C,\n cd: (this: void, c: C) => D,\n de: (this: void, d: D) => E,\n ef: (this: void, e: E) => F,\n fg: (this: void, f: F) => G,\n gh: (this: void, g: G) => H,\n hi: (this: void, h: H) => I,\n ij: (this: void, i: I) => J,\n jk: (this: void, j: J) => K,\n): (...a: A) => K;\nexport function flow(...fns: [UnknownFunction, ...UnknownFunction[]]): UnknownFunction {\n if (fns.length === 1) {\n return fns[0];\n }\n\n const [first, ...rest] = fns;\n return (...args: unknown[]): unknown => {\n let result = first(...args);\n for (const fn of rest) {\n result = fn(result);\n }\n return result;\n };\n}\n","import type { MaybeAsync, UnknownFunction } from './types';\n\n/**\n * Pipes a value through a series of potentially async functions, from left to right.\n * Each function receives the awaited output of the previous function.\n * Unlike pipe, pipeAsync awaits between each step, enabling async composition.\n *\n * @example\n * // Basic async usage\n * const result = await pipeAsync(\n * 5,\n * async (n) => n * 2, // 10\n * (n) => n + 1, // 11\n * async (n) => n.toString() // \"11\"\n * );\n * // result: \"11\"\n *\n * @example\n * // With Result and curried helpers\n * import { ok, flatMapWith, mapWith } from \"@railway-ts/pipelines/result\";\n *\n * const result = await pipeAsync(\n * ok(5),\n * flatMapWith(async (n) => ok(n * 2)),\n * mapWith((n) => n.toString())\n * );\n * // result: Result<string, never> containing \"10\"\n *\n * @param a - The initial value (or Promise) to pipe through the functions\n * @param ab - The first function to apply to the initial value\n * @param functions - Additional functions to apply in sequence\n * @returns A Promise of the final result after applying all functions\n */\n\nexport function pipeAsync<A, B>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>): Promise<B>;\nexport function pipeAsync<A, B, C>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n): Promise<C>;\nexport function pipeAsync<A, B, C, D>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n): Promise<D>;\nexport function pipeAsync<A, B, C, D, E>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n): Promise<E>;\nexport function pipeAsync<A, B, C, D, E, F>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n): Promise<F>;\nexport function pipeAsync<A, B, C, D, E, F, G>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n): Promise<G>;\nexport function pipeAsync<A, B, C, D, E, F, G, H>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n): Promise<H>;\nexport function pipeAsync<A, B, C, D, E, F, G, H, I>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n hi: (this: void, h: H) => MaybeAsync<I>,\n): Promise<I>;\nexport function pipeAsync<A, B, C, D, E, F, G, H, I, J>(\n a: MaybeAsync<A>,\n ab: (this: void, a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n hi: (this: void, h: H) => MaybeAsync<I>,\n ij: (this: void, i: I) => MaybeAsync<J>,\n): Promise<J>;\nexport async function pipeAsync(a: unknown, ...fns: UnknownFunction[]): Promise<unknown> {\n let result = await a;\n for (const fn of fns) {\n result = await fn(result);\n }\n return result;\n}\n","import type { MaybeAsync, UnknownFunction } from './types';\n\n/**\n * Creates a new function that is the async composition of the provided functions, applied from left to right.\n * Unlike flow, flowAsync awaits between each step, enabling async composition.\n * The returned function always returns a Promise.\n *\n * @example\n * // Basic async usage\n * const processNumber = flowAsync(\n * async (n: number) => n * 2,\n * (n) => n + 1,\n * async (n) => n.toString()\n * );\n *\n * const result = await processNumber(5); // \"11\"\n *\n * @example\n * // With Result and curried helpers\n * import { ok, flatMapWith, mapWith } from \"@railway-ts/pipelines/result\";\n *\n * const process = flowAsync(\n * (n: number) => ok(n),\n * flatMapWith(async (n) => ok(n * 2)),\n * mapWith((n) => n.toString())\n * );\n *\n * const result = await process(5); // Result<string, never> containing \"10\"\n *\n * @param ab - The first function in the composition\n * @param functions - Additional functions to compose in sequence\n * @returns A new function that applies all the composed functions in sequence, returning a Promise\n */\nexport function flowAsync<A extends unknown[], B>(ab: (this: void, ...a: A) => MaybeAsync<B>): (...a: A) => Promise<B>;\nexport function flowAsync<A extends unknown[], B, C>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n): (...a: A) => Promise<C>;\nexport function flowAsync<A extends unknown[], B, C, D>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n): (...a: A) => Promise<D>;\nexport function flowAsync<A extends unknown[], B, C, D, E>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n): (...a: A) => Promise<E>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n): (...a: A) => Promise<F>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F, G>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n): (...a: A) => Promise<G>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F, G, H>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n): (...a: A) => Promise<H>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n hi: (this: void, h: H) => MaybeAsync<I>,\n): (...a: A) => Promise<I>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I, J>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n hi: (this: void, h: H) => MaybeAsync<I>,\n ij: (this: void, i: I) => MaybeAsync<J>,\n): (...a: A) => Promise<J>;\nexport function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(\n ab: (this: void, ...a: A) => MaybeAsync<B>,\n bc: (this: void, b: B) => MaybeAsync<C>,\n cd: (this: void, c: C) => MaybeAsync<D>,\n de: (this: void, d: D) => MaybeAsync<E>,\n ef: (this: void, e: E) => MaybeAsync<F>,\n fg: (this: void, f: F) => MaybeAsync<G>,\n gh: (this: void, g: G) => MaybeAsync<H>,\n hi: (this: void, h: H) => MaybeAsync<I>,\n ij: (this: void, i: I) => MaybeAsync<J>,\n jk: (this: void, j: J) => MaybeAsync<K>,\n): (...a: A) => Promise<K>;\nexport function flowAsync(\n first: (...args: unknown[]) => unknown,\n ...fns: UnknownFunction[]\n): (...args: unknown[]) => Promise<unknown> {\n return async (...args: unknown[]) => {\n let result = await first(...args);\n for (const fn of fns) {\n result = await fn(result);\n }\n return result;\n };\n}\n","import type { UnknownFunction } from './types';\n\n/**\n * Curries a multi-parameter function into a sequence of unary functions.\n * Enables partial application at any depth and composes cleanly with `pipe`.\n *\n * Note: This curry is unary-only at each step to ensure compatibility with `pipe` and `flow`.\n *\n * @example\n * // Basic (2-arity)\n * const add = (a: number, b: number) => a + b;\n * const add5 = curry(add)(5);\n * add5(3); // 8\n *\n * @example\n * // 3-arity and partial application\n * const multiply = (a: number, b: number, c: number) => a * b * c;\n * const curriedMultiply = curry(multiply);\n * curriedMultiply(2)(3)(4); // 24\n *\n * @example\n * // With pipe\n * import { pipe } from \"@/utils\";\n * const divide = (divisor: number, dividend: number) => dividend / divisor;\n * const result = pipe(100, curry(divide)(2), (n) => n + 1); // 51\n *\n * @example\n * // With Result validators\n * import { ok, err, flatMap, type Result } from \"@/result\";\n * const between = (min: number, max: number, n: number): Result<number, string> =>\n * n >= min && n <= max ? ok(n) : err(`Value must be between ${min} and ${max}`);\n * const validateAge = curry(between)(0)(120);\n * pipe(ok(25), (r) => flatMap(r, validateAge)); // ok(25)\n *\n * @param fn - The multi-argument function to transform into a unary curried chain\n * @returns A curried function that takes one argument at each application step\n */\n\n// 2-arity\nexport function curry<A, B, R>(fn: (a: A, b: B) => R): (a: A) => (b: B) => R;\n\n// 3-arity\nexport function curry<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (a: A) => (b: B) => (c: C) => R;\n\n// 4-arity\nexport function curry<A, B, C, D, R>(fn: (a: A, b: B, c: C, d: D) => R): (a: A) => (b: B) => (c: C) => (d: D) => R;\n\n// 5-arity\nexport function curry<A, B, C, D, E, R>(\n fn: (a: A, b: B, c: C, d: D, e: E) => R,\n): (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R;\n\n// Implementation\nexport function curry<T extends UnknownFunction>(fn: T): UnknownFunction {\n const arity = fn.length;\n\n return function curried(...args: unknown[]): unknown {\n if (args.length >= arity) {\n return (fn as UnknownFunction)(...args);\n }\n\n return function (...nextArgs: unknown[]): unknown {\n return curried(...args, ...nextArgs);\n };\n };\n}\n","import type { UnknownFunction } from './types';\n\n/**\n * Uncurries a curried unary function chain back into a multi-argument function.\n * Inverse of `curry`. Useful when calling curried APIs with positional arguments.\n *\n * Note: Expects strictly unary nesting (the shape produced by `curry`).\n *\n * @example\n * // 2-arity\n * const addCurried = (a: number) => (b: number) => a + b;\n * const add = uncurry(addCurried);\n * add(5, 3); // 8\n *\n * @example\n * // 3-arity\n * const multiplyCurried = (a: number) => (b: number) => (c: number) => a * b * c;\n * const multiply = uncurry(multiplyCurried);\n * multiply(2, 3, 4); // 24\n *\n * @example\n * // Round-trip with curry\n * import { curry } from \"@railway-ts/pipelines\";\n * const divide = (divisor: number, dividend: number) => dividend / divisor;\n * const divideCurried = curry(divide);\n * const divideUncurried = uncurry(divideCurried);\n * divideUncurried(2, 100); // 50\n *\n * @param fn - A curried unary function chain (e.g., a => b => c => r)\n * @returns A multi-argument function equivalent to applying the curried chain in sequence\n */\n\n// Overloads ordered from most specific (5-arity) to least specific (2-arity)\n// This ensures TypeScript matches the correct overload\n\n// 5-arity\nexport function uncurry<A, B, C, D, E, R>(\n fn: (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R,\n): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// 5-arity\nexport function uncurry<A, B, C, D, E, R>(\n fn: (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R,\n): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// 4-arity\nexport function uncurry<A, B, C, D, R>(fn: (a: A) => (b: B) => (c: C) => (d: D) => R): (a: A, b: B, c: C, d: D) => R;\n\n// 3-arity\nexport function uncurry<A, B, C, R>(fn: (a: A) => (b: B) => (c: C) => R): (a: A, b: B, c: C) => R;\n\n// 2-arity\nexport function uncurry<A, B, R>(fn: (a: A) => (b: B) => R): (a: A, b: B) => R;\n\n// 1-arity (identity - technically not curried, but allows for consistent API)\nexport function uncurry<A, R>(fn: (a: A) => R): (a: A) => R;\n\n// Implementation - looser types allow overloads to work correctly\nexport function uncurry(fn: unknown): unknown {\n return function uncurried(...args: unknown[]): unknown {\n // Apply arguments sequentially to the curried function chain\n let result = fn;\n\n for (const arg of args) {\n result = (result as UnknownFunction)(arg);\n }\n\n return result;\n };\n}\n","import type { UnknownFunction } from './types';\n\n/**\n * Transforms a multi-argument function into one that accepts a single tuple argument.\n * This makes multi-arg functions composable in `pipe`/`flow` when your data is a tuple.\n *\n * @example\n * // Basic\n * const add = (a: number, b: number) => a + b;\n * const tupledAdd = tupled(add);\n * tupledAdd([5, 3]); // 8\n *\n * @example\n * // With pipe (tuple input)\n * import { pipe } from \"@/utils\";\n * const distance = (x: number, y: number) => Math.hypot(x, y);\n * pipe([3, 4] as [number, number], tupled(distance)); // 5\n *\n * @example\n * // With Result\n * import { ok, err, flatMapResult, mapResult, type Result } from \"@railway-ts/pipelines/result\";\n * const divide = (dividend: number, divisor: number): Result<number, string> =>\n * divisor === 0 ? err(\"Division by zero\") : ok(dividend / divisor);\n * const tupledDivide = tupled(divide);\n * pipe(ok<[number, number], string>([10, 2]),\n * (r) => flatMapResult(r, tupledDivide),\n * (r) => mapResult(r, (n) => n * 2)\n * ); // ok(10)\n *\n * @example\n * // With Option\n * import { some, none, flatMapOption, type Option } from \"@railway-ts/pipelines/option\";\n * const safeParse = (str: string, radix: number): Option<number> => {\n * const n = Number.parseInt(str, radix);\n * return Number.isNaN(n) ? none() : some(n);\n * };\n * const tupledParse = tupled(safeParse);\n * flatMapOption(some([\"FF\", 16] as [string, number]), tupledParse); // some(255)\n *\n * @param fn - A function taking positional arguments to be adapted to a single tuple argument\n * @returns A function that takes a tuple and applies it to `fn` as positional args\n */\n\n// 2-arity\nexport function tupled<A, B, R>(fn: (a: A, b: B) => R): (args: [A, B]) => R;\n\n// 3-arity\nexport function tupled<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (args: [A, B, C]) => R;\n\n// 4-arity\nexport function tupled<A, B, C, D, R>(fn: (a: A, b: B, c: C, d: D) => R): (args: [A, B, C, D]) => R;\n\n// 5-arity\nexport function tupled<A, B, C, D, E, R>(fn: (a: A, b: B, c: C, d: D, e: E) => R): (args: [A, B, C, D, E]) => R;\n\n// Implementation\nexport function tupled<T extends UnknownFunction>(fn: T): (args: unknown[]) => unknown {\n return function tupledFn(args: unknown[]): unknown {\n return fn(...args);\n };\n}\n","import type { UnknownFunction } from './types';\n\n/**\n * Transforms a function that accepts a tuple into a multi-argument function.\n * Inverse of `tupled`. Useful when callers have positional arguments but your core API uses tuples.\n *\n * @example\n * // Basic\n * const tupledAdd = ([a, b]: [number, number]) => a + b;\n * const add = untupled(tupledAdd);\n * add(5, 3); // 8\n *\n * @example\n * // 3-arity\n * const sum3Tupled = ([a, b, c]: [number, number, number]) => a + b + c;\n * const sum3 = untupled(sum3Tupled);\n * sum3(1, 2, 3); // 6\n *\n * @example\n * // With Result\n * import { ok, err, flatMapResult, type Result } from \"@railway-ts/pipelines/result\";\n * const validateRange = ([min, max, value]: [number, number, number]): Result<number, string> =>\n * value >= min && value <= max ? ok(value) : err(`Value ${value} not between ${min} and ${max}`);\n * const validate = untupled(validateRange);\n * flatMapResult(ok(50), (n) => validate(0, 100, n)); // ok(50)\n *\n * @example\n * // With Option\n * import { some, none, type Option } from \"@railway-ts/pipelines/option\";\n * const parsePair = ([x, y]: [string, string]): Option<number> => {\n * const a = Number(x), b = Number(y);\n * return Number.isNaN(a) || Number.isNaN(b) ? none() : some(a + b);\n * };\n * const parse = untupled(parsePair);\n * parse(\"2\", \"3\"); // some(5)\n *\n * @param fn - A function that accepts a tuple of arguments\n * @returns A function that accepts the same arguments positionally\n */\n\n// 2-arity\nexport function untupled<A, B, R>(fn: (args: [A, B]) => R): (a: A, b: B) => R;\n\n// 3-arity\nexport function untupled<A, B, C, R>(fn: (args: [A, B, C]) => R): (a: A, b: B, c: C) => R;\n\n// 4-arity\nexport function untupled<A, B, C, D, R>(fn: (args: [A, B, C, D]) => R): (a: A, b: B, c: C, d: D) => R;\n\n// 5-arity\nexport function untupled<A, B, C, D, E, R>(fn: (args: [A, B, C, D, E]) => R): (a: A, b: B, c: C, d: D, e: E) => R;\n\n// Implementation\nexport function untupled<T extends UnknownFunction>(fn: T): UnknownFunction {\n return function untupledFn(...args: unknown[]): unknown {\n return fn(args);\n };\n}\n"]}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
type MaybeAsync<T> = T | Promise<T>;
|
|
2
|
+
type UnknownFunction = (...params: unknown[]) => unknown;
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Pipes a value through a series of functions, from left to right.
|
|
3
6
|
* Each function receives the output of the previous function.
|
|
@@ -120,6 +123,89 @@ declare function flow<A extends unknown[], B, C, D, E, F, G, H, I>(ab: (this: vo
|
|
|
120
123
|
declare function flow<A extends unknown[], B, C, D, E, F, G, H, I, J>(ab: (this: void, ...a: A) => B, bc: (this: void, b: B) => C, cd: (this: void, c: C) => D, de: (this: void, d: D) => E, ef: (this: void, e: E) => F, fg: (this: void, f: F) => G, gh: (this: void, g: G) => H, hi: (this: void, h: H) => I, ij: (this: void, i: I) => J): (...a: A) => J;
|
|
121
124
|
declare function flow<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(ab: (this: void, ...a: A) => B, bc: (this: void, b: B) => C, cd: (this: void, c: C) => D, de: (this: void, d: D) => E, ef: (this: void, e: E) => F, fg: (this: void, f: F) => G, gh: (this: void, g: G) => H, hi: (this: void, h: H) => I, ij: (this: void, i: I) => J, jk: (this: void, j: J) => K): (...a: A) => K;
|
|
122
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Pipes a value through a series of potentially async functions, from left to right.
|
|
128
|
+
* Each function receives the awaited output of the previous function.
|
|
129
|
+
* Unlike pipe, pipeAsync awaits between each step, enabling async composition.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Basic async usage
|
|
133
|
+
* const result = await pipeAsync(
|
|
134
|
+
* 5,
|
|
135
|
+
* async (n) => n * 2, // 10
|
|
136
|
+
* (n) => n + 1, // 11
|
|
137
|
+
* async (n) => n.toString() // "11"
|
|
138
|
+
* );
|
|
139
|
+
* // result: "11"
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* // With Result and curried helpers
|
|
143
|
+
* import { ok, flatMapWith, mapWith } from "@railway-ts/pipelines/result";
|
|
144
|
+
*
|
|
145
|
+
* const result = await pipeAsync(
|
|
146
|
+
* ok(5),
|
|
147
|
+
* flatMapWith(async (n) => ok(n * 2)),
|
|
148
|
+
* mapWith((n) => n.toString())
|
|
149
|
+
* );
|
|
150
|
+
* // result: Result<string, never> containing "10"
|
|
151
|
+
*
|
|
152
|
+
* @param a - The initial value (or Promise) to pipe through the functions
|
|
153
|
+
* @param ab - The first function to apply to the initial value
|
|
154
|
+
* @param functions - Additional functions to apply in sequence
|
|
155
|
+
* @returns A Promise of the final result after applying all functions
|
|
156
|
+
*/
|
|
157
|
+
declare function pipeAsync<A, B>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>): Promise<B>;
|
|
158
|
+
declare function pipeAsync<A, B, C>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>): Promise<C>;
|
|
159
|
+
declare function pipeAsync<A, B, C, D>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>): Promise<D>;
|
|
160
|
+
declare function pipeAsync<A, B, C, D, E>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>): Promise<E>;
|
|
161
|
+
declare function pipeAsync<A, B, C, D, E, F>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>): Promise<F>;
|
|
162
|
+
declare function pipeAsync<A, B, C, D, E, F, G>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>): Promise<G>;
|
|
163
|
+
declare function pipeAsync<A, B, C, D, E, F, G, H>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>): Promise<H>;
|
|
164
|
+
declare function pipeAsync<A, B, C, D, E, F, G, H, I>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>, hi: (this: void, h: H) => MaybeAsync<I>): Promise<I>;
|
|
165
|
+
declare function pipeAsync<A, B, C, D, E, F, G, H, I, J>(a: MaybeAsync<A>, ab: (this: void, a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>, hi: (this: void, h: H) => MaybeAsync<I>, ij: (this: void, i: I) => MaybeAsync<J>): Promise<J>;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Creates a new function that is the async composition of the provided functions, applied from left to right.
|
|
169
|
+
* Unlike flow, flowAsync awaits between each step, enabling async composition.
|
|
170
|
+
* The returned function always returns a Promise.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* // Basic async usage
|
|
174
|
+
* const processNumber = flowAsync(
|
|
175
|
+
* async (n: number) => n * 2,
|
|
176
|
+
* (n) => n + 1,
|
|
177
|
+
* async (n) => n.toString()
|
|
178
|
+
* );
|
|
179
|
+
*
|
|
180
|
+
* const result = await processNumber(5); // "11"
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* // With Result and curried helpers
|
|
184
|
+
* import { ok, flatMapWith, mapWith } from "@railway-ts/pipelines/result";
|
|
185
|
+
*
|
|
186
|
+
* const process = flowAsync(
|
|
187
|
+
* (n: number) => ok(n),
|
|
188
|
+
* flatMapWith(async (n) => ok(n * 2)),
|
|
189
|
+
* mapWith((n) => n.toString())
|
|
190
|
+
* );
|
|
191
|
+
*
|
|
192
|
+
* const result = await process(5); // Result<string, never> containing "10"
|
|
193
|
+
*
|
|
194
|
+
* @param ab - The first function in the composition
|
|
195
|
+
* @param functions - Additional functions to compose in sequence
|
|
196
|
+
* @returns A new function that applies all the composed functions in sequence, returning a Promise
|
|
197
|
+
*/
|
|
198
|
+
declare function flowAsync<A extends unknown[], B>(ab: (this: void, ...a: A) => MaybeAsync<B>): (...a: A) => Promise<B>;
|
|
199
|
+
declare function flowAsync<A extends unknown[], B, C>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>): (...a: A) => Promise<C>;
|
|
200
|
+
declare function flowAsync<A extends unknown[], B, C, D>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>): (...a: A) => Promise<D>;
|
|
201
|
+
declare function flowAsync<A extends unknown[], B, C, D, E>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>): (...a: A) => Promise<E>;
|
|
202
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>): (...a: A) => Promise<F>;
|
|
203
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F, G>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>): (...a: A) => Promise<G>;
|
|
204
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F, G, H>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>): (...a: A) => Promise<H>;
|
|
205
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>, hi: (this: void, h: H) => MaybeAsync<I>): (...a: A) => Promise<I>;
|
|
206
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I, J>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>, hi: (this: void, h: H) => MaybeAsync<I>, ij: (this: void, i: I) => MaybeAsync<J>): (...a: A) => Promise<J>;
|
|
207
|
+
declare function flowAsync<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(ab: (this: void, ...a: A) => MaybeAsync<B>, bc: (this: void, b: B) => MaybeAsync<C>, cd: (this: void, c: C) => MaybeAsync<D>, de: (this: void, d: D) => MaybeAsync<E>, ef: (this: void, e: E) => MaybeAsync<F>, fg: (this: void, f: F) => MaybeAsync<G>, gh: (this: void, g: G) => MaybeAsync<H>, hi: (this: void, h: H) => MaybeAsync<I>, ij: (this: void, i: I) => MaybeAsync<J>, jk: (this: void, j: J) => MaybeAsync<K>): (...a: A) => Promise<K>;
|
|
208
|
+
|
|
123
209
|
/**
|
|
124
210
|
* Curries a multi-parameter function into a sequence of unary functions.
|
|
125
211
|
* Enables partial application at any depth and composes cleanly with `pipe`.
|
|
@@ -146,11 +232,11 @@ declare function flow<A extends unknown[], B, C, D, E, F, G, H, I, J, K>(ab: (th
|
|
|
146
232
|
*
|
|
147
233
|
* @example
|
|
148
234
|
* // With Result validators
|
|
149
|
-
* import { ok, err,
|
|
235
|
+
* import { ok, err, flatMap, type Result } from "@/result";
|
|
150
236
|
* const between = (min: number, max: number, n: number): Result<number, string> =>
|
|
151
237
|
* n >= min && n <= max ? ok(n) : err(`Value must be between ${min} and ${max}`);
|
|
152
238
|
* const validateAge = curry(between)(0)(120);
|
|
153
|
-
* pipe(ok(25), (r) =>
|
|
239
|
+
* pipe(ok(25), (r) => flatMap(r, validateAge)); // ok(25)
|
|
154
240
|
*
|
|
155
241
|
* @param fn - The multi-argument function to transform into a unary curried chain
|
|
156
242
|
* @returns A curried function that takes one argument at each application step
|
|
@@ -283,4 +369,4 @@ declare function untupled<A, B, C, R>(fn: (args: [A, B, C]) => R): (a: A, b: B,
|
|
|
283
369
|
declare function untupled<A, B, C, D, R>(fn: (args: [A, B, C, D]) => R): (a: A, b: B, c: C, d: D) => R;
|
|
284
370
|
declare function untupled<A, B, C, D, E, R>(fn: (args: [A, B, C, D, E]) => R): (a: A, b: B, c: C, d: D, e: E) => R;
|
|
285
371
|
|
|
286
|
-
export { curry, flow, pipe, tupled, uncurry, untupled };
|
|
372
|
+
export { type MaybeAsync, type UnknownFunction, curry, flow, flowAsync, pipe, pipeAsync, tupled, uncurry, untupled };
|