UNPKG

apitally

Version:

Simple API monitoring & analytics for REST APIs built with Express, Fastify, NestJS, AdonisJS, Hono, H3, Elysia, and Koa.

178 lines (177 loc) 6.35 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/express/utils.js var regExpToParseExpressPathRegExp = /^\/\^\\?\/?(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\\?\/?\([^)]+\)\)))\\\/.*/; var regExpToReplaceExpressPathRegExpParams = /\(\?:\\?\/?\([^)]+\)\)/; var regexpExpressParamRegexp = /\(\?:\\?\\?\/?\([^)]+\)\)/g; var regexpExpressPathParamRegexp = /(:[^)]+)\([^)]+\)/g; var EXPRESS_ROOT_PATH_REGEXP_VALUE = "/^\\/?(?=\\/|$)/i"; var STACK_ITEM_VALID_NAMES = [ "router", "bound dispatch", "mounted_app" ]; var getRouterInfo = /* @__PURE__ */ __name(function(app) { var _a, _b; if (app.stack) { return { stack: app.stack, version: "v4" }; } else if ((_a = app._router) == null ? void 0 : _a.stack) { return { stack: app._router.stack, version: "v4" }; } else if ((_b = app.router) == null ? void 0 : _b.stack) { return { stack: app.router.stack, version: "v5" }; } return { stack: null, version: "v4" }; }, "getRouterInfo"); var getRouteMethods = /* @__PURE__ */ __name(function(route) { let methods = Object.keys(route.methods); methods = methods.filter((method) => method !== "_all"); methods = methods.map((method) => method.toUpperCase()); return methods; }, "getRouteMethods"); var getRouteMiddlewares = /* @__PURE__ */ __name(function(route) { return route.stack.map((item) => { return item.handle.name || "anonymous"; }); }, "getRouteMiddlewares"); var hasParams = /* @__PURE__ */ __name(function(expressPathRegExp) { return regexpExpressParamRegexp.test(expressPathRegExp); }, "hasParams"); var parseExpressRoute = /* @__PURE__ */ __name(function(route, basePath) { const paths = []; if (Array.isArray(route.path)) { paths.push(...route.path); } else { paths.push(route.path); } const endpoints = paths.map((path) => { const completePath = basePath && path === "/" ? basePath : `${basePath}${path}`; const endpoint = { path: completePath.replace(regexpExpressPathParamRegexp, "$1"), methods: getRouteMethods(route), middlewares: getRouteMiddlewares(route) }; return endpoint; }); return endpoints; }, "parseExpressRoute"); var parseExpressPathRegExp = /* @__PURE__ */ __name(function(expressPathRegExp, keys) { let parsedRegExp = expressPathRegExp.toString(); let expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp); let paramIndex = 0; while (hasParams(parsedRegExp)) { const paramName = keys[paramIndex].name; const paramId = `:${paramName}`; parsedRegExp = parsedRegExp.replace(regExpToReplaceExpressPathRegExpParams, (str) => { if (str.startsWith("(?:\\/")) { return `\\/${paramId}`; } return paramId; }); paramIndex++; } if (parsedRegExp !== expressPathRegExp.toString()) { expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp); } return expressPathRegExpExec[1].replace(/\\\//g, "/"); }, "parseExpressPathRegExp"); var parseExpressPath = /* @__PURE__ */ __name(function(expressPath, params) { let result = expressPath; for (const [paramName, paramValue] of Object.entries(params)) { result = result.replace(paramValue, `:${paramName}`); } return result; }, "parseExpressPath"); var parseEndpoints = /* @__PURE__ */ __name(function(app, basePath, endpoints) { const routerInfo = getRouterInfo(app); const stack = routerInfo.stack; const version = routerInfo.version; endpoints = endpoints || []; basePath = basePath || ""; if (!stack) { if (endpoints.length) { endpoints = addEndpoints(endpoints, [ { path: basePath, methods: [], middlewares: [] } ]); } } else { endpoints = parseStack(stack, basePath, endpoints, version); } return endpoints; }, "parseEndpoints"); var addEndpoints = /* @__PURE__ */ __name(function(currentEndpoints, endpointsToAdd) { endpointsToAdd.forEach((newEndpoint) => { const existingEndpoint = currentEndpoints.find((endpoint) => endpoint.path === newEndpoint.path); if (existingEndpoint !== void 0) { const newMethods = newEndpoint.methods.filter((method) => !existingEndpoint.methods.includes(method)); existingEndpoint.methods = existingEndpoint.methods.concat(newMethods); } else { currentEndpoints.push(newEndpoint); } }); return currentEndpoints; }, "addEndpoints"); var parseStack = /* @__PURE__ */ __name(function(stack, basePath, endpoints, version) { stack.forEach((stackItem) => { if (stackItem.route) { const newEndpoints = parseExpressRoute(stackItem.route, basePath); endpoints = addEndpoints(endpoints, newEndpoints); } else if (STACK_ITEM_VALID_NAMES.includes(stackItem.name)) { let newBasePath = basePath; if (version === "v4") { const isExpressPathRegExp = regExpToParseExpressPathRegExp.test(stackItem.regexp); if (isExpressPathRegExp) { const parsedPath = parseExpressPathRegExp(stackItem.regexp, stackItem.keys); newBasePath += `/${parsedPath}`; } else if (!stackItem.path && stackItem.regexp && stackItem.regexp.toString() !== EXPRESS_ROOT_PATH_REGEXP_VALUE) { const regExpPath = `RegExp(${stackItem.regexp})`; newBasePath += `/${regExpPath}`; } } else if (version === "v5") { if (!stackItem.path) { return; } else if (stackItem.path !== "/") { newBasePath += stackItem.path.startsWith("/") ? stackItem.path : `/${stackItem.path}`; } } endpoints = parseEndpoints(stackItem.handle, newBasePath, endpoints); } }); return endpoints; }, "parseStack"); var getEndpoints = /* @__PURE__ */ __name(function(app, basePath) { const endpoints = parseEndpoints(app); const standardHttpMethods = [ "GET", "POST", "PUT", "DELETE", "PATCH" ]; return endpoints.flatMap((route) => route.methods.filter((method) => standardHttpMethods.includes(method.toUpperCase())).map((method) => ({ method, path: (basePath + route.path).replace(/\/\//g, "/") }))); }, "getEndpoints"); export { getEndpoints, getRouterInfo, parseExpressPath, parseExpressPathRegExp }; //# sourceMappingURL=utils.js.map