UNPKG

apitally

Version:

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

216 lines 7.55 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 middleware_exports = {}; __export(middleware_exports, { setConsumer: () => setConsumer, useApitally: () => useApitally }); module.exports = __toCommonJS(middleware_exports); var import_node_async_hooks = require("node:async_hooks"); var import_client = require("../common/client.js"); var import_consumerRegistry = require("../common/consumerRegistry.js"); var import_packageVersions = require("../common/packageVersions.js"); var import_requestLogger = require("../common/requestLogger.js"); var import_loggers = require("../loggers/index.js"); function useApitally(app, config) { const client = new import_client.ApitallyClient(config); const middleware = getMiddleware(client); app.use(middleware); const setStartupData = /* @__PURE__ */ __name((attempt = 1) => { const appInfo = getAppInfo(app, config.appVersion); if (appInfo.paths.length > 0 || attempt >= 10) { client.setStartupData(appInfo); client.startSync(); } else { setTimeout(() => setStartupData(attempt + 1), 500); } }, "setStartupData"); setTimeout(() => setStartupData(), 500); } __name(useApitally, "useApitally"); function getMiddleware(client) { const logsContext = new import_node_async_hooks.AsyncLocalStorage(); if (client.requestLogger.config.captureLogs) { (0, import_loggers.patchConsole)(logsContext); (0, import_loggers.patchWinston)(logsContext); } return async (ctx, next) => { if (!client.isEnabled() || ctx.request.method.toUpperCase() === "OPTIONS") { await next(); return; } await logsContext.run([], async () => { var _a; let path; let statusCode; let serverError; const startTime = performance.now(); try { await next(); } catch (error) { path = getPath(ctx); statusCode = error.statusCode || error.status || 500; if (path && statusCode === 500 && error instanceof Error) { serverError = error; client.serverErrorCounter.addServerError({ consumer: (_a = getConsumer(ctx)) == null ? void 0 : _a.identifier, method: ctx.request.method, path, type: error.name, msg: error.message, traceback: error.stack || "" }); } throw error; } finally { const responseTime = performance.now() - startTime; const consumer = getConsumer(ctx); client.consumerRegistry.addOrUpdateConsumer(consumer); if (!path) { path = getPath(ctx); } if (path) { try { client.requestCounter.addRequest({ consumer: consumer == null ? void 0 : consumer.identifier, method: ctx.request.method, path, statusCode: statusCode || ctx.response.status, responseTime, requestSize: ctx.request.length, responseSize: ctx.response.length }); } catch (error) { client.logger.error("Error while logging request in Apitally middleware.", { context: ctx, error }); } } if (client.requestLogger.enabled) { const logs = logsContext.getStore(); client.requestLogger.logRequest({ timestamp: Date.now() / 1e3, method: ctx.request.method, path, url: ctx.request.href, headers: (0, import_requestLogger.convertHeaders)(ctx.request.headers), size: ctx.request.length, consumer: consumer == null ? void 0 : consumer.identifier, body: (0, import_requestLogger.convertBody)(ctx.request.body, ctx.request.get("content-type")) }, { statusCode: statusCode || ctx.response.status, responseTime: responseTime / 1e3, headers: (0, import_requestLogger.convertHeaders)(ctx.response.headers), size: ctx.response.length, body: (0, import_requestLogger.convertBody)(ctx.response.body, ctx.response.get("content-type")) }, serverError, logs); } } }); }; } __name(getMiddleware, "getMiddleware"); function getPath(ctx) { return ctx._matchedRoute || ctx.routePath; } __name(getPath, "getPath"); function setConsumer(ctx, consumer) { ctx.state.apitallyConsumer = consumer || void 0; } __name(setConsumer, "setConsumer"); function getConsumer(ctx) { if (ctx.state.apitallyConsumer) { return (0, import_consumerRegistry.consumerFromStringOrObject)(ctx.state.apitallyConsumer); } else if (ctx.state.consumerIdentifier) { process.emitWarning("The consumerIdentifier property on the ctx.state object is deprecated. Use apitallyConsumer instead.", "DeprecationWarning"); return (0, import_consumerRegistry.consumerFromStringOrObject)(ctx.state.consumerIdentifier); } return null; } __name(getConsumer, "getConsumer"); function getAppInfo(app, appVersion) { const versions = [ [ "nodejs", process.version.replace(/^v/, "") ] ]; const koaVersion = (0, import_packageVersions.getPackageVersion)("koa"); const apitallyVersion = (0, import_packageVersions.getPackageVersion)("../.."); if (koaVersion) { versions.push([ "koa", koaVersion ]); } if (apitallyVersion) { versions.push([ "apitally", apitallyVersion ]); } if (appVersion) { versions.push([ "app", appVersion ]); } return { paths: listEndpoints(app), versions: Object.fromEntries(versions), client: "js:koa" }; } __name(getAppInfo, "getAppInfo"); function isKoaRouterMiddleware(middleware) { return typeof middleware === "function" && middleware.router && Array.isArray(middleware.router.stack); } __name(isKoaRouterMiddleware, "isKoaRouterMiddleware"); function listEndpoints(app) { const endpoints = []; app.middleware.forEach((middleware) => { if (isKoaRouterMiddleware(middleware)) { middleware.router.stack.forEach((layer) => { if (layer.methods && layer.methods.length > 0) { layer.methods.forEach((method) => { if (![ "HEAD", "OPTIONS" ].includes(method.toUpperCase())) { endpoints.push({ method: method.toUpperCase(), path: layer.path }); } }); } }); } }); return endpoints; } __name(listEndpoints, "listEndpoints"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { setConsumer, useApitally }); //# sourceMappingURL=middleware.cjs.map