apitally 0.25.6 → 0.25.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/common/client.cjs +12 -12
  2. package/dist/common/client.cjs.map +1 -1
  3. package/dist/common/client.d.cts +6 -6
  4. package/dist/common/client.d.ts +6 -6
  5. package/dist/common/client.js +6 -6
  6. package/dist/common/client.js.map +1 -1
  7. package/dist/common/consumerRegistry.cjs +2 -0
  8. package/dist/common/consumerRegistry.cjs.map +1 -1
  9. package/dist/common/consumerRegistry.d.cts +1 -1
  10. package/dist/common/consumerRegistry.d.ts +1 -1
  11. package/dist/common/consumerRegistry.js +1 -0
  12. package/dist/common/consumerRegistry.js.map +1 -1
  13. package/dist/common/requestCounter.cjs +5 -0
  14. package/dist/common/requestCounter.cjs.map +1 -1
  15. package/dist/common/requestCounter.d.cts +1 -1
  16. package/dist/common/requestCounter.d.ts +1 -1
  17. package/dist/common/requestCounter.js +1 -0
  18. package/dist/common/requestCounter.js.map +1 -1
  19. package/dist/common/requestLogger.cjs +53 -37
  20. package/dist/common/requestLogger.cjs.map +1 -1
  21. package/dist/common/requestLogger.d.cts +3 -2
  22. package/dist/common/requestLogger.d.ts +3 -2
  23. package/dist/common/requestLogger.js +51 -36
  24. package/dist/common/requestLogger.js.map +1 -1
  25. package/dist/common/serverErrorCounter.cjs +2 -0
  26. package/dist/common/serverErrorCounter.cjs.map +1 -1
  27. package/dist/common/serverErrorCounter.d.cts +1 -1
  28. package/dist/common/serverErrorCounter.d.ts +1 -1
  29. package/dist/common/serverErrorCounter.js +1 -0
  30. package/dist/common/serverErrorCounter.js.map +1 -1
  31. package/dist/common/spanCollector.cjs +3 -1
  32. package/dist/common/spanCollector.cjs.map +1 -1
  33. package/dist/common/spanCollector.d.cts +1 -1
  34. package/dist/common/spanCollector.d.ts +1 -1
  35. package/dist/common/spanCollector.js +1 -0
  36. package/dist/common/spanCollector.js.map +1 -1
  37. package/dist/common/tempGzipFile.cjs +11 -5
  38. package/dist/common/tempGzipFile.cjs.map +1 -1
  39. package/dist/common/tempGzipFile.d.cts +2 -2
  40. package/dist/common/tempGzipFile.d.ts +2 -2
  41. package/dist/common/tempGzipFile.js +10 -5
  42. package/dist/common/tempGzipFile.js.map +1 -1
  43. package/dist/common/validationErrorCounter.cjs +5 -0
  44. package/dist/common/validationErrorCounter.cjs.map +1 -1
  45. package/dist/common/validationErrorCounter.d.cts +1 -1
  46. package/dist/common/validationErrorCounter.d.ts +1 -1
  47. package/dist/common/validationErrorCounter.js +1 -0
  48. package/dist/common/validationErrorCounter.js.map +1 -1
  49. package/dist/elysia/index.cjs +2 -12
  50. package/dist/elysia/index.cjs.map +1 -1
  51. package/dist/elysia/index.d.cts +1 -1
  52. package/dist/elysia/index.d.ts +1 -1
  53. package/dist/elysia/index.js +2 -2
  54. package/dist/elysia/index.js.map +1 -1
  55. package/dist/elysia/plugin.cjs +5 -0
  56. package/dist/elysia/plugin.cjs.map +1 -1
  57. package/dist/elysia/plugin.d.cts +1 -1
  58. package/dist/elysia/plugin.d.ts +1 -1
  59. package/dist/elysia/plugin.js +1 -0
  60. package/dist/elysia/plugin.js.map +1 -1
  61. package/dist/fastify/index.cjs +2 -12
  62. package/dist/fastify/index.cjs.map +1 -1
  63. package/dist/fastify/index.d.cts +1 -1
  64. package/dist/fastify/index.d.ts +1 -1
  65. package/dist/fastify/index.js +2 -2
  66. package/dist/fastify/index.js.map +1 -1
  67. package/dist/fastify/plugin.cjs +4 -1
  68. package/dist/fastify/plugin.cjs.map +1 -1
  69. package/dist/fastify/plugin.d.cts +2 -2
  70. package/dist/fastify/plugin.d.ts +2 -2
  71. package/dist/fastify/plugin.js +3 -1
  72. package/dist/fastify/plugin.js.map +1 -1
  73. package/dist/hapi/index.cjs +2 -12
  74. package/dist/hapi/index.cjs.map +1 -1
  75. package/dist/hapi/index.d.cts +1 -1
  76. package/dist/hapi/index.d.ts +1 -1
  77. package/dist/hapi/index.js +2 -2
  78. package/dist/hapi/index.js.map +1 -1
  79. package/dist/hapi/plugin.cjs +2 -0
  80. package/dist/hapi/plugin.cjs.map +1 -1
  81. package/dist/hapi/plugin.d.cts +1 -1
  82. package/dist/hapi/plugin.d.ts +1 -1
  83. package/dist/hapi/plugin.js +1 -0
  84. package/dist/hapi/plugin.js.map +1 -1
  85. package/package.json +9 -3
@@ -29,6 +29,6 @@ declare module "fastify" {
29
29
  declare const apitallyPlugin: FastifyPluginAsync<ApitallyConfig>;
30
30
  declare function setConsumer(request: FastifyRequest, consumer: ApitallyConsumer | string | null | undefined): void;
31
31
 
32
- declare const _default: FastifyPluginAsync<ApitallyConfig>;
32
+ declare const apitallyFastifyPlugin: FastifyPluginAsync<ApitallyConfig>;
33
33
 
34
- export { apitallyPlugin, _default as default, setConsumer };
34
+ export { apitallyFastifyPlugin, apitallyPlugin, apitallyFastifyPlugin as default, setConsumer };
@@ -271,10 +271,12 @@ function extractNestValidationErrors(message) {
271
271
  }
272
272
  }
