Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

next-pipe-middleware

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

next-pipe-middleware - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0-alpha.0

dist/compose.d.ts

16

dist/index.d.ts

@@ -1,14 +0,2 @@

import { NextRequest, NextResponse } from 'next/server';
export declare type Request = NextRequest;
export declare type Response = NextResponse;
export declare type FinalResponse = {
res: Response;
final: true;
};
export declare type PipeableMiddleware = (req: Request, res: Response) => Promise<Response | FinalResponse>;
declare type Option = {
matcher?: (path: string) => boolean | Promise<boolean>;
};
declare type PipeMiddleware = (req: Request, res: Response, middlewares: (PipeableMiddleware | [PipeableMiddleware, Option])[]) => Promise<Response>;
export declare const pipeMiddleware: PipeMiddleware;
export {};
export { composeMiddleware } from './compose';
export type { ComposableMiddleware } from './compose';

@@ -1,26 +0,2 @@

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
export const pipeMiddleware = (req, res, middlewares) => __awaiter(void 0, void 0, void 0, function* () {
if (middlewares.length === 0) {
return res;
}
const [next, ...rest] = middlewares;
const [middleware, nextMiddlewareOption] = typeof next === 'function' ? [next, null] : [next[0], next[1]];
if ((nextMiddlewareOption === null || nextMiddlewareOption === void 0 ? void 0 : nextMiddlewareOption.matcher) &&
nextMiddlewareOption.matcher(req.nextUrl.pathname) === false) {
return pipeMiddleware(req, res, rest);
}
const result = yield middleware(req, res);
if ('final' in result) {
return result.final ? result.res : pipeMiddleware(req, res, rest);
}
return pipeMiddleware(req, result, rest);
});
export { composeMiddleware } from './compose';
//# sourceMappingURL=index.js.map
{
"name": "next-pipe-middleware",
"version": "1.0.1",
"version": "2.0.0-alpha.0",
"type": "module",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

# 🧵 Next Pipe Middleware
This is a library for building Next.js middleware declaratively.
You can create highly readable and manageable middleware by piping multiple functions together.
This is a library for building Next.js complex middleware declaratively.
You can create highly readable and manageable middleware by composing multiple functions together.
## 🌟 Features
- Multiple middleware executions in series
- Conditional execution of middleware
- Middleware processes that can be terminated midstream
- Path-based middleware execution (like "Nested Middleware")
- Composition of functions divided by interest (including early exit)

@@ -18,19 +17,47 @@ ## 🔏 Requirements

### Basic
Pass NextRequest, NextResponse, and arrays of multiple middleware to `pipeMiddleware` function.
```ts
export default async function middleware(req: NextRequest) {
return pipeMiddleware(req, NextResponse.next(), [
fooMiddleware,
barMiddleware,
hogeMiddleware,
])
/**
* Path : Middleware execution order
*
* `/` : root1 -> root2
* `/foo` : root1 -> root2 -> foo
* `/foo/bar/hoge` : root1 -> root2 -> foo -> fooBar
* `/foo/bar/xxxx/baz` : root1 -> root2 -> foo -> fooId -> fooIdBaz
*/
return composeMiddleware(req, NextResponse.next(), {
scripts: [root1, root2],
'/foo': {
scripts: [foo],
'/bar': {
scripts: [fooBar],
},
'/[id]': {
scripts: [fooId],
'/baz': [fooIdBaz]path
},
// ↓ Either writing method will work, but if you want to nest more, you have to write it in the Object
'/qux': [fooQux]
'/qux': {
scripts: [fooQux]
}
}
})
}
```
Each middleware function (`PipeableMiddleware`) differs from the Next.js middleware functions only in that it takes a NextResponse as its second argument:
Each middleware function is a `ComposableMiddleware` function.
This is almost identical to the Next.js middleware, differing only in that it takes additional arguments.
```ts
const fooMiddleware: PipeableMiddleware = async (req, res) => {
res.cookies.set('foo', 'bar')
/**
* type ComposableMiddleware = (
* req: NextRequest,
* res: NextResponse,
* handler?: {...} // explained at next section
* ) => Promise<Response>;
*/
const fooMiddleware: ComposableMiddleware = async (req, res) => {
res.cookies.set('foo', 'foo')
return res;

@@ -40,28 +67,16 @@ };

### Conditional middleware
If you want to control execution of middleware according to the page path, pass an object containing a matcher function as the second element of the tuple
```ts
export default async function middleware(req: NextRequest) {
return pipeMiddleware(req, NextResponse.next(), [
basicAuthMiddleware,
[redirectMiddleware, {matcher: (path) => path.startsWith('/secret')}],
[refreshTokenMiddleware, {matcher: (path) => path.startsWith('/my')}],
])
}
```
### Early Exit
If you want to abort whole process at a particular middleware without executing subsequent functions, use a handler that is given from third argument.
### Terminable middleware
If you want to terminate the entire process on a particular piece of middleware (i.e., you do not want subsequent pieces of middleware to run), change the response format as follows
```ts
const basicAuth: PipeableMiddleware = async (req, res) => {
const success = validateBasicAuth(req);
const basicAuth: PipeableMiddleware = async (req, res, { breakAll, breakOnce }) => {
const success = validateBasicAuth(req); // returns boolean
if (success) {
return res;
} else {
return {
res: NextResponse.rewrite(/**/),
final: true,
}; // terminate process after this middleware by returning object with `final: true` and `res`
return breakAll(res); // All subsequent middleware (`refreshToken`, `foo` and others) will not be executed !!
// or
return breakOnce(res); // Only subsequent middleware in the same hierarchy (`refreshToken`) will not be executed (`foo` will be executed).
}

@@ -71,7 +86,9 @@ };

export default async function middleware(req: NextRequest) {
return pipeMiddleware(req, NextResponse.next(), [
basicAuthMiddleware, // if basic auth failed, the process ends here.
redirectMiddleware,
refreshTokenMiddleware
])
return composeMiddleware(req, NextResponse.next(), {
scripts: [basicAuth, refreshToken],
'/foo': {
scripts: [foo],
...
}
})
}

@@ -82,39 +99,2 @@ ```

## 📖 Appendix
[Demo](https://codesandbox.io/s/next-pipe-middleware-w9rvlh?file=/middleware.ts)
<details>
<summary>Motivation</summary>
If you want to implement the following at the middleware file:
- Applying Basic-auth, if it fails, **terminates** at that point.
- If user access to specific page, redirect and **terminates** at that point.
- Refresh the authentication token.
Without this library, you would have to write codes like this:
```ts
export default async function middleware(req: NextRequest) {
const res = NextResponse.next()
const success = await basicAuthMiddleware(req, res);
if (!success) {
return NextResponse.rewrite(new URL('/api/basic-auth', req.url))
}
if (req.url.startsWith('/secret')) {
const [shouldRedirect, redirectRes] = await redirectMiddleware(req, res);
if (shouldRedirect) {
return redirectRes;
}
}
if (req.url.startsWith('/my')) {
await refreshTokenMiddleware(req, res);
}
return res;
}
```
It is difficult to know what kind of process the middleware consists of, because it is necessary to check whether the process should be terminated depending on the response, or whether it should be executed according to the path, etc.
This library allows you to write what you want to do declaratively and readably as above.
</details>

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc