next-api-middleware
Version:
Middleware solution for Next.js API routes
187 lines (180 loc) • 5.21 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// lib/index.ts
var lib_exports = {};
__export(lib_exports, {
label: () => label,
use: () => use
});
module.exports = __toCommonJS(lib_exports);
// lib/promises.ts
function controlledPromise() {
let resolve;
let reject;
const promise = new Promise((actualResolve, actualReject) => {
resolve = actualResolve;
reject = actualReject;
});
return {
promise,
resolve,
reject
};
}
function isPromise(input) {
return typeof input === "object" && input !== null && "then" in input;
}
// lib/executor.ts
function makeMiddlewareExecutor(middlewareFns) {
return function curryApiHandler(apiRouteFn) {
return async function finalRouteHandler(req, res) {
await new Executor(middlewareFns, apiRouteFn, req, res).run();
};
};
}
var Executor = class {
constructor([currentFn, ...remaining], apiRouteFn, req, res, previousStackPosition) {
this.apiRouteFn = apiRouteFn;
this.req = req;
this.res = res;
this.internalPromise = controlledPromise();
this.succeed = this.internalPromise.resolve;
this.fail = this.internalPromise.reject;
this.teardownPromise = controlledPromise();
this.currentFn = currentFn;
this.remaining = remaining;
this.stackPosition = 1 + (previousStackPosition || 0);
}
async run() {
try {
const cleanupPromise = controlledPromise();
this.result = this.currentFn(this.req, this.res, (error) => {
cleanupPromise.resolve();
if (error) {
throw error;
}
return this.teardownPromise.promise;
});
let asyncMiddlewareFailed = false;
if (isPromise(this.result)) {
this.result.then(
() => {
this.succeed();
},
(err) => {
asyncMiddlewareFailed = true;
cleanupPromise.resolve();
this.fail(err);
}
);
}
await cleanupPromise.promise;
queueMicrotask(() => {
if (!asyncMiddlewareFailed) {
this.runRemaining();
}
});
} catch (err) {
this.fail(err);
}
return this.internalPromise.promise;
}
async runRemaining() {
try {
if (this.remaining.length === 0) {
await this.apiRouteFn(this.req, this.res);
} else {
const remainingExecutor = new Executor(
this.remaining,
this.apiRouteFn,
this.req,
this.res,
this.stackPosition
);
await remainingExecutor.run();
}
this.finish();
} catch (err) {
this.finish(err);
}
}
finish(error) {
if (isPromise(this.result)) {
if (error) {
this.teardownPromise.reject(error);
} else {
this.teardownPromise.resolve();
}
} else {
if (error) {
this.fail(error);
} else {
this.succeed();
}
}
}
};
// lib/validation.ts
function isValidMiddleware(input, throwOnFailure = false) {
const valid = typeof input === "function" && input.length === 3;
if (!valid && throwOnFailure) {
throw new Error("Invalid middleware");
}
return valid;
}
function isValidMiddlewareArray(input, throwOnFailure = false) {
return input.every((item) => isValidMiddleware(item, throwOnFailure));
}
// lib/label.ts
function label(middleware, defaults = []) {
isValidMiddlewareArray(Object.values(middleware).flat(), true);
return function curryMiddlewareChoices(...chosenMiddleware) {
const middlewareFns = [];
for (const choice of [...defaults, ...chosenMiddleware]) {
if (typeof choice === "string") {
const fn = middleware[choice];
if (!fn) {
throw new Error(`Middleware "${choice}" not available`);
}
middlewareFns.push(...Array.isArray(fn) ? fn : [fn]);
continue;
}
if (Array.isArray(choice) && isValidMiddlewareArray(choice, true)) {
middlewareFns.push(...choice);
continue;
}
if (isValidMiddleware(choice, true)) {
middlewareFns.push(choice);
continue;
}
}
return makeMiddlewareExecutor(middlewareFns);
};
}
// lib/use.ts
function use(...middleware) {
const middlewareFns = middleware.flat();
isValidMiddlewareArray(middlewareFns, true);
return makeMiddlewareExecutor(middlewareFns);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
label,
use
});