273
273
  __name(extractNestValidationErrors, "extractNestValidationErrors");
274
- var plugin_default = fp(apitallyPlugin, {
274
+ const apitallyFastifyPlugin = fp(apitallyPlugin, {
275
275
  name: "apitally"
276
276
  });
277
+ var plugin_default = apitallyFastifyPlugin;
277
278
  export {
279
+ apitallyFastifyPlugin,
278
280
  apitallyPlugin,
279
281
  plugin_default as default,
280
282
  setConsumer
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fastify/plugin.ts"],"sourcesContent":["import type {\n FastifyError,\n FastifyPluginAsync,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { AsyncLocalStorage, AsyncResource } from \"node:async_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport {\n ApitallyConfig,\n ApitallyConsumer,\n PathInfo,\n ValidationError,\n} from \"../common/types.js\";\nimport {\n patchConsole,\n patchNestLogger,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\n\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst ASYNC_RESOURCE_SYMBOL = Symbol(\"apitally.asyncResource\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"fastify\" {\n interface FastifyReply {\n payload: any;\n serverError?: FastifyError;\n }\n\n interface FastifyRequest {\n apitallyConsumer?: ApitallyConsumer | string | null;\n consumerIdentifier?: ApitallyConsumer | string | null; // For backwards compatibility\n\n [LOGS_SYMBOL]?: LogRecord[];\n [ASYNC_RESOURCE_SYMBOL]?: AsyncResource;\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n }\n}\n\nconst apitallyPlugin: FastifyPluginAsync<ApitallyConfig> = async (\n fastify,\n config,\n) => {\n const client = new ApitallyClient(config);\n const routes: PathInfo[] = [];\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n patchPinoLogger(fastify.log, logsContext);\n patchNestLogger(logsContext);\n }\n\n fastify.decorateRequest(\"apitallyConsumer\", null);\n fastify.decorateRequest(\"consumerIdentifier\", null); // For backwards compatibility\n fastify.decorateReply(\"payload\", null);\n\n fastify.addHook(\"onRoute\", (routeOptions) => {\n const methods = Array.isArray(routeOptions.method)\n ? routeOptions.method\n : [routeOptions.method];\n methods.forEach((method) => {\n if (![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase())) {\n routes.push({\n method: method.toUpperCase(),\n path: routeOptions.url,\n });\n }\n });\n });\n\n fastify.addHook(\"onReady\", () => {\n client.setStartupData(getAppInfo(routes, config.appVersion));\n client.startSync();\n });\n\n fastify.addHook(\"onClose\", async () => {\n await client.handleShutdown();\n });\n\n // Establish logs context and start span for each request\n fastify.addHook(\"onRequest\", (request, reply, done) => {\n if (client.isEnabled()) {\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n logsContext.run(logs, () => {\n const spanHandle = client.spanCollector.startSpan();\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n spanHandle.runInContext(() => {\n const asyncResource = new AsyncResource(\"ApitallyContext\");\n request[ASYNC_RESOURCE_SYMBOL] = asyncResource;\n asyncResource.runInAsyncScope(done, request.raw);\n });\n });\n } else {\n done();\n }\n });\n\n // Restore async context for later hooks and route handlers\n fastify.addHook(\"preValidation\", (request, reply, done) => {\n if (client.isEnabled() && request[ASYNC_RESOURCE_SYMBOL]) {\n const asyncResource = request[ASYNC_RESOURCE_SYMBOL];\n asyncResource.runInAsyncScope(done, request.raw);\n } else {\n done();\n }\n });\n\n fastify.addHook(\"onSend\", (request, reply, payload: any, done) => {\n const contentType = reply.getHeader(\"content-type\") as string | undefined;\n if (client.requestLogger.isSupportedContentType(contentType)) {\n reply.payload = payload;\n }\n done();\n });\n\n fastify.addHook(\"onError\", (request, reply, error, done) => {\n if (!error.statusCode || error.statusCode === 500) {\n reply.serverError = error;\n }\n done();\n });\n\n fastify.addHook(\"onResponse\", (request, reply, done) => {\n if (client.isEnabled() && request.method.toUpperCase() !== \"OPTIONS\") {\n // Get path from routeOptions if available (from v4), otherwise fallback to deprecated routerPath\n const consumer = getConsumer(request);\n const path =\n \"routeOptions\" in request\n ? (request as any).routeOptions.url\n : (request as any).routerPath;\n const requestSize = parseContentLength(request.headers[\"content-length\"]);\n const responseSize = parseContentLength(\n reply.getHeader(\"content-length\"),\n );\n const responseTime = getResponseTime(reply);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path,\n statusCode: reply.statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (\n (reply.statusCode === 400 || reply.statusCode === 422) &&\n reply.payload\n ) {\n try {\n const parsedPayload = JSON.parse(reply.payload);\n const validationErrors: ValidationError[] = [];\n\n if (\n (!parsedPayload.code ||\n parsedPayload.code === \"FST_ERR_VALIDATION\") &&\n typeof parsedPayload.message === \"string\"\n ) {\n validationErrors.push(...extractAjvErrors(parsedPayload.message));\n } else if (Array.isArray(parsedPayload.message)) {\n validationErrors.push(\n ...extractNestValidationErrors(parsedPayload.message),\n );\n }\n\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n ...error,\n });\n });\n } catch (error) {} // eslint-disable-line no-empty\n }\n\n if (reply.statusCode === 500 && reply.serverError) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n type: reply.serverError.name,\n msg: reply.serverError.message,\n traceback: reply.serverError.stack || \"\",\n });\n }\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(`${request.method} ${path}`);\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp: Date.now() / 1000,\n method: request.method,\n path,\n url: `${request.protocol}://${request.host ?? request.hostname}${request.originalUrl ?? request.url}`,\n headers: convertHeaders(request.headers),\n size: requestSize,\n consumer: consumer?.identifier,\n body: convertBody(request.body, request.headers[\"content-type\"]),\n },\n {\n statusCode: reply.statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(reply.getHeaders()),\n size: responseSize,\n body: convertBody(\n reply.payload,\n reply.getHeader(\"content-type\")?.toString(),\n ),\n },\n reply.serverError,\n logs,\n spans,\n traceId,\n );\n }\n }\n\n done();\n });\n};\n\nfunction getAppInfo(routes: PathInfo[], appVersion?: string) {\n const versions = [[\"nodejs\", process.version.replace(/^v/, \"\")]];\n const fastifyVersion = getPackageVersion(\"fastify\");\n const pinoVersion = getPackageVersion(\"pino\");\n const nestjsVersion = getPackageVersion(\"@nestjs/core\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (fastifyVersion) {\n versions.push([\"fastify\", fastifyVersion]);\n }\n if (pinoVersion) {\n versions.push([\"pino\", pinoVersion]);\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: routes,\n versions: Object.fromEntries(versions),\n client: \"js:fastify\",\n };\n}\n\nexport function setConsumer(\n request: FastifyRequest,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(request: FastifyRequest) {\n if (request.apitallyConsumer) {\n return consumerFromStringOrObject(request.apitallyConsumer);\n } else if (request.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(request.consumerIdentifier);\n }\n return null;\n}\n\nfunction getResponseTime(reply: FastifyReply) {\n if (reply.elapsedTime !== undefined) {\n return reply.elapsedTime;\n } else if ((reply as any).getResponseTime !== undefined) {\n return (reply as any).getResponseTime();\n }\n return 0;\n}\n\nfunction extractAjvErrors(message: string): ValidationError[] {\n try {\n const regex =\n /(?<=^|, )((?:headers|params|query|querystring|body)[/.][^ ]+)(?= )/g;\n const matches: { match: string; index: number }[] = [];\n let match: RegExpExecArray | null;\n while ((match = regex.exec(message)) !== null) {\n matches.push({ match: match[0], index: match.index });\n }\n\n return matches.map((m, i) => {\n const endIndex =\n i + 1 < matches.length ? matches[i + 1].index - 2 : message.length;\n const matchSplit = m.match.split(/[/.]/);\n if (matchSplit[0] === \"querystring\") {\n matchSplit[0] = \"query\";\n }\n return {\n loc: matchSplit.join(\".\"),\n msg: message.substring(m.index, endIndex),\n type: \"\",\n };\n });\n } catch (error) {\n return [];\n }\n}\n\nfunction extractNestValidationErrors(message: any[]): ValidationError[] {\n try {\n return message\n .filter((msg: any) => typeof msg === \"string\")\n .map((msg: any) => ({\n loc: \"\",\n msg,\n type: \"\",\n }));\n } catch (error) {\n return [];\n }\n}\n\nexport { apitallyPlugin };\n\nexport default fp(apitallyPlugin, {\n name: \"apitally\",\n});\n"],"mappings":"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","names":["fp","AsyncLocalStorage","AsyncResource","ApitallyClient","consumerFromStringOrObject","parseContentLength","getPackageVersion","convertBody","convertHeaders","patchConsole","patchNestLogger","patchPinoLogger","patchWinston","LOGS_SYMBOL","Symbol","ASYNC_RESOURCE_SYMBOL","SPAN_HANDLE_SYMBOL","apitallyPlugin","fastify","config","client","routes","logsContext","requestLogger","captureLogs","log","decorateRequest","decorateReply","addHook","routeOptions","methods","Array","isArray","method","forEach","includes","toUpperCase","push","path","url","setStartupData","getAppInfo","appVersion","startSync","handleShutdown","request","reply","done","isEnabled","logs","run","spanHandle","spanCollector","startSpan","runInContext","asyncResource","runInAsyncScope","raw","payload","contentType","getHeader","isSupportedContentType","error","statusCode","serverError","consumer","getConsumer","routerPath","requestSize","headers","responseSize","responseTime","getResponseTime","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","parsedPayload","JSON","parse","validationErrors","code","message","extractAjvErrors","extractNestValidationErrors","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","traceback","stack","setName","spans","end","traceId","enabled","logRequest","timestamp","Date","now","protocol","host","hostname","originalUrl","size","body","getHeaders","toString","versions","process","version","replace","fastifyVersion","pinoVersion","nestjsVersion","apitallyVersion","paths","Object","fromEntries","setConsumer","apitallyConsumer","undefined","consumerIdentifier","emitWarning","elapsedTime","regex","matches","match","exec","index","map","m","i","endIndex","length","matchSplit","split","loc","join","substring","filter"]}
1
+ {"version":3,"sources":["../../src/fastify/plugin.ts"],"sourcesContent":["import type {\n FastifyError,\n FastifyPluginAsync,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { AsyncLocalStorage, AsyncResource } from \"node:async_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport {\n ApitallyConfig,\n ApitallyConsumer,\n PathInfo,\n ValidationError,\n} from \"../common/types.js\";\nimport {\n patchConsole,\n patchNestLogger,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\n\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst ASYNC_RESOURCE_SYMBOL = Symbol(\"apitally.asyncResource\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"fastify\" {\n interface FastifyReply {\n payload: any;\n serverError?: FastifyError;\n }\n\n interface FastifyRequest {\n apitallyConsumer?: ApitallyConsumer | string | null;\n consumerIdentifier?: ApitallyConsumer | string | null; // For backwards compatibility\n\n [LOGS_SYMBOL]?: LogRecord[];\n [ASYNC_RESOURCE_SYMBOL]?: AsyncResource;\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n }\n}\n\nconst apitallyPlugin: FastifyPluginAsync<ApitallyConfig> = async (\n fastify,\n config,\n) => {\n const client = new ApitallyClient(config);\n const routes: PathInfo[] = [];\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n patchPinoLogger(fastify.log, logsContext);\n patchNestLogger(logsContext);\n }\n\n fastify.decorateRequest(\"apitallyConsumer\", null);\n fastify.decorateRequest(\"consumerIdentifier\", null); // For backwards compatibility\n fastify.decorateReply(\"payload\", null);\n\n fastify.addHook(\"onRoute\", (routeOptions) => {\n const methods = Array.isArray(routeOptions.method)\n ? routeOptions.method\n : [routeOptions.method];\n methods.forEach((method) => {\n if (![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase())) {\n routes.push({\n method: method.toUpperCase(),\n path: routeOptions.url,\n });\n }\n });\n });\n\n fastify.addHook(\"onReady\", () => {\n client.setStartupData(getAppInfo(routes, config.appVersion));\n client.startSync();\n });\n\n fastify.addHook(\"onClose\", async () => {\n await client.handleShutdown();\n });\n\n // Establish logs context and start span for each request\n fastify.addHook(\"onRequest\", (request, reply, done) => {\n if (client.isEnabled()) {\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n logsContext.run(logs, () => {\n const spanHandle = client.spanCollector.startSpan();\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n spanHandle.runInContext(() => {\n const asyncResource = new AsyncResource(\"ApitallyContext\");\n request[ASYNC_RESOURCE_SYMBOL] = asyncResource;\n asyncResource.runInAsyncScope(done, request.raw);\n });\n });\n } else {\n done();\n }\n });\n\n // Restore async context for later hooks and route handlers\n fastify.addHook(\"preValidation\", (request, reply, done) => {\n if (client.isEnabled() && request[ASYNC_RESOURCE_SYMBOL]) {\n const asyncResource = request[ASYNC_RESOURCE_SYMBOL];\n asyncResource.runInAsyncScope(done, request.raw);\n } else {\n done();\n }\n });\n\n fastify.addHook(\"onSend\", (request, reply, payload: any, done) => {\n const contentType = reply.getHeader(\"content-type\") as string | undefined;\n if (client.requestLogger.isSupportedContentType(contentType)) {\n reply.payload = payload;\n }\n done();\n });\n\n fastify.addHook(\"onError\", (request, reply, error, done) => {\n if (!error.statusCode || error.statusCode === 500) {\n reply.serverError = error;\n }\n done();\n });\n\n fastify.addHook(\"onResponse\", (request, reply, done) => {\n if (client.isEnabled() && request.method.toUpperCase() !== \"OPTIONS\") {\n // Get path from routeOptions if available (from v4), otherwise fallback to deprecated routerPath\n const consumer = getConsumer(request);\n const path =\n \"routeOptions\" in request\n ? (request as any).routeOptions.url\n : (request as any).routerPath;\n const requestSize = parseContentLength(request.headers[\"content-length\"]);\n const responseSize = parseContentLength(\n reply.getHeader(\"content-length\"),\n );\n const responseTime = getResponseTime(reply);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path,\n statusCode: reply.statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (\n (reply.statusCode === 400 || reply.statusCode === 422) &&\n reply.payload\n ) {\n try {\n const parsedPayload = JSON.parse(reply.payload);\n const validationErrors: ValidationError[] = [];\n\n if (\n (!parsedPayload.code ||\n parsedPayload.code === \"FST_ERR_VALIDATION\") &&\n typeof parsedPayload.message === \"string\"\n ) {\n validationErrors.push(...extractAjvErrors(parsedPayload.message));\n } else if (Array.isArray(parsedPayload.message)) {\n validationErrors.push(\n ...extractNestValidationErrors(parsedPayload.message),\n );\n }\n\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n ...error,\n });\n });\n } catch (error) {} // eslint-disable-line no-empty\n }\n\n if (reply.statusCode === 500 && reply.serverError) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n type: reply.serverError.name,\n msg: reply.serverError.message,\n traceback: reply.serverError.stack || \"\",\n });\n }\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(`${request.method} ${path}`);\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp: Date.now() / 1000,\n method: request.method,\n path,\n url: `${request.protocol}://${request.host ?? request.hostname}${request.originalUrl ?? request.url}`,\n headers: convertHeaders(request.headers),\n size: requestSize,\n consumer: consumer?.identifier,\n body: convertBody(request.body, request.headers[\"content-type\"]),\n },\n {\n statusCode: reply.statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(reply.getHeaders()),\n size: responseSize,\n body: convertBody(\n reply.payload,\n reply.getHeader(\"content-type\")?.toString(),\n ),\n },\n reply.serverError,\n logs,\n spans,\n traceId,\n );\n }\n }\n\n done();\n });\n};\n\nfunction getAppInfo(routes: PathInfo[], appVersion?: string) {\n const versions = [[\"nodejs\", process.version.replace(/^v/, \"\")]];\n const fastifyVersion = getPackageVersion(\"fastify\");\n const pinoVersion = getPackageVersion(\"pino\");\n const nestjsVersion = getPackageVersion(\"@nestjs/core\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (fastifyVersion) {\n versions.push([\"fastify\", fastifyVersion]);\n }\n if (pinoVersion) {\n versions.push([\"pino\", pinoVersion]);\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: routes,\n versions: Object.fromEntries(versions),\n client: \"js:fastify\",\n };\n}\n\nexport function setConsumer(\n request: FastifyRequest,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(request: FastifyRequest) {\n if (request.apitallyConsumer) {\n return consumerFromStringOrObject(request.apitallyConsumer);\n } else if (request.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(request.consumerIdentifier);\n }\n return null;\n}\n\nfunction getResponseTime(reply: FastifyReply) {\n if (reply.elapsedTime !== undefined) {\n return reply.elapsedTime;\n } else if ((reply as any).getResponseTime !== undefined) {\n return (reply as any).getResponseTime();\n }\n return 0;\n}\n\nfunction extractAjvErrors(message: string): ValidationError[] {\n try {\n const regex =\n /(?<=^|, )((?:headers|params|query|querystring|body)[/.][^ ]+)(?= )/g;\n const matches: { match: string; index: number }[] = [];\n let match: RegExpExecArray | null;\n while ((match = regex.exec(message)) !== null) {\n matches.push({ match: match[0], index: match.index });\n }\n\n return matches.map((m, i) => {\n const endIndex =\n i + 1 < matches.length ? matches[i + 1].index - 2 : message.length;\n const matchSplit = m.match.split(/[/.]/);\n if (matchSplit[0] === \"querystring\") {\n matchSplit[0] = \"query\";\n }\n return {\n loc: matchSplit.join(\".\"),\n msg: message.substring(m.index, endIndex),\n type: \"\",\n };\n });\n } catch (error) {\n return [];\n }\n}\n\nfunction extractNestValidationErrors(message: any[]): ValidationError[] {\n try {\n return message\n .filter((msg: any) => typeof msg === \"string\")\n .map((msg: any) => ({\n loc: \"\",\n msg,\n type: \"\",\n }));\n } catch (error) {\n return [];\n }\n}\n\nexport { apitallyPlugin };\n\nexport const apitallyFastifyPlugin = fp(apitallyPlugin, {\n name: \"apitally\",\n});\n\nexport default apitallyFastifyPlugin;\n"],"mappings":"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","names":["fp","AsyncLocalStorage","AsyncResource","ApitallyClient","consumerFromStringOrObject","parseContentLength","getPackageVersion","convertBody","convertHeaders","patchConsole","patchNestLogger","patchPinoLogger","patchWinston","LOGS_SYMBOL","Symbol","ASYNC_RESOURCE_SYMBOL","SPAN_HANDLE_SYMBOL","apitallyPlugin","fastify","config","client","routes","logsContext","requestLogger","captureLogs","log","decorateRequest","decorateReply","addHook","routeOptions","methods","Array","isArray","method","forEach","includes","toUpperCase","push","path","url","setStartupData","getAppInfo","appVersion","startSync","handleShutdown","request","reply","done","isEnabled","logs","run","spanHandle","spanCollector","startSpan","runInContext","asyncResource","runInAsyncScope","raw","payload","contentType","getHeader","isSupportedContentType","error","statusCode","serverError","consumer","getConsumer","routerPath","requestSize","headers","responseSize","responseTime","getResponseTime","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","parsedPayload","JSON","parse","validationErrors","code","message","extractAjvErrors","extractNestValidationErrors","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","traceback","stack","setName","spans","end","traceId","enabled","logRequest","timestamp","Date","now","protocol","host","hostname","originalUrl","size","body","getHeaders","toString","versions","process","version","replace","fastifyVersion","pinoVersion","nestjsVersion","apitallyVersion","paths","Object","fromEntries","setConsumer","apitallyConsumer","undefined","consumerIdentifier","emitWarning","elapsedTime","regex","matches","match","exec","index","map","m","i","endIndex","length","matchSplit","split","loc","join","substring","filter","apitallyFastifyPlugin"]}
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,22 +15,14 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var hapi_exports = {};
30
20
  __export(hapi_exports, {
31
- apitallyPlugin: () => import_plugin.default,
21
+ apitallyPlugin: () => import_plugin.apitallyPlugin,
32
22
  setConsumer: () => import_plugin.setConsumer
33
23
  });
34
24
  module.exports = __toCommonJS(hapi_exports);
35
- var import_plugin = __toESM(require('./plugin.cjs'), 1);
25
+ var import_plugin = require('./plugin.cjs');
36
26
  // Annotate the CommonJS export names for ESM import in node:
37
27
  0 && (module.exports = {
38
28
  apitallyPlugin,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { default as apitallyPlugin, setConsumer } from \"./plugin.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;;;;;;oBAAuD;","names":[]}
1
+ {"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { apitallyPlugin, setConsumer } from \"./plugin.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AACA;;;;;;oBAA4C;","names":[]}
@@ -1,5 +1,5 @@
1
1
  export { ApitallyConfig, ApitallyConsumer } from '../common/types.cjs';
2
- export { default as apitallyPlugin, setConsumer } from './plugin.cjs';
2
+ export { apitallyPlugin, setConsumer } from './plugin.cjs';
3
3
  import '../common/logging.cjs';
4
4
  import 'winston';
5
5
  import '../common/requestLogger.cjs';
@@ -1,5 +1,5 @@
1
1
  export { ApitallyConfig, ApitallyConsumer } from '../common/types.js';
2
- export { default as apitallyPlugin, setConsumer } from './plugin.js';
2
+ export { apitallyPlugin, setConsumer } from './plugin.js';
3
3
  import '../common/logging.js';
4
4
  import 'winston';
5
5
  import '../common/requestLogger.js';
@@ -1,6 +1,6 @@
1
- import { default as default2, setConsumer } from "./plugin.js";
1
+ import { apitallyPlugin, setConsumer } from "./plugin.js";
2
2
  export {
3
- default2 as apitallyPlugin,
3
+ apitallyPlugin,
4
4
  setConsumer
5
5
  };
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { default as apitallyPlugin, setConsumer } from \"./plugin.js\";\n"],"mappings":"AACA,SAAoBA,WAAXC,UAA2BC,mBAAmB;","names":["apitallyPlugin","default","setConsumer"]}
1
+ {"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { apitallyPlugin, setConsumer } from \"./plugin.js\";\n"],"mappings":"AACA,SAASA,gBAAgBC,mBAAmB;","names":["apitallyPlugin","setConsumer"]}
@@ -19,6 +19,7 @@ var __copyProps = (to, from, except, desc) => {
19
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
20
  var plugin_exports = {};
21
21
  __export(plugin_exports, {
22
+ apitallyPlugin: () => apitallyPlugin,
22
23
  default: () => apitallyPlugin,
23
24
  setConsumer: () => setConsumer
24
25
  });
@@ -205,6 +206,7 @@ function setConsumer(request, consumer) {
205
206
  __name(setConsumer, "setConsumer");
206
207
  // Annotate the CommonJS export names for ESM import in node:
207
208
  0 && (module.exports = {
209
+ apitallyPlugin,
208
210
  setConsumer
209
211
  });
210
212
  //# sourceMappingURL=plugin.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with span and logs context\n const spanHandle = client.spanCollector.startSpan();\n const logs: LogRecord[] = [];\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n request[LOGS_SYMBOL] = logs;\n const lifecycle = (request as any)._lifecycle.bind(request);\n (request as any)._lifecycle = () =>\n spanHandle.runInContext(() => logsContext.run(logs, lifecycle));\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(\n `${request.method.toUpperCase()} ${request.route.path}`,\n );\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n spans,\n traceId,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AACA;;;;;;AAAA,8BAAkC;AAClC,6BAA4B;AAE5B,oBAA+B;AAC/B,8BAA2C;AAE3C,2BAA+B;AAG/B,qBAKO;AACP,mBAAmC;AAEnC,MAAMA,oBAAoBC,uBAAO,oBAAA;AACjC,MAAMC,sBAAsBD,uBAAO,sBAAA;AACnC,MAAME,sBAAsBF,uBAAO,sBAAA;AACnC,MAAMG,uBAAuBH,uBAAO,uBAAA;AACpC,MAAMI,uBAAuBJ,uBAAO,uBAAA;AACpC,MAAMK,cAAcL,uBAAO,eAAA;AAC3B,MAAMM,qBAAqBN,uBAAO,qBAAA;AAmBnB,SAAf,eAAuCO,QAAsB;AAC3D,QAAMC,SAAS,IAAIC,6BAAeF,MAAAA;AAClC,QAAMG,cAAc,IAAIC,0CAAAA;AACxB,MAAIC,oBAAoB;AAExB,MAAIJ,OAAOK,cAAcC,WAAWN,OAAOK,cAAcN,OAAOQ,aAAa;AAC3EC,qCAAaN,WAAAA;AACbO,qCAAaP,WAAAA;EACf;AAEA,SAAO;IACLQ,MAAM;IACNC,UAAU,sCAAgBC,QAAc;AACtCA,aAAOC,IAAI,eAAe,YAAA;AACxB,YACE,YAAYD,UACZZ,OAAOK,cAAcC,WACrBN,OAAOK,cAAcN,OAAOQ,aAC5B;AACAH,8BAAoB,UAAMU,gCACvBF,OAAeG,QAChBb,WAAAA;QAEJ;MACF,CAAA;AAEAU,aAAOC,IAAI,eAAe,MAAA;AACxB,cAAMG,cAAUC,yBAAWL,QAAQb,OAAOmB,UAAU;AACpDlB,eAAOmB,eAAeH,OAAAA;AACtBhB,eAAOoB,UAAS;MAClB,CAAA;AAEAR,aAAOC,IAAI,aAAa,YAAA;AACtB,cAAMb,OAAOqB,eAAc;MAC7B,CAAA;AAEAT,aAAOU,OAAOC,GAAG,WAAW,CAACC,GAAGC,UAAAA;AAC9B,YACE,CAACrB,qBACDJ,OAAOK,cAAcC,WACrBN,OAAOK,cAAcN,OAAOQ,eAC5BkB,MAAMC,YAAY,OAClB;AACAC,qDAAuBF,OAAOvB,WAAAA;QAChC;MACF,CAAA;AAEAU,aAAOC,IAAI,aAAa,OAAOe,SAASC,MAAAA;AACtC,YAAI,CAAC7B,OAAO8B,UAAS,KAAMF,QAAQG,OAAOC,YAAW,MAAO,WAAW;AACrE,iBAAOH,EAAEI;QACX;AAEAL,gBAAQrC,iBAAAA,IAAqB2C,mCAAYC,IAAG;AAG5C,cAAMC,aAAapC,OAAOqC,cAAcC,UAAS;AACjD,cAAMC,OAAoB,CAAA;AAC1BX,gBAAQ9B,kBAAAA,IAAsBsC;AAC9BR,gBAAQ/B,WAAAA,IAAe0C;AACvB,cAAMC,YAAaZ,QAAgBa,WAAWC,KAAKd,OAAAA;AAClDA,gBAAgBa,aAAa,MAC5BL,WAAWO,aAAa,MAAMzC,YAAY0C,IAAIL,MAAMC,SAAAA,CAAAA;AAEtD,cAAMK,qBACJ7C,OAAOK,cAAcC,WACrBN,OAAOK,cAAcN,OAAO+C,kBAC5B9C,OAAOK,cAAc0C,uBACnBnB,QAAQoB,QAAQ,cAAA,CAAe;AAEnC,cAAMC,SAAmB,CAAA;AACzB,YAAIC,OAAO;AACXtB,gBAAQN,OAAOC,GAAG,QAAQ,CAAC4B,OAAeC,aAAAA;AACxC,cAAIP,oBAAoB;AACtBI,mBAAOI,KAAKC,OAAOC,KAAKJ,OAAOC,QAAAA,CAAAA;UACjC;AACAF,kBAAQI,OAAOE,WAAWL,OAAOC,QAAAA;QACnC,CAAA;AACAxB,gBAAQN,OAAOmC,KAAK,UAAU,MAAA;AAC5B,cAAIR,OAAOS,SAAS,GAAG;AACrB9B,oBAAQnC,mBAAAA,IAAuB6D,OAAOK,OAAOV,MAAAA;UAC/C;AACArB,kBAAQlC,mBAAAA,IAAuBwD;QACjC,CAAA;AAEA,eAAOrB,EAAEI;MACX,CAAA;AAEArB,aAAOC,IAAI,iBAAiB,OAAOe,SAASC,MAAAA;AAC1C,YACE,CAAC7B,OAAO8B,UAAS,KACjBF,QAAQG,OAAOC,YAAW,MAAO,iBACjC4B,qBAAOhC,QAAQiC,QAAQ,GACvB;AACA,iBAAOhC,EAAEI;QACX;AAEA,cAAM6B,sBACJ9D,OAAOK,cAAcC,WACrBN,OAAOK,cAAcN,OAAOgE,mBAC5B/D,OAAOK,cAAc0C,uBACnBnB,QAAQiC,SAASG,WAAW;AAEhC,cAAMf,SAAmB,CAAA;AACzB,YAAIC,OAAO;AACXtB,gBAAQiC,SAASvC,OAAOC,GACtB,QACA,CAAC4B,OAAeC,aAAAA;AACd,cAAIU,qBAAqB;AACvBb,mBAAOI,KAAKC,OAAOC,KAAKJ,OAAOC,QAAAA,CAAAA;UACjC;AACAF,kBAAQI,OAAOE,WAAWL,OAAOC,QAAAA;QACnC,CAAA;AAEFxB,gBAAQiC,SAASvC,OAAOmC,KAAK,UAAU,MAAA;AACrC,cAAIR,OAAOS,SAAS,GAAG;AACrB9B,oBAAQjC,oBAAAA,IAAwB2D,OAAOK,OAAOV,MAAAA;UAChD;AACArB,kBAAQhC,oBAAAA,IAAwBsD;QAClC,CAAA;AAEA,eAAOrB,EAAEI;MACX,CAAA;AAEArB,aAAOC,IAAI,kBAAkB,OAAOe,SAASC,MAAAA;AArKnD;AAsKQ,YAAI,CAAC7B,OAAO8B,UAAS,KAAMF,QAAQG,OAAOC,YAAW,MAAO,WAAW;AACrE,iBAAOH,EAAEI;QACX;AAEA,cAAMgC,YAAYrC,QAAQrC,iBAAAA;AAC1B,cAAM2E,eAAeD,YAAY/B,mCAAYC,IAAG,IAAK8B,YAAY;AACjE,cAAME,aAAaC,KAAKjC,IAAG,IAAK+B,gBAAgB;AAEhD,cAAM9B,aAAaR,QAAQ9B,kBAAAA;AAC3BsC,iDAAYiC,QACV,GAAGzC,QAAQG,OAAOC,YAAW,CAAA,IAAMJ,QAAQ0C,MAAMC,IAAI;AAEvD,cAAMC,QAAQpC,yCAAYqC;AAC1B,cAAMC,UAAUtC,yCAAYsC;AAE5B,cAAMC,cAAc/C,QAAQnC,mBAAAA;AAC5B,cAAMmF,cAAchD,QAAQlC,mBAAAA;AAC5B,cAAMmE,WAAWjC,QAAQiC;AACzB,YAAIgB;AACJ,YAAIC;AACJ,YAAIC,eAAenD,QAAQjC,oBAAAA;AAC3B,YAAIqF,eAAepD,QAAQhC,oBAAAA;AAC3B,cAAMqF,QACHpB,SAAiBqB,kBAAkBC,QAC/BtB,SAAiBqB,SAClBE;AAEN,gBAAIxB,qBAAOC,QAAAA,GAAW;AAEpBgB,yBAAahB,cAASwB,WAATxB,mBAAiBgB,eAAc;AAC5CC,8BAAkBjB,cAASwB,WAATxB,mBAAiBb,YAAW,CAAC;QACjD,OAAO;AAEL6B,uBAAahB,SAASgB,cAAc;AACpCC,4BAAkBjB,SAASb,WAAW,CAAC;QACzC;AAEA,YACE,CAAC+B,gBACAlB,SAAiByB,YAClBtF,OAAOK,cAAcC,WACrBN,OAAOK,cAAcN,OAAOgE,wBAC3BH,qBAAOC,QAAAA,KACN7D,OAAOK,cAAc0C,uBAAuBc,SAASG,WAAW,IAClE;AACA,gBAAMuB,kBAAmB1B,SAAiByB;AAC1C,cACEC,mBACAA,gBAAgBC,SAChBD,gBAAgBE,aAChB,OAAOF,gBAAgBC,UAAU,YACjC,OAAOD,gBAAgBE,cAAc,UACrC;AACAV,2BAAezB,OAAOC,KACpBgC,gBAAgBC,OAChBD,gBAAgBE,SAAS;UAE7B;QACF;AAEA,YAAI,CAACT,gBAAgBD,cAAc;AACjCC,yBAAeD,aAAarB;QAC9B;AAEA,cAAMgC,WAAW9D,QAAQ+D,uBACrBC,oDAA2BhE,QAAQ+D,gBAAgB,IACnD;AACJ3F,eAAO6F,iBAAiBC,oBAAoBJ,QAAAA;AAE5C,YAAI9D,QAAQ0C,MAAMC,MAAM;AACtBvE,iBAAO+F,eAAeC,WAAW;YAC/BN,UAAUA,qCAAUO;YACpBlE,QAAQH,QAAQG;YAChBwC,MAAM3C,QAAQ0C,MAAMC;YACpBM;YACAX;YACAU;YACAI;UACF,CAAA;AAEA,cAAIH,eAAe,OAAOI,OAAO;AAC/BjF,mBAAOkG,mBAAmBC,eAAe;cACvCT,UAAUA,qCAAUO;cACpBlE,QAAQH,QAAQG;cAChBwC,MAAM3C,QAAQ0C,MAAMC;cACpB6B,MAAMnB,MAAMvE;cACZ2F,KAAKpB,MAAMqB;cACXC,WAAWtB,MAAMuB,SAAS;YAC5B,CAAA;UACF;QACF;AAEA,YAAIxG,OAAOK,cAAcC,SAAS;AAChC,gBAAMiC,OAAOX,QAAQ/B,WAAAA;AACrBG,iBAAOK,cAAcoG,WACnB;YACEtC;YACAuB,UAAUA,qCAAUO;YACpBlE,QAAQH,QAAQG;YAChBwC,MAAM3C,QAAQ0C,MAAMC;YACpBmC,OAAK9E,aAAQ8E,QAAR9E,mBAAa+E,SAAQ;YAC1B3D,aAAS4D,qCAAehF,QAAQoB,OAAO;YACvCE,MAAM0B;YACNiC,MAAMlC;UACR,GACA;YACEE;YACAX,cAAcA,eAAe;YAC7BlB,aAAS4D,qCAAe9B,eAAAA;YACxB5B,MAAM8B;YACN6B,MAAM9B;UACR,GACAE,OACA1C,MACAiC,OACAE,OAAAA;QAEJ;AAEA,eAAO7C,EAAEI;MACX,CAAA;IACF,GAzOU;EA0OZ;AACF;AAvPwB6E;AAyPjB,SAASC,YACdnF,SACA8D,UAAsD;AAEtD9D,UAAQ+D,mBAAmBD,YAAYN;AACzC;AALgB2B;","names":["START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","SPAN_HANDLE_SYMBOL","config","client","ApitallyClient","logsContext","AsyncLocalStorage","pinoLoggerPatched","requestLogger","enabled","captureLogs","patchConsole","patchWinston","name","register","server","ext","patchPinoLogger","logger","appInfo","getAppInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","handleHapiRequestEvent","request","h","isEnabled","method","toUpperCase","continue","performance","now","spanHandle","spanCollector","startSpan","logs","lifecycle","_lifecycle","bind","runInContext","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","isBoom","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","setName","route","path","spans","end","traceId","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerFromStringOrObject","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","convertHeaders","body","apitallyPlugin","setConsumer"]}
1
+ {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with span and logs context\n const spanHandle = client.spanCollector.startSpan();\n const logs: LogRecord[] = [];\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n request[LOGS_SYMBOL] = logs;\n const lifecycle = (request as any)._lifecycle.bind(request);\n (request as any)._lifecycle = () =>\n spanHandle.runInContext(() => logsContext.run(logs, lifecycle));\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(\n `${request.method.toUpperCase()} ${request.route.path}`,\n );\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n spans,\n traceId,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n\nexport { apitallyPlugin };\n"],"mappings":"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","names":["START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","SPAN_HANDLE_SYMBOL","config","client","ApitallyClient","logsContext","AsyncLocalStorage","pinoLoggerPatched","requestLogger","enabled","captureLogs","patchConsole","patchWinston","name","register","server","ext","patchPinoLogger","logger","appInfo","getAppInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","handleHapiRequestEvent","request","h","isEnabled","method","toUpperCase","continue","performance","now","spanHandle","spanCollector","startSpan","logs","lifecycle","_lifecycle","bind","runInContext","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","isBoom","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","setName","route","path","spans","end","traceId","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerFromStringOrObject","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","convertHeaders","body","apitallyPlugin","setConsumer"]}
@@ -37,4 +37,4 @@ declare function apitallyPlugin(config: ApitallyConfig): {
37
37
  };
38
38
  declare function setConsumer(request: Request, consumer: ApitallyConsumer | string | null | undefined): void;
39
39
 
40
- export { apitallyPlugin as default, setConsumer };
40
+ export { apitallyPlugin, apitallyPlugin as default, setConsumer };
@@ -37,4 +37,4 @@ declare function apitallyPlugin(config: ApitallyConfig): {
37
37
  };
38
38
  declare function setConsumer(request: Request, consumer: ApitallyConsumer | string | null | undefined): void;
39
39
 
40
- export { apitallyPlugin as default, setConsumer };
40
+ export { apitallyPlugin, apitallyPlugin as default, setConsumer };
@@ -181,6 +181,7 @@ function setConsumer(request, consumer) {
181
181
  }
182
182
  __name(setConsumer, "setConsumer");
183
183
  export {
184
+ apitallyPlugin,
184
185
  apitallyPlugin as default,
185
186
  setConsumer
186
187
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with span and logs context\n const spanHandle = client.spanCollector.startSpan();\n const logs: LogRecord[] = [];\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n request[LOGS_SYMBOL] = logs;\n const lifecycle = (request as any)._lifecycle.bind(request);\n (request as any)._lifecycle = () =>\n spanHandle.runInContext(() => logsContext.run(logs, lifecycle));\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(\n `${request.method.toUpperCase()} ${request.route.path}`,\n );\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n spans,\n traceId,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","SPAN_HANDLE_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","spanHandle","spanCollector","startSpan","logs","lifecycle","_lifecycle","bind","runInContext","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","setName","route","path","spans","end","traceId","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
1
+ {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with span and logs context\n const spanHandle = client.spanCollector.startSpan();\n const logs: LogRecord[] = [];\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n request[LOGS_SYMBOL] = logs;\n const lifecycle = (request as any)._lifecycle.bind(request);\n (request as any)._lifecycle = () =>\n spanHandle.runInContext(() => logsContext.run(logs, lifecycle));\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(\n `${request.method.toUpperCase()} ${request.route.path}`,\n );\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n spans,\n traceId,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n\nexport { apitallyPlugin };\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","SPAN_HANDLE_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","spanHandle","spanCollector","startSpan","logs","lifecycle","_lifecycle","bind","runInContext","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","setName","route","path","spans","end","traceId","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apitally",
3
- "version": "0.25.6",
3
+ "version": "0.25.8",
4
4
  "description": "Simple API monitoring & analytics for REST APIs built with Express, Fastify, NestJS, AdonisJS, Hono, H3, Elysia, Hapi, and Koa.",
5
5
  "author": "Apitally <hello@apitally.io>",
6
6
  "license": "MIT",
@@ -287,11 +287,17 @@
287
287
  "optional": true
288
288
  }
289
289
  },
290
+ "overrides": {
291
+ "@arethetypeswrong/cli": {
292
+ "fflate": "0.8.2"
293
+ }
294
+ },
290
295
  "devDependencies": {
291
296
  "@adonisjs/core": "^7.0.0",
297
+ "@arethetypeswrong/cli": "^0.18.2",
292
298
  "@eslint/js": "^9.29.0",
293
299
  "@hapi/hapi": "^21.4.3",
294
- "@hono/zod-validator": "^0.7.0",
300
+ "@hono/zod-validator": "^0.9.0",
295
301
  "@koa/router": "^13.1.0",
296
302
  "@nestjs/common": "^11.0.0",
297
303
  "@nestjs/core": "^11.0.0",
@@ -323,7 +329,7 @@
323
329
  "fastify": "^5.0.0",
324
330
  "fastify-plugin": "^5.0.1",
325
331
  "globals": "^17.0.0",
326
- "h3": "2.0.1-rc.20",
332
+ "h3": "2.0.1-rc.25",
327
333
  "hono": "^4.6.5",
328
334
  "koa": "^3.0.0",
329
335
  "koa-bodyparser": "^4.4.1",