@velascosoftware/next-api-router
Version:
165 lines (158 loc) • 5.49 kB
JavaScript
var httpStatusCodes = require('http-status-codes');
var server = require('next/server');
var pathToRegexp = require('path-to-regexp');
// src/http/routing/ApiRouter.ts
// src/http/utils/metadata.ts
var store = /* @__PURE__ */ new WeakMap();
function getMap(target) {
let m = store.get(target);
if (!m) {
m = /* @__PURE__ */ new Map();
store.set(target, m);
}
return m;
}
function defineMetadata(key, value, target) {
const R = globalThis.Reflect;
if (R && typeof R.defineMetadata === "function") {
R.defineMetadata(key, value, target);
return;
}
getMap(target).set(key, value);
}
function getMetadata(key, target) {
const R = globalThis.Reflect;
if (R && typeof R.getMetadata === "function") {
return R.getMetadata(key, target);
}
return getMap(target).get(key);
}
// src/http/decorators/RoutingMapping.ts
var routesMetadataKey = Symbol("routes");
var routeMiddlewaresKey = Symbol("route_middlewares");
var controllerMiddlewaresKey = Symbol("controller_middlewares");
function RequestMapping(path, method) {
return function(target, propertyKey) {
const routes = getMetadata(routesMetadataKey, target.constructor) || [];
routes.push({
path,
method,
handlerName: propertyKey
});
defineMetadata(routesMetadataKey, routes, target.constructor);
};
}
function Use(...middlewares) {
return function(target, propertyKey) {
const map = getMetadata(routeMiddlewaresKey, target.constructor) || {};
map[propertyKey] = [...map[propertyKey] || [], ...middlewares];
defineMetadata(routeMiddlewaresKey, map, target.constructor);
};
}
function UseController(...middlewares) {
return function(constructor) {
const list = getMetadata(controllerMiddlewaresKey, constructor) || [];
defineMetadata(controllerMiddlewaresKey, [...list, ...middlewares], constructor);
};
}
function getRoutes(target) {
return getMetadata(routesMetadataKey, target.constructor) || [];
}
function getControllerMiddlewares(target) {
return getMetadata(controllerMiddlewaresKey, target.constructor) || [];
}
function getRouteMiddlewares(target) {
return getMetadata(routeMiddlewaresKey, target.constructor) || {};
}
// src/http/routing/ApiRouter.ts
var ApiRouter = class {
routes = [];
basePath = "";
globalErrorHandler = (err, req) => {
const reqPath = req.nextUrl.pathname;
return server.NextResponse.json({
success: false,
message: httpStatusCodes.getReasonPhrase(httpStatusCodes.StatusCodes.INTERNAL_SERVER_ERROR),
path: reqPath
}, { status: httpStatusCodes.StatusCodes.INTERNAL_SERVER_ERROR });
};
constructor(basePath = "", controller) {
this.basePath = basePath;
const controllerRoutes = getRoutes(controller);
const classMiddlewares = getControllerMiddlewares(controller);
const routeMwsMap = getRouteMiddlewares(controller);
for (const route of controllerRoutes) {
const fullPath = `${this.basePath}${route.path}`.replace(/\/+$/, "");
const matcher = pathToRegexp.match(fullPath, { decode: decodeURIComponent });
const handler = controller[route.handlerName].bind(controller);
const methodMiddlewares = routeMwsMap[route.handlerName] || [];
this.routes.push({
method: route.method,
path: fullPath,
matcher,
handlers: [...classMiddlewares, ...methodMiddlewares, handler]
});
}
}
onError(handler) {
this.globalErrorHandler = handler;
}
async handle(req) {
const reqMethod = req.method?.toUpperCase();
const reqPath = req.nextUrl.pathname.replace(/^\/api/, "");
for (const route of this.routes) {
if (route.method !== reqMethod) continue;
const match = route.matcher(reqPath);
if (match) {
const params = match.params;
const stack = [...route.handlers];
const execute = async (i) => {
if (i < stack.length - 1) {
return stack[i](req, params, () => execute(i + 1));
}
return stack[i](req, params, () => execute(i));
};
try {
return await execute(0);
} catch (err) {
if (route.onError) {
return await route.onError(err, req, params);
}
if (this.globalErrorHandler) {
return await this.globalErrorHandler(err, req, params);
}
return server.NextResponse.json({
success: false,
message: httpStatusCodes.getReasonPhrase(httpStatusCodes.StatusCodes.INTERNAL_SERVER_ERROR)
}, { status: httpStatusCodes.StatusCodes.INTERNAL_SERVER_ERROR });
}
}
}
return server.NextResponse.json({ sucess: false, message: "Not Found" }, { status: httpStatusCodes.StatusCodes.NOT_FOUND });
}
};
// src/next/createNextRoute.ts
function createNextRoute(controller, basePath = "") {
const router = new ApiRouter(basePath, controller);
const handle = (req) => router.handle(req);
return {
GET: handle,
POST: handle,
PUT: handle,
PATCH: handle,
DELETE: handle,
OPTIONS: handle,
HEAD: handle
};
}
exports.ApiRouter = ApiRouter;
exports.RequestMapping = RequestMapping;
exports.Use = Use;
exports.UseController = UseController;
exports.createNextRoute = createNextRoute;
exports.getControllerMiddlewares = getControllerMiddlewares;
exports.getRouteMiddlewares = getRouteMiddlewares;
exports.getRoutes = getRoutes;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map
;