{"version":3,"sources":["../../src/express/index.ts","../../src/express/middleware.ts","../../src/common/client.ts","../../src/common/consumerRegistry.ts","../../src/common/logging.ts","../../src/common/paramValidation.ts","../../src/common/requestCounter.ts","../../src/common/requestLogger.ts","../../src/common/sentry.ts","../../src/common/serverErrorCounter.ts","../../src/common/tempGzipFile.ts","../../src/common/validationErrorCounter.ts","../../src/common/packageVersions.ts","../../src/common/utils.ts","../../src/express/utils.js"],"sourcesContent":["export type { ApitallyConsumer } from \"../common/types.js\";\nexport { useApitally } from \"./middleware.js\";\n","import type { Express, NextFunction, Request, Response, Router } from \"express\";\nimport { performance } from \"perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport {\n  ApitallyConfig,\n  ApitallyConsumer,\n  StartupData,\n  ValidationError,\n} from \"../common/types.js\";\nimport { parseContentLength } from \"../common/utils.js\";\nimport { getEndpoints, parseExpressPath } from \"./utils.js\";\n\ndeclare module \"express\" {\n  interface Request {\n    apitallyConsumer?: ApitallyConsumer | string | null;\n    consumerIdentifier?: ApitallyConsumer | string | null; // For backwards compatibility\n  }\n}\n\nexport const useApitally = (\n  app: Express | Router,\n  config: ApitallyConfig & { basePath?: string },\n) => {\n  const client = new ApitallyClient(config);\n  const middleware = getMiddleware(app, client);\n  app.use(middleware);\n  setTimeout(() => {\n    client.setStartupData(getAppInfo(app, config.basePath, config.appVersion));\n  }, 1000);\n};\n\nconst getMiddleware = (app: Express | Router, client: ApitallyClient) => {\n  let errorHandlerConfigured = false;\n\n  return (req: Request, res: Response, next: NextFunction) => {\n    if (!client.isEnabled()) {\n      next();\n      return;\n    }\n    if (!errorHandlerConfigured) {\n      // Add error handling middleware to the bottom of the stack when handling the first request\n      app.use(\n        (err: Error, req: Request, res: Response, next: NextFunction): void => {\n          res.locals.serverError = err;\n          next(err);\n        },\n      );\n      errorHandlerConfigured = true;\n    }\n    try {\n      const startTime = performance.now();\n      const originalSend = res.send;\n      res.send = (body) => {\n        const contentType = res.get(\"content-type\");\n        if (client.requestLogger.isSupportedContentType(contentType)) {\n          res.locals.body = body;\n        }\n        return originalSend.call(res, body);\n      };\n\n      res.on(\"finish\", () => {\n        try {\n          const responseTime = performance.now() - startTime;\n          const path = getRoutePath(req);\n          const consumer = getConsumer(req);\n          client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n          const requestSize = parseContentLength(req.get(\"content-length\"));\n          const responseSize = parseContentLength(res.get(\"content-length\"));\n\n          if (path) {\n            client.requestCounter.addRequest({\n              consumer: consumer?.identifier,\n              method: req.method,\n              path,\n              statusCode: res.statusCode,\n              responseTime: responseTime,\n              requestSize,\n              responseSize,\n            });\n            if (\n              (res.statusCode === 400 || res.statusCode === 422) &&\n              res.locals.body\n            ) {\n              let jsonBody: any;\n              try {\n                jsonBody = JSON.parse(res.locals.body);\n              } catch {\n                // Ignore\n              }\n              if (jsonBody) {\n                const validationErrors: ValidationError[] = [];\n                if (validationErrors.length === 0) {\n                  validationErrors.push(\n                    ...extractExpressValidatorErrors(jsonBody),\n                  );\n                }\n                if (validationErrors.length === 0) {\n                  validationErrors.push(...extractCelebrateErrors(jsonBody));\n                }\n                if (validationErrors.length === 0) {\n                  validationErrors.push(\n                    ...extractNestValidationErrors(jsonBody),\n                  );\n                }\n                validationErrors.forEach((error) => {\n                  client.validationErrorCounter.addValidationError({\n                    consumer: consumer?.identifier,\n                    method: req.method,\n                    path: req.route.path,\n                    ...error,\n                  });\n                });\n              }\n            }\n            if (res.statusCode === 500 && res.locals.serverError) {\n              const serverError = res.locals.serverError as Error;\n              client.serverErrorCounter.addServerError({\n                consumer: consumer?.identifier,\n                method: req.method,\n                path: req.route.path,\n                type: serverError.name,\n                msg: serverError.message,\n                traceback: serverError.stack || \"\",\n              });\n            }\n          }\n          if (client.requestLogger.enabled) {\n            client.requestLogger.logRequest(\n              {\n                timestamp: Date.now() / 1000,\n                method: req.method,\n                path,\n                url: `${req.protocol}://${req.host}${req.originalUrl}`,\n                headers: convertHeaders(req.headers),\n                size: requestSize,\n                consumer: consumer?.identifier,\n                body: convertBody(req.body, req.get(\"content-type\")),\n              },\n              {\n                statusCode: res.statusCode,\n                responseTime: responseTime / 1000,\n                headers: convertHeaders(res.getHeaders()),\n                size: responseSize,\n                body: convertBody(res.locals.body, res.get(\"content-type\")),\n              },\n              res.locals.serverError,\n            );\n          }\n        } catch (error) {\n          client.logger.error(\n            \"Error while logging request in Apitally middleware.\",\n            { request: req, response: res, error },\n          );\n        }\n      });\n    } catch (error) {\n      client.logger.error(\"Error in Apitally middleware.\", {\n        request: req,\n        response: res,\n        error,\n      });\n    } finally {\n      next();\n    }\n  };\n};\n\nconst getRoutePath = (req: Request) => {\n  if (!req.route) {\n    return;\n  }\n  if (req.baseUrl) {\n    const routerPath = getRouterPath(req.app._router.stack, req.baseUrl);\n    return req.route.path === \"/\" ? routerPath : routerPath + req.route.path;\n  }\n  return req.route.path;\n};\n\nconst getRouterPath = (stack: any[], baseUrl: string) => {\n  const routerPaths: string[] = [];\n  while (stack && stack.length > 0) {\n    const routerLayer = stack.find(\n      (layer) =>\n        layer.name === \"router\" && layer.path && layer.regexp?.test(baseUrl),\n    );\n    if (routerLayer) {\n      if (routerLayer.keys.length > 0) {\n        const parsedPath = parseExpressPath(\n          routerLayer.regexp,\n          routerLayer.keys,\n        );\n        routerPaths.push(\"/\" + parsedPath);\n      } else {\n        routerPaths.push(routerLayer.path);\n      }\n      stack = routerLayer.handle?.stack;\n      baseUrl = baseUrl.slice(routerLayer.path.length);\n    } else {\n      break;\n    }\n  }\n  return routerPaths.filter((path) => path !== \"/\").join(\"\");\n};\n\nconst getConsumer = (req: Request) => {\n  if (req.apitallyConsumer) {\n    return consumerFromStringOrObject(req.apitallyConsumer);\n  } else if (req.consumerIdentifier) {\n    // For backwards compatibility\n    process.emitWarning(\n      \"The consumerIdentifier property on the request object is deprecated. Use apitallyConsumer instead.\",\n      \"DeprecationWarning\",\n    );\n    return consumerFromStringOrObject(req.consumerIdentifier);\n  }\n  return null;\n};\n\nconst extractExpressValidatorErrors = (responseBody: any) => {\n  try {\n    const errors: ValidationError[] = [];\n    if (\n      responseBody &&\n      responseBody.errors &&\n      Array.isArray(responseBody.errors)\n    ) {\n      responseBody.errors.forEach((error: any) => {\n        if (error.location && error.path && error.msg && error.type) {\n          errors.push({\n            loc: `${error.location}.${error.path}`,\n            msg: error.msg,\n            type: error.type,\n          });\n        }\n      });\n    }\n    return errors;\n  } catch (error) {\n    return [];\n  }\n};\n\nconst extractCelebrateErrors = (responseBody: any) => {\n  try {\n    const errors: ValidationError[] = [];\n    if (responseBody && responseBody.validation) {\n      Object.values(responseBody.validation).forEach((error: any) => {\n        if (\n          error.source &&\n          error.keys &&\n          Array.isArray(error.keys) &&\n          error.message\n        ) {\n          error.keys.forEach((key: string) => {\n            errors.push({\n              loc: `${error.source}.${key}`,\n              msg: subsetJoiMessage(error.message, key),\n              type: \"\",\n            });\n          });\n        }\n      });\n    }\n    return errors;\n  } catch (error) {\n    return [];\n  }\n};\n\nconst extractNestValidationErrors = (responseBody: any) => {\n  try {\n    const errors: ValidationError[] = [];\n    if (responseBody && Array.isArray(responseBody.message)) {\n      responseBody.message.forEach((message: any) => {\n        errors.push({\n          loc: \"\",\n          msg: message,\n          type: \"\",\n        });\n      });\n    }\n    return errors;\n  } catch (error) {\n    return [];\n  }\n};\n\nconst subsetJoiMessage = (message: string, key: string) => {\n  const messageWithKey = message\n    .split(\". \")\n    .find((message) => message.includes(`\"${key}\"`));\n  return messageWithKey ? messageWithKey : message;\n};\n\nconst getAppInfo = (\n  app: Express | Router,\n  basePath?: string,\n  appVersion?: string,\n): StartupData => {\n  const versions: Array<[string, string]> = [\n    [\"nodejs\", process.version.replace(/^v/, \"\")],\n  ];\n  const expressVersion = getPackageVersion(\"express\");\n  const nestjsVersion = getPackageVersion(\"@nestjs/core\");\n  const apitallyVersion = getPackageVersion(\"../..\");\n  if (expressVersion) {\n    versions.push([\"express\", expressVersion]);\n  }\n  if (nestjsVersion) {\n    versions.push([\"nestjs\", nestjsVersion]);\n  }\n  if (apitallyVersion) {\n    versions.push([\"apitally\", apitallyVersion]);\n  }\n  if (appVersion) {\n    versions.push([\"app\", appVersion]);\n  }\n  return {\n    paths: getEndpoints(app, basePath || \"\"),\n    versions: Object.fromEntries(versions),\n    client: \"js:express\",\n  };\n};\n","import { randomUUID } from \"crypto\";\nimport fetchRetry from \"fetch-retry\";\n\nimport ConsumerRegistry from \"./consumerRegistry.js\";\nimport { Logger, getLogger } from \"./logging.js\";\nimport { isValidClientId, isValidEnv } from \"./paramValidation.js\";\nimport RequestCounter from \"./requestCounter.js\";\nimport RequestLogger from \"./requestLogger.js\";\nimport ServerErrorCounter from \"./serverErrorCounter.js\";\nimport {\n  ApitallyConfig,\n  StartupData,\n  StartupPayload,\n  SyncPayload,\n} from \"./types.js\";\nimport ValidationErrorCounter from \"./validationErrorCounter.js\";\n\nconst SYNC_INTERVAL = 60000; // 60 seconds\nconst INITIAL_SYNC_INTERVAL = 10000; // 10 seconds\nconst INITIAL_SYNC_INTERVAL_DURATION = 3600000; // 1 hour\nconst MAX_QUEUE_TIME = 3.6e6; // 1 hour\n\nclass HTTPError extends Error {\n  public response: Response;\n\n  constructor(response: Response) {\n    const reason = response.status\n      ? `status code ${response.status}`\n      : \"an unknown error\";\n    super(`Request failed with ${reason}`);\n    this.response = response;\n  }\n}\n\nexport class ApitallyClient {\n  private clientId: string;\n  private env: string;\n\n  private static instance?: ApitallyClient;\n  private instanceUuid: string;\n  private syncDataQueue: SyncPayload[];\n  private syncIntervalId?: NodeJS.Timeout;\n  public startupData?: StartupData;\n  private startupDataSent: boolean = false;\n  private enabled: boolean = true;\n\n  public requestCounter: RequestCounter;\n  public requestLogger: RequestLogger;\n  public validationErrorCounter: ValidationErrorCounter;\n  public serverErrorCounter: ServerErrorCounter;\n  public consumerRegistry: ConsumerRegistry;\n  public logger: Logger;\n\n  constructor({\n    clientId,\n    env = \"dev\",\n    requestLoggingConfig,\n    logger,\n  }: ApitallyConfig) {\n    if (ApitallyClient.instance) {\n      throw new Error(\"Apitally client is already initialized\");\n    }\n    if (!isValidClientId(clientId)) {\n      throw new Error(\n        `Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`,\n      );\n    }\n    if (!isValidEnv(env)) {\n      throw new Error(\n        `Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`,\n      );\n    }\n\n    ApitallyClient.instance = this;\n    this.clientId = clientId;\n    this.env = env;\n    this.instanceUuid = randomUUID();\n    this.syncDataQueue = [];\n    this.requestCounter = new RequestCounter();\n    this.requestLogger = new RequestLogger(requestLoggingConfig);\n    this.validationErrorCounter = new ValidationErrorCounter();\n    this.serverErrorCounter = new ServerErrorCounter();\n    this.consumerRegistry = new ConsumerRegistry();\n    this.logger = logger || getLogger();\n\n    this.startSync();\n    this.handleShutdown = this.handleShutdown.bind(this);\n  }\n\n  public static getInstance() {\n    if (!ApitallyClient.instance) {\n      throw new Error(\"Apitally client is not initialized\");\n    }\n    return ApitallyClient.instance;\n  }\n\n  public isEnabled() {\n    return this.enabled;\n  }\n\n  public static async shutdown() {\n    if (ApitallyClient.instance) {\n      await ApitallyClient.instance.handleShutdown();\n    }\n  }\n\n  public async handleShutdown() {\n    this.enabled = false;\n    this.stopSync();\n    await this.sendSyncData();\n    await this.sendLogData();\n    await this.requestLogger.close();\n    ApitallyClient.instance = undefined;\n  }\n\n  private getHubUrlPrefix() {\n    const baseURL =\n      process.env.APITALLY_HUB_BASE_URL || \"https://hub.apitally.io\";\n    const version = \"v2\";\n    return `${baseURL}/${version}/${this.clientId}/${this.env}/`;\n  }\n\n  private async sendData(url: string, payload: any) {\n    const fetchWithRetry = fetchRetry(fetch, {\n      retries: 3,\n      retryDelay: 1000,\n      retryOn: [408, 429, 500, 502, 503, 504],\n    });\n    const response = await fetchWithRetry(this.getHubUrlPrefix() + url, {\n      method: \"POST\",\n      body: JSON.stringify(payload),\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n    if (!response.ok) {\n      throw new HTTPError(response);\n    }\n  }\n\n  private startSync() {\n    this.sync();\n    this.syncIntervalId = setInterval(() => {\n      this.sync();\n    }, INITIAL_SYNC_INTERVAL);\n    setTimeout(() => {\n      clearInterval(this.syncIntervalId);\n      this.syncIntervalId = setInterval(() => {\n        this.sync();\n      }, SYNC_INTERVAL);\n    }, INITIAL_SYNC_INTERVAL_DURATION);\n  }\n\n  private async sync() {\n    try {\n      const promises = [this.sendSyncData(), this.sendLogData()];\n      if (!this.startupDataSent) {\n        promises.push(this.sendStartupData());\n      }\n      await Promise.all(promises);\n    } catch (error) {\n      this.logger.error(\"Error while syncing with Apitally Hub\", {\n        error,\n      });\n    }\n  }\n\n  private stopSync() {\n    if (this.syncIntervalId) {\n      clearInterval(this.syncIntervalId);\n      this.syncIntervalId = undefined;\n    }\n  }\n\n  public setStartupData(data: StartupData) {\n    this.startupData = data;\n    this.startupDataSent = false;\n    this.sendStartupData();\n  }\n\n  private async sendStartupData() {\n    if (this.startupData) {\n      this.logger.debug(\"Sending startup data to Apitally Hub\");\n      const payload: StartupPayload = {\n        instance_uuid: this.instanceUuid,\n        message_uuid: randomUUID(),\n        ...this.startupData,\n      };\n      try {\n        await this.sendData(\"startup\", payload);\n        this.startupDataSent = true;\n      } catch (error) {\n        const handled = this.handleHubError(error);\n        if (!handled) {\n          this.logger.error((error as Error).message);\n          this.logger.debug(\n            \"Error while sending startup data to Apitally Hub (will retry)\",\n            { error },\n          );\n        }\n      }\n    }\n  }\n\n  private async sendSyncData() {\n    this.logger.debug(\"Synchronizing data with Apitally Hub\");\n    const newPayload: SyncPayload = {\n      timestamp: Date.now() / 1000,\n      instance_uuid: this.instanceUuid,\n      message_uuid: randomUUID(),\n      requests: this.requestCounter.getAndResetRequests(),\n      validation_errors:\n        this.validationErrorCounter.getAndResetValidationErrors(),\n      server_errors: this.serverErrorCounter.getAndResetServerErrors(),\n      consumers: this.consumerRegistry.getAndResetUpdatedConsumers(),\n    };\n    this.syncDataQueue.push(newPayload);\n\n    let i = 0;\n    while (this.syncDataQueue.length > 0) {\n      const payload = this.syncDataQueue.shift();\n      if (payload) {\n        try {\n          if (Date.now() - payload.timestamp * 1000 <= MAX_QUEUE_TIME) {\n            if (i > 0) {\n              await this.randomDelay();\n            }\n            await this.sendData(\"sync\", payload);\n            i += 1;\n          }\n        } catch (error) {\n          const handled = this.handleHubError(error);\n          if (!handled) {\n            this.logger.debug(\n              \"Error while synchronizing data with Apitally Hub (will retry)\",\n              { error },\n            );\n            this.syncDataQueue.push(payload);\n            break;\n          }\n        }\n      }\n    }\n  }\n\n  private async sendLogData() {\n    this.logger.debug(\"Sending request log data to Apitally Hub\");\n    await this.requestLogger.rotateFile();\n\n    const fetchWithRetry = fetchRetry(fetch, {\n      retries: 3,\n      retryDelay: 1000,\n      retryOn: [408, 429, 500, 502, 503, 504],\n    });\n\n    let i = 0;\n    let logFile;\n    while ((logFile = this.requestLogger.getFile())) {\n      if (i > 0) {\n        await this.randomDelay();\n      }\n\n      try {\n        const response = await fetchWithRetry(\n          `${this.getHubUrlPrefix()}log?uuid=${logFile.uuid}`,\n          {\n            method: \"POST\",\n            body: await logFile.getContent(),\n          },\n        );\n\n        if (response.status === 402 && response.headers.has(\"Retry-After\")) {\n          const retryAfter = parseInt(\n            response.headers.get(\"Retry-After\") ?? \"0\",\n          );\n          if (retryAfter > 0) {\n            this.requestLogger.suspendUntil = Date.now() + retryAfter * 1000;\n            this.requestLogger.clear();\n            return;\n          }\n        }\n\n        if (!response.ok) {\n          throw new HTTPError(response);\n        }\n\n        logFile.delete();\n      } catch (error) {\n        this.requestLogger.retryFileLater(logFile);\n        break;\n      }\n\n      i++;\n      if (i >= 10) break;\n    }\n  }\n\n  private handleHubError(error: unknown) {\n    if (error instanceof HTTPError) {\n      if (error.response.status === 404) {\n        this.logger.error(`Invalid Apitally client ID: '${this.clientId}'`);\n        this.enabled = false;\n        this.stopSync();\n        return true;\n      }\n      if (error.response.status === 422) {\n        this.logger.error(\"Received validation error from Apitally Hub\");\n        return true;\n      }\n    }\n    return false;\n  }\n\n  private async randomDelay() {\n    const delay = 100 + Math.random() * 400;\n    await new Promise((resolve) => setTimeout(resolve, delay));\n  }\n}\n","import { ApitallyConsumer } from \"./types.js\";\n\nexport const consumerFromStringOrObject = (\n  consumer: ApitallyConsumer | string,\n) => {\n  if (typeof consumer === \"string\") {\n    consumer = String(consumer).trim().substring(0, 128);\n    return consumer ? { identifier: consumer } : null;\n  } else {\n    consumer.identifier = String(consumer.identifier).trim().substring(0, 128);\n    consumer.name = consumer.name?.trim().substring(0, 64);\n    consumer.group = consumer.group?.trim().substring(0, 64);\n    return consumer.identifier ? consumer : null;\n  }\n};\n\nexport default class ConsumerRegistry {\n  private consumers: Map<string, ApitallyConsumer>;\n  private updated: Set<string>;\n\n  constructor() {\n    this.consumers = new Map();\n    this.updated = new Set();\n  }\n\n  public addOrUpdateConsumer(consumer?: ApitallyConsumer | null) {\n    if (!consumer || (!consumer.name && !consumer.group)) {\n      return;\n    }\n    const existing = this.consumers.get(consumer.identifier);\n    if (!existing) {\n      this.consumers.set(consumer.identifier, consumer);\n      this.updated.add(consumer.identifier);\n    } else {\n      if (consumer.name && consumer.name !== existing.name) {\n        existing.name = consumer.name;\n        this.updated.add(consumer.identifier);\n      }\n      if (consumer.group && consumer.group !== existing.group) {\n        existing.group = consumer.group;\n        this.updated.add(consumer.identifier);\n      }\n    }\n  }\n\n  public getAndResetUpdatedConsumers() {\n    const data: Array<ApitallyConsumer> = [];\n    this.updated.forEach((identifier) => {\n      const consumer = this.consumers.get(identifier);\n      if (consumer) {\n        data.push(consumer);\n      }\n    });\n    this.updated.clear();\n    return data;\n  }\n}\n","import { createLogger, format, transports } from \"winston\";\n\nexport interface Logger {\n  debug: (message: string, meta?: object) => void;\n  info: (message: string, meta?: object) => void;\n  warn: (message: string, meta?: object) => void;\n  error: (message: string, meta?: object) => void;\n}\n\nexport const getLogger = () => {\n  return createLogger({\n    level: process.env.APITALLY_DEBUG ? \"debug\" : \"warn\",\n    format: format.combine(\n      format.colorize(),\n      format.timestamp(),\n      format.printf(\n        (info) => `${info.timestamp} ${info.level}: ${info.message}`,\n      ),\n    ),\n    transports: [new transports.Console()],\n  });\n};\n","export function isValidClientId(clientId: string): boolean {\n  const regexExp =\n    /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n  return regexExp.test(clientId);\n}\n\nexport function isValidEnv(env: string): boolean {\n  const regexExp = /^[\\w-]{1,32}$/;\n  return regexExp.test(env);\n}\n","import { RequestInfo, RequestsItem } from \"./types.js\";\n\nexport default class RequestCounter {\n  private requestCounts: Map<string, number>;\n  private requestSizeSums: Map<string, number>;\n  private responseSizeSums: Map<string, number>;\n  private responseTimes: Map<string, Map<number, number>>;\n  private requestSizes: Map<string, Map<number, number>>;\n  private responseSizes: Map<string, Map<number, number>>;\n\n  constructor() {\n    this.requestCounts = new Map<string, number>();\n    this.requestSizeSums = new Map<string, number>();\n    this.responseSizeSums = new Map<string, number>();\n    this.responseTimes = new Map<string, Map<number, number>>();\n    this.requestSizes = new Map<string, Map<number, number>>();\n    this.responseSizes = new Map<string, Map<number, number>>();\n  }\n\n  private getKey(requestInfo: RequestInfo) {\n    return [\n      requestInfo.consumer || \"\",\n      requestInfo.method.toUpperCase(),\n      requestInfo.path,\n      requestInfo.statusCode,\n    ].join(\"|\");\n  }\n\n  addRequest(requestInfo: RequestInfo) {\n    const key = this.getKey(requestInfo);\n\n    // Increment request count\n    this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);\n\n    // Add response time\n    if (!this.responseTimes.has(key)) {\n      this.responseTimes.set(key, new Map<number, number>());\n    }\n    const responseTimeMap = this.responseTimes.get(key)!;\n    const responseTimeMsBin = Math.floor(requestInfo.responseTime / 10) * 10; // Rounded to nearest 10ms\n    responseTimeMap.set(\n      responseTimeMsBin,\n      (responseTimeMap.get(responseTimeMsBin) || 0) + 1,\n    );\n\n    // Add request size\n    if (requestInfo.requestSize !== undefined) {\n      requestInfo.requestSize = Number(requestInfo.requestSize);\n      this.requestSizeSums.set(\n        key,\n        (this.requestSizeSums.get(key) || 0) + requestInfo.requestSize,\n      );\n      if (!this.requestSizes.has(key)) {\n        this.requestSizes.set(key, new Map<number, number>());\n      }\n      const requestSizeMap = this.requestSizes.get(key)!;\n      const requestSizeKbBin = Math.floor(requestInfo.requestSize / 1000); // Rounded down to nearest KB\n      requestSizeMap.set(\n        requestSizeKbBin,\n        (requestSizeMap.get(requestSizeKbBin) || 0) + 1,\n      );\n    }\n\n    // Add response size\n    if (requestInfo.responseSize !== undefined) {\n      requestInfo.responseSize = Number(requestInfo.responseSize);\n      this.responseSizeSums.set(\n        key,\n        (this.responseSizeSums.get(key) || 0) + requestInfo.responseSize,\n      );\n      if (!this.responseSizes.has(key)) {\n        this.responseSizes.set(key, new Map<number, number>());\n      }\n      const responseSizeMap = this.responseSizes.get(key)!;\n      const responseSizeKbBin = Math.floor(requestInfo.responseSize / 1000); // Rounded down to nearest KB\n      responseSizeMap.set(\n        responseSizeKbBin,\n        (responseSizeMap.get(responseSizeKbBin) || 0) + 1,\n      );\n    }\n  }\n\n  getAndResetRequests() {\n    const data: Array<RequestsItem> = [];\n    this.requestCounts.forEach((count, key) => {\n      const [consumer, method, path, statusCodeStr] = key.split(\"|\");\n      const responseTimes =\n        this.responseTimes.get(key) || new Map<number, number>();\n      const requestSizes =\n        this.requestSizes.get(key) || new Map<number, number>();\n      const responseSizes =\n        this.responseSizes.get(key) || new Map<number, number>();\n      data.push({\n        consumer: consumer || null,\n        method,\n        path,\n        status_code: parseInt(statusCodeStr),\n        request_count: count,\n        request_size_sum: this.requestSizeSums.get(key) || 0,\n        response_size_sum: this.responseSizeSums.get(key) || 0,\n        response_times: Object.fromEntries(responseTimes),\n        request_sizes: Object.fromEntries(requestSizes),\n        response_sizes: Object.fromEntries(responseSizes),\n      });\n    });\n\n    // Reset the counts and times\n    this.requestCounts.clear();\n    this.requestSizeSums.clear();\n    this.responseSizeSums.clear();\n    this.responseTimes.clear();\n    this.requestSizes.clear();\n    this.responseSizes.clear();\n\n    return data;\n  }\n}\n","import AsyncLock from \"async-lock\";\nimport { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { unlinkSync, writeFileSync } from \"fs\";\nimport { IncomingHttpHeaders, OutgoingHttpHeaders } from \"http\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport {\n  truncateExceptionMessage,\n  truncateExceptionStackTrace,\n} from \"./serverErrorCounter.js\";\nimport TempGzipFile from \"./tempGzipFile.js\";\n\nconst MAX_BODY_SIZE = 50_000; // 50 KB (uncompressed)\nconst MAX_FILE_SIZE = 1_000_000; // 1 MB (compressed)\nconst MAX_FILES = 50;\nconst MAX_PENDING_WRITES = 100;\nconst BODY_TOO_LARGE = Buffer.from(\"<body too large>\");\nconst BODY_MASKED = Buffer.from(\"<masked>\");\nconst MASKED = \"******\";\nconst ALLOWED_CONTENT_TYPES = [\"application/json\", \"text/plain\"];\nconst EXCLUDE_PATH_PATTERNS = [\n  /\\/_?healthz?$/i,\n  /\\/_?health[_-]?checks?$/i,\n  /\\/_?heart[_-]?beats?$/i,\n  /\\/ping$/i,\n  /\\/ready$/i,\n  /\\/live$/i,\n];\nconst EXCLUDE_USER_AGENT_PATTERNS = [\n  /health[-_ ]?check/i,\n  /microsoft-azure-application-lb/i,\n  /googlehc/i,\n  /kube-probe/i,\n];\nconst MASK_QUERY_PARAM_PATTERNS = [\n  /auth/i,\n  /api-?key/i,\n  /secret/i,\n  /token/i,\n  /password/i,\n  /pwd/i,\n];\nconst MASK_HEADER_PATTERNS = [\n  /auth/i,\n  /api-?key/i,\n  /secret/i,\n  /token/i,\n  /cookie/i,\n];\n\nexport type Request = {\n  timestamp: number;\n  method: string;\n  path?: string;\n  url: string;\n  headers: [string, string][];\n  size?: number;\n  consumer?: string;\n  body?: Buffer;\n};\n\nexport type Response = {\n  statusCode: number;\n  responseTime: number;\n  headers: [string, string][];\n  size?: number;\n  body?: Buffer;\n};\n\nexport type RequestLoggingConfig = {\n  enabled: boolean;\n  logQueryParams: boolean;\n  logRequestHeaders: boolean;\n  logRequestBody: boolean;\n  logResponseHeaders: boolean;\n  logResponseBody: boolean;\n  logException: boolean;\n  maskQueryParams: RegExp[];\n  maskHeaders: RegExp[];\n  maskRequestBodyCallback?: (request: Request) => Buffer | null | undefined;\n  maskResponseBodyCallback?: (\n    request: Request,\n    response: Response,\n  ) => Buffer | null | undefined;\n  excludePaths: RegExp[];\n  excludeCallback?: (request: Request, response: Response) => boolean;\n};\n\nconst DEFAULT_CONFIG: RequestLoggingConfig = {\n  enabled: false,\n  logQueryParams: true,\n  logRequestHeaders: false,\n  logRequestBody: false,\n  logResponseHeaders: true,\n  logResponseBody: false,\n  logException: true,\n  maskQueryParams: [],\n  maskHeaders: [],\n  excludePaths: [],\n};\n\nexport default class RequestLogger {\n  public config: RequestLoggingConfig;\n  public enabled: boolean;\n  public suspendUntil: number | null = null;\n  private pendingWrites: string[] = [];\n  private currentFile: TempGzipFile | null = null;\n  private files: TempGzipFile[] = [];\n  private maintainIntervalId?: NodeJS.Timeout;\n  private lock = new AsyncLock();\n\n  constructor(config?: Partial<RequestLoggingConfig>) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n    this.enabled = this.config.enabled && checkWritableFs();\n\n    if (this.enabled) {\n      this.maintainIntervalId = setInterval(() => {\n        this.maintain();\n      }, 1000);\n    }\n  }\n\n  private shouldExcludePath(urlPath: string) {\n    const patterns = [...this.config.excludePaths, ...EXCLUDE_PATH_PATTERNS];\n    return matchPatterns(urlPath, patterns);\n  }\n\n  private shouldExcludeUserAgent(userAgent?: string) {\n    return userAgent\n      ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS)\n      : false;\n  }\n\n  private shouldMaskQueryParam(name: string) {\n    const patterns = [\n      ...this.config.maskQueryParams,\n      ...MASK_QUERY_PARAM_PATTERNS,\n    ];\n    return matchPatterns(name, patterns);\n  }\n\n  private shouldMaskHeader(name: string) {\n    const patterns = [...this.config.maskHeaders, ...MASK_HEADER_PATTERNS];\n    return matchPatterns(name, patterns);\n  }\n\n  private hasSupportedContentType(headers: [string, string][]) {\n    const contentType = headers.find(\n      ([k]) => k.toLowerCase() === \"content-type\",\n    )?.[1];\n    return this.isSupportedContentType(contentType);\n  }\n\n  public isSupportedContentType(contentType?: string | null) {\n    return (\n      typeof contentType === \"string\" &&\n      ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t))\n    );\n  }\n\n  private maskQueryParams(search: string) {\n    const params = new URLSearchParams(search);\n    for (const [key] of params) {\n      if (this.shouldMaskQueryParam(key)) {\n        params.set(key, MASKED);\n      }\n    }\n    return params.toString();\n  }\n\n  private maskHeaders(headers: [string, string][]): [string, string][] {\n    return headers.map(([k, v]) => [k, this.shouldMaskHeader(k) ? MASKED : v]);\n  }\n\n  logRequest(request: Request, response: Response, error?: Error) {\n    if (!this.enabled || this.suspendUntil !== null) return;\n\n    const url = new URL(request.url);\n    const path = request.path ?? url.pathname;\n    const userAgent = request.headers.find(\n      ([k]) => k.toLowerCase() === \"user-agent\",\n    )?.[1];\n\n    if (\n      this.shouldExcludePath(path) ||\n      this.shouldExcludeUserAgent(userAgent) ||\n      (this.config.excludeCallback?.(request, response) ?? false)\n    ) {\n      return;\n    }\n\n    // Process query params\n    url.search = this.config.logQueryParams\n      ? this.maskQueryParams(url.search)\n      : \"\";\n    request.url = url.toString();\n\n    // Process request body\n    if (\n      !this.config.logRequestBody ||\n      !this.hasSupportedContentType(request.headers)\n    ) {\n      request.body = undefined;\n    } else if (request.body) {\n      if (request.body.length > MAX_BODY_SIZE) {\n        request.body = BODY_TOO_LARGE;\n      } else if (this.config.maskRequestBodyCallback) {\n        try {\n          request.body =\n            this.config.maskRequestBodyCallback(request) ?? BODY_MASKED;\n          if (request.body.length > MAX_BODY_SIZE) {\n            request.body = BODY_TOO_LARGE;\n          }\n        } catch {\n          request.body = undefined;\n        }\n      }\n    }\n\n    // Process response body\n    if (\n      !this.config.logResponseBody ||\n      !this.hasSupportedContentType(response.headers)\n    ) {\n      response.body = undefined;\n    } else if (response.body) {\n      if (response.body.length > MAX_BODY_SIZE) {\n        response.body = BODY_TOO_LARGE;\n      } else if (this.config.maskResponseBodyCallback) {\n        try {\n          response.body =\n            this.config.maskResponseBodyCallback(request, response) ??\n            BODY_MASKED;\n          if (response.body.length > MAX_BODY_SIZE) {\n            response.body = BODY_TOO_LARGE;\n          }\n        } catch {\n          response.body = undefined;\n        }\n      }\n    }\n\n    // Process headers\n    request.headers = this.config.logRequestHeaders\n      ? this.maskHeaders(request.headers)\n      : [];\n    response.headers = this.config.logResponseHeaders\n      ? this.maskHeaders(response.headers)\n      : [];\n\n    const item = {\n      uuid: randomUUID(),\n      request: skipEmptyValues(request),\n      response: skipEmptyValues(response),\n      exception:\n        error && this.config.logException\n          ? {\n              type: error.name,\n              message: truncateExceptionMessage(error.message),\n              stacktrace: truncateExceptionStackTrace(error.stack || \"\"),\n              sentryEventId: getSentryEventId(),\n            }\n          : null,\n    };\n    [item.request.body, item.response.body].forEach((body) => {\n      if (body) {\n        // @ts-expect-error Different return type\n        body.toJSON = function () {\n          return this.toString(\"base64\");\n        };\n      }\n    });\n    this.pendingWrites.push(JSON.stringify(item));\n\n    if (this.pendingWrites.length > MAX_PENDING_WRITES) {\n      this.pendingWrites.shift();\n    }\n  }\n\n  async writeToFile() {\n    if (!this.enabled || this.pendingWrites.length === 0) {\n      return;\n    }\n    return this.lock.acquire(\"file\", async () => {\n      if (!this.currentFile) {\n        this.currentFile = new TempGzipFile();\n      }\n      while (this.pendingWrites.length > 0) {\n        const item = this.pendingWrites.shift();\n        if (item) {\n          await this.currentFile.writeLine(Buffer.from(item));\n        }\n      }\n    });\n  }\n\n  getFile() {\n    return this.files.shift();\n  }\n\n  retryFileLater(file: TempGzipFile) {\n    this.files.unshift(file);\n  }\n\n  async rotateFile() {\n    return this.lock.acquire(\"file\", async () => {\n      if (this.currentFile) {\n        await this.currentFile.close();\n        this.files.push(this.currentFile);\n        this.currentFile = null;\n      }\n    });\n  }\n\n  async maintain() {\n    await this.writeToFile();\n    if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {\n      await this.rotateFile();\n    }\n    while (this.files.length > MAX_FILES) {\n      const file = this.files.shift();\n      file?.delete();\n    }\n    if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {\n      this.suspendUntil = null;\n    }\n  }\n\n  async clear() {\n    this.pendingWrites = [];\n    await this.rotateFile();\n    this.files.forEach((file) => {\n      file.delete();\n    });\n    this.files = [];\n  }\n\n  async close() {\n    this.enabled = false;\n    await this.clear();\n    if (this.maintainIntervalId) {\n      clearInterval(this.maintainIntervalId);\n    }\n  }\n}\n\nexport function convertHeaders(\n  headers:\n    | Headers\n    | IncomingHttpHeaders\n    | OutgoingHttpHeaders\n    | Record<string, string | string[] | number | undefined>,\n) {\n  if (headers instanceof Headers) {\n    return Array.from(headers.entries());\n  }\n  return Object.entries(headers).flatMap(([key, value]) => {\n    if (value === undefined) {\n      return [];\n    }\n    if (Array.isArray(value)) {\n      return value.map((v) => [key, v]);\n    }\n    return [[key, value.toString()]];\n  }) as [string, string][];\n}\n\nexport function convertBody(body: any, contentType?: string | null) {\n  if (!body || !contentType) {\n    return;\n  }\n  try {\n    if (contentType.startsWith(\"application/json\")) {\n      if (isValidJsonString(body)) {\n        return Buffer.from(body);\n      } else {\n        return Buffer.from(JSON.stringify(body));\n      }\n    }\n    if (contentType.startsWith(\"text/\") && typeof body === \"string\") {\n      return Buffer.from(body);\n    }\n  } catch (error) {\n    return;\n  }\n}\n\nfunction isValidJsonString(body: any) {\n  if (typeof body !== \"string\") {\n    return false;\n  }\n  try {\n    JSON.parse(body);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction matchPatterns(value: string, patterns: RegExp[]) {\n  return patterns.some((pattern) => {\n    return pattern.test(value);\n  });\n}\n\nfunction skipEmptyValues<T extends Record<string, any>>(data: T) {\n  return Object.fromEntries(\n    Object.entries(data).filter(([_, v]) => {\n      if (v == null || Number.isNaN(v)) return false;\n      if (Array.isArray(v) || Buffer.isBuffer(v) || typeof v === \"string\") {\n        return v.length > 0;\n      }\n      return true;\n    }),\n  ) as Partial<T>;\n}\n\nfunction checkWritableFs() {\n  try {\n    const testPath = join(tmpdir(), `apitally-${randomUUID()}`);\n    writeFileSync(testPath, \"test\");\n    unlinkSync(testPath);\n    return true;\n  } catch (error) {\n    return false;\n  }\n}\n","import type * as Sentry from \"@sentry/node\";\n\nlet sentry: typeof Sentry | undefined;\n\n// Initialize Sentry when the module is loaded\n(async () => {\n  try {\n    sentry = await import(\"@sentry/node\");\n  } catch (e) {\n    // Sentry SDK is not installed, ignore\n  }\n})();\n\n/**\n * Returns the last Sentry event ID if available\n */\nexport function getSentryEventId(): string | undefined {\n  if (sentry && sentry.lastEventId) {\n    return sentry.lastEventId();\n  }\n  return undefined;\n}\n","import { createHash } from \"crypto\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport { ConsumerMethodPath, ServerError, ServerErrorsItem } from \"./types.js\";\n\nconst MAX_MSG_LENGTH = 2048;\nconst MAX_STACKTRACE_LENGTH = 65536;\n\nexport default class ServerErrorCounter {\n  private errorCounts: Map<string, number>;\n  private errorDetails: Map<string, ConsumerMethodPath & ServerError>;\n  private sentryEventIds: Map<string, string>;\n\n  constructor() {\n    this.errorCounts = new Map();\n    this.errorDetails = new Map();\n    this.sentryEventIds = new Map();\n  }\n\n  public addServerError(serverError: ConsumerMethodPath & ServerError) {\n    const key = this.getKey(serverError);\n    if (!this.errorDetails.has(key)) {\n      this.errorDetails.set(key, serverError);\n    }\n    this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n\n    const sentryEventId = getSentryEventId();\n    if (sentryEventId) {\n      this.sentryEventIds.set(key, sentryEventId);\n    }\n  }\n\n  public getAndResetServerErrors() {\n    const data: Array<ServerErrorsItem> = [];\n    this.errorCounts.forEach((count, key) => {\n      const serverError = this.errorDetails.get(key);\n      if (serverError) {\n        data.push({\n          consumer: serverError.consumer || null,\n          method: serverError.method,\n          path: serverError.path,\n          type: serverError.type,\n          msg: truncateExceptionMessage(serverError.msg),\n          traceback: truncateExceptionStackTrace(serverError.traceback),\n          sentry_event_id: this.sentryEventIds.get(key) || null,\n          error_count: count,\n        });\n      }\n    });\n    this.errorCounts.clear();\n    this.errorDetails.clear();\n    return data;\n  }\n\n  private getKey(serverError: ConsumerMethodPath & ServerError) {\n    const hashInput = [\n      serverError.consumer || \"\",\n      serverError.method.toUpperCase(),\n      serverError.path,\n      serverError.type,\n      serverError.msg.trim(),\n      serverError.traceback.trim(),\n    ].join(\"|\");\n    return createHash(\"md5\").update(hashInput).digest(\"hex\");\n  }\n}\n\nexport function truncateExceptionMessage(msg: string) {\n  if (msg.length <= MAX_MSG_LENGTH) {\n    return msg;\n  }\n  const suffix = \"... (truncated)\";\n  const cutoff = MAX_MSG_LENGTH - suffix.length;\n  return msg.substring(0, cutoff) + suffix;\n}\n\nexport function truncateExceptionStackTrace(stack: string) {\n  const suffix = \"... (truncated) ...\";\n  const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;\n  const lines = stack.trim().split(\"\\n\");\n  const truncatedLines: string[] = [];\n  let length = 0;\n  for (const line of lines) {\n    if (length + line.length + 1 > cutoff) {\n      truncatedLines.push(suffix);\n      break;\n    }\n    truncatedLines.push(line);\n    length += line.length + 1;\n  }\n  return truncatedLines.join(\"\\n\");\n}\n","import { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { createWriteStream, readFile, unlinkSync, WriteStream } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { createGzip, Gzip } from \"zlib\";\n\nexport default class TempGzipFile {\n  public uuid: string;\n  private filePath: string;\n  private gzip: Gzip;\n  private writeStream: WriteStream;\n  private readyPromise: Promise<void>;\n  private closedPromise: Promise<void>;\n\n  constructor() {\n    this.uuid = randomUUID();\n    this.filePath = join(tmpdir(), `apitally-${this.uuid}.gz`);\n    this.writeStream = createWriteStream(this.filePath);\n    this.readyPromise = new Promise<void>((resolve, reject) => {\n      this.writeStream.once(\"ready\", resolve);\n      this.writeStream.once(\"error\", reject);\n    });\n    this.closedPromise = new Promise<void>((resolve, reject) => {\n      this.writeStream.once(\"close\", resolve);\n      this.writeStream.once(\"error\", reject);\n    });\n    this.gzip = createGzip();\n    this.gzip.pipe(this.writeStream);\n  }\n\n  get size() {\n    return this.writeStream.bytesWritten;\n  }\n\n  async writeLine(data: Buffer) {\n    await this.readyPromise;\n    return new Promise<void>((resolve, reject) => {\n      this.gzip.write(Buffer.concat([data, Buffer.from(\"\\n\")]), (error) => {\n        if (error) {\n          reject(error);\n        } else {\n          resolve();\n        }\n      });\n    });\n  }\n\n  async getContent() {\n    return new Promise<Buffer>((resolve, reject) => {\n      readFile(this.filePath, (error, data) => {\n        if (error) {\n          reject(error);\n        } else {\n          resolve(data);\n        }\n      });\n    });\n  }\n\n  async close() {\n    await new Promise<void>((resolve) => {\n      this.gzip.end(() => {\n        resolve();\n      });\n    });\n    await this.closedPromise;\n  }\n\n  async delete() {\n    await this.close();\n    unlinkSync(this.filePath);\n  }\n}\n","import { createHash } from \"crypto\";\n\nimport {\n  ConsumerMethodPath,\n  ValidationError,\n  ValidationErrorsItem,\n} from \"./types.js\";\n\nexport default class ValidationErrorCounter {\n  private errorCounts: Map<string, number>;\n  private errorDetails: Map<string, ConsumerMethodPath & ValidationError>;\n\n  constructor() {\n    this.errorCounts = new Map();\n    this.errorDetails = new Map();\n  }\n\n  public addValidationError(\n    validationError: ConsumerMethodPath & ValidationError,\n  ) {\n    const key = this.getKey(validationError);\n    if (!this.errorDetails.has(key)) {\n      this.errorDetails.set(key, validationError);\n    }\n    this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n  }\n\n  public getAndResetValidationErrors() {\n    const data: Array<ValidationErrorsItem> = [];\n    this.errorCounts.forEach((count, key) => {\n      const validationError = this.errorDetails.get(key);\n      if (validationError) {\n        data.push({\n          consumer: validationError.consumer || null,\n          method: validationError.method,\n          path: validationError.path,\n          loc: validationError.loc.split(\".\"),\n          msg: validationError.msg,\n          type: validationError.type,\n          error_count: count,\n        });\n      }\n    });\n    this.errorCounts.clear();\n    this.errorDetails.clear();\n    return data;\n  }\n\n  private getKey(validationError: ConsumerMethodPath & ValidationError) {\n    const hashInput = [\n      validationError.consumer || \"\",\n      validationError.method.toUpperCase(),\n      validationError.path,\n      validationError.loc,\n      validationError.msg.trim(),\n      validationError.type,\n    ].join(\"|\");\n    return createHash(\"md5\").update(hashInput).digest(\"hex\");\n  }\n}\n","import { createRequire } from \"module\";\n\nexport function getPackageVersion(name: string): string | null {\n  const packageJsonPath = `${name}/package.json`;\n  try {\n    return require(packageJsonPath).version || null;\n  } catch (error) {\n    try {\n      const _require = createRequire(import.meta.url);\n      return _require(packageJsonPath).version || null;\n    } catch (error) {\n      return null;\n    }\n  }\n}\n","import { OutgoingHttpHeader } from \"http\";\n\nexport function parseContentLength(\n  contentLength: OutgoingHttpHeader | undefined | null,\n): number | undefined {\n  if (contentLength === undefined || contentLength === null) {\n    return undefined;\n  }\n  if (typeof contentLength === \"number\") {\n    return contentLength;\n  }\n  if (typeof contentLength === \"string\") {\n    const parsed = parseInt(contentLength);\n    return isNaN(parsed) ? undefined : parsed;\n  }\n  if (Array.isArray(contentLength)) {\n    return parseContentLength(contentLength[0]);\n  }\n  return undefined;\n}\n","// Adapted from https://github.com/AlbertoFdzM/express-list-endpoints/blob/305535d43008b46f34e18b01947762e039af6d2d/src/index.js\n// and also incorporated changes from https://github.com/AlbertoFdzM/express-list-endpoints/pull/96\n\n/**\n * @typedef {Object} Route\n * @property {Object} methods\n * @property {string | string[]} path\n * @property {any[]} stack\n *\n * @typedef {Object} Endpoint\n * @property {string} path Path name\n * @property {string[]} methods Methods handled\n * @property {string[]} middlewares Mounted middlewares\n */\n\nconst regExpToParseExpressPathRegExp =\n  /^\\/\\^\\\\?\\/?(?:(:?[\\w\\\\.-]*(?:\\\\\\/:?[\\w\\\\.-]*)*)|(\\(\\?:\\\\?\\/?\\([^)]+\\)\\)))\\\\\\/.*/;\nconst regExpToReplaceExpressPathRegExpParams = /\\(\\?:\\\\?\\/?\\([^)]+\\)\\)/;\nconst regexpExpressParamRegexp = /\\(\\?:\\\\?\\\\?\\/?\\([^)]+\\)\\)/g;\nconst regexpExpressPathParamRegexp = /(:[^)]+)\\([^)]+\\)/g;\n\nconst EXPRESS_ROOT_PATH_REGEXP_VALUE = \"/^\\\\/?(?=\\\\/|$)/i\";\nconst STACK_ITEM_VALID_NAMES = [\"router\", \"bound dispatch\", \"mounted_app\"];\n\n/**\n * Returns all the verbs detected for the passed route\n * @param {Route} route\n */\nconst getRouteMethods = function (route) {\n  let methods = Object.keys(route.methods);\n\n  methods = methods.filter((method) => method !== \"_all\");\n  methods = methods.map((method) => method.toUpperCase());\n\n  return methods;\n};\n\n/**\n * Returns the names (or anonymous) of all the middlewares attached to the\n * passed route\n * @param {Route} route\n * @returns {string[]}\n */\nconst getRouteMiddlewares = function (route) {\n  return route.stack.map((item) => {\n    return item.handle.name || \"anonymous\";\n  });\n};\n\n/**\n * Returns true if found regexp related with express params\n * @param {string} expressPathRegExp\n * @returns {boolean}\n */\nconst hasParams = function (expressPathRegExp) {\n  return regexpExpressParamRegexp.test(expressPathRegExp);\n};\n\n/**\n * @param {Route} route Express route object to be parsed\n * @param {string} basePath The basePath the route is on\n * @return {Endpoint[]} Endpoints info\n */\nconst parseExpressRoute = function (route, basePath) {\n  const paths = [];\n\n  if (Array.isArray(route.path)) {\n    paths.push(...route.path);\n  } else {\n    paths.push(route.path);\n  }\n\n  /** @type {Endpoint[]} */\n  const endpoints = paths.map((path) => {\n    const completePath =\n      basePath && path === \"/\" ? basePath : `${basePath}${path}`;\n\n    /** @type {Endpoint} */\n    const endpoint = {\n      path: completePath.replace(regexpExpressPathParamRegexp, \"$1\"),\n      methods: getRouteMethods(route),\n      middlewares: getRouteMiddlewares(route),\n    };\n\n    return endpoint;\n  });\n\n  return endpoints;\n};\n\n/**\n * @param {RegExp} expressPathRegExp\n * @param {any[]} params\n * @returns {string}\n */\nexport const parseExpressPath = function (expressPathRegExp, params) {\n  let parsedRegExp = expressPathRegExp.toString();\n  let expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp);\n  let paramIndex = 0;\n\n  while (hasParams(parsedRegExp)) {\n    const paramName = params[paramIndex].name;\n    const paramId = `:${paramName}`;\n\n    parsedRegExp = parsedRegExp.replace(\n      regExpToReplaceExpressPathRegExpParams,\n      (str) => {\n        // Express >= 4.20.0 uses a different RegExp for parameters: it\n        // captures the slash as part of the parameter. We need to check\n        // for this case and add the slash to the value that will replace\n        // the parameter in the path.\n        if (str.startsWith(\"(?:\\\\/\")) {\n          return `\\\\/${paramId}`;\n        }\n\n        return paramId;\n      },\n    );\n\n    paramIndex++;\n  }\n\n  if (parsedRegExp !== expressPathRegExp.toString()) {\n    expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp);\n  }\n\n  const parsedPath = expressPathRegExpExec[1].replace(/\\\\\\//g, \"/\");\n\n  return parsedPath;\n};\n\n/**\n * @param {import('express').Express | import('express').Router | any} app\n * @param {string} [basePath]\n * @param {Endpoint[]} [endpoints]\n * @returns {Endpoint[]}\n */\nconst parseEndpoints = function (app, basePath, endpoints) {\n  const stack = app.stack || (app._router && app._router.stack);\n\n  endpoints = endpoints || [];\n  basePath = basePath || \"\";\n\n  if (!stack) {\n    if (endpoints.length) {\n      endpoints = addEndpoints(endpoints, [\n        {\n          path: basePath,\n          methods: [],\n          middlewares: [],\n        },\n      ]);\n    }\n  } else {\n    endpoints = parseStack(stack, basePath, endpoints);\n  }\n\n  return endpoints;\n};\n\n/**\n * Ensures the path of the new endpoints isn't yet in the array.\n * If the path is already in the array merges the endpoints with the existing\n * one, if not, it adds them to the array.\n *\n * @param {Endpoint[]} currentEndpoints Array of current endpoints\n * @param {Endpoint[]} endpointsToAdd New endpoints to be added to the array\n * @returns {Endpoint[]} Updated endpoints array\n */\nconst addEndpoints = function (currentEndpoints, endpointsToAdd) {\n  endpointsToAdd.forEach((newEndpoint) => {\n    const existingEndpoint = currentEndpoints.find(\n      (endpoint) => endpoint.path === newEndpoint.path,\n    );\n\n    if (existingEndpoint !== undefined) {\n      const newMethods = newEndpoint.methods.filter(\n        (method) => !existingEndpoint.methods.includes(method),\n      );\n\n      existingEndpoint.methods = existingEndpoint.methods.concat(newMethods);\n    } else {\n      currentEndpoints.push(newEndpoint);\n    }\n  });\n\n  return currentEndpoints;\n};\n\n/**\n * @param {any[]} stack\n * @param {string} basePath\n * @param {Endpoint[]} endpoints\n * @returns {Endpoint[]}\n */\nconst parseStack = function (stack, basePath, endpoints) {\n  stack.forEach((stackItem) => {\n    if (stackItem.route) {\n      const newEndpoints = parseExpressRoute(stackItem.route, basePath);\n\n      endpoints = addEndpoints(endpoints, newEndpoints);\n    } else if (STACK_ITEM_VALID_NAMES.includes(stackItem.name)) {\n      const isExpressPathRegexp = regExpToParseExpressPathRegExp.test(\n        stackItem.regexp,\n      );\n\n      let newBasePath = basePath;\n\n      if (isExpressPathRegexp) {\n        const parsedPath = parseExpressPath(stackItem.regexp, stackItem.keys);\n\n        newBasePath += `/${parsedPath}`;\n      } else if (\n        !stackItem.path &&\n        stackItem.regexp &&\n        stackItem.regexp.toString() !== EXPRESS_ROOT_PATH_REGEXP_VALUE\n      ) {\n        const regExpPath = ` RegExp(${stackItem.regexp}) `;\n\n        newBasePath += `/${regExpPath}`;\n      }\n\n      endpoints = parseEndpoints(stackItem.handle, newBasePath, endpoints);\n    }\n  });\n\n  return endpoints;\n};\n\nexport const getEndpoints = function (app, basePath) {\n  const endpoints = parseEndpoints(app);\n  return endpoints.flatMap((route) =>\n    route.methods\n      .filter((method) => ![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase()))\n      .map((method) => ({\n        method,\n        path: (basePath + route.path).replace(/\\/\\//g, \"/\"),\n      })),\n  );\n};\n"],"mappings":"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","names":["import_crypto","consumerFromStringOrObject","consumer","_a","String","trim","substring","identifier","name","group","ConsumerRegistry","consumers","updated","constructor","Map","Set","addOrUpdateConsumer","existing","get","set","add","getAndResetUpdatedConsumers","data","forEach","push","clear","getLogger","createLogger","level","process","env","APITALLY_DEBUG","format","combine","colorize","timestamp","printf","info","message","transports","Console","isValidClientId","clientId","regexExp","test","isValidEnv","env","RequestCounter","requestCounts","requestSizeSums","responseSizeSums","responseTimes","requestSizes","responseSizes","constructor","Map","getKey","requestInfo","consumer","method","toUpperCase","path","statusCode","join","addRequest","key","set","get","has","responseTimeMap","responseTimeMsBin","Math","floor","responseTime","requestSize","undefined","Number","requestSizeMap","requestSizeKbBin","responseSize","responseSizeMap","responseSizeKbBin","getAndResetRequests","data","forEach","count","statusCodeStr","split","push","status_code","parseInt","request_count","request_size_sum","response_size_sum","response_times","Object","fromEntries","request_sizes","response_sizes","clear","import_buffer","import_crypto","import_fs","import_os","import_path","sentry","e","getSentryEventId","lastEventId","undefined","MAX_MSG_LENGTH","MAX_STACKTRACE_LENGTH","ServerErrorCounter","errorCounts","errorDetails","sentryEventIds","constructor","Map","addServerError","serverError","key","getKey","has","set","get","sentryEventId","getSentryEventId","getAndResetServerErrors","data","forEach","count","push","consumer","method","path","type","msg","truncateExceptionMessage","traceback","truncateExceptionStackTrace","sentry_event_id","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","length","suffix","cutoff","substring","stack","lines","split","truncatedLines","line","import_crypto","TempGzipFile","uuid","filePath","gzip","writeStream","readyPromise","closedPromise","constructor","randomUUID","join","tmpdir","createWriteStream","Promise","resolve","reject","once","createGzip","pipe","size","bytesWritten","writeLine","data","write","Buffer","concat","from","error","getContent","readFile","close","end","delete","unlinkSync","MAX_BODY_SIZE","MAX_FILE_SIZE","MAX_FILES","MAX_PENDING_WRITES","BODY_TOO_LARGE","Buffer","from","BODY_MASKED","MASKED","ALLOWED_CONTENT_TYPES","EXCLUDE_PATH_PATTERNS","EXCLUDE_USER_AGENT_PATTERNS","MASK_QUERY_PARAM_PATTERNS","MASK_HEADER_PATTERNS","DEFAULT_CONFIG","enabled","logQueryParams","logRequestHeaders","logRequestBody","logResponseHeaders","logResponseBody","logException","maskQueryParams","maskHeaders","excludePaths","RequestLogger","config","suspendUntil","pendingWrites","currentFile","files","maintainIntervalId","lock","AsyncLock","constructor","checkWritableFs","setInterval","maintain","shouldExcludePath","urlPath","patterns","matchPatterns","shouldExcludeUserAgent","userAgent","shouldMaskQueryParam","name","shouldMaskHeader","hasSupportedContentType","headers","_a","contentType","find","k","toLowerCase","isSupportedContentType","some","t","startsWith","search","params","URLSearchParams","key","set","toString","map","v","logRequest","request","response","error","url","URL","path","pathname","excludeCallback","body","undefined","length","maskRequestBodyCallback","maskResponseBodyCallback","item","uuid","randomUUID","skipEmptyValues","exception","type","message","truncateExceptionMessage","stacktrace","truncateExceptionStackTrace","stack","sentryEventId","getSentryEventId","forEach","toJSON","push","JSON","stringify","shift","writeToFile","acquire","TempGzipFile","writeLine","getFile","retryFileLater","file","unshift","rotateFile","close","size","delete","Date","now","clear","clearInterval","convertHeaders","Headers","Array","entries","Object","flatMap","value","isArray","convertBody","isValidJsonString","parse","pattern","test","data","fromEntries","filter","_","Number","isNaN","isBuffer","testPath","join","tmpdir","writeFileSync","unlinkSync","import_crypto","ValidationErrorCounter","errorCounts","errorDetails","constructor","Map","addValidationError","validationError","key","getKey","has","set","get","getAndResetValidationErrors","data","forEach","count","push","consumer","method","path","loc","split","msg","type","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","SYNC_INTERVAL","INITIAL_SYNC_INTERVAL","INITIAL_SYNC_INTERVAL_DURATION","MAX_QUEUE_TIME","HTTPError","Error","response","constructor","reason","status","ApitallyClient","clientId","env","instanceUuid","syncDataQueue","syncIntervalId","startupData","startupDataSent","enabled","requestCounter","requestLogger","validationErrorCounter","serverErrorCounter","consumerRegistry","logger","requestLoggingConfig","instance","isValidClientId","isValidEnv","randomUUID","RequestCounter","RequestLogger","ValidationErrorCounter","ServerErrorCounter","ConsumerRegistry","getLogger","startSync","handleShutdown","bind","getInstance","isEnabled","shutdown","stopSync","sendSyncData","sendLogData","close","undefined","getHubUrlPrefix","baseURL","process","APITALLY_HUB_BASE_URL","version","sendData","url","payload","fetchWithRetry","fetchRetry","fetch","retries","retryDelay","retryOn","method","body","JSON","stringify","headers","ok","sync","setInterval","setTimeout","clearInterval","promises","push","sendStartupData","Promise","all","error","setStartupData","data","debug","instance_uuid","message_uuid","handled","handleHubError","message","newPayload","timestamp","Date","now","requests","getAndResetRequests","validation_errors","getAndResetValidationErrors","server_errors","getAndResetServerErrors","consumers","getAndResetUpdatedConsumers","i","length","shift","randomDelay","rotateFile","logFile","getFile","uuid","getContent","has","retryAfter","parseInt","get","suspendUntil","clear","delete","retryFileLater","delay","Math","random","resolve","getPackageVersion","name","packageJsonPath","require","version","error","_require","createRequire","url","parseContentLength","contentLength","undefined","parsed","parseInt","isNaN","Array","isArray","regExpToParseExpressPathRegExp","regExpToReplaceExpressPathRegExpParams","regexpExpressParamRegexp","regexpExpressPathParamRegexp","EXPRESS_ROOT_PATH_REGEXP_VALUE","STACK_ITEM_VALID_NAMES","getRouteMethods","route","methods","Object","keys","filter","method","map","toUpperCase","getRouteMiddlewares","stack","item","handle","name","hasParams","expressPathRegExp","test","parseExpressRoute","basePath","paths","Array","isArray","path","push","endpoints","completePath","endpoint","replace","middlewares","parseExpressPath","params","parsedRegExp","toString","expressPathRegExpExec","exec","paramIndex","paramName","paramId","str","startsWith","parsedPath","parseEndpoints","app","_router","length","addEndpoints","parseStack","currentEndpoints","endpointsToAdd","forEach","newEndpoint","existingEndpoint","find","undefined","newMethods","includes","concat","stackItem","newEndpoints","isExpressPathRegexp","regexp","newBasePath","regExpPath","getEndpoints","flatMap","useApitally","app","config","client","ApitallyClient","middleware","getMiddleware","use","setTimeout","setStartupData","getAppInfo","basePath","appVersion","errorHandlerConfigured","req","res","next","isEnabled","err","locals","serverError","startTime","performance","now","originalSend","send","body","contentType","get","requestLogger","isSupportedContentType","call","on","responseTime","path","getRoutePath","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestSize","parseContentLength","responseSize","requestCounter","addRequest","identifier","method","statusCode","jsonBody","JSON","parse","validationErrors","length","push","extractExpressValidatorErrors","extractCelebrateErrors","extractNestValidationErrors","forEach","error","validationErrorCounter","addValidationError","route","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","enabled","logRequest","timestamp","Date","url","protocol","host","originalUrl","headers","convertHeaders","size","convertBody","getHeaders","logger","request","response","baseUrl","routerPath","getRouterPath","_router","_a","routerPaths","routerLayer","find","layer","regexp","test","keys","parsedPath","parseExpressPath","handle","slice","filter","join","apitallyConsumer","consumerFromStringOrObject","consumerIdentifier","process","emitWarning","responseBody","errors","Array","isArray","location","loc","validation","Object","values","source","key","subsetJoiMessage","messageWithKey","split","includes","versions","version","replace","expressVersion","getPackageVersion","nestjsVersion","apitallyVersion","paths","getEndpoints","fromEntries"]}