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
JavaScript
;
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