nextjs-middleware-stack 1.0.2 โ 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -6
- package/dist/main.d.ts +3 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +7 -4
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ๐ฃ๏ธ `middlewareStack` โ A Lightweight Middleware Router for Next.js
|
|
2
2
|
|
|
3
|
-
A composable middleware stack for Next.js, supporting
|
|
3
|
+
A composable middleware stack for Next.js, supporting `string`-based route patterns (with dynamic parameters and wildcards), raw `RegExp` objects, and custom sync/async predicate functions.
|
|
4
4
|
|
|
5
5
|
Perfect for building layered request logic like authentication, logging, redirects, or feature flags in Next.js Edge or Node middlewares.
|
|
6
6
|
|
|
@@ -12,6 +12,7 @@ Perfect for building layered request logic like authentication, logging, redirec
|
|
|
12
12
|
- `:param` dynamic segments
|
|
13
13
|
- `**` wildcards (greedy)
|
|
14
14
|
- โ
`RegExp` support
|
|
15
|
+
- โ
Custom `PatternFn` support: `(req) => boolean | Promise<boolean>`
|
|
15
16
|
- โ
Middleware short-circuiting (first matching response stops the stack)
|
|
16
17
|
- โ
Fully compatible with `next/server` and middleware in `apps/<name>/src/middleware.ts`
|
|
17
18
|
|
|
@@ -27,14 +28,22 @@ npm install compare-path
|
|
|
27
28
|
|
|
28
29
|
## ๐ง API
|
|
29
30
|
|
|
30
|
-
### `middlewareStack(routes: [
|
|
31
|
+
### `middlewareStack(routes: [Pattern, MiddlewareHandler][])`
|
|
31
32
|
|
|
32
33
|
Creates a Next.js-compatible middleware handler from an ordered list of route matchers and handler functions.
|
|
33
34
|
|
|
35
|
+
```ts
|
|
36
|
+
export type PatternFn = (req: Request) => boolean | Promise<boolean>
|
|
37
|
+
export type Pattern = PatternFn | string | RegExp
|
|
38
|
+
```
|
|
39
|
+
|
|
34
40
|
#### Parameters:
|
|
35
41
|
|
|
36
42
|
- `routes`: An array of tuples where:
|
|
37
|
-
- The first item is a
|
|
43
|
+
- The first item is a `Pattern`:
|
|
44
|
+
- a string pattern (e.g., `/users/:id`)
|
|
45
|
+
- a `RegExp`
|
|
46
|
+
- a function/async function `(req) => boolean | Promise<boolean>`
|
|
38
47
|
- The second item is a handler function `(req: NextRequest) => Response | void | Promise<Response | void>`.
|
|
39
48
|
|
|
40
49
|
#### Returns:
|
|
@@ -45,7 +54,7 @@ Creates a Next.js-compatible middleware handler from an ordered list of route ma
|
|
|
45
54
|
|
|
46
55
|
## ๐ Supported Path Shapes
|
|
47
56
|
|
|
48
|
-
You can use
|
|
57
|
+
You can use `string`-based shape patterns (powered by `compare-path`), `RegExp`, or predicate functions.
|
|
49
58
|
|
|
50
59
|
| Shape | Matches Path Example |
|
|
51
60
|
| --------------- | --------------------------- |
|
|
@@ -56,6 +65,8 @@ You can use either `string`-based shape patterns (powered by `compare-path`) or
|
|
|
56
65
|
|
|
57
66
|
> Use RegExp when you need full regex control.
|
|
58
67
|
|
|
68
|
+
Use a predicate function when matching depends on request headers, cookies, or any custom runtime logic.
|
|
69
|
+
|
|
59
70
|
---
|
|
60
71
|
|
|
61
72
|
## ๐งช Example Usage (Auth Middleware)
|
|
@@ -116,6 +127,26 @@ export default middlewareStack([
|
|
|
116
127
|
|
|
117
128
|
---
|
|
118
129
|
|
|
130
|
+
## ๐งช Example with `PatternFn`
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { middlewareStack } from './utils/middleware-stack'
|
|
134
|
+
|
|
135
|
+
export default middlewareStack([
|
|
136
|
+
[
|
|
137
|
+
async (req) => {
|
|
138
|
+
// Match only API requests that include an auth header
|
|
139
|
+
return req.url.includes('/api/') && !!req.headers.get('authorization')
|
|
140
|
+
},
|
|
141
|
+
async (req) => {
|
|
142
|
+
// Custom logic for authenticated API requests
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
])
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
119
150
|
## ๐งน Integration in Next.js
|
|
120
151
|
|
|
121
152
|
You must also export the `config` to ensure the middleware applies to your desired routes:
|
|
@@ -136,7 +167,7 @@ export const config = {
|
|
|
136
167
|
|
|
137
168
|
Internally, `middlewareStack` will iterate through your routes and:
|
|
138
169
|
|
|
139
|
-
1. Compare the current
|
|
170
|
+
1. Compare the current request to each route pattern (`compare-path`, `RegExp`, or `PatternFn`).
|
|
140
171
|
2. If matched, execute the handler.
|
|
141
172
|
3. If a `Response` is returned from the handler, it stops further execution and returns immediately.
|
|
142
173
|
|
|
@@ -147,7 +178,8 @@ Internally, `middlewareStack` will iterate through your routes and:
|
|
|
147
178
|
- Middleware order matters! First match wins.
|
|
148
179
|
- Use RegExp for more complex or legacy patterns.
|
|
149
180
|
- Use string shapes for clean, readable routes with parameters.
|
|
181
|
+
- Use `PatternFn` for request-aware matching (cookies, headers, auth, geo, etc).
|
|
150
182
|
|
|
151
183
|
---
|
|
152
184
|
|
|
153
|
-
Islam Yamor.
|
|
185
|
+
Islam Yamor.
|
package/dist/main.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export type MiddlewareHandler<T = Request, R = Response> = (req: T) => R | void | Promise<R | void>;
|
|
2
|
-
export
|
|
2
|
+
export type PatternFn = (req: Request) => boolean | Promise<boolean>;
|
|
3
|
+
export type Pattern = PatternFn | string | RegExp;
|
|
4
|
+
export declare function middlewareStack<T = Request, R = Response>(routes: [Pattern, MiddlewareHandler<T, R>][]): (req: T) => Promise<R | void>;
|
|
3
5
|
//# sourceMappingURL=main.d.ts.map
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;AACnG,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACpE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAA;AAEjD,wBAAgB,eAAe,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,QAAQ,EACvD,MAAM,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAE9B,KAAK,CAAC,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAsBzC"}
|
package/dist/main.js
CHANGED
|
@@ -14,13 +14,16 @@ const compare_path_1 = require("compare-path");
|
|
|
14
14
|
function middlewareStack(routes) {
|
|
15
15
|
return (req) => __awaiter(this, void 0, void 0, function* () {
|
|
16
16
|
var _a, _b;
|
|
17
|
-
const url = (
|
|
17
|
+
// const url = (req as MaybeNextRequest).nextUrl?.pathname ?? (req as Request).url
|
|
18
|
+
const currentUrl = (_b = (_a = req.nextUrl) === null || _a === void 0 ? void 0 : _a.pathname) !== null && _b !== void 0 ? _b : new URL(req.url).pathname;
|
|
18
19
|
for (const [pattern, handler] of routes) {
|
|
19
20
|
const isMatch = typeof pattern === 'string'
|
|
20
|
-
? (0, compare_path_1.comparePath)(pattern,
|
|
21
|
+
? (0, compare_path_1.comparePath)(pattern, currentUrl)
|
|
21
22
|
: pattern instanceof RegExp
|
|
22
|
-
? pattern.test(
|
|
23
|
-
:
|
|
23
|
+
? pattern.test(currentUrl)
|
|
24
|
+
: typeof pattern === 'function'
|
|
25
|
+
? yield pattern(req)
|
|
26
|
+
: false;
|
|
24
27
|
if (isMatch) {
|
|
25
28
|
const result = yield handler(req);
|
|
26
29
|
if (result)
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;AAMA,0CAyBC;AA/BD,+CAA0C;AAM1C,SAAgB,eAAe,CAC7B,MAA4C;IAE5C,OAAO,CAAO,GAAM,EAAqB,EAAE;;QAEzC,kFAAkF;QAClF,MAAM,UAAU,GACd,MAAA,MAAC,GAAwB,CAAC,OAAO,0CAAE,QAAQ,mCAAI,IAAI,GAAG,CAAE,GAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;QAEvF,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,EAAE,CAAC;YACxC,MAAM,OAAO,GACX,OAAO,OAAO,KAAK,QAAQ;gBACzB,CAAC,CAAC,IAAA,0BAAW,EAAC,OAAO,EAAE,UAAU,CAAC;gBAClC,CAAC,CAAC,OAAO,YAAY,MAAM;oBAC3B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;oBAC1B,CAAC,CAAC,OAAO,OAAO,KAAK,UAAU;wBAC/B,CAAC,CAAC,MAAM,OAAO,CAAC,GAAc,CAAC;wBAC/B,CAAC,CAAC,KAAK,CAAA;YAEX,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;gBACjC,IAAI,MAAM;oBAAE,OAAO,MAAM,CAAA,CAAC,gDAAgD;YAC5E,CAAC;QACH,CAAC;IACH,CAAC,CAAA,CAAA;AACH,CAAC"}
|