# next-route-handler-pipe

> Pipe together functions to create reusable function pipelines for your Next.js route handlers.

Latest version **2.0.0** (published 2024-02-27) · MIT license · 0 weekly downloads

## Install

```sh
npm install next-route-handler-pipe
pnpm add next-route-handler-pipe
yarn add next-route-handler-pipe
bun add next-route-handler-pipe
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.0.0 |
| Published | 2024-02-27 |
| First published | 2023-12-18 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Dependencies | 0 |
| Unpacked size | 9.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 66 |
| Author | kolbysisk |
| Maintainers | kolbysisk |

## Links

- npm: https://www.npmjs.com/package/next-route-handler-pipe
- Repository: https://github.com/KolbySisk/next-route-handler-pipe
- Homepage: https://github.com/KolbySisk/next-route-handler-pipe#readme
- Issues: https://github.com/KolbySisk/next-route-handler-pipe/issues
- npm.io page: https://npm.io/package/next-route-handler-pipe

## Recent versions

- 2.0.0 (latest) — 2024-02-27
- 1.0.5 — 2024-01-03
- 1.0.4 — 2023-12-19
- 1.0.3 — 2023-12-18
- 1.0.2 — 2023-12-18
- 1.0.1 — 2023-12-18
- 1.0.0 — 2023-12-18

## README

<p align="center">
  <h1 align="center">next-route-handler-pipe</h1>
  <p align="center">
    <img src="https://miro.medium.com/v2/resize:fit:4800/format:webp/1*iEaKA8z_dgcbF6Qfzbk5Sg.png" />
  </p>
</p>
<p align="center">
  <a href="https://twitter.com/kolbysisk" rel="nofollow"><img src="https://img.shields.io/badge/created%20by-@kolbysisk-e57060.svg" alt="Created by Kolby Sisk"></a>
  <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/kolbysisk/next-route-handler-pipe" alt="License"></a>
</p>

> ⚠️ This package is for projects using Next.js App Router. For projects using Pages Router see [next-api-route-middleware](https://github.com/KolbySisk/next-api-route-middleware).

## Introduction

Piping functions allows us to abstract reusable code that runs before the route handler is invoked.

### Example uses:

- ✅ Validate body/query data
- 🔒 Verifying signatures
- 🪝 Catch errors
- ✨ Add data to the `req` object

## Getting started

### 1. Install'r

`npm i next-route-handler-pipe`

### 2. Create a pipe function

A pipe function is a function that accepts `req`, `event`, and `next`. It should return `await next()` when done, or return a `NextResponse`.

```ts
// PipeFunction accepts a generic when mutating req
export const withUser: PipeFunction<{ userId: string }> = async (req, event, next) => {
  const { userId } = await validateUserRequest();

  if (userId) {
    req.userId = userId;
    return await next();
  } else {
    return NextResponse.json({ message: 'Invalid auth token.' }, { status: 401 });
  }
};
```

### 3. Create a pipe

Import the `pipe` function and pass it pipe functions followed by a handler. If a pipe function adds data to the req you can compose an intersection type with `NextRequest` & the added data.

```ts
import { pipe } from 'next-route-handler-pipe';

async function handler(req: NextRequest & { userId: string }) {
  console.log(req.userId);
}

export const POST = pipe(withUser, handler);
```

## Examples

### validateBody

Combine with Zod to create an awesome validation pattern.

```ts
// validate-body.ts

// This is a pipe function that makes use of the factory pattern, meaning it returns a pipe function.
// This allows us to pass args into our pipe, like a zod schema.

export const validateBody = (zodSchema: z.ZodSchema): PipeFunction<{ data: any }> => {
  return async function (req, event, next) {
    // Get the body of the request and parse with Zod
    const body = await req.json();
    const validation = zodSchema.safeParse(typeof body === 'object' ? body : JSON.parse(body));

    // If validation fails we return early, preventing the handler from running.
    if (!validation.success) {
      console.error('Validation error from validateBody', validation.error);
      return NextResponse.json({ message: 'Validation error' }, { status: 400 });
    }
    // If validation passes we can add the parsed data to the req for easy access in our handler.
    else {
      req.data = validation.data;
      // Always return await next() in your pipe function.
      return await next();
    }
  };
};
```

```ts
// route.ts

// Create a Zod schema
const postSchema = z
  .object({
    postId: z.string(),
    postTitle: z.string(),
    authorName: z.string(),
  })

  // We can even add a Zod transform if we need
  .transform(({ postId, postTitle, authorName }) => ({
    post_id: postId,
    post_title: postTitle,
    author_first_name: authorName.split(' ')[0],
    author_last_name: authorName.split(' ')[1],
  }));

// Infer type from schema
type Post = z.infer<typeof postSchema>;

// Add intersection with `NextRequest` & your inferred type
async function handler(req: NextRequest & { data: Post }) {
  // We've validated that this data will always exist at this point
  const { post_id, post_title } = req.data;
}

// Notice we're calling the validateBody function - that's because it's a factory that will return a pipe function
export const POST = pipe(validateBody(postSchema), handler);
```

### catchErrors

We can also perform actions with inner pipe functions. In this example we wrap the inner pipe functions in a try catch, allowing us to catch any errors that bubble up.

```ts
export const catchErrors: PipeFunction = async (req, event, next) => {
  try {
    return await next();
  } catch (error) {
    console.error(error);
    return NextResponse.json({ message: 'Server error!' }, { status: 500 });
  }
};
```

---
_Source: https://npm.io/package/next-route-handler-pipe · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
