UNPKG

@velascosoftware/next-api-router

Version:
156 lines (150 loc) 5.16 kB
import { getReasonPhrase, StatusCodes } from 'http-status-codes'; import { NextResponse } from 'next/server'; import { match } from '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 NextResponse.json({ success: false, message: getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), path: reqPath }, { status: 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 = 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 NextResponse.json({ success: false, message: getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR) }, { status: StatusCodes.INTERNAL_SERVER_ERROR }); } } } return NextResponse.json({ sucess: false, message: "Not Found" }, { status: 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 }; } export { ApiRouter, RequestMapping, Use, UseController, createNextRoute, getControllerMiddlewares, getRouteMiddlewares, getRoutes }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map