Next.js 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 handler.
The library does not contain routing utilities. I believe mechanism built in Next.js itself or next-connect library are pretty enough solutions.
Features
Installing
npm i next-api-compose -S
yarn add next-api-compose
Basic usage:
import { compose } from 'next-api-compose'
export default compose([withBar, withFoo], (request, response) => {
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
Advanced usage:
import { compose } from 'next-api-compose'
export default compose(
{ sharedErrorHandler, middlewareChain: [withBar, withFoo, withError] },
(request, response) => {
const { foo, bar } = request
response.status(200).json({ foo, bar })
}
)
async function sharedErrorHandler(error, _request, response) {
response.status(418).json({ error: error.message })
}
function withFoo(handler) {
return async function (request, response) {
request.foo = 'foo'
return handler(request, response)
}
}
function withBar(handler) {
return async function (request, response) {
request.bar = 'bar'
return handler(request, response)
}
}
function withError() {
return async function () {
throw new Error('some error')
}
}
TypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
import type {
ExtendedNextApiHandler,
NextApiComposeMiddlewares,
NextApiComposeOptions
} from 'next-api-compose'
import { compose } from 'next-api-compose'
type NextApiRequestWithFoo = NextApiRequest & Partial<{ foo: string }>
type NextApiRequestWithBar = NextApiRequest & Partial<{ bar: string }>
type NextApiRequestWithFooBar = NextApiRequestWithFoo & NextApiRequestWithBar
const mws: NextApiComposeMiddlewares<NextApiRequestWithFooBar> = [withFoo, withBar]
const options: NextApiComposeOptions<NextApiRequestWithFooBar> = {
sharedErrorHandler: handleErrors,
middlewareChain: mws
}
export default compose<NextApiRequestWithFooBar>(options, (request, response) => {
const { foo, bar } = request
response.status(200).json({ foo, bar })
})
function handleErrors(error: Error, _request: NextApiRequest, response: NextApiResponse) {
response.status(418).json({ error: error.message })
}
function withFoo(handler: ExtendedNextApiHandler<NextApiRequestWithFoo>) {
return async function (request: NextApiRequestWithFoo, response: NextApiResponse) {
request.foo = 'foo'
return handler(request, response)
}
}
function withBar(handler: ExtendedNextApiHandler<NextApiRequestWithBar>) {
return async function (request: NextApiRequestWithBar, response: NextApiResponse) {
request.bar = 'bar'
return handler(request, response)
}
}
License
This project is licensed under the MIT license.
All contributions are welcome.