> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cbrock.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Pipe & Flow

> Function composition utilities.

`pipe` and `flow` are utility functions for composing sequences of transformations. Both are fully typed: each function's return type becomes the next function's argument type, with no loss of type information.

```typescript theme={null}
import { pipe, flow } from 'ts-chas/pipe';
```

Both support up to 10 functions in a single call. If you need more, break your pipeline into named intermediate steps.

***

## `pipe(value, ...fns)`

Takes an initial value and passes it through a sequence of functions left-to-right. Returns the output of the final function.

```typescript theme={null}
import { pipe } from 'ts-chas/pipe';

const add5  = (x: number) => x + 5;
const double = (x: number) => x * 2;

const result = pipe(10, add5, double);
// add5(10) = 15, double(15) = 30
// result: 30
```

Each function's return type informs the next function's parameter type:

```typescript theme={null}
const result = pipe(
  'hello world',
  (s) => s.split(' '),        // string → string[]
  (words) => words.length,    // string[] → number
  (n) => `Word count: ${n}`   // number → string
);
// 'Word count: 2'
```

***

## `flow(...fns)`

Composes functions into a single reusable function without an initial value. Call the result later with your input. Think of it as a named, reusable pipeline.

```typescript theme={null}
import { flow } from 'ts-chas/pipe';

const add5  = (x: number) => x + 5;
const double = (x: number) => x * 2;

const calculate = flow(add5, double);
// calculate is typed as (x: number) => number

calculate(10); // 30
calculate(0);  // 10
```

`flow` is useful for defining transforms you want to pass as callbacks or store as constants:

```typescript theme={null}
const normalizeEmail = flow(
  (s: string) => s.trim(),
  (s) => s.toLowerCase(),
  (s) => s.replace(/\s+/g, '')
);

['  Alice@Example.COM ', ' BOB@TEST.ORG'].map(normalizeEmail);
// ['alice@example.com', 'bob@test.org']
```

***

## Built-in `.pipe()` on `Result` and `ResultAsync`

`Result` and `ResultAsync` have their own `.pipe()` method. It behaves like `pipe`, but is Result-aware: if any step returns an `Err`, the chain short-circuits and subsequent functions are skipped.

```typescript theme={null}
import { chas } from 'ts-chas';

const add5  = (x: number) => x + 5;
const double = (x: number) => x * 2;

const result = chas.ok(10).pipe(add5, double);
// Ok(30)

const errResult = chas.err('something went wrong').pipe(add5, double);
// Err('something went wrong') — add5 and double are never called
```

This also works on `ResultAsync`:

```typescript theme={null}
const asyncResult = chas.okAsync(10).pipe(add5, double);
// ResultAsync<30, never>
```

***

## Complete example

This example shows all three forms working together in a data transformation pipeline:

```typescript theme={null}
import { pipe, flow } from 'ts-chas/pipe';
import { chas } from 'ts-chas';

interface RawProduct {
  name: string;
  price_cents: number;
  tags: string | null;
}

interface Product {
  name: string;
  priceUsd: number;
  tags: string[];
}

// Reusable transforms defined with flow
const centsToUsd = flow(
  (cents: number) => cents / 100,
  (usd) => Math.round(usd * 100) / 100
);

const parseTags = (raw: string | null): string[] =>
  raw ? raw.split(',').map(t => t.trim()).filter(Boolean) : [];

// A single-value transformation using pipe
function toProduct(raw: RawProduct): Product {
  return pipe(
    raw,
    (r) => ({ ...r, priceUsd: centsToUsd(r.price_cents) }),
    (r) => ({ ...r, tags: parseTags(r.tags) }),
    ({ name, priceUsd, tags }) => ({ name, priceUsd, tags })
  );
}

// Result-aware pipeline using the built-in .pipe() on Result
function parseAndTransform(input: unknown): chas.Result<Product, string> {
  return chas
    .tryCatch(
      () => input as RawProduct,
      () => 'Invalid product data'
    )
    .pipe(
      (raw) => ({ ...raw, name: raw.name.trim() }),
      toProduct
    );
}

// Usage
const result = parseAndTransform({ name: '  Widget ', price_cents: 1999, tags: 'sale, new' });

if (result.isOk()) {
  console.log(result.value);
  // { name: 'Widget', priceUsd: 19.99, tags: ['sale', 'new'] }
}
```
