UNPKG

apitally

Version:

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

202 lines 7.47 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); 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); var utils_exports = {}; __export(utils_exports, { getEndpoints: () => getEndpoints, getRouterInfo: () => getRouterInfo, parseExpressPath: () => parseExpressPath, parseExpressPathRegExp: () => parseExpressPathRegExp }); module.exports = __toCommonJS(utils_exports); const regExpToParseExpressPathRegExp = /^\/\^\\?\/?(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\\?\/?\([^)]+\)\)))\\\/.*/; const regExpToReplaceExpressPathRegExpParams = /\(\?:\\?\/?\([^)]+\)\)/; const regexpExpressParamRegexp = /\(\?:\\?\\?\/?\([^)]+\)\)/g; const regexpExpressPathParamRegexp = /(:[^)]+)\([^)]+\)/g; const EXPRESS_ROOT_PATH_REGEXP_VALUE = "/^\\/?(?=\\/|$)/i"; const STACK_ITEM_VALID_NAMES = [ "router", "bound dispatch", "mounted_app" ]; const 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"); const 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"); const getRouteMiddlewares = /* @__PURE__ */ __name(function(route) { return route.stack.map((item) => { return item.handle.name || "anonymous"; }); }, "getRouteMiddlewares"); const hasParams = /* @__PURE__ */ __name(function(expressPathRegExp) { return regexpExpressParamRegexp.test(expressPathRegExp); }, "hasParams"); const 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"); const 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"); const 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"); const 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"); const 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"); const 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"); const 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"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { getEndpoints, getRouterInfo, parseExpressPath, parseExpressPathRegExp }); //# sourceMappingURL=utils.cjs.map