@loggerjs/node 0.4.0 → 0.5.1

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 (102) hide show
  1. package/README.md +5 -1
  2. package/dist/bullmq-integration.cjs +169 -0
  3. package/dist/bullmq-integration.cjs.map +1 -0
  4. package/dist/bullmq-integration.js +168 -0
  5. package/dist/bullmq-integration.js.map +1 -0
  6. package/dist/cli-integration.cjs +116 -0
  7. package/dist/cli-integration.cjs.map +1 -0
  8. package/dist/cli-integration.js +115 -0
  9. package/dist/cli-integration.js.map +1 -0
  10. package/dist/context.cjs +37 -0
  11. package/dist/context.cjs.map +1 -0
  12. package/dist/context.js +35 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/database-integration.cjs +128 -0
  15. package/dist/database-integration.cjs.map +1 -0
  16. package/dist/database-integration.js +127 -0
  17. package/dist/database-integration.js.map +1 -0
  18. package/dist/diagnostics-channel-integration.cjs +66 -0
  19. package/dist/diagnostics-channel-integration.cjs.map +1 -0
  20. package/dist/diagnostics-channel-integration.js +65 -0
  21. package/dist/diagnostics-channel-integration.js.map +1 -0
  22. package/dist/express-integration.cjs +130 -0
  23. package/dist/express-integration.cjs.map +1 -0
  24. package/dist/express-integration.js +129 -0
  25. package/dist/express-integration.js.map +1 -0
  26. package/dist/fastify-integration.cjs +120 -0
  27. package/dist/fastify-integration.cjs.map +1 -0
  28. package/dist/fastify-integration.js +119 -0
  29. package/dist/fastify-integration.js.map +1 -0
  30. package/dist/file-transport.cjs +260 -0
  31. package/dist/file-transport.cjs.map +1 -0
  32. package/dist/file-transport.js +259 -0
  33. package/dist/file-transport.js.map +1 -0
  34. package/dist/hapi-integration.cjs +61 -0
  35. package/dist/hapi-integration.cjs.map +1 -0
  36. package/dist/hapi-integration.js +60 -0
  37. package/dist/hapi-integration.js.map +1 -0
  38. package/dist/http-transport.cjs +55 -0
  39. package/dist/http-transport.cjs.map +1 -0
  40. package/dist/http-transport.js +54 -0
  41. package/dist/http-transport.js.map +1 -0
  42. package/dist/koa-integration.cjs +57 -0
  43. package/dist/koa-integration.cjs.map +1 -0
  44. package/dist/koa-integration.js +56 -0
  45. package/dist/koa-integration.js.map +1 -0
  46. package/dist/logger-diagnostics.cjs +46 -0
  47. package/dist/logger-diagnostics.cjs.map +1 -0
  48. package/dist/logger-diagnostics.js +45 -0
  49. package/dist/logger-diagnostics.js.map +1 -0
  50. package/dist/nest-integration.cjs +138 -0
  51. package/dist/nest-integration.cjs.map +1 -0
  52. package/dist/nest-integration.js +137 -0
  53. package/dist/nest-integration.js.map +1 -0
  54. package/dist/node-fetch-integration.cjs +113 -0
  55. package/dist/node-fetch-integration.cjs.map +1 -0
  56. package/dist/node-fetch-integration.js +112 -0
  57. package/dist/node-fetch-integration.js.map +1 -0
  58. package/dist/node-http-client-integration.cjs +192 -0
  59. package/dist/node-http-client-integration.cjs.map +1 -0
  60. package/dist/node-http-client-integration.js +192 -0
  61. package/dist/node-http-client-integration.js.map +1 -0
  62. package/dist/payload-transforms.cjs +29 -0
  63. package/dist/payload-transforms.cjs.map +1 -0
  64. package/dist/payload-transforms.js +28 -0
  65. package/dist/payload-transforms.js.map +1 -0
  66. package/dist/prisma-integration.cjs +150 -0
  67. package/dist/prisma-integration.cjs.map +1 -0
  68. package/dist/prisma-integration.js +149 -0
  69. package/dist/prisma-integration.js.map +1 -0
  70. package/dist/process-integration.cjs +134 -0
  71. package/dist/process-integration.cjs.map +1 -0
  72. package/dist/process-integration.js +133 -0
  73. package/dist/process-integration.js.map +1 -0
  74. package/dist/queue-integration.cjs +148 -0
  75. package/dist/queue-integration.cjs.map +1 -0
  76. package/dist/queue-integration.js +147 -0
  77. package/dist/queue-integration.js.map +1 -0
  78. package/dist/redis-integration.cjs +154 -0
  79. package/dist/redis-integration.cjs.map +1 -0
  80. package/dist/redis-integration.js +153 -0
  81. package/dist/redis-integration.js.map +1 -0
  82. package/dist/rotating-file-transport.cjs +318 -0
  83. package/dist/rotating-file-transport.cjs.map +1 -0
  84. package/dist/rotating-file-transport.js +317 -0
  85. package/dist/rotating-file-transport.js.map +1 -0
  86. package/dist/serverless-integration.cjs +104 -0
  87. package/dist/serverless-integration.cjs.map +1 -0
  88. package/dist/serverless-integration.js +103 -0
  89. package/dist/serverless-integration.js.map +1 -0
  90. package/dist/stdout-transport.cjs +197 -0
  91. package/dist/stdout-transport.cjs.map +1 -0
  92. package/dist/stdout-transport.js +195 -0
  93. package/dist/stdout-transport.js.map +1 -0
  94. package/dist/syslog-transport.cjs +135 -0
  95. package/dist/syslog-transport.cjs.map +1 -0
  96. package/dist/syslog-transport.js +133 -0
  97. package/dist/syslog-transport.js.map +1 -0
  98. package/dist/worker-transport.cjs +285 -0
  99. package/dist/worker-transport.cjs.map +1 -0
  100. package/dist/worker-transport.js +284 -0
  101. package/dist/worker-transport.js.map +1 -0
  102. package/package.json +104 -77
@@ -0,0 +1,130 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/express-integration.ts
4
+ const defaultRandom = () => Math.random();
5
+ function defaultSanitizeUrl(url) {
6
+ const queryIndex = url.indexOf("?");
7
+ const hashIndex = url.indexOf("#");
8
+ const end = Math.min(queryIndex >= 0 ? queryIndex : url.length, hashIndex >= 0 ? hashIndex : url.length);
9
+ return url.slice(0, end);
10
+ }
11
+ function defaultLevel(status, _req, _res, aborted) {
12
+ if (aborted) return "warn";
13
+ if (status >= 500) return "error";
14
+ if (status >= 400) return "warn";
15
+ return "info";
16
+ }
17
+ function requestUrl(req) {
18
+ return req.originalUrl ?? req.url ?? req.path ?? "/";
19
+ }
20
+ function headerValue(value) {
21
+ if (typeof value === "number") return String(value);
22
+ return value;
23
+ }
24
+ function pickRequestHeaders(req, names) {
25
+ if (!names || names.length === 0 || !req.headers) return void 0;
26
+ const out = {};
27
+ for (const name of names) {
28
+ const value = req.headers[name.toLowerCase()] ?? req.headers[name];
29
+ if (value !== void 0) out[name.toLowerCase()] = value;
30
+ }
31
+ return Object.keys(out).length > 0 ? out : void 0;
32
+ }
33
+ function pickResponseHeaders(res, names) {
34
+ if (!names || names.length === 0 || !res.getHeader) return void 0;
35
+ const out = {};
36
+ for (const name of names) {
37
+ const value = headerValue(res.getHeader(name));
38
+ if (value !== void 0) out[name.toLowerCase()] = value;
39
+ }
40
+ return Object.keys(out).length > 0 ? out : void 0;
41
+ }
42
+ function defaultRoute(req) {
43
+ const path = req.route?.path;
44
+ return typeof path === "string" ? path : void 0;
45
+ }
46
+ function removeListener(res, event, listener) {
47
+ if (res.off) {
48
+ res.off(event, listener);
49
+ return;
50
+ }
51
+ res.removeListener?.(event, listener);
52
+ }
53
+ function onResponseDone(res, event, listener) {
54
+ if (res.once) {
55
+ res.once(event, listener);
56
+ return;
57
+ }
58
+ res.on?.(event, listener);
59
+ }
60
+ function expressIntegration(logger, options = {}) {
61
+ const name = options.name ?? "express";
62
+ const minStatus = options.minStatus ?? 400;
63
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
64
+ const captureAborted = options.captureAborted ?? true;
65
+ const sampleRate = options.sampleRate ?? 1;
66
+ const random = options.random ?? defaultRandom;
67
+ const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;
68
+ const levelFor = options.level ?? defaultLevel;
69
+ const routeFor = options.getRoute ?? defaultRoute;
70
+ const bindContext = options.bindContext ?? true;
71
+ return (req, res, next) => {
72
+ const started = Date.now();
73
+ const method = (req.method ?? "GET").toUpperCase();
74
+ const url = sanitizeUrl(requestUrl(req));
75
+ const requestId = options.getRequestId?.(req, res);
76
+ let completed = false;
77
+ const context = {
78
+ httpMethod: method,
79
+ httpUrl: url,
80
+ requestId,
81
+ ...options.context?.(req, res)
82
+ };
83
+ const shouldCapture = (status, aborted) => {
84
+ if (aborted && captureAborted) return true;
85
+ if (status >= minStatus) return true;
86
+ if (!captureAll) return false;
87
+ return sampleRate >= 1 || random() < sampleRate;
88
+ };
89
+ const cleanup = () => {
90
+ removeListener(res, "finish", onFinish);
91
+ removeListener(res, "close", onClose);
92
+ };
93
+ const logRequest = (event) => {
94
+ if (completed) return;
95
+ completed = true;
96
+ cleanup();
97
+ const status = res.statusCode ?? 0;
98
+ const aborted = event === "close" && res.writableEnded !== true;
99
+ if (!shouldCapture(status, aborted)) return;
100
+ const http = {
101
+ kind: name,
102
+ framework: "express",
103
+ method,
104
+ url,
105
+ route: routeFor(req),
106
+ status,
107
+ durationMs: Date.now() - started,
108
+ aborted,
109
+ requestId,
110
+ remoteAddress: req.ip ?? req.socket?.remoteAddress,
111
+ requestHeaders: pickRequestHeaders(req, options.captureRequestHeaders),
112
+ responseHeaders: pickResponseHeaders(res, options.captureResponseHeaders)
113
+ };
114
+ logger.log(levelFor(status, req, res, aborted), `Express ${status} ${method} ${url}`, { http });
115
+ };
116
+ const onFinish = () => logRequest("finish");
117
+ const onClose = () => logRequest("close");
118
+ onResponseDone(res, "finish", onFinish);
119
+ onResponseDone(res, "close", onClose);
120
+ if (bindContext) {
121
+ (0, _loggerjs_core.withContext)(context, () => next());
122
+ return;
123
+ }
124
+ next();
125
+ };
126
+ }
127
+ //#endregion
128
+ exports.expressIntegration = expressIntegration;
129
+
130
+ //# sourceMappingURL=express-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-integration.cjs","names":[],"sources":["../src/express-integration.ts"],"sourcesContent":["import { withContext, type LoggerLevel, type LoggerLike, type LogData } from \"@loggerjs/core\";\n\nexport interface ExpressRequestLike {\n method?: string;\n originalUrl?: string;\n url?: string;\n path?: string;\n headers?: Record<string, string | string[] | undefined>;\n ip?: string;\n route?: { path?: string };\n socket?: { remoteAddress?: string };\n [key: string]: unknown;\n}\n\nexport interface ExpressResponseLike {\n statusCode?: number;\n writableEnded?: boolean;\n headersSent?: boolean;\n getHeader?: (name: string) => number | string | string[] | undefined;\n once?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n on?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n off?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n removeListener?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n}\n\nexport type ExpressNextFunction = (error?: unknown) => void;\nexport type ExpressRequestHandler = (\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n next: ExpressNextFunction,\n) => void;\n\nexport interface ExpressIntegrationOptions {\n name?: string;\n minStatus?: number;\n captureAll?: boolean;\n captureSuccessful?: boolean;\n captureAborted?: boolean;\n sampleRate?: number;\n random?: () => number;\n bindContext?: boolean;\n captureRequestHeaders?: readonly string[];\n captureResponseHeaders?: readonly string[];\n sanitizeUrl?: (url: string) => string;\n getRequestId?: (req: ExpressRequestLike, res: ExpressResponseLike) => string | undefined;\n getRoute?: (req: ExpressRequestLike) => string | undefined;\n context?: (\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n ) => Record<string, unknown> | undefined;\n level?: (\n status: number,\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n aborted: boolean,\n ) => LoggerLevel;\n}\n\nconst defaultRandom = () => Math.random();\n\nfunction defaultSanitizeUrl(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n const hashIndex = url.indexOf(\"#\");\n const end = Math.min(\n queryIndex >= 0 ? queryIndex : url.length,\n hashIndex >= 0 ? hashIndex : url.length,\n );\n return url.slice(0, end);\n}\n\nfunction defaultLevel(\n status: number,\n _req: ExpressRequestLike,\n _res: ExpressResponseLike,\n aborted: boolean,\n): LoggerLevel {\n if (aborted) return \"warn\";\n if (status >= 500) return \"error\";\n if (status >= 400) return \"warn\";\n return \"info\";\n}\n\nfunction requestUrl(req: ExpressRequestLike): string {\n return req.originalUrl ?? req.url ?? req.path ?? \"/\";\n}\n\nfunction headerValue(value: number | string | string[] | undefined): string | string[] | undefined {\n if (typeof value === \"number\") return String(value);\n return value;\n}\n\nfunction pickRequestHeaders(\n req: ExpressRequestLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !req.headers) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = req.headers[name.toLowerCase()] ?? req.headers[name];\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction pickResponseHeaders(\n res: ExpressResponseLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !res.getHeader) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = headerValue(res.getHeader(name));\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction defaultRoute(req: ExpressRequestLike): string | undefined {\n const path = req.route?.path;\n return typeof path === \"string\" ? path : undefined;\n}\n\nfunction removeListener(res: ExpressResponseLike, event: \"finish\" | \"close\", listener: () => void) {\n if (res.off) {\n res.off(event, listener);\n return;\n }\n res.removeListener?.(event, listener);\n}\n\nfunction onResponseDone(res: ExpressResponseLike, event: \"finish\" | \"close\", listener: () => void) {\n if (res.once) {\n res.once(event, listener);\n return;\n }\n res.on?.(event, listener);\n}\n\nexport function expressIntegration(\n logger: LoggerLike,\n options: ExpressIntegrationOptions = {},\n): ExpressRequestHandler {\n const name = options.name ?? \"express\";\n const minStatus = options.minStatus ?? 400;\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const captureAborted = options.captureAborted ?? true;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;\n const levelFor = options.level ?? defaultLevel;\n const routeFor = options.getRoute ?? defaultRoute;\n const bindContext = options.bindContext ?? true;\n\n return (req, res, next) => {\n const started = Date.now();\n const method = (req.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(requestUrl(req));\n const requestId = options.getRequestId?.(req, res);\n let completed = false;\n\n const context = {\n httpMethod: method,\n httpUrl: url,\n requestId,\n ...options.context?.(req, res),\n };\n\n const shouldCapture = (status: number, aborted: boolean) => {\n if (aborted && captureAborted) return true;\n if (status >= minStatus) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n const cleanup = () => {\n removeListener(res, \"finish\", onFinish);\n removeListener(res, \"close\", onClose);\n };\n\n const logRequest = (event: \"finish\" | \"close\") => {\n if (completed) return;\n completed = true;\n cleanup();\n const status = res.statusCode ?? 0;\n const aborted = event === \"close\" && res.writableEnded !== true;\n if (!shouldCapture(status, aborted)) return;\n const http: Record<string, unknown> = {\n kind: name,\n framework: \"express\",\n method,\n url,\n route: routeFor(req),\n status,\n durationMs: Date.now() - started,\n aborted,\n requestId,\n remoteAddress: req.ip ?? req.socket?.remoteAddress,\n requestHeaders: pickRequestHeaders(req, options.captureRequestHeaders),\n responseHeaders: pickResponseHeaders(res, options.captureResponseHeaders),\n };\n logger.log(levelFor(status, req, res, aborted), `Express ${status} ${method} ${url}`, {\n http,\n } as LogData);\n };\n\n const onFinish = () => logRequest(\"finish\");\n const onClose = () => logRequest(\"close\");\n onResponseDone(res, \"finish\", onFinish);\n onResponseDone(res, \"close\", onClose);\n\n if (bindContext) {\n withContext(context, () => next());\n return;\n }\n next();\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ import { withContext } from "@loggerjs/core";
2
+ //#region src/express-integration.ts
3
+ const defaultRandom = () => Math.random();
4
+ function defaultSanitizeUrl(url) {
5
+ const queryIndex = url.indexOf("?");
6
+ const hashIndex = url.indexOf("#");
7
+ const end = Math.min(queryIndex >= 0 ? queryIndex : url.length, hashIndex >= 0 ? hashIndex : url.length);
8
+ return url.slice(0, end);
9
+ }
10
+ function defaultLevel(status, _req, _res, aborted) {
11
+ if (aborted) return "warn";
12
+ if (status >= 500) return "error";
13
+ if (status >= 400) return "warn";
14
+ return "info";
15
+ }
16
+ function requestUrl(req) {
17
+ return req.originalUrl ?? req.url ?? req.path ?? "/";
18
+ }
19
+ function headerValue(value) {
20
+ if (typeof value === "number") return String(value);
21
+ return value;
22
+ }
23
+ function pickRequestHeaders(req, names) {
24
+ if (!names || names.length === 0 || !req.headers) return void 0;
25
+ const out = {};
26
+ for (const name of names) {
27
+ const value = req.headers[name.toLowerCase()] ?? req.headers[name];
28
+ if (value !== void 0) out[name.toLowerCase()] = value;
29
+ }
30
+ return Object.keys(out).length > 0 ? out : void 0;
31
+ }
32
+ function pickResponseHeaders(res, names) {
33
+ if (!names || names.length === 0 || !res.getHeader) return void 0;
34
+ const out = {};
35
+ for (const name of names) {
36
+ const value = headerValue(res.getHeader(name));
37
+ if (value !== void 0) out[name.toLowerCase()] = value;
38
+ }
39
+ return Object.keys(out).length > 0 ? out : void 0;
40
+ }
41
+ function defaultRoute(req) {
42
+ const path = req.route?.path;
43
+ return typeof path === "string" ? path : void 0;
44
+ }
45
+ function removeListener(res, event, listener) {
46
+ if (res.off) {
47
+ res.off(event, listener);
48
+ return;
49
+ }
50
+ res.removeListener?.(event, listener);
51
+ }
52
+ function onResponseDone(res, event, listener) {
53
+ if (res.once) {
54
+ res.once(event, listener);
55
+ return;
56
+ }
57
+ res.on?.(event, listener);
58
+ }
59
+ function expressIntegration(logger, options = {}) {
60
+ const name = options.name ?? "express";
61
+ const minStatus = options.minStatus ?? 400;
62
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
63
+ const captureAborted = options.captureAborted ?? true;
64
+ const sampleRate = options.sampleRate ?? 1;
65
+ const random = options.random ?? defaultRandom;
66
+ const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;
67
+ const levelFor = options.level ?? defaultLevel;
68
+ const routeFor = options.getRoute ?? defaultRoute;
69
+ const bindContext = options.bindContext ?? true;
70
+ return (req, res, next) => {
71
+ const started = Date.now();
72
+ const method = (req.method ?? "GET").toUpperCase();
73
+ const url = sanitizeUrl(requestUrl(req));
74
+ const requestId = options.getRequestId?.(req, res);
75
+ let completed = false;
76
+ const context = {
77
+ httpMethod: method,
78
+ httpUrl: url,
79
+ requestId,
80
+ ...options.context?.(req, res)
81
+ };
82
+ const shouldCapture = (status, aborted) => {
83
+ if (aborted && captureAborted) return true;
84
+ if (status >= minStatus) return true;
85
+ if (!captureAll) return false;
86
+ return sampleRate >= 1 || random() < sampleRate;
87
+ };
88
+ const cleanup = () => {
89
+ removeListener(res, "finish", onFinish);
90
+ removeListener(res, "close", onClose);
91
+ };
92
+ const logRequest = (event) => {
93
+ if (completed) return;
94
+ completed = true;
95
+ cleanup();
96
+ const status = res.statusCode ?? 0;
97
+ const aborted = event === "close" && res.writableEnded !== true;
98
+ if (!shouldCapture(status, aborted)) return;
99
+ const http = {
100
+ kind: name,
101
+ framework: "express",
102
+ method,
103
+ url,
104
+ route: routeFor(req),
105
+ status,
106
+ durationMs: Date.now() - started,
107
+ aborted,
108
+ requestId,
109
+ remoteAddress: req.ip ?? req.socket?.remoteAddress,
110
+ requestHeaders: pickRequestHeaders(req, options.captureRequestHeaders),
111
+ responseHeaders: pickResponseHeaders(res, options.captureResponseHeaders)
112
+ };
113
+ logger.log(levelFor(status, req, res, aborted), `Express ${status} ${method} ${url}`, { http });
114
+ };
115
+ const onFinish = () => logRequest("finish");
116
+ const onClose = () => logRequest("close");
117
+ onResponseDone(res, "finish", onFinish);
118
+ onResponseDone(res, "close", onClose);
119
+ if (bindContext) {
120
+ withContext(context, () => next());
121
+ return;
122
+ }
123
+ next();
124
+ };
125
+ }
126
+ //#endregion
127
+ export { expressIntegration };
128
+
129
+ //# sourceMappingURL=express-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-integration.js","names":[],"sources":["../src/express-integration.ts"],"sourcesContent":["import { withContext, type LoggerLevel, type LoggerLike, type LogData } from \"@loggerjs/core\";\n\nexport interface ExpressRequestLike {\n method?: string;\n originalUrl?: string;\n url?: string;\n path?: string;\n headers?: Record<string, string | string[] | undefined>;\n ip?: string;\n route?: { path?: string };\n socket?: { remoteAddress?: string };\n [key: string]: unknown;\n}\n\nexport interface ExpressResponseLike {\n statusCode?: number;\n writableEnded?: boolean;\n headersSent?: boolean;\n getHeader?: (name: string) => number | string | string[] | undefined;\n once?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n on?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n off?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n removeListener?: (event: \"finish\" | \"close\", listener: () => void) => unknown;\n}\n\nexport type ExpressNextFunction = (error?: unknown) => void;\nexport type ExpressRequestHandler = (\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n next: ExpressNextFunction,\n) => void;\n\nexport interface ExpressIntegrationOptions {\n name?: string;\n minStatus?: number;\n captureAll?: boolean;\n captureSuccessful?: boolean;\n captureAborted?: boolean;\n sampleRate?: number;\n random?: () => number;\n bindContext?: boolean;\n captureRequestHeaders?: readonly string[];\n captureResponseHeaders?: readonly string[];\n sanitizeUrl?: (url: string) => string;\n getRequestId?: (req: ExpressRequestLike, res: ExpressResponseLike) => string | undefined;\n getRoute?: (req: ExpressRequestLike) => string | undefined;\n context?: (\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n ) => Record<string, unknown> | undefined;\n level?: (\n status: number,\n req: ExpressRequestLike,\n res: ExpressResponseLike,\n aborted: boolean,\n ) => LoggerLevel;\n}\n\nconst defaultRandom = () => Math.random();\n\nfunction defaultSanitizeUrl(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n const hashIndex = url.indexOf(\"#\");\n const end = Math.min(\n queryIndex >= 0 ? queryIndex : url.length,\n hashIndex >= 0 ? hashIndex : url.length,\n );\n return url.slice(0, end);\n}\n\nfunction defaultLevel(\n status: number,\n _req: ExpressRequestLike,\n _res: ExpressResponseLike,\n aborted: boolean,\n): LoggerLevel {\n if (aborted) return \"warn\";\n if (status >= 500) return \"error\";\n if (status >= 400) return \"warn\";\n return \"info\";\n}\n\nfunction requestUrl(req: ExpressRequestLike): string {\n return req.originalUrl ?? req.url ?? req.path ?? \"/\";\n}\n\nfunction headerValue(value: number | string | string[] | undefined): string | string[] | undefined {\n if (typeof value === \"number\") return String(value);\n return value;\n}\n\nfunction pickRequestHeaders(\n req: ExpressRequestLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !req.headers) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = req.headers[name.toLowerCase()] ?? req.headers[name];\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction pickResponseHeaders(\n res: ExpressResponseLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !res.getHeader) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = headerValue(res.getHeader(name));\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction defaultRoute(req: ExpressRequestLike): string | undefined {\n const path = req.route?.path;\n return typeof path === \"string\" ? path : undefined;\n}\n\nfunction removeListener(res: ExpressResponseLike, event: \"finish\" | \"close\", listener: () => void) {\n if (res.off) {\n res.off(event, listener);\n return;\n }\n res.removeListener?.(event, listener);\n}\n\nfunction onResponseDone(res: ExpressResponseLike, event: \"finish\" | \"close\", listener: () => void) {\n if (res.once) {\n res.once(event, listener);\n return;\n }\n res.on?.(event, listener);\n}\n\nexport function expressIntegration(\n logger: LoggerLike,\n options: ExpressIntegrationOptions = {},\n): ExpressRequestHandler {\n const name = options.name ?? \"express\";\n const minStatus = options.minStatus ?? 400;\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const captureAborted = options.captureAborted ?? true;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;\n const levelFor = options.level ?? defaultLevel;\n const routeFor = options.getRoute ?? defaultRoute;\n const bindContext = options.bindContext ?? true;\n\n return (req, res, next) => {\n const started = Date.now();\n const method = (req.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(requestUrl(req));\n const requestId = options.getRequestId?.(req, res);\n let completed = false;\n\n const context = {\n httpMethod: method,\n httpUrl: url,\n requestId,\n ...options.context?.(req, res),\n };\n\n const shouldCapture = (status: number, aborted: boolean) => {\n if (aborted && captureAborted) return true;\n if (status >= minStatus) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n const cleanup = () => {\n removeListener(res, \"finish\", onFinish);\n removeListener(res, \"close\", onClose);\n };\n\n const logRequest = (event: \"finish\" | \"close\") => {\n if (completed) return;\n completed = true;\n cleanup();\n const status = res.statusCode ?? 0;\n const aborted = event === \"close\" && res.writableEnded !== true;\n if (!shouldCapture(status, aborted)) return;\n const http: Record<string, unknown> = {\n kind: name,\n framework: \"express\",\n method,\n url,\n route: routeFor(req),\n status,\n durationMs: Date.now() - started,\n aborted,\n requestId,\n remoteAddress: req.ip ?? req.socket?.remoteAddress,\n requestHeaders: pickRequestHeaders(req, options.captureRequestHeaders),\n responseHeaders: pickResponseHeaders(res, options.captureResponseHeaders),\n };\n logger.log(levelFor(status, req, res, aborted), `Express ${status} ${method} ${url}`, {\n http,\n } as LogData);\n };\n\n const onFinish = () => logRequest(\"finish\");\n const onClose = () => logRequest(\"close\");\n onResponseDone(res, \"finish\", onFinish);\n onResponseDone(res, \"close\", onClose);\n\n if (bindContext) {\n withContext(context, () => next());\n return;\n }\n next();\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/fastify-integration.ts
4
+ const defaultRandom = () => Math.random();
5
+ function defaultSanitizeUrl(url) {
6
+ const queryIndex = url.indexOf("?");
7
+ const hashIndex = url.indexOf("#");
8
+ const end = Math.min(queryIndex >= 0 ? queryIndex : url.length, hashIndex >= 0 ? hashIndex : url.length);
9
+ return url.slice(0, end);
10
+ }
11
+ function defaultLevel(status, _request, _reply, error) {
12
+ if (error || status >= 500) return "error";
13
+ if (status >= 400) return "warn";
14
+ return "info";
15
+ }
16
+ function headerValue(value) {
17
+ if (typeof value === "number") return String(value);
18
+ return value;
19
+ }
20
+ function pickRequestHeaders(request, names) {
21
+ if (!names || names.length === 0 || !request.headers) return void 0;
22
+ const out = {};
23
+ for (const name of names) {
24
+ const value = request.headers[name.toLowerCase()] ?? request.headers[name];
25
+ if (value !== void 0) out[name.toLowerCase()] = value;
26
+ }
27
+ return Object.keys(out).length > 0 ? out : void 0;
28
+ }
29
+ function pickResponseHeaders(reply, names) {
30
+ if (!names || names.length === 0 || !reply.getHeader) return void 0;
31
+ const out = {};
32
+ for (const name of names) {
33
+ const value = headerValue(reply.getHeader(name));
34
+ if (value !== void 0) out[name.toLowerCase()] = value;
35
+ }
36
+ return Object.keys(out).length > 0 ? out : void 0;
37
+ }
38
+ function defaultRoute(request) {
39
+ return request.routeOptions?.url ?? request.routerPath;
40
+ }
41
+ function fastifyIntegration(logger, options = {}) {
42
+ const name = options.name ?? "fastify";
43
+ const minStatus = options.minStatus ?? 400;
44
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
45
+ const sampleRate = options.sampleRate ?? 1;
46
+ const random = options.random ?? defaultRandom;
47
+ const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;
48
+ const levelFor = options.level ?? defaultLevel;
49
+ const routeFor = options.getRoute ?? defaultRoute;
50
+ const bindContext = options.bindContext ?? true;
51
+ const states = /* @__PURE__ */ new WeakMap();
52
+ const shouldCapture = (status, error) => {
53
+ if (error) return true;
54
+ if (status >= minStatus) return true;
55
+ if (!captureAll) return false;
56
+ return sampleRate >= 1 || random() < sampleRate;
57
+ };
58
+ return (instance, _pluginOptions, done) => {
59
+ instance.addHook("onRequest", (request, reply, next) => {
60
+ const method = (request.method ?? "GET").toUpperCase();
61
+ const url = sanitizeUrl(request.url ?? "/");
62
+ const requestId = options.getRequestId?.(request, reply) ?? request.id;
63
+ states.set(request, { started: Date.now() });
64
+ const context = {
65
+ httpMethod: method,
66
+ httpUrl: url,
67
+ requestId,
68
+ ...options.context?.(request, reply)
69
+ };
70
+ if (bindContext) {
71
+ (0, _loggerjs_core.withContext)(context, () => next());
72
+ return;
73
+ }
74
+ next();
75
+ });
76
+ instance.addHook("onError", (request, _reply, error, next) => {
77
+ const state = states.get(request);
78
+ if (state) state.error = error;
79
+ else states.set(request, {
80
+ started: Date.now(),
81
+ error
82
+ });
83
+ next();
84
+ });
85
+ instance.addHook("onResponse", (request, reply, next) => {
86
+ const state = states.get(request) ?? { started: Date.now() };
87
+ states.delete(request);
88
+ const status = reply.statusCode ?? 0;
89
+ const error = state.error;
90
+ if (!shouldCapture(status, error)) {
91
+ next();
92
+ return;
93
+ }
94
+ const method = (request.method ?? "GET").toUpperCase();
95
+ const url = sanitizeUrl(request.url ?? "/");
96
+ const requestId = options.getRequestId?.(request, reply) ?? request.id;
97
+ const data = { http: {
98
+ kind: name,
99
+ framework: "fastify",
100
+ method,
101
+ url,
102
+ route: routeFor(request),
103
+ status,
104
+ durationMs: Date.now() - state.started,
105
+ requestId,
106
+ remoteAddress: request.ip,
107
+ requestHeaders: pickRequestHeaders(request, options.captureRequestHeaders),
108
+ responseHeaders: pickResponseHeaders(reply, options.captureResponseHeaders)
109
+ } };
110
+ if (error) data.error = error;
111
+ logger.log(levelFor(status, request, reply, error), `Fastify ${status} ${method} ${url}`, { ...data });
112
+ next();
113
+ });
114
+ done?.();
115
+ };
116
+ }
117
+ //#endregion
118
+ exports.fastifyIntegration = fastifyIntegration;
119
+
120
+ //# sourceMappingURL=fastify-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify-integration.cjs","names":[],"sources":["../src/fastify-integration.ts"],"sourcesContent":["import { withContext, type LoggerLevel, type LoggerLike, type LogData } from \"@loggerjs/core\";\n\nexport interface FastifyRequestLike {\n id?: string;\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n ip?: string;\n routeOptions?: { url?: string };\n routerPath?: string;\n [key: string]: unknown;\n}\n\nexport interface FastifyReplyLike {\n statusCode?: number;\n getHeader?: (name: string) => number | string | string[] | undefined;\n [key: string]: unknown;\n}\n\nexport type FastifyDone = (error?: unknown) => void;\nexport type FastifyOnRequestHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: FastifyDone,\n) => void;\nexport type FastifyOnResponseHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: FastifyDone,\n) => void;\nexport type FastifyOnErrorHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n error: unknown,\n done: FastifyDone,\n) => void;\n\nexport interface FastifyInstanceLike {\n addHook: (\n name: \"onRequest\" | \"onResponse\" | \"onError\",\n hook: FastifyOnRequestHook | FastifyOnResponseHook | FastifyOnErrorHook,\n ) => unknown;\n}\n\nexport type FastifyPluginCallback = (\n instance: FastifyInstanceLike,\n options: unknown,\n done?: FastifyDone,\n) => void;\n\nexport interface FastifyIntegrationOptions {\n name?: string;\n minStatus?: number;\n captureAll?: boolean;\n captureSuccessful?: boolean;\n sampleRate?: number;\n random?: () => number;\n bindContext?: boolean;\n captureRequestHeaders?: readonly string[];\n captureResponseHeaders?: readonly string[];\n sanitizeUrl?: (url: string) => string;\n getRequestId?: (request: FastifyRequestLike, reply: FastifyReplyLike) => string | undefined;\n getRoute?: (request: FastifyRequestLike) => string | undefined;\n context?: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => Record<string, unknown> | undefined;\n level?: (\n status: number,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n error: unknown,\n ) => LoggerLevel;\n}\n\ninterface RequestState {\n started: number;\n error?: unknown;\n}\n\nconst defaultRandom = () => Math.random();\n\nfunction defaultSanitizeUrl(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n const hashIndex = url.indexOf(\"#\");\n const end = Math.min(\n queryIndex >= 0 ? queryIndex : url.length,\n hashIndex >= 0 ? hashIndex : url.length,\n );\n return url.slice(0, end);\n}\n\nfunction defaultLevel(\n status: number,\n _request: FastifyRequestLike,\n _reply: FastifyReplyLike,\n error: unknown,\n): LoggerLevel {\n if (error || status >= 500) return \"error\";\n if (status >= 400) return \"warn\";\n return \"info\";\n}\n\nfunction headerValue(value: number | string | string[] | undefined): string | string[] | undefined {\n if (typeof value === \"number\") return String(value);\n return value;\n}\n\nfunction pickRequestHeaders(\n request: FastifyRequestLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !request.headers) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = request.headers[name.toLowerCase()] ?? request.headers[name];\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction pickResponseHeaders(\n reply: FastifyReplyLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !reply.getHeader) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = headerValue(reply.getHeader(name));\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction defaultRoute(request: FastifyRequestLike): string | undefined {\n return request.routeOptions?.url ?? request.routerPath;\n}\n\nexport function fastifyIntegration(\n logger: LoggerLike,\n options: FastifyIntegrationOptions = {},\n): FastifyPluginCallback {\n const name = options.name ?? \"fastify\";\n const minStatus = options.minStatus ?? 400;\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;\n const levelFor = options.level ?? defaultLevel;\n const routeFor = options.getRoute ?? defaultRoute;\n const bindContext = options.bindContext ?? true;\n const states = new WeakMap<FastifyRequestLike, RequestState>();\n\n const shouldCapture = (status: number, error: unknown) => {\n if (error) return true;\n if (status >= minStatus) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return (instance, _pluginOptions, done) => {\n instance.addHook(\n \"onRequest\",\n (request: FastifyRequestLike, reply: FastifyReplyLike, next: FastifyDone) => {\n const method = (request.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(request.url ?? \"/\");\n const requestId = options.getRequestId?.(request, reply) ?? request.id;\n states.set(request, { started: Date.now() });\n const context = {\n httpMethod: method,\n httpUrl: url,\n requestId,\n ...options.context?.(request, reply),\n };\n if (bindContext) {\n withContext(context, () => next());\n return;\n }\n next();\n },\n );\n\n instance.addHook(\n \"onError\",\n (\n request: FastifyRequestLike,\n _reply: FastifyReplyLike,\n error: unknown,\n next: FastifyDone,\n ) => {\n const state = states.get(request);\n if (state) state.error = error;\n else states.set(request, { started: Date.now(), error });\n next();\n },\n );\n\n instance.addHook(\n \"onResponse\",\n (request: FastifyRequestLike, reply: FastifyReplyLike, next: FastifyDone) => {\n const state = states.get(request) ?? { started: Date.now() };\n states.delete(request);\n const status = reply.statusCode ?? 0;\n const error = state.error;\n if (!shouldCapture(status, error)) {\n next();\n return;\n }\n\n const method = (request.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(request.url ?? \"/\");\n const requestId = options.getRequestId?.(request, reply) ?? request.id;\n const http: Record<string, unknown> = {\n kind: name,\n framework: \"fastify\",\n method,\n url,\n route: routeFor(request),\n status,\n durationMs: Date.now() - state.started,\n requestId,\n remoteAddress: request.ip,\n requestHeaders: pickRequestHeaders(request, options.captureRequestHeaders),\n responseHeaders: pickResponseHeaders(reply, options.captureResponseHeaders),\n };\n const data: Record<string, unknown> = { http };\n if (error) data.error = error;\n logger.log(levelFor(status, request, reply, error), `Fastify ${status} ${method} ${url}`, {\n ...data,\n } as LogData);\n next();\n },\n );\n\n done?.();\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { withContext } from "@loggerjs/core";
2
+ //#region src/fastify-integration.ts
3
+ const defaultRandom = () => Math.random();
4
+ function defaultSanitizeUrl(url) {
5
+ const queryIndex = url.indexOf("?");
6
+ const hashIndex = url.indexOf("#");
7
+ const end = Math.min(queryIndex >= 0 ? queryIndex : url.length, hashIndex >= 0 ? hashIndex : url.length);
8
+ return url.slice(0, end);
9
+ }
10
+ function defaultLevel(status, _request, _reply, error) {
11
+ if (error || status >= 500) return "error";
12
+ if (status >= 400) return "warn";
13
+ return "info";
14
+ }
15
+ function headerValue(value) {
16
+ if (typeof value === "number") return String(value);
17
+ return value;
18
+ }
19
+ function pickRequestHeaders(request, names) {
20
+ if (!names || names.length === 0 || !request.headers) return void 0;
21
+ const out = {};
22
+ for (const name of names) {
23
+ const value = request.headers[name.toLowerCase()] ?? request.headers[name];
24
+ if (value !== void 0) out[name.toLowerCase()] = value;
25
+ }
26
+ return Object.keys(out).length > 0 ? out : void 0;
27
+ }
28
+ function pickResponseHeaders(reply, names) {
29
+ if (!names || names.length === 0 || !reply.getHeader) return void 0;
30
+ const out = {};
31
+ for (const name of names) {
32
+ const value = headerValue(reply.getHeader(name));
33
+ if (value !== void 0) out[name.toLowerCase()] = value;
34
+ }
35
+ return Object.keys(out).length > 0 ? out : void 0;
36
+ }
37
+ function defaultRoute(request) {
38
+ return request.routeOptions?.url ?? request.routerPath;
39
+ }
40
+ function fastifyIntegration(logger, options = {}) {
41
+ const name = options.name ?? "fastify";
42
+ const minStatus = options.minStatus ?? 400;
43
+ const captureAll = options.captureAll ?? options.captureSuccessful ?? false;
44
+ const sampleRate = options.sampleRate ?? 1;
45
+ const random = options.random ?? defaultRandom;
46
+ const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;
47
+ const levelFor = options.level ?? defaultLevel;
48
+ const routeFor = options.getRoute ?? defaultRoute;
49
+ const bindContext = options.bindContext ?? true;
50
+ const states = /* @__PURE__ */ new WeakMap();
51
+ const shouldCapture = (status, error) => {
52
+ if (error) return true;
53
+ if (status >= minStatus) return true;
54
+ if (!captureAll) return false;
55
+ return sampleRate >= 1 || random() < sampleRate;
56
+ };
57
+ return (instance, _pluginOptions, done) => {
58
+ instance.addHook("onRequest", (request, reply, next) => {
59
+ const method = (request.method ?? "GET").toUpperCase();
60
+ const url = sanitizeUrl(request.url ?? "/");
61
+ const requestId = options.getRequestId?.(request, reply) ?? request.id;
62
+ states.set(request, { started: Date.now() });
63
+ const context = {
64
+ httpMethod: method,
65
+ httpUrl: url,
66
+ requestId,
67
+ ...options.context?.(request, reply)
68
+ };
69
+ if (bindContext) {
70
+ withContext(context, () => next());
71
+ return;
72
+ }
73
+ next();
74
+ });
75
+ instance.addHook("onError", (request, _reply, error, next) => {
76
+ const state = states.get(request);
77
+ if (state) state.error = error;
78
+ else states.set(request, {
79
+ started: Date.now(),
80
+ error
81
+ });
82
+ next();
83
+ });
84
+ instance.addHook("onResponse", (request, reply, next) => {
85
+ const state = states.get(request) ?? { started: Date.now() };
86
+ states.delete(request);
87
+ const status = reply.statusCode ?? 0;
88
+ const error = state.error;
89
+ if (!shouldCapture(status, error)) {
90
+ next();
91
+ return;
92
+ }
93
+ const method = (request.method ?? "GET").toUpperCase();
94
+ const url = sanitizeUrl(request.url ?? "/");
95
+ const requestId = options.getRequestId?.(request, reply) ?? request.id;
96
+ const data = { http: {
97
+ kind: name,
98
+ framework: "fastify",
99
+ method,
100
+ url,
101
+ route: routeFor(request),
102
+ status,
103
+ durationMs: Date.now() - state.started,
104
+ requestId,
105
+ remoteAddress: request.ip,
106
+ requestHeaders: pickRequestHeaders(request, options.captureRequestHeaders),
107
+ responseHeaders: pickResponseHeaders(reply, options.captureResponseHeaders)
108
+ } };
109
+ if (error) data.error = error;
110
+ logger.log(levelFor(status, request, reply, error), `Fastify ${status} ${method} ${url}`, { ...data });
111
+ next();
112
+ });
113
+ done?.();
114
+ };
115
+ }
116
+ //#endregion
117
+ export { fastifyIntegration };
118
+
119
+ //# sourceMappingURL=fastify-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify-integration.js","names":[],"sources":["../src/fastify-integration.ts"],"sourcesContent":["import { withContext, type LoggerLevel, type LoggerLike, type LogData } from \"@loggerjs/core\";\n\nexport interface FastifyRequestLike {\n id?: string;\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n ip?: string;\n routeOptions?: { url?: string };\n routerPath?: string;\n [key: string]: unknown;\n}\n\nexport interface FastifyReplyLike {\n statusCode?: number;\n getHeader?: (name: string) => number | string | string[] | undefined;\n [key: string]: unknown;\n}\n\nexport type FastifyDone = (error?: unknown) => void;\nexport type FastifyOnRequestHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: FastifyDone,\n) => void;\nexport type FastifyOnResponseHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n done: FastifyDone,\n) => void;\nexport type FastifyOnErrorHook = (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n error: unknown,\n done: FastifyDone,\n) => void;\n\nexport interface FastifyInstanceLike {\n addHook: (\n name: \"onRequest\" | \"onResponse\" | \"onError\",\n hook: FastifyOnRequestHook | FastifyOnResponseHook | FastifyOnErrorHook,\n ) => unknown;\n}\n\nexport type FastifyPluginCallback = (\n instance: FastifyInstanceLike,\n options: unknown,\n done?: FastifyDone,\n) => void;\n\nexport interface FastifyIntegrationOptions {\n name?: string;\n minStatus?: number;\n captureAll?: boolean;\n captureSuccessful?: boolean;\n sampleRate?: number;\n random?: () => number;\n bindContext?: boolean;\n captureRequestHeaders?: readonly string[];\n captureResponseHeaders?: readonly string[];\n sanitizeUrl?: (url: string) => string;\n getRequestId?: (request: FastifyRequestLike, reply: FastifyReplyLike) => string | undefined;\n getRoute?: (request: FastifyRequestLike) => string | undefined;\n context?: (\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n ) => Record<string, unknown> | undefined;\n level?: (\n status: number,\n request: FastifyRequestLike,\n reply: FastifyReplyLike,\n error: unknown,\n ) => LoggerLevel;\n}\n\ninterface RequestState {\n started: number;\n error?: unknown;\n}\n\nconst defaultRandom = () => Math.random();\n\nfunction defaultSanitizeUrl(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n const hashIndex = url.indexOf(\"#\");\n const end = Math.min(\n queryIndex >= 0 ? queryIndex : url.length,\n hashIndex >= 0 ? hashIndex : url.length,\n );\n return url.slice(0, end);\n}\n\nfunction defaultLevel(\n status: number,\n _request: FastifyRequestLike,\n _reply: FastifyReplyLike,\n error: unknown,\n): LoggerLevel {\n if (error || status >= 500) return \"error\";\n if (status >= 400) return \"warn\";\n return \"info\";\n}\n\nfunction headerValue(value: number | string | string[] | undefined): string | string[] | undefined {\n if (typeof value === \"number\") return String(value);\n return value;\n}\n\nfunction pickRequestHeaders(\n request: FastifyRequestLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !request.headers) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = request.headers[name.toLowerCase()] ?? request.headers[name];\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction pickResponseHeaders(\n reply: FastifyReplyLike,\n names: readonly string[] | undefined,\n): Record<string, string | string[]> | undefined {\n if (!names || names.length === 0 || !reply.getHeader) return undefined;\n const out: Record<string, string | string[]> = {};\n for (const name of names) {\n const value = headerValue(reply.getHeader(name));\n if (value !== undefined) out[name.toLowerCase()] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction defaultRoute(request: FastifyRequestLike): string | undefined {\n return request.routeOptions?.url ?? request.routerPath;\n}\n\nexport function fastifyIntegration(\n logger: LoggerLike,\n options: FastifyIntegrationOptions = {},\n): FastifyPluginCallback {\n const name = options.name ?? \"fastify\";\n const minStatus = options.minStatus ?? 400;\n const captureAll = options.captureAll ?? options.captureSuccessful ?? false;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const sanitizeUrl = options.sanitizeUrl ?? defaultSanitizeUrl;\n const levelFor = options.level ?? defaultLevel;\n const routeFor = options.getRoute ?? defaultRoute;\n const bindContext = options.bindContext ?? true;\n const states = new WeakMap<FastifyRequestLike, RequestState>();\n\n const shouldCapture = (status: number, error: unknown) => {\n if (error) return true;\n if (status >= minStatus) return true;\n if (!captureAll) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n return (instance, _pluginOptions, done) => {\n instance.addHook(\n \"onRequest\",\n (request: FastifyRequestLike, reply: FastifyReplyLike, next: FastifyDone) => {\n const method = (request.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(request.url ?? \"/\");\n const requestId = options.getRequestId?.(request, reply) ?? request.id;\n states.set(request, { started: Date.now() });\n const context = {\n httpMethod: method,\n httpUrl: url,\n requestId,\n ...options.context?.(request, reply),\n };\n if (bindContext) {\n withContext(context, () => next());\n return;\n }\n next();\n },\n );\n\n instance.addHook(\n \"onError\",\n (\n request: FastifyRequestLike,\n _reply: FastifyReplyLike,\n error: unknown,\n next: FastifyDone,\n ) => {\n const state = states.get(request);\n if (state) state.error = error;\n else states.set(request, { started: Date.now(), error });\n next();\n },\n );\n\n instance.addHook(\n \"onResponse\",\n (request: FastifyRequestLike, reply: FastifyReplyLike, next: FastifyDone) => {\n const state = states.get(request) ?? { started: Date.now() };\n states.delete(request);\n const status = reply.statusCode ?? 0;\n const error = state.error;\n if (!shouldCapture(status, error)) {\n next();\n return;\n }\n\n const method = (request.method ?? \"GET\").toUpperCase();\n const url = sanitizeUrl(request.url ?? \"/\");\n const requestId = options.getRequestId?.(request, reply) ?? request.id;\n const http: Record<string, unknown> = {\n kind: name,\n framework: \"fastify\",\n method,\n url,\n route: routeFor(request),\n status,\n durationMs: Date.now() - state.started,\n requestId,\n remoteAddress: request.ip,\n requestHeaders: pickRequestHeaders(request, options.captureRequestHeaders),\n responseHeaders: pickResponseHeaders(reply, options.captureResponseHeaders),\n };\n const data: Record<string, unknown> = { http };\n if (error) data.error = error;\n logger.log(levelFor(status, request, reply, error), `Fastify ${status} ${method} ${url}`, {\n ...data,\n } as LogData);\n next();\n },\n );\n\n done?.();\n };\n}\n"],"mappings":"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"}