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.
- package/dist/common/client.cjs +12 -12
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.d.cts +6 -6
- package/dist/common/client.d.ts +6 -6
- package/dist/common/client.js +6 -6
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.cjs +2 -0
- package/dist/common/consumerRegistry.cjs.map +1 -1
- package/dist/common/consumerRegistry.d.cts +1 -1
- package/dist/common/consumerRegistry.d.ts +1 -1
- package/dist/common/consumerRegistry.js +1 -0
- package/dist/common/consumerRegistry.js.map +1 -1
- package/dist/common/requestCounter.cjs +5 -0
- package/dist/common/requestCounter.cjs.map +1 -1
- package/dist/common/requestCounter.d.cts +1 -1
- package/dist/common/requestCounter.d.ts +1 -1
- package/dist/common/requestCounter.js +1 -0
- package/dist/common/requestCounter.js.map +1 -1
- package/dist/common/requestLogger.cjs +53 -37
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.d.cts +3 -2
- package/dist/common/requestLogger.d.ts +3 -2
- package/dist/common/requestLogger.js +51 -36
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/serverErrorCounter.cjs +2 -0
- package/dist/common/serverErrorCounter.cjs.map +1 -1
- package/dist/common/serverErrorCounter.d.cts +1 -1
- package/dist/common/serverErrorCounter.d.ts +1 -1
- package/dist/common/serverErrorCounter.js +1 -0
- package/dist/common/serverErrorCounter.js.map +1 -1
- package/dist/common/spanCollector.cjs +3 -1
- package/dist/common/spanCollector.cjs.map +1 -1
- package/dist/common/spanCollector.d.cts +1 -1
- package/dist/common/spanCollector.d.ts +1 -1
- package/dist/common/spanCollector.js +1 -0
- package/dist/common/spanCollector.js.map +1 -1
- package/dist/common/tempGzipFile.cjs +11 -5
- package/dist/common/tempGzipFile.cjs.map +1 -1
- package/dist/common/tempGzipFile.d.cts +2 -2
- package/dist/common/tempGzipFile.d.ts +2 -2
- package/dist/common/tempGzipFile.js +10 -5
- package/dist/common/tempGzipFile.js.map +1 -1
- package/dist/common/validationErrorCounter.cjs +5 -0
- package/dist/common/validationErrorCounter.cjs.map +1 -1
- package/dist/common/validationErrorCounter.d.cts +1 -1
- package/dist/common/validationErrorCounter.d.ts +1 -1
- package/dist/common/validationErrorCounter.js +1 -0
- package/dist/common/validationErrorCounter.js.map +1 -1
- package/dist/elysia/index.cjs +2 -12
- package/dist/elysia/index.cjs.map +1 -1
- package/dist/elysia/index.d.cts +1 -1
- package/dist/elysia/index.d.ts +1 -1
- package/dist/elysia/index.js +2 -2
- package/dist/elysia/index.js.map +1 -1
- package/dist/elysia/plugin.cjs +5 -0
- package/dist/elysia/plugin.cjs.map +1 -1
- package/dist/elysia/plugin.d.cts +1 -1
- package/dist/elysia/plugin.d.ts +1 -1
- package/dist/elysia/plugin.js +1 -0
- package/dist/elysia/plugin.js.map +1 -1
- package/dist/fastify/index.cjs +2 -12
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.d.cts +1 -1
- package/dist/fastify/index.d.ts +1 -1
- package/dist/fastify/index.js +2 -2
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +4 -1
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.d.cts +2 -2
- package/dist/fastify/plugin.d.ts +2 -2
- package/dist/fastify/plugin.js +3 -1
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/hapi/index.cjs +2 -12
- package/dist/hapi/index.cjs.map +1 -1
- package/dist/hapi/index.d.cts +1 -1
- package/dist/hapi/index.d.ts +1 -1
- package/dist/hapi/index.js +2 -2
- package/dist/hapi/index.js.map +1 -1
- package/dist/hapi/plugin.cjs +2 -0
- package/dist/hapi/plugin.cjs.map +1 -1
- package/dist/hapi/plugin.d.cts +1 -1
- package/dist/hapi/plugin.d.ts +1 -1
- package/dist/hapi/plugin.js +1 -0
- package/dist/hapi/plugin.js.map +1 -1
- package/package.json +9 -3
package/dist/fastify/plugin.d.ts
CHANGED
|
@@ -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
|
|
32
|
+
declare const apitallyFastifyPlugin: FastifyPluginAsync<ApitallyConfig>;
|
|
33
33
|
|
|
34
|
-
export { apitallyPlugin,
|
|
34
|
+
export { apitallyFastifyPlugin, apitallyPlugin, apitallyFastifyPlugin as default, setConsumer };
|
package/dist/fastify/plugin.js
CHANGED
|
@@ -271,10 +271,12 @@ function extractNestValidationErrors(message) {
|
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
__name(extractNestValidationErrors, "extractNestValidationErrors");
|
|
274
|
-
|
|
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":";;AAMA,OAAOA,QAAQ;AACf,SAASC,mBAAmBC,qBAAqB;AAEjD,SAASC,sBAAsB;AAC/B,SAASC,kCAAkC;AAC3C,SAASC,0BAA0B;AACnC,SAASC,yBAAyB;AAElC,SAASC,aAAaC,sBAAsB;AAQ5C,SACEC,cACAC,iBACAC,iBACAC,oBACK;AAEP,MAAMC,cAAcC,uBAAO,eAAA;AAC3B,MAAMC,wBAAwBD,uBAAO,wBAAA;AACrC,MAAME,qBAAqBF,uBAAO,qBAAA;AAkBlC,MAAMG,iBAAqD,8BACzDC,SACAC,WAAAA;AAEA,QAAMC,SAAS,IAAIjB,eAAegB,MAAAA;AAClC,QAAME,SAAqB,CAAA;AAC3B,QAAMC,cAAc,IAAIrB,kBAAAA;AAExB,MAAImB,OAAOG,cAAcJ,OAAOK,aAAa;AAC3Cf,iBAAaa,WAAAA;AACbV,iBAAaU,WAAAA;AACbX,oBAAgBO,QAAQO,KAAKH,WAAAA;AAC7BZ,oBAAgBY,WAAAA;EAClB;AAEAJ,UAAQQ,gBAAgB,oBAAoB,IAAA;AAC5CR,UAAQQ,gBAAgB,sBAAsB,IAAA;AAC9CR,UAAQS,cAAc,WAAW,IAAA;AAEjCT,UAAQU,QAAQ,WAAW,CAACC,iBAAAA;AAC1B,UAAMC,UAAUC,MAAMC,QAAQH,aAAaI,MAAM,IAC7CJ,aAAaI,SACb;MAACJ,aAAaI;;AAClBH,YAAQI,QAAQ,CAACD,WAAAA;AACf,UAAI,CAAC;QAAC;QAAQ;QAAWE,SAASF,OAAOG,YAAW,CAAA,GAAK;AACvDf,eAAOgB,KAAK;UACVJ,QAAQA,OAAOG,YAAW;UAC1BE,MAAMT,aAAaU;QACrB,CAAA;MACF;IACF,CAAA;EACF,CAAA;AAEArB,UAAQU,QAAQ,WAAW,MAAA;AACzBR,WAAOoB,eAAeC,WAAWpB,QAAQF,OAAOuB,UAAU,CAAA;AAC1DtB,WAAOuB,UAAS;EAClB,CAAA;AAEAzB,UAAQU,QAAQ,WAAW,YAAA;AACzB,UAAMR,OAAOwB,eAAc;EAC7B,CAAA;AAGA1B,UAAQU,QAAQ,aAAa,CAACiB,SAASC,OAAOC,SAAAA;AAC5C,QAAI3B,OAAO4B,UAAS,GAAI;AACtB,YAAMC,OAAoB,CAAA;AAC1BJ,cAAQhC,WAAAA,IAAeoC;AACvB3B,kBAAY4B,IAAID,MAAM,MAAA;AACpB,cAAME,aAAa/B,OAAOgC,cAAcC,UAAS;AACjDR,gBAAQ7B,kBAAAA,IAAsBmC;AAC9BA,mBAAWG,aAAa,MAAA;AACtB,gBAAMC,gBAAgB,IAAIrD,cAAc,iBAAA;AACxC2C,kBAAQ9B,qBAAAA,IAAyBwC;AACjCA,wBAAcC,gBAAgBT,MAAMF,QAAQY,GAAG;QACjD,CAAA;MACF,CAAA;IACF,OAAO;AACLV,WAAAA;IACF;EACF,CAAA;AAGA7B,UAAQU,QAAQ,iBAAiB,CAACiB,SAASC,OAAOC,SAAAA;AAChD,QAAI3B,OAAO4B,UAAS,KAAMH,QAAQ9B,qBAAAA,GAAwB;AACxD,YAAMwC,gBAAgBV,QAAQ9B,qBAAAA;AAC9BwC,oBAAcC,gBAAgBT,MAAMF,QAAQY,GAAG;IACjD,OAAO;AACLV,WAAAA;IACF;EACF,CAAA;AAEA7B,UAAQU,QAAQ,UAAU,CAACiB,SAASC,OAAOY,SAAcX,SAAAA;AACvD,UAAMY,cAAcb,MAAMc,UAAU,cAAA;AACpC,QAAIxC,OAAOG,cAAcsC,uBAAuBF,WAAAA,GAAc;AAC5Db,YAAMY,UAAUA;IAClB;AACAX,SAAAA;EACF,CAAA;AAEA7B,UAAQU,QAAQ,WAAW,CAACiB,SAASC,OAAOgB,OAAOf,SAAAA;AACjD,QAAI,CAACe,MAAMC,cAAcD,MAAMC,eAAe,KAAK;AACjDjB,YAAMkB,cAAcF;IACtB;AACAf,SAAAA;EACF,CAAA;AAEA7B,UAAQU,QAAQ,cAAc,CAACiB,SAASC,OAAOC,SAAAA;AAjIjD;AAkII,QAAI3B,OAAO4B,UAAS,KAAMH,QAAQZ,OAAOG,YAAW,MAAO,WAAW;AAEpE,YAAM6B,WAAWC,YAAYrB,OAAAA;AAC7B,YAAMP,OACJ,kBAAkBO,UACbA,QAAgBhB,aAAaU,MAC7BM,QAAgBsB;AACvB,YAAMC,cAAc/D,mBAAmBwC,QAAQwB,QAAQ,gBAAA,CAAiB;AACxE,YAAMC,eAAejE,mBACnByC,MAAMc,UAAU,gBAAA,CAAA;AAElB,YAAMW,eAAeC,gBAAgB1B,KAAAA;AACrC1B,aAAOqD,iBAAiBC,oBAAoBT,QAAAA;AAC5C7C,aAAOuD,eAAeC,WAAW;QAC/BX,UAAUA,qCAAUY;QACpB5C,QAAQY,QAAQZ;QAChBK;QACAyB,YAAYjB,MAAMiB;QAClBQ;QACAH;QACAE;MACF,CAAA;AAEA,WACGxB,MAAMiB,eAAe,OAAOjB,MAAMiB,eAAe,QAClDjB,MAAMY,SACN;AACA,YAAI;AACF,gBAAMoB,gBAAgBC,KAAKC,MAAMlC,MAAMY,OAAO;AAC9C,gBAAMuB,mBAAsC,CAAA;AAE5C,eACG,CAACH,cAAcI,QACdJ,cAAcI,SAAS,yBACzB,OAAOJ,cAAcK,YAAY,UACjC;AACAF,6BAAiB5C,KAAI,GAAI+C,iBAAiBN,cAAcK,OAAO,CAAA;UACjE,WAAWpD,MAAMC,QAAQ8C,cAAcK,OAAO,GAAG;AAC/CF,6BAAiB5C,KAAI,GAChBgD,4BAA4BP,cAAcK,OAAO,CAAA;UAExD;AAEAF,2BAAiB/C,QAAQ,CAAC4B,UAAAA;AACxB1C,mBAAOkE,uBAAuBC,mBAAmB;cAC/CtB,UAAUA,qCAAUY;cACpB5C,QAAQY,QAAQZ;cAChBK;cACA,GAAGwB;YACL,CAAA;UACF,CAAA;QACF,SAASA,OAAO;QAAC;MACnB;AAEA,UAAIhB,MAAMiB,eAAe,OAAOjB,MAAMkB,aAAa;AACjD5C,eAAOoE,mBAAmBC,eAAe;UACvCxB,UAAUA,qCAAUY;UACpB5C,QAAQY,QAAQZ;UAChBK;UACAoD,MAAM5C,MAAMkB,YAAY2B;UACxBC,KAAK9C,MAAMkB,YAAYmB;UACvBU,WAAW/C,MAAMkB,YAAY8B,SAAS;QACxC,CAAA;MACF;AAEA,YAAM3C,aAAaN,QAAQ7B,kBAAAA;AAC3BmC,+CAAY4C,QAAQ,GAAGlD,QAAQZ,MAAM,IAAIK,IAAAA;AACzC,YAAM0D,QAAQ7C,yCAAY8C;AAC1B,YAAMC,UAAU/C,yCAAY+C;AAE5B,UAAI9E,OAAOG,cAAc4E,SAAS;AAChC,cAAMlD,OAAOJ,QAAQhC,WAAAA;AACrBO,eAAOG,cAAc6E,WACnB;UACEC,WAAWC,KAAKC,IAAG,IAAK;UACxBtE,QAAQY,QAAQZ;UAChBK;UACAC,KAAK,GAAGM,QAAQ2D,QAAQ,MAAM3D,QAAQ4D,QAAQ5D,QAAQ6D,QAAQ,GAAG7D,QAAQ8D,eAAe9D,QAAQN,GAAG;UACnG8B,SAAS7D,eAAeqC,QAAQwB,OAAO;UACvCuC,MAAMxC;UACNH,UAAUA,qCAAUY;UACpBgC,MAAMtG,YAAYsC,QAAQgE,MAAMhE,QAAQwB,QAAQ,cAAA,CAAe;QACjE,GACA;UACEN,YAAYjB,MAAMiB;UAClBQ,cAAcA,eAAe;UAC7BF,SAAS7D,eAAesC,MAAMgE,WAAU,CAAA;UACxCF,MAAMtC;UACNuC,MAAMtG,YACJuC,MAAMY,UACNZ,WAAMc,UAAU,cAAA,MAAhBd,mBAAiCiE,UAAAA;QAErC,GACAjE,MAAMkB,aACNf,MACA+C,OACAE,OAAAA;MAEJ;IACF;AAEAnD,SAAAA;EACF,CAAA;AACF,GA9L2D;AAgM3D,SAASN,WAAWpB,QAAoBqB,YAAmB;AACzD,QAAMsE,WAAW;IAAC;MAAC;MAAUC,QAAQC,QAAQC,QAAQ,MAAM,EAAA;;;AAC3D,QAAMC,iBAAiB9G,kBAAkB,SAAA;AACzC,QAAM+G,cAAc/G,kBAAkB,MAAA;AACtC,QAAMgH,gBAAgBhH,kBAAkB,cAAA;AACxC,QAAMiH,kBAAkBjH,kBAAkB,OAAA;AAC1C,MAAI8G,gBAAgB;AAClBJ,aAAS3E,KAAK;MAAC;MAAW+E;KAAe;EAC3C;AACA,MAAIC,aAAa;AACfL,aAAS3E,KAAK;MAAC;MAAQgF;KAAY;EACrC;AACA,MAAIC,eAAe;AACjBN,aAAS3E,KAAK;MAAC;MAAUiF;KAAc;EACzC;AACA,MAAIC,iBAAiB;AACnBP,aAAS3E,KAAK;MAAC;MAAYkF;KAAgB;EAC7C;AACA,MAAI7E,YAAY;AACdsE,aAAS3E,KAAK;MAAC;MAAOK;KAAW;EACnC;AACA,SAAO;IACL8E,OAAOnG;IACP2F,UAAUS,OAAOC,YAAYV,QAAAA;IAC7B5F,QAAQ;EACV;AACF;AA1BSqB;AA4BF,SAASkF,YACd9E,SACAoB,UAAsD;AAEtDpB,UAAQ+E,mBAAmB3D,YAAY4D;AACzC;AALgBF;AAOhB,SAASzD,YAAYrB,SAAuB;AAC1C,MAAIA,QAAQ+E,kBAAkB;AAC5B,WAAOxH,2BAA2ByC,QAAQ+E,gBAAgB;EAC5D,WAAW/E,QAAQiF,oBAAoB;AAErCb,YAAQc,YACN,sGACA,oBAAA;AAEF,WAAO3H,2BAA2ByC,QAAQiF,kBAAkB;EAC9D;AACA,SAAO;AACT;AAZS5D;AAcT,SAASM,gBAAgB1B,OAAmB;AAC1C,MAAIA,MAAMkF,gBAAgBH,QAAW;AACnC,WAAO/E,MAAMkF;EACf,WAAYlF,MAAc0B,oBAAoBqD,QAAW;AACvD,WAAQ/E,MAAc0B,gBAAe;EACvC;AACA,SAAO;AACT;AAPSA;AAST,SAASY,iBAAiBD,SAAe;AACvC,MAAI;AACF,UAAM8C,QACJ;AACF,UAAMC,UAA8C,CAAA;AACpD,QAAIC;AACJ,YAAQA,QAAQF,MAAMG,KAAKjD,OAAAA,OAAc,MAAM;AAC7C+C,cAAQ7F,KAAK;QAAE8F,OAAOA,MAAM,CAAA;QAAIE,OAAOF,MAAME;MAAM,CAAA;IACrD;AAEA,WAAOH,QAAQI,IAAI,CAACC,GAAGC,MAAAA;AACrB,YAAMC,WACJD,IAAI,IAAIN,QAAQQ,SAASR,QAAQM,IAAI,CAAA,EAAGH,QAAQ,IAAIlD,QAAQuD;AAC9D,YAAMC,aAAaJ,EAAEJ,MAAMS,MAAM,MAAA;AACjC,UAAID,WAAW,CAAA,MAAO,eAAe;AACnCA,mBAAW,CAAA,IAAK;MAClB;AACA,aAAO;QACLE,KAAKF,WAAWG,KAAK,GAAA;QACrBlD,KAAKT,QAAQ4D,UAAUR,EAAEF,OAAOI,QAAAA;QAChC/C,MAAM;MACR;IACF,CAAA;EACF,SAAS5B,OAAO;AACd,WAAO,CAAA;EACT;AACF;AA1BSsB;AA4BT,SAASC,4BAA4BF,SAAc;AACjD,MAAI;AACF,WAAOA,QACJ6D,OAAO,CAACpD,QAAa,OAAOA,QAAQ,QAAA,EACpC0C,IAAI,CAAC1C,SAAc;MAClBiD,KAAK;MACLjD;MACAF,MAAM;IACR,EAAA;EACJ,SAAS5B,OAAO;AACd,WAAO,CAAA;EACT;AACF;AAZSuB;AAgBT,IAAA,iBAAerF,GAAGiB,gBAAgB;EAChC0E,MAAM;AACR,CAAA;","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"]}
|
package/dist/hapi/index.cjs
CHANGED
|
@@ -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.
|
|
21
|
+
apitallyPlugin: () => import_plugin.apitallyPlugin,
|
|
32
22
|
setConsumer: () => import_plugin.setConsumer
|
|
33
23
|
});
|
|
34
24
|
module.exports = __toCommonJS(hapi_exports);
|
|
35
|
-
var import_plugin =
|
|
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,
|
package/dist/hapi/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport {
|
|
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":[]}
|
package/dist/hapi/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.cjs';
|
|
2
|
-
export {
|
|
2
|
+
export { apitallyPlugin, setConsumer } from './plugin.cjs';
|
|
3
3
|
import '../common/logging.cjs';
|
|
4
4
|
import 'winston';
|
|
5
5
|
import '../common/requestLogger.cjs';
|
package/dist/hapi/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.js';
|
|
2
|
-
export {
|
|
2
|
+
export { apitallyPlugin, setConsumer } from './plugin.js';
|
|
3
3
|
import '../common/logging.js';
|
|
4
4
|
import 'winston';
|
|
5
5
|
import '../common/requestLogger.js';
|
package/dist/hapi/index.js
CHANGED
package/dist/hapi/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hapi/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport {
|
|
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"]}
|
package/dist/hapi/plugin.cjs
CHANGED
|
@@ -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
|
package/dist/hapi/plugin.cjs.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;;;;;;;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"]}
|
package/dist/hapi/plugin.d.cts
CHANGED
|
@@ -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 };
|
package/dist/hapi/plugin.d.ts
CHANGED
|
@@ -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 };
|
package/dist/hapi/plugin.js
CHANGED
package/dist/hapi/plugin.js.map
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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",
|