Skip to content

revamp #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/MIGRATE_V2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Migration guide for next-api-compose v2.0.0

The old version supported only the Pages Directory API Routes. The new version supports both Pages Directory API Routes and the App Directory API Routes.

In order to migrate from versions below v2.0.0, the only thing you need to do is to change the import statement from:

```js
import { compose } from "next-api-compose";
```

to:

```js
import { compose } from "next-api-compose/pages";
```

any other imported functions from the library should be imported from the same module.

e.g.

```js
import { compose, convert } from "next-api-compose/pages";
```

Back to the [README.md](./README.md)
40 changes: 22 additions & 18 deletions README.md → .github/PAGES_ROUTER.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Next.js API Compose · [![version](https://badgen.net/npm/v/next-api-compose)](https://www.npmjs.com/package/next-api-compose) [![codecov](https://codecov.io/gh/neg4n/next-api-compose/branch/development/graph/badge.svg?token=VDJSVV76LD)](https://codecov.io/gh/neg4n/next-api-compose) [![CodeFactor](https://www.codefactor.io/repository/github/neg4n/next-api-compose/badge)](https://www.codefactor.io/repository/github/neg4n/next-api-compose) [![npm bundle size](https://badgen.net/bundlephobia/minzip/next-api-compose)](https://bundlephobia.com/package/next-api-compose)
# Next.js API Compose · [![version](https://badgen.net/npm/v/next-api-compose)](https://www.npmjs.com/package/next-api-compose) [![npm bundle size](https://badgen.net/bundlephobia/minzip/next-api-compose)](https://bundlephobia.com/package/next-api-compose)

## Introduction

This library provides simple yet complete higher order function
with responsibility of composing multiple middleware functions into one [Next.js API route][next-api-routes] handler.
with responsibility of composing multiple middleware functions into one [Next.js API route][next-api-routes] handler in the pages directory router configuration.

The library **does not** contain routing utilities. I believe mechanism built in
Learn more about using the library for App Directory's Route Handlers [here](./README.md).

The library for pages router **does not** contain routing utilities. I believe mechanism built in
[Next.js][next-homepage] itself or [next-connect][next-connect] library are sufficient solutions.

## Features
Expand All @@ -16,25 +18,27 @@ The library **does not** contain routing utilities. I believe mechanism built in
- [x] 🔧 Compatible with [Express][express]/[Connect][connect] middleware
- [x] 💢 Error handling
- [x] 📦 No dependencies
- [x] 💯 100% Test coverage
- [x] 💯 100% Test coverage for pages router

## Installing

```sh
npm i next-api-compose -S
# or
yarn add next-api-compose
# or
pnpm i next-api-compose
```

## Basic usage:

```js
import { compose } from 'next-api-compose'
import { compose } from "next-api-compose/pages";

export default compose([withBar, withFoo], (request, response) => {
const { foo, bar } = request
response.status(200).json({ foo, bar })
})
const { foo, bar } = request;
response.status(200).json({ foo, bar });
});
```

_the `withBar` middleware will append `bar` property to `request` object, then `withFoo` will do accordingly the same but with `foo` property_
Expand All @@ -44,15 +48,15 @@ _the `withBar` middleware will append `bar` property to `request` object, then `
If you want to use `next-api-compose` along with [Connect][connect] middleware that is widely used eg. in [Express][express] framework, there is special utility function for it.

```js
import { compose, convert } from 'next-api-compose'
import helmet from 'helmet'
import { compose, convert } from "next-api-compose/pages";
import helmet from "helmet";

const withHelmet = convert(helmet())
const withHelmet = convert(helmet());

export default compose([withBar, withFoo, withHelmet], (request, response) => {
const { foo, bar } = request
response.status(200).json({ foo, bar })
})
const { foo, bar } = request;
response.status(200).json({ foo, bar });
});
```

_in this example, popular middleware [helmet][helmet] is converted using utility function from `next-api-compose` and passed as one element in middleware chain_
Expand All @@ -77,9 +81,9 @@ _the `example/` directory contains simple [Next.js][next-homepage] application i
```js
export const config = {
api: {
externalResolver: true
}
}
externalResolver: true,
},
};
```

to your [Next.js API route configuration][next-api-routes-config] in order to dismiss false positive
Expand All @@ -89,7 +93,7 @@ _the `example/` directory contains simple [Next.js][next-homepage] application i
2. If you are using TypeScript and strict types _(no `any` at all)_, you may want to use [Partial][typescript-partial]

```ts
type NextApiRequestWithFoo = NextApiRequest & Partial<{ foo: string }>
type NextApiRequestWithFoo = NextApiRequest & Partial<{ foo: string }>;
```

when extending [API Route parameters' objects][next-extending-api-parameters] to avoid type errors during usage of `compose`.
Expand Down
94 changes: 94 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<picture>

<source media="(prefers-color-scheme: dark)" srcset="./assets/code_dark.png">
<source media="(prefers-color-scheme: light)" srcset="./assets/code_light.png">

</picture>

# Next.js API Compose &middot; [![version](https://badgen.net/npm/v/next-api-compose)](https://www.npmjs.com/package/next-api-compose) [![npm bundle size](https://badgen.net/bundlephobia/minzip/next-api-compose)](https://bundlephobia.com/package/next-api-compose)

## Introduction

This library provides hassle-free way of composing multiple middleware functions into one [Next.js API Route Handler][next-api-route-handlers]'s method in the **[App Directory][next-app-router-intro]** router.

> [!IMPORTANT]
> The `2.0.0` version of the library supports both [app] and pages directory API utilities. If you're still using Pages Router and you want to migrate from versions below `2.0.0`, please read [migration guide](./MIGRATE_V2.md).

## Features

- [x] 😇 Simple and powerful API
- [x] 🚀 Designed both for Pages Router and App Router
- [x] 🥷 Excellent TypeScript support
- [x] 🧬 Maintaining order of middleware chain
- [x] 📦 No dependencies, small footprint

## Installing and basic usage

Install the package by running:

```sh
npm i next-api-compose -S
# or
yarn add next-api-compose
# or
pnpm i next-api-compose
```

then create an API Route Handler in the **[App Directory][next-app-router-intro]**:

in TypeScript **(recommended)**

```ts
import type { NextRequest } from "next/server";
import { compose } from "next-api-compose";

function someMiddleware(request: NextRequest & { foo: string }) {
request.foo = "bar";
}

const { GET } = compose({
GET: [
[someMiddleware],
(request /* This is automatically inferred */) => {
return new Response(request.foo);
// ^ (property) foo: string - autocomplete works here
},
],
});

export { GET };
```

in JavaScript:

```js
import { compose } from "next-api-compose";

function someMiddleware(request) {
request.foo = "bar";
}

const { GET } = compose({
GET: [
[someMiddleware],
(request) => {
return new Response(request.foo);
},
],
});

export { GET };
```

## Theory and caveats

1. Unfortunately there is no way to dynamically export named ESModules _(or at least I did not find a way)_ so you have to use `export { GET, POST }` syntax instead of something like `export compose(...)` if you're composing GET and POST methods :(

2. Middleware is executed as specified in per-method array, so if you want to execute middleware in specific order, you have to be careful about it. Early returned `new Response()` halts the middleware chain.

## License and contributions

The project is licensed under The MIT License. Thanks for all the contributions! Feel free to open an issue or a pull request.

[next-api-route-handlers]: https://nextjs.org/docs/app/building-your-application/routing/route-handlers
[next-app-router-intro]: https://nextjs.org/docs/app/building-your-application/routing#the-app-router
Binary file added .github/assets/code_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/assets/code_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 14 additions & 16 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
name: Coverage
on: pull_request
name: "coverage"

on:
pull_request:
branches:
- master
- main
jobs:
run:
coverage:
runs-on: ubuntu-latest
steps:
- name: Fetch
uses: actions/checkout@master
- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
- uses: actions/checkout@v3
- name: Jest coverage report
uses: ArtiomTr/jest-coverage-report-action@v2.2.4
with:
node-version: 16
- name: Test
run: |
npm ci
npm t -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
package-manager: pnpm
working-directory: "./packages/next-api-compose/"
test-script: pnpm jest --json --coverage --testLocationInResults --outputFile=report.json
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ node_modules
lib
coverage
.vscode
.DS_Store
.DS_Store
dist
report.json
.turbo
example-app
Loading