next-mw
Version:
A middleware manager for Next.js
171 lines (169 loc) • 4.86 kB
JavaScript
// src/index.ts
import {
NextResponse
} from "next/server";
// src/matcher.ts
import { match as pathMatch } from "path-to-regexp";
var matcherCache = /* @__PURE__ */ new Map();
var regexCache = /* @__PURE__ */ new Map();
function getMatcherFunction(pattern) {
if (matcherCache.has(pattern)) {
return matcherCache.get(pattern);
}
const fn = pathMatch(pattern, { decode: decodeURIComponent });
matcherCache.set(pattern, fn);
return fn;
}
function getRegex(regexStr) {
if (regexCache.has(regexStr)) return regexCache.get(regexStr);
const re = new RegExp(regexStr);
regexCache.set(regexStr, re);
return re;
}
function matchPath(path, pattern) {
const matcherFn = getMatcherFunction(pattern);
return matcherFn(path) !== false;
}
function checkHasConditions(req, conditions) {
for (const condition of conditions) {
switch (condition.type) {
case "header": {
const headerValue = req.headers.get(condition.key);
if (headerValue === null) return false;
if (condition.value !== void 0 && headerValue !== condition.value)
return false;
break;
}
case "query": {
const queryValue = req.nextUrl.searchParams.get(condition.key);
if (queryValue === null) return false;
if (condition.value !== void 0 && queryValue !== condition.value)
return false;
break;
}
case "cookie": {
const cookie = req.cookies.get(condition.key);
if (!cookie) return false;
if (condition.value !== void 0 && cookie.value !== condition.value)
return false;
break;
}
default:
return false;
}
}
return true;
}
function checkMissingConditions(req, conditions) {
for (const condition of conditions) {
switch (condition.type) {
case "header": {
const headerValue = req.headers.get(condition.key);
if (headerValue !== null) {
if (condition.value === void 0 || headerValue === condition.value)
return false;
}
break;
}
case "query": {
const queryValue = req.nextUrl.searchParams.get(condition.key);
if (queryValue !== null) {
if (condition.value === void 0 || queryValue === condition.value)
return false;
}
break;
}
case "cookie": {
const cookie = req.cookies.get(condition.key);
if (cookie) {
if (condition.value === void 0 || cookie.value === condition.value)
return false;
}
break;
}
default:
return false;
}
}
return true;
}
function matchMatcherCondition(req, condition) {
let pathToMatch = req.nextUrl.pathname;
if (condition.locale === false && req.nextUrl.locale) {
const localePrefix = "/" + req.nextUrl.locale;
if (pathToMatch.startsWith(localePrefix)) {
pathToMatch = pathToMatch.slice(localePrefix.length) || "/";
}
}
if (!matchPath(pathToMatch, condition.source)) {
return false;
}
if (condition.regexp) {
const re = getRegex(condition.regexp);
if (!re.test(pathToMatch)) {
return false;
}
}
if (condition.has && !checkHasConditions(req, condition.has)) {
return false;
}
if (condition.missing && !checkMissingConditions(req, condition.missing)) {
return false;
}
return true;
}
function matchRequest(req, matcher) {
if (!matcher) return true;
const matchers = Array.isArray(matcher) ? matcher : [matcher];
for (const m of matchers) {
if (typeof m === "string") {
if (matchPath(req.nextUrl.pathname, m)) {
return true;
}
} else {
if (matchMatcherCondition(req, m)) {
return true;
}
}
}
return false;
}
// src/index.ts
function middlewares(...modules) {
for (const module of modules) {
if (module.config) {
if (module.config.matcher !== void 0 && (module.config.include !== void 0 || module.config.exclude !== void 0)) {
throw new Error(
"Cannot define both 'matcher' and 'include/exclude' in middleware config."
);
}
}
}
return async function(req, ev) {
for (const module of modules) {
if (module.config) {
if (module.config.matcher !== void 0) {
if (!matchRequest(req, module.config.matcher)) {
continue;
}
} else {
if (module.config.include !== void 0 && !matchRequest(req, module.config.include)) {
continue;
}
if (module.config.exclude !== void 0 && matchRequest(req, module.config.exclude)) {
continue;
}
}
}
const result = await module.middleware(req, ev);
if (result) {
return result;
}
}
return NextResponse.next();
};
}
export {
middlewares
};
//# sourceMappingURL=index.mjs.map