snapwyr 1.0.0

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 (50) hide show
  1. package/README.md +420 -0
  2. package/dist/dashboard.d.mts +1 -0
  3. package/dist/dashboard.d.ts +1 -0
  4. package/dist/dashboard.js +35 -0
  5. package/dist/dashboard.js.map +1 -0
  6. package/dist/dashboard.mjs +8 -0
  7. package/dist/dashboard.mjs.map +1 -0
  8. package/dist/express.d.mts +26 -0
  9. package/dist/express.d.ts +26 -0
  10. package/dist/express.js +203 -0
  11. package/dist/express.js.map +1 -0
  12. package/dist/express.mjs +183 -0
  13. package/dist/express.mjs.map +1 -0
  14. package/dist/fastify.d.mts +13 -0
  15. package/dist/fastify.d.ts +13 -0
  16. package/dist/fastify.js +204 -0
  17. package/dist/fastify.js.map +1 -0
  18. package/dist/fastify.mjs +184 -0
  19. package/dist/fastify.mjs.map +1 -0
  20. package/dist/hono.d.mts +18 -0
  21. package/dist/hono.d.ts +18 -0
  22. package/dist/hono.js +190 -0
  23. package/dist/hono.js.map +1 -0
  24. package/dist/hono.mjs +170 -0
  25. package/dist/hono.mjs.map +1 -0
  26. package/dist/index.d.mts +28 -0
  27. package/dist/index.d.ts +28 -0
  28. package/dist/index.js +78 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/index.mjs +51 -0
  31. package/dist/index.mjs.map +1 -0
  32. package/dist/koa.d.mts +21 -0
  33. package/dist/koa.d.ts +21 -0
  34. package/dist/koa.js +185 -0
  35. package/dist/koa.js.map +1 -0
  36. package/dist/koa.mjs +165 -0
  37. package/dist/koa.mjs.map +1 -0
  38. package/dist/nestjs.d.mts +19 -0
  39. package/dist/nestjs.d.ts +19 -0
  40. package/dist/nestjs.js +211 -0
  41. package/dist/nestjs.js.map +1 -0
  42. package/dist/nestjs.mjs +191 -0
  43. package/dist/nestjs.mjs.map +1 -0
  44. package/dist/nextjs.d.mts +33 -0
  45. package/dist/nextjs.d.ts +33 -0
  46. package/dist/nextjs.js +191 -0
  47. package/dist/nextjs.js.map +1 -0
  48. package/dist/nextjs.mjs +178 -0
  49. package/dist/nextjs.mjs.map +1 -0
  50. package/package.json +174 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fastify.ts","../src/utils.ts"],"sourcesContent":["import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport { generateRequestId } from '@snapwyr/core';\nimport { logRequest } from './utils.js';\n\nconst requestTimingMap = new WeakMap<\n object,\n { id: string; startTime: number }\n>();\n\n/**\n * @example\n * ```ts\n * await fastify.register(snapwyr, { logBody: true });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction snapwyrPlugin(fastify: any, config: SnapWyrConfig, done: () => void) {\n if (config.enabled === false) {\n done();\n return;\n }\n\n fastify.addHook(\n 'onRequest',\n (request: any, reply: any, hookDone: () => void) => {\n const id = generateRequestId();\n requestTimingMap.set(request, { id, startTime: Date.now() });\n\n if (config.requestId) {\n try {\n reply.header('X-Request-ID', id);\n } catch {}\n }\n hookDone();\n }\n );\n\n fastify.addHook(\n 'onResponse',\n (request: any, reply: any, hookDone: () => void) => {\n const timing = requestTimingMap.get(request) || {\n id: generateRequestId(),\n startTime: Date.now(),\n };\n const duration = Date.now() - timing.startTime;\n const status = reply.statusCode;\n\n requestTimingMap.delete(request);\n\n if (\n config.statusCodes &&\n config.statusCodes.length > 0 &&\n !config.statusCodes.includes(status)\n ) {\n hookDone();\n return;\n }\n\n if (config.errorsOnly && status < 400) {\n hookDone();\n return;\n }\n\n let requestBody: string | undefined;\n if (config.logBody && request.body) {\n try {\n const body =\n typeof request.body === 'string'\n ? request.body\n : JSON.stringify(request.body);\n requestBody = config.bodySizeLimit\n ? body.slice(0, config.bodySizeLimit)\n : body;\n } catch {}\n }\n\n logRequest({\n id: timing.id,\n method: request.method,\n status,\n duration,\n url: request.url,\n startTime: timing.startTime,\n config,\n requestBody: config.logBody ? requestBody : undefined,\n });\n\n hookDone();\n }\n );\n\n done();\n}\n\nObject.defineProperty(snapwyrPlugin, Symbol.for('skip-override'), {\n value: true,\n writable: false,\n});\n\nexport const snapwyr = snapwyrPlugin;\n\nexport type { SnapWyrConfig, LogEntry };\n","import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport {\n snapwyr as coreEmitter,\n getByteSize,\n formatBytes,\n redactSensitiveData,\n} from '@snapwyr/core';\n\nexport interface LogParams {\n id: string;\n method: string;\n status: number;\n duration: number;\n url: string;\n startTime: number;\n config: SnapWyrConfig;\n requestBody?: string;\n responseBody?: string;\n error?: string;\n}\n\nexport function logRequest(params: LogParams): void {\n const { id, method, status, duration, url, startTime, config, error } =\n params;\n let { requestBody, responseBody } = params;\n\n if (config.silent) return;\n\n const showTimestamp = config.showTimestamp !== false;\n const format = config.format || 'pretty';\n const slowThreshold = config.slowThreshold ?? 1000;\n const isSlow = duration >= slowThreshold;\n\n const requestSize = requestBody ? getByteSize(requestBody) : 0;\n const responseSize = responseBody ? getByteSize(responseBody) : 0;\n const totalSize = requestSize + responseSize;\n\n if (config.redact && config.redact.length > 0) {\n if (requestBody)\n requestBody = redactSensitiveData(requestBody, config.redact);\n if (responseBody)\n responseBody = redactSensitiveData(responseBody, config.redact);\n }\n\n const logEntry: LogEntry = {\n id,\n timestamp: new Date(startTime).toISOString(),\n method: method.toUpperCase(),\n url,\n status,\n duration,\n slow: isSlow,\n };\n\n if (config.prefix) logEntry.prefix = config.prefix;\n if (error) logEntry.error = error;\n if (requestBody) logEntry.requestBody = requestBody;\n if (responseBody) logEntry.responseBody = responseBody;\n if (config.sizeTracking) {\n logEntry.requestSize = requestSize;\n logEntry.responseSize = responseSize;\n logEntry.totalSize = totalSize;\n }\n\n try {\n coreEmitter.emit('request', {\n id,\n method: method.toUpperCase(),\n url,\n status,\n duration,\n timestamp: startTime,\n requestBody,\n responseBody,\n error,\n requestSize: config.sizeTracking ? requestSize : undefined,\n responseSize: config.sizeTracking ? responseSize : undefined,\n direction: 'incoming',\n });\n } catch {}\n\n if (config.transport) {\n config.transport(logEntry);\n }\n\n if (format === 'json') {\n console.log(JSON.stringify(logEntry));\n return;\n }\n\n const useEmoji = config.emoji === true;\n let statusEmoji = '';\n if (useEmoji) {\n if (error || status >= 500) statusEmoji = '✗ ';\n else if (status >= 400) statusEmoji = '⚠ ';\n else if (status >= 300) statusEmoji = '↪ ';\n else statusEmoji = '✓ ';\n }\n\n const statusColor =\n status >= 500\n ? '\\x1b[31m'\n : status >= 400\n ? '\\x1b[33m'\n : status >= 300\n ? '\\x1b[36m'\n : '\\x1b[32m';\n const durationColor = isSlow\n ? '\\x1b[31m'\n : duration < 100\n ? '\\x1b[32m'\n : '\\x1b[33m';\n const methodColors: Record<string, string> = {\n GET: '\\x1b[34m',\n POST: '\\x1b[32m',\n PUT: '\\x1b[33m',\n PATCH: '\\x1b[35m',\n DELETE: '\\x1b[31m',\n };\n const methodColor = methodColors[method] || '';\n const reset = '\\x1b[0m';\n const dim = '\\x1b[2m';\n const bold = '\\x1b[1m';\n const timestamp = showTimestamp\n ? new Date(startTime).toISOString().slice(11, 23) + ' '\n : '';\n const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : '';\n const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : '';\n const sizeDisplay = config.sizeTracking\n ? `${dim}${formatBytes(totalSize)}${reset} `\n : '';\n\n const parts = [\n config.prefix ? `${dim}${config.prefix} ${reset}` : '',\n requestIdDisplay,\n `${dim}${timestamp}${reset}`,\n `${methodColor}${method.padEnd(6)}${reset}`,\n `${statusColor}${statusEmoji}${status}${reset}`,\n `${durationColor}${duration}ms${reset}${slowIndicator}`,\n sizeDisplay,\n `${dim}${url}${reset}`,\n ].filter(Boolean);\n\n if (error) parts.push(`\\n ${dim}Error: ${error}${reset}`);\n if (requestBody) parts.push(`\\n ${dim}Request: ${requestBody}${reset}`);\n if (responseBody) parts.push(`\\n ${dim}Response: ${responseBody}${reset}`);\n\n console.log(parts.join(' '));\n}\n"],"mappings":"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","names":["import_core","coreEmitter"]}
@@ -0,0 +1,184 @@
1
+ // src/fastify.ts
2
+ import { generateRequestId } from "@snapwyr/core";
3
+
4
+ // src/utils.ts
5
+ import {
6
+ snapwyr as coreEmitter,
7
+ getByteSize,
8
+ formatBytes,
9
+ redactSensitiveData
10
+ } from "@snapwyr/core";
11
+ function logRequest(params) {
12
+ const { id, method, status, duration, url, startTime, config, error } = params;
13
+ let { requestBody, responseBody } = params;
14
+ if (config.silent) return;
15
+ const showTimestamp = config.showTimestamp !== false;
16
+ const format = config.format || "pretty";
17
+ const slowThreshold = config.slowThreshold ?? 1e3;
18
+ const isSlow = duration >= slowThreshold;
19
+ const requestSize = requestBody ? getByteSize(requestBody) : 0;
20
+ const responseSize = responseBody ? getByteSize(responseBody) : 0;
21
+ const totalSize = requestSize + responseSize;
22
+ if (config.redact && config.redact.length > 0) {
23
+ if (requestBody)
24
+ requestBody = redactSensitiveData(requestBody, config.redact);
25
+ if (responseBody)
26
+ responseBody = redactSensitiveData(responseBody, config.redact);
27
+ }
28
+ const logEntry = {
29
+ id,
30
+ timestamp: new Date(startTime).toISOString(),
31
+ method: method.toUpperCase(),
32
+ url,
33
+ status,
34
+ duration,
35
+ slow: isSlow
36
+ };
37
+ if (config.prefix) logEntry.prefix = config.prefix;
38
+ if (error) logEntry.error = error;
39
+ if (requestBody) logEntry.requestBody = requestBody;
40
+ if (responseBody) logEntry.responseBody = responseBody;
41
+ if (config.sizeTracking) {
42
+ logEntry.requestSize = requestSize;
43
+ logEntry.responseSize = responseSize;
44
+ logEntry.totalSize = totalSize;
45
+ }
46
+ try {
47
+ coreEmitter.emit("request", {
48
+ id,
49
+ method: method.toUpperCase(),
50
+ url,
51
+ status,
52
+ duration,
53
+ timestamp: startTime,
54
+ requestBody,
55
+ responseBody,
56
+ error,
57
+ requestSize: config.sizeTracking ? requestSize : void 0,
58
+ responseSize: config.sizeTracking ? responseSize : void 0,
59
+ direction: "incoming"
60
+ });
61
+ } catch {
62
+ }
63
+ if (config.transport) {
64
+ config.transport(logEntry);
65
+ }
66
+ if (format === "json") {
67
+ console.log(JSON.stringify(logEntry));
68
+ return;
69
+ }
70
+ const useEmoji = config.emoji === true;
71
+ let statusEmoji = "";
72
+ if (useEmoji) {
73
+ if (error || status >= 500) statusEmoji = "\u2717 ";
74
+ else if (status >= 400) statusEmoji = "\u26A0 ";
75
+ else if (status >= 300) statusEmoji = "\u21AA ";
76
+ else statusEmoji = "\u2713 ";
77
+ }
78
+ const statusColor = status >= 500 ? "\x1B[31m" : status >= 400 ? "\x1B[33m" : status >= 300 ? "\x1B[36m" : "\x1B[32m";
79
+ const durationColor = isSlow ? "\x1B[31m" : duration < 100 ? "\x1B[32m" : "\x1B[33m";
80
+ const methodColors = {
81
+ GET: "\x1B[34m",
82
+ POST: "\x1B[32m",
83
+ PUT: "\x1B[33m",
84
+ PATCH: "\x1B[35m",
85
+ DELETE: "\x1B[31m"
86
+ };
87
+ const methodColor = methodColors[method] || "";
88
+ const reset = "\x1B[0m";
89
+ const dim = "\x1B[2m";
90
+ const bold = "\x1B[1m";
91
+ const timestamp = showTimestamp ? new Date(startTime).toISOString().slice(11, 23) + " " : "";
92
+ const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : "";
93
+ const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : "";
94
+ const sizeDisplay = config.sizeTracking ? `${dim}${formatBytes(totalSize)}${reset} ` : "";
95
+ const parts = [
96
+ config.prefix ? `${dim}${config.prefix} ${reset}` : "",
97
+ requestIdDisplay,
98
+ `${dim}${timestamp}${reset}`,
99
+ `${methodColor}${method.padEnd(6)}${reset}`,
100
+ `${statusColor}${statusEmoji}${status}${reset}`,
101
+ `${durationColor}${duration}ms${reset}${slowIndicator}`,
102
+ sizeDisplay,
103
+ `${dim}${url}${reset}`
104
+ ].filter(Boolean);
105
+ if (error) parts.push(`
106
+ ${dim}Error: ${error}${reset}`);
107
+ if (requestBody) parts.push(`
108
+ ${dim}Request: ${requestBody}${reset}`);
109
+ if (responseBody) parts.push(`
110
+ ${dim}Response: ${responseBody}${reset}`);
111
+ console.log(parts.join(" "));
112
+ }
113
+
114
+ // src/fastify.ts
115
+ var requestTimingMap = /* @__PURE__ */ new WeakMap();
116
+ function snapwyrPlugin(fastify, config, done) {
117
+ if (config.enabled === false) {
118
+ done();
119
+ return;
120
+ }
121
+ fastify.addHook(
122
+ "onRequest",
123
+ (request, reply, hookDone) => {
124
+ const id = generateRequestId();
125
+ requestTimingMap.set(request, { id, startTime: Date.now() });
126
+ if (config.requestId) {
127
+ try {
128
+ reply.header("X-Request-ID", id);
129
+ } catch {
130
+ }
131
+ }
132
+ hookDone();
133
+ }
134
+ );
135
+ fastify.addHook(
136
+ "onResponse",
137
+ (request, reply, hookDone) => {
138
+ const timing = requestTimingMap.get(request) || {
139
+ id: generateRequestId(),
140
+ startTime: Date.now()
141
+ };
142
+ const duration = Date.now() - timing.startTime;
143
+ const status = reply.statusCode;
144
+ requestTimingMap.delete(request);
145
+ if (config.statusCodes && config.statusCodes.length > 0 && !config.statusCodes.includes(status)) {
146
+ hookDone();
147
+ return;
148
+ }
149
+ if (config.errorsOnly && status < 400) {
150
+ hookDone();
151
+ return;
152
+ }
153
+ let requestBody;
154
+ if (config.logBody && request.body) {
155
+ try {
156
+ const body = typeof request.body === "string" ? request.body : JSON.stringify(request.body);
157
+ requestBody = config.bodySizeLimit ? body.slice(0, config.bodySizeLimit) : body;
158
+ } catch {
159
+ }
160
+ }
161
+ logRequest({
162
+ id: timing.id,
163
+ method: request.method,
164
+ status,
165
+ duration,
166
+ url: request.url,
167
+ startTime: timing.startTime,
168
+ config,
169
+ requestBody: config.logBody ? requestBody : void 0
170
+ });
171
+ hookDone();
172
+ }
173
+ );
174
+ done();
175
+ }
176
+ Object.defineProperty(snapwyrPlugin, /* @__PURE__ */ Symbol.for("skip-override"), {
177
+ value: true,
178
+ writable: false
179
+ });
180
+ var snapwyr = snapwyrPlugin;
181
+ export {
182
+ snapwyr
183
+ };
184
+ //# sourceMappingURL=fastify.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fastify.ts","../src/utils.ts"],"sourcesContent":["import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport { generateRequestId } from '@snapwyr/core';\nimport { logRequest } from './utils.js';\n\nconst requestTimingMap = new WeakMap<\n object,\n { id: string; startTime: number }\n>();\n\n/**\n * @example\n * ```ts\n * await fastify.register(snapwyr, { logBody: true });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction snapwyrPlugin(fastify: any, config: SnapWyrConfig, done: () => void) {\n if (config.enabled === false) {\n done();\n return;\n }\n\n fastify.addHook(\n 'onRequest',\n (request: any, reply: any, hookDone: () => void) => {\n const id = generateRequestId();\n requestTimingMap.set(request, { id, startTime: Date.now() });\n\n if (config.requestId) {\n try {\n reply.header('X-Request-ID', id);\n } catch {}\n }\n hookDone();\n }\n );\n\n fastify.addHook(\n 'onResponse',\n (request: any, reply: any, hookDone: () => void) => {\n const timing = requestTimingMap.get(request) || {\n id: generateRequestId(),\n startTime: Date.now(),\n };\n const duration = Date.now() - timing.startTime;\n const status = reply.statusCode;\n\n requestTimingMap.delete(request);\n\n if (\n config.statusCodes &&\n config.statusCodes.length > 0 &&\n !config.statusCodes.includes(status)\n ) {\n hookDone();\n return;\n }\n\n if (config.errorsOnly && status < 400) {\n hookDone();\n return;\n }\n\n let requestBody: string | undefined;\n if (config.logBody && request.body) {\n try {\n const body =\n typeof request.body === 'string'\n ? request.body\n : JSON.stringify(request.body);\n requestBody = config.bodySizeLimit\n ? body.slice(0, config.bodySizeLimit)\n : body;\n } catch {}\n }\n\n logRequest({\n id: timing.id,\n method: request.method,\n status,\n duration,\n url: request.url,\n startTime: timing.startTime,\n config,\n requestBody: config.logBody ? requestBody : undefined,\n });\n\n hookDone();\n }\n );\n\n done();\n}\n\nObject.defineProperty(snapwyrPlugin, Symbol.for('skip-override'), {\n value: true,\n writable: false,\n});\n\nexport const snapwyr = snapwyrPlugin;\n\nexport type { SnapWyrConfig, LogEntry };\n","import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport {\n snapwyr as coreEmitter,\n getByteSize,\n formatBytes,\n redactSensitiveData,\n} from '@snapwyr/core';\n\nexport interface LogParams {\n id: string;\n method: string;\n status: number;\n duration: number;\n url: string;\n startTime: number;\n config: SnapWyrConfig;\n requestBody?: string;\n responseBody?: string;\n error?: string;\n}\n\nexport function logRequest(params: LogParams): void {\n const { id, method, status, duration, url, startTime, config, error } =\n params;\n let { requestBody, responseBody } = params;\n\n if (config.silent) return;\n\n const showTimestamp = config.showTimestamp !== false;\n const format = config.format || 'pretty';\n const slowThreshold = config.slowThreshold ?? 1000;\n const isSlow = duration >= slowThreshold;\n\n const requestSize = requestBody ? getByteSize(requestBody) : 0;\n const responseSize = responseBody ? getByteSize(responseBody) : 0;\n const totalSize = requestSize + responseSize;\n\n if (config.redact && config.redact.length > 0) {\n if (requestBody)\n requestBody = redactSensitiveData(requestBody, config.redact);\n if (responseBody)\n responseBody = redactSensitiveData(responseBody, config.redact);\n }\n\n const logEntry: LogEntry = {\n id,\n timestamp: new Date(startTime).toISOString(),\n method: method.toUpperCase(),\n url,\n status,\n duration,\n slow: isSlow,\n };\n\n if (config.prefix) logEntry.prefix = config.prefix;\n if (error) logEntry.error = error;\n if (requestBody) logEntry.requestBody = requestBody;\n if (responseBody) logEntry.responseBody = responseBody;\n if (config.sizeTracking) {\n logEntry.requestSize = requestSize;\n logEntry.responseSize = responseSize;\n logEntry.totalSize = totalSize;\n }\n\n try {\n coreEmitter.emit('request', {\n id,\n method: method.toUpperCase(),\n url,\n status,\n duration,\n timestamp: startTime,\n requestBody,\n responseBody,\n error,\n requestSize: config.sizeTracking ? requestSize : undefined,\n responseSize: config.sizeTracking ? responseSize : undefined,\n direction: 'incoming',\n });\n } catch {}\n\n if (config.transport) {\n config.transport(logEntry);\n }\n\n if (format === 'json') {\n console.log(JSON.stringify(logEntry));\n return;\n }\n\n const useEmoji = config.emoji === true;\n let statusEmoji = '';\n if (useEmoji) {\n if (error || status >= 500) statusEmoji = '✗ ';\n else if (status >= 400) statusEmoji = '⚠ ';\n else if (status >= 300) statusEmoji = '↪ ';\n else statusEmoji = '✓ ';\n }\n\n const statusColor =\n status >= 500\n ? '\\x1b[31m'\n : status >= 400\n ? '\\x1b[33m'\n : status >= 300\n ? '\\x1b[36m'\n : '\\x1b[32m';\n const durationColor = isSlow\n ? '\\x1b[31m'\n : duration < 100\n ? '\\x1b[32m'\n : '\\x1b[33m';\n const methodColors: Record<string, string> = {\n GET: '\\x1b[34m',\n POST: '\\x1b[32m',\n PUT: '\\x1b[33m',\n PATCH: '\\x1b[35m',\n DELETE: '\\x1b[31m',\n };\n const methodColor = methodColors[method] || '';\n const reset = '\\x1b[0m';\n const dim = '\\x1b[2m';\n const bold = '\\x1b[1m';\n const timestamp = showTimestamp\n ? new Date(startTime).toISOString().slice(11, 23) + ' '\n : '';\n const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : '';\n const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : '';\n const sizeDisplay = config.sizeTracking\n ? `${dim}${formatBytes(totalSize)}${reset} `\n : '';\n\n const parts = [\n config.prefix ? `${dim}${config.prefix} ${reset}` : '',\n requestIdDisplay,\n `${dim}${timestamp}${reset}`,\n `${methodColor}${method.padEnd(6)}${reset}`,\n `${statusColor}${statusEmoji}${status}${reset}`,\n `${durationColor}${duration}ms${reset}${slowIndicator}`,\n sizeDisplay,\n `${dim}${url}${reset}`,\n ].filter(Boolean);\n\n if (error) parts.push(`\\n ${dim}Error: ${error}${reset}`);\n if (requestBody) parts.push(`\\n ${dim}Request: ${requestBody}${reset}`);\n if (responseBody) parts.push(`\\n ${dim}Response: ${responseBody}${reset}`);\n\n console.log(parts.join(' '));\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,18 @@
1
+ import { SnapWyrConfig } from '@snapwyr/core';
2
+ export { LogEntry, SnapWyrConfig } from '@snapwyr/core';
3
+
4
+ interface HonoContext {
5
+ req: {
6
+ method: string;
7
+ path: string;
8
+ query: (key?: string) => string | Record<string, string> | undefined;
9
+ raw: Request;
10
+ };
11
+ res: Response | undefined;
12
+ header: (name: string, value: string) => void;
13
+ }
14
+ type HonoNext = () => Promise<void>;
15
+ type HonoMiddleware = (c: HonoContext, next: HonoNext) => Promise<Response | void>;
16
+ declare function snapwyr(config?: SnapWyrConfig): HonoMiddleware;
17
+
18
+ export { snapwyr };
package/dist/hono.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { SnapWyrConfig } from '@snapwyr/core';
2
+ export { LogEntry, SnapWyrConfig } from '@snapwyr/core';
3
+
4
+ interface HonoContext {
5
+ req: {
6
+ method: string;
7
+ path: string;
8
+ query: (key?: string) => string | Record<string, string> | undefined;
9
+ raw: Request;
10
+ };
11
+ res: Response | undefined;
12
+ header: (name: string, value: string) => void;
13
+ }
14
+ type HonoNext = () => Promise<void>;
15
+ type HonoMiddleware = (c: HonoContext, next: HonoNext) => Promise<Response | void>;
16
+ declare function snapwyr(config?: SnapWyrConfig): HonoMiddleware;
17
+
18
+ export { snapwyr };
package/dist/hono.js ADDED
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/hono.ts
21
+ var hono_exports = {};
22
+ __export(hono_exports, {
23
+ snapwyr: () => snapwyr
24
+ });
25
+ module.exports = __toCommonJS(hono_exports);
26
+ var import_core2 = require("@snapwyr/core");
27
+
28
+ // src/utils.ts
29
+ var import_core = require("@snapwyr/core");
30
+ function logRequest(params) {
31
+ const { id, method, status, duration, url, startTime, config, error } = params;
32
+ let { requestBody, responseBody } = params;
33
+ if (config.silent) return;
34
+ const showTimestamp = config.showTimestamp !== false;
35
+ const format = config.format || "pretty";
36
+ const slowThreshold = config.slowThreshold ?? 1e3;
37
+ const isSlow = duration >= slowThreshold;
38
+ const requestSize = requestBody ? (0, import_core.getByteSize)(requestBody) : 0;
39
+ const responseSize = responseBody ? (0, import_core.getByteSize)(responseBody) : 0;
40
+ const totalSize = requestSize + responseSize;
41
+ if (config.redact && config.redact.length > 0) {
42
+ if (requestBody)
43
+ requestBody = (0, import_core.redactSensitiveData)(requestBody, config.redact);
44
+ if (responseBody)
45
+ responseBody = (0, import_core.redactSensitiveData)(responseBody, config.redact);
46
+ }
47
+ const logEntry = {
48
+ id,
49
+ timestamp: new Date(startTime).toISOString(),
50
+ method: method.toUpperCase(),
51
+ url,
52
+ status,
53
+ duration,
54
+ slow: isSlow
55
+ };
56
+ if (config.prefix) logEntry.prefix = config.prefix;
57
+ if (error) logEntry.error = error;
58
+ if (requestBody) logEntry.requestBody = requestBody;
59
+ if (responseBody) logEntry.responseBody = responseBody;
60
+ if (config.sizeTracking) {
61
+ logEntry.requestSize = requestSize;
62
+ logEntry.responseSize = responseSize;
63
+ logEntry.totalSize = totalSize;
64
+ }
65
+ try {
66
+ import_core.snapwyr.emit("request", {
67
+ id,
68
+ method: method.toUpperCase(),
69
+ url,
70
+ status,
71
+ duration,
72
+ timestamp: startTime,
73
+ requestBody,
74
+ responseBody,
75
+ error,
76
+ requestSize: config.sizeTracking ? requestSize : void 0,
77
+ responseSize: config.sizeTracking ? responseSize : void 0,
78
+ direction: "incoming"
79
+ });
80
+ } catch {
81
+ }
82
+ if (config.transport) {
83
+ config.transport(logEntry);
84
+ }
85
+ if (format === "json") {
86
+ console.log(JSON.stringify(logEntry));
87
+ return;
88
+ }
89
+ const useEmoji = config.emoji === true;
90
+ let statusEmoji = "";
91
+ if (useEmoji) {
92
+ if (error || status >= 500) statusEmoji = "\u2717 ";
93
+ else if (status >= 400) statusEmoji = "\u26A0 ";
94
+ else if (status >= 300) statusEmoji = "\u21AA ";
95
+ else statusEmoji = "\u2713 ";
96
+ }
97
+ const statusColor = status >= 500 ? "\x1B[31m" : status >= 400 ? "\x1B[33m" : status >= 300 ? "\x1B[36m" : "\x1B[32m";
98
+ const durationColor = isSlow ? "\x1B[31m" : duration < 100 ? "\x1B[32m" : "\x1B[33m";
99
+ const methodColors = {
100
+ GET: "\x1B[34m",
101
+ POST: "\x1B[32m",
102
+ PUT: "\x1B[33m",
103
+ PATCH: "\x1B[35m",
104
+ DELETE: "\x1B[31m"
105
+ };
106
+ const methodColor = methodColors[method] || "";
107
+ const reset = "\x1B[0m";
108
+ const dim = "\x1B[2m";
109
+ const bold = "\x1B[1m";
110
+ const timestamp = showTimestamp ? new Date(startTime).toISOString().slice(11, 23) + " " : "";
111
+ const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : "";
112
+ const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : "";
113
+ const sizeDisplay = config.sizeTracking ? `${dim}${(0, import_core.formatBytes)(totalSize)}${reset} ` : "";
114
+ const parts = [
115
+ config.prefix ? `${dim}${config.prefix} ${reset}` : "",
116
+ requestIdDisplay,
117
+ `${dim}${timestamp}${reset}`,
118
+ `${methodColor}${method.padEnd(6)}${reset}`,
119
+ `${statusColor}${statusEmoji}${status}${reset}`,
120
+ `${durationColor}${duration}ms${reset}${slowIndicator}`,
121
+ sizeDisplay,
122
+ `${dim}${url}${reset}`
123
+ ].filter(Boolean);
124
+ if (error) parts.push(`
125
+ ${dim}Error: ${error}${reset}`);
126
+ if (requestBody) parts.push(`
127
+ ${dim}Request: ${requestBody}${reset}`);
128
+ if (responseBody) parts.push(`
129
+ ${dim}Response: ${responseBody}${reset}`);
130
+ console.log(parts.join(" "));
131
+ }
132
+
133
+ // src/hono.ts
134
+ function snapwyr(config = {}) {
135
+ return async function(c, next) {
136
+ if (config.enabled === false) {
137
+ await next();
138
+ return;
139
+ }
140
+ const id = (0, import_core2.generateRequestId)();
141
+ const startTime = Date.now();
142
+ const method = c.req.method;
143
+ const queryObj = c.req.query();
144
+ const queryString = typeof queryObj === "object" && queryObj ? new URLSearchParams(queryObj).toString() : "";
145
+ const url = c.req.path + (queryString ? "?" + queryString : "");
146
+ if (config.requestId)
147
+ try {
148
+ c.header("X-Request-ID", id);
149
+ } catch {
150
+ }
151
+ let requestBody;
152
+ if (config.logBody) {
153
+ try {
154
+ const body = await c.req.raw.clone().text().catch(() => null);
155
+ if (body) requestBody = body.slice(0, config.bodySizeLimit || 500);
156
+ } catch {
157
+ }
158
+ }
159
+ await next();
160
+ const duration = Date.now() - startTime;
161
+ const status = c.res?.status ?? 200;
162
+ if (config.statusCodes && config.statusCodes.length > 0 && !config.statusCodes.includes(status))
163
+ return;
164
+ let responseBody;
165
+ if (config.logBody && c.res) {
166
+ try {
167
+ const resBody = await c.res.clone().text().catch(() => null);
168
+ if (resBody)
169
+ responseBody = resBody.slice(0, config.bodySizeLimit || 500);
170
+ } catch {
171
+ }
172
+ }
173
+ logRequest({
174
+ id,
175
+ method,
176
+ status,
177
+ duration,
178
+ url,
179
+ startTime,
180
+ config,
181
+ requestBody: config.logBody ? requestBody : void 0,
182
+ responseBody: config.logBody ? responseBody : void 0
183
+ });
184
+ };
185
+ }
186
+ // Annotate the CommonJS export names for ESM import in node:
187
+ 0 && (module.exports = {
188
+ snapwyr
189
+ });
190
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hono.ts","../src/utils.ts"],"sourcesContent":["import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport { generateRequestId } from '@snapwyr/core';\nimport { logRequest } from './utils.js';\n\ninterface HonoContext {\n req: {\n method: string;\n path: string;\n query: (key?: string) => string | Record<string, string> | undefined;\n raw: Request;\n };\n res: Response | undefined;\n header: (name: string, value: string) => void;\n}\ntype HonoNext = () => Promise<void>;\ntype HonoMiddleware = (\n c: HonoContext,\n next: HonoNext\n) => Promise<Response | void>;\n\nexport function snapwyr(config: SnapWyrConfig = {}): HonoMiddleware {\n return async function (c, next) {\n if (config.enabled === false) {\n await next();\n return;\n }\n\n const id = generateRequestId();\n const startTime = Date.now();\n const method = c.req.method;\n const queryObj = c.req.query();\n const queryString =\n typeof queryObj === 'object' && queryObj\n ? new URLSearchParams(queryObj as Record<string, string>).toString()\n : '';\n const url = c.req.path + (queryString ? '?' + queryString : '');\n\n if (config.requestId)\n try {\n c.header('X-Request-ID', id);\n } catch {}\n\n let requestBody: string | undefined;\n if (config.logBody) {\n try {\n const body = await c.req.raw\n .clone()\n .text()\n .catch(() => null);\n if (body) requestBody = body.slice(0, config.bodySizeLimit || 500);\n } catch {}\n }\n\n await next();\n\n const duration = Date.now() - startTime;\n const status = c.res?.status ?? 200;\n\n if (\n config.statusCodes &&\n config.statusCodes.length > 0 &&\n !config.statusCodes.includes(status)\n )\n return;\n\n let responseBody: string | undefined;\n if (config.logBody && c.res) {\n try {\n const resBody = await c.res\n .clone()\n .text()\n .catch(() => null);\n if (resBody)\n responseBody = resBody.slice(0, config.bodySizeLimit || 500);\n } catch {}\n }\n\n logRequest({\n id,\n method,\n status,\n duration,\n url,\n startTime,\n config,\n requestBody: config.logBody ? requestBody : undefined,\n responseBody: config.logBody ? responseBody : undefined,\n });\n };\n}\n\nexport type { SnapWyrConfig, LogEntry };\n","import type { SnapWyrConfig, LogEntry } from '@snapwyr/core';\nimport {\n snapwyr as coreEmitter,\n getByteSize,\n formatBytes,\n redactSensitiveData,\n} from '@snapwyr/core';\n\nexport interface LogParams {\n id: string;\n method: string;\n status: number;\n duration: number;\n url: string;\n startTime: number;\n config: SnapWyrConfig;\n requestBody?: string;\n responseBody?: string;\n error?: string;\n}\n\nexport function logRequest(params: LogParams): void {\n const { id, method, status, duration, url, startTime, config, error } =\n params;\n let { requestBody, responseBody } = params;\n\n if (config.silent) return;\n\n const showTimestamp = config.showTimestamp !== false;\n const format = config.format || 'pretty';\n const slowThreshold = config.slowThreshold ?? 1000;\n const isSlow = duration >= slowThreshold;\n\n const requestSize = requestBody ? getByteSize(requestBody) : 0;\n const responseSize = responseBody ? getByteSize(responseBody) : 0;\n const totalSize = requestSize + responseSize;\n\n if (config.redact && config.redact.length > 0) {\n if (requestBody)\n requestBody = redactSensitiveData(requestBody, config.redact);\n if (responseBody)\n responseBody = redactSensitiveData(responseBody, config.redact);\n }\n\n const logEntry: LogEntry = {\n id,\n timestamp: new Date(startTime).toISOString(),\n method: method.toUpperCase(),\n url,\n status,\n duration,\n slow: isSlow,\n };\n\n if (config.prefix) logEntry.prefix = config.prefix;\n if (error) logEntry.error = error;\n if (requestBody) logEntry.requestBody = requestBody;\n if (responseBody) logEntry.responseBody = responseBody;\n if (config.sizeTracking) {\n logEntry.requestSize = requestSize;\n logEntry.responseSize = responseSize;\n logEntry.totalSize = totalSize;\n }\n\n try {\n coreEmitter.emit('request', {\n id,\n method: method.toUpperCase(),\n url,\n status,\n duration,\n timestamp: startTime,\n requestBody,\n responseBody,\n error,\n requestSize: config.sizeTracking ? requestSize : undefined,\n responseSize: config.sizeTracking ? responseSize : undefined,\n direction: 'incoming',\n });\n } catch {}\n\n if (config.transport) {\n config.transport(logEntry);\n }\n\n if (format === 'json') {\n console.log(JSON.stringify(logEntry));\n return;\n }\n\n const useEmoji = config.emoji === true;\n let statusEmoji = '';\n if (useEmoji) {\n if (error || status >= 500) statusEmoji = '✗ ';\n else if (status >= 400) statusEmoji = '⚠ ';\n else if (status >= 300) statusEmoji = '↪ ';\n else statusEmoji = '✓ ';\n }\n\n const statusColor =\n status >= 500\n ? '\\x1b[31m'\n : status >= 400\n ? '\\x1b[33m'\n : status >= 300\n ? '\\x1b[36m'\n : '\\x1b[32m';\n const durationColor = isSlow\n ? '\\x1b[31m'\n : duration < 100\n ? '\\x1b[32m'\n : '\\x1b[33m';\n const methodColors: Record<string, string> = {\n GET: '\\x1b[34m',\n POST: '\\x1b[32m',\n PUT: '\\x1b[33m',\n PATCH: '\\x1b[35m',\n DELETE: '\\x1b[31m',\n };\n const methodColor = methodColors[method] || '';\n const reset = '\\x1b[0m';\n const dim = '\\x1b[2m';\n const bold = '\\x1b[1m';\n const timestamp = showTimestamp\n ? new Date(startTime).toISOString().slice(11, 23) + ' '\n : '';\n const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : '';\n const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : '';\n const sizeDisplay = config.sizeTracking\n ? `${dim}${formatBytes(totalSize)}${reset} `\n : '';\n\n const parts = [\n config.prefix ? `${dim}${config.prefix} ${reset}` : '',\n requestIdDisplay,\n `${dim}${timestamp}${reset}`,\n `${methodColor}${method.padEnd(6)}${reset}`,\n `${statusColor}${statusEmoji}${status}${reset}`,\n `${durationColor}${duration}ms${reset}${slowIndicator}`,\n sizeDisplay,\n `${dim}${url}${reset}`,\n ].filter(Boolean);\n\n if (error) parts.push(`\\n ${dim}Error: ${error}${reset}`);\n if (requestBody) parts.push(`\\n ${dim}Request: ${requestBody}${reset}`);\n if (responseBody) parts.push(`\\n ${dim}Response: ${responseBody}${reset}`);\n\n console.log(parts.join(' '));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,IAAAA,eAAkC;;;ACAlC,kBAKO;AAeA,SAAS,WAAW,QAAyB;AAClD,QAAM,EAAE,IAAI,QAAQ,QAAQ,UAAU,KAAK,WAAW,QAAQ,MAAM,IAClE;AACF,MAAI,EAAE,aAAa,aAAa,IAAI;AAEpC,MAAI,OAAO,OAAQ;AAEnB,QAAM,gBAAgB,OAAO,kBAAkB;AAC/C,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,gBAAgB,OAAO,iBAAiB;AAC9C,QAAM,SAAS,YAAY;AAE3B,QAAM,cAAc,kBAAc,yBAAY,WAAW,IAAI;AAC7D,QAAM,eAAe,mBAAe,yBAAY,YAAY,IAAI;AAChE,QAAM,YAAY,cAAc;AAEhC,MAAI,OAAO,UAAU,OAAO,OAAO,SAAS,GAAG;AAC7C,QAAI;AACF,wBAAc,iCAAoB,aAAa,OAAO,MAAM;AAC9D,QAAI;AACF,yBAAe,iCAAoB,cAAc,OAAO,MAAM;AAAA,EAClE;AAEA,QAAM,WAAqB;AAAA,IACzB;AAAA,IACA,WAAW,IAAI,KAAK,SAAS,EAAE,YAAY;AAAA,IAC3C,QAAQ,OAAO,YAAY;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AAEA,MAAI,OAAO,OAAQ,UAAS,SAAS,OAAO;AAC5C,MAAI,MAAO,UAAS,QAAQ;AAC5B,MAAI,YAAa,UAAS,cAAc;AACxC,MAAI,aAAc,UAAS,eAAe;AAC1C,MAAI,OAAO,cAAc;AACvB,aAAS,cAAc;AACvB,aAAS,eAAe;AACxB,aAAS,YAAY;AAAA,EACvB;AAEA,MAAI;AACF,gBAAAC,QAAY,KAAK,WAAW;AAAA,MAC1B;AAAA,MACA,QAAQ,OAAO,YAAY;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,OAAO,eAAe,cAAc;AAAA,MACjD,cAAc,OAAO,eAAe,eAAe;AAAA,MACnD,WAAW;AAAA,IACb,CAAC;AAAA,EACH,QAAQ;AAAA,EAAC;AAET,MAAI,OAAO,WAAW;AACpB,WAAO,UAAU,QAAQ;AAAA,EAC3B;AAEA,MAAI,WAAW,QAAQ;AACrB,YAAQ,IAAI,KAAK,UAAU,QAAQ,CAAC;AACpC;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,UAAU;AAClC,MAAI,cAAc;AAClB,MAAI,UAAU;AACZ,QAAI,SAAS,UAAU,IAAK,eAAc;AAAA,aACjC,UAAU,IAAK,eAAc;AAAA,aAC7B,UAAU,IAAK,eAAc;AAAA,QACjC,eAAc;AAAA,EACrB;AAEA,QAAM,cACJ,UAAU,MACN,aACA,UAAU,MACR,aACA,UAAU,MACR,aACA;AACV,QAAM,gBAAgB,SAClB,aACA,WAAW,MACT,aACA;AACN,QAAM,eAAuC;AAAA,IAC3C,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACA,QAAM,cAAc,aAAa,MAAM,KAAK;AAC5C,QAAM,QAAQ;AACd,QAAM,MAAM;AACZ,QAAM,OAAO;AACb,QAAM,YAAY,gBACd,IAAI,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,IAAI,EAAE,IAAI,MAClD;AACJ,QAAM,gBAAgB,SAAS,IAAI,IAAI,SAAS,KAAK,KAAK;AAC1D,QAAM,mBAAmB,OAAO,YAAY,GAAG,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM;AACvE,QAAM,cAAc,OAAO,eACvB,GAAG,GAAG,OAAG,yBAAY,SAAS,CAAC,GAAG,KAAK,MACvC;AAEJ,QAAM,QAAQ;AAAA,IACZ,OAAO,SAAS,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI,KAAK,KAAK;AAAA,IACpD;AAAA,IACA,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK;AAAA,IAC1B,GAAG,WAAW,GAAG,OAAO,OAAO,CAAC,CAAC,GAAG,KAAK;AAAA,IACzC,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,GAAG,KAAK;AAAA,IAC7C,GAAG,aAAa,GAAG,QAAQ,KAAK,KAAK,GAAG,aAAa;AAAA,IACrD;AAAA,IACA,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK;AAAA,EACtB,EAAE,OAAO,OAAO;AAEhB,MAAI,MAAO,OAAM,KAAK;AAAA,IAAO,GAAG,UAAU,KAAK,GAAG,KAAK,EAAE;AACzD,MAAI,YAAa,OAAM,KAAK;AAAA,IAAO,GAAG,YAAY,WAAW,GAAG,KAAK,EAAE;AACvE,MAAI,aAAc,OAAM,KAAK;AAAA,IAAO,GAAG,aAAa,YAAY,GAAG,KAAK,EAAE;AAE1E,UAAQ,IAAI,MAAM,KAAK,GAAG,CAAC;AAC7B;;;ADhIO,SAAS,QAAQ,SAAwB,CAAC,GAAmB;AAClE,SAAO,eAAgB,GAAG,MAAM;AAC9B,QAAI,OAAO,YAAY,OAAO;AAC5B,YAAM,KAAK;AACX;AAAA,IACF;AAEA,UAAM,SAAK,gCAAkB;AAC7B,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,SAAS,EAAE,IAAI;AACrB,UAAM,WAAW,EAAE,IAAI,MAAM;AAC7B,UAAM,cACJ,OAAO,aAAa,YAAY,WAC5B,IAAI,gBAAgB,QAAkC,EAAE,SAAS,IACjE;AACN,UAAM,MAAM,EAAE,IAAI,QAAQ,cAAc,MAAM,cAAc;AAE5D,QAAI,OAAO;AACT,UAAI;AACF,UAAE,OAAO,gBAAgB,EAAE;AAAA,MAC7B,QAAQ;AAAA,MAAC;AAEX,QAAI;AACJ,QAAI,OAAO,SAAS;AAClB,UAAI;AACF,cAAM,OAAO,MAAM,EAAE,IAAI,IACtB,MAAM,EACN,KAAK,EACL,MAAM,MAAM,IAAI;AACnB,YAAI,KAAM,eAAc,KAAK,MAAM,GAAG,OAAO,iBAAiB,GAAG;AAAA,MACnE,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,UAAM,KAAK;AAEX,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,UAAM,SAAS,EAAE,KAAK,UAAU;AAEhC,QACE,OAAO,eACP,OAAO,YAAY,SAAS,KAC5B,CAAC,OAAO,YAAY,SAAS,MAAM;AAEnC;AAEF,QAAI;AACJ,QAAI,OAAO,WAAW,EAAE,KAAK;AAC3B,UAAI;AACF,cAAM,UAAU,MAAM,EAAE,IACrB,MAAM,EACN,KAAK,EACL,MAAM,MAAM,IAAI;AACnB,YAAI;AACF,yBAAe,QAAQ,MAAM,GAAG,OAAO,iBAAiB,GAAG;AAAA,MAC/D,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,eAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,OAAO,UAAU,cAAc;AAAA,MAC5C,cAAc,OAAO,UAAU,eAAe;AAAA,IAChD,CAAC;AAAA,EACH;AACF;","names":["import_core","coreEmitter"]}
package/dist/hono.mjs ADDED
@@ -0,0 +1,170 @@
1
+ // src/hono.ts
2
+ import { generateRequestId } from "@snapwyr/core";
3
+
4
+ // src/utils.ts
5
+ import {
6
+ snapwyr as coreEmitter,
7
+ getByteSize,
8
+ formatBytes,
9
+ redactSensitiveData
10
+ } from "@snapwyr/core";
11
+ function logRequest(params) {
12
+ const { id, method, status, duration, url, startTime, config, error } = params;
13
+ let { requestBody, responseBody } = params;
14
+ if (config.silent) return;
15
+ const showTimestamp = config.showTimestamp !== false;
16
+ const format = config.format || "pretty";
17
+ const slowThreshold = config.slowThreshold ?? 1e3;
18
+ const isSlow = duration >= slowThreshold;
19
+ const requestSize = requestBody ? getByteSize(requestBody) : 0;
20
+ const responseSize = responseBody ? getByteSize(responseBody) : 0;
21
+ const totalSize = requestSize + responseSize;
22
+ if (config.redact && config.redact.length > 0) {
23
+ if (requestBody)
24
+ requestBody = redactSensitiveData(requestBody, config.redact);
25
+ if (responseBody)
26
+ responseBody = redactSensitiveData(responseBody, config.redact);
27
+ }
28
+ const logEntry = {
29
+ id,
30
+ timestamp: new Date(startTime).toISOString(),
31
+ method: method.toUpperCase(),
32
+ url,
33
+ status,
34
+ duration,
35
+ slow: isSlow
36
+ };
37
+ if (config.prefix) logEntry.prefix = config.prefix;
38
+ if (error) logEntry.error = error;
39
+ if (requestBody) logEntry.requestBody = requestBody;
40
+ if (responseBody) logEntry.responseBody = responseBody;
41
+ if (config.sizeTracking) {
42
+ logEntry.requestSize = requestSize;
43
+ logEntry.responseSize = responseSize;
44
+ logEntry.totalSize = totalSize;
45
+ }
46
+ try {
47
+ coreEmitter.emit("request", {
48
+ id,
49
+ method: method.toUpperCase(),
50
+ url,
51
+ status,
52
+ duration,
53
+ timestamp: startTime,
54
+ requestBody,
55
+ responseBody,
56
+ error,
57
+ requestSize: config.sizeTracking ? requestSize : void 0,
58
+ responseSize: config.sizeTracking ? responseSize : void 0,
59
+ direction: "incoming"
60
+ });
61
+ } catch {
62
+ }
63
+ if (config.transport) {
64
+ config.transport(logEntry);
65
+ }
66
+ if (format === "json") {
67
+ console.log(JSON.stringify(logEntry));
68
+ return;
69
+ }
70
+ const useEmoji = config.emoji === true;
71
+ let statusEmoji = "";
72
+ if (useEmoji) {
73
+ if (error || status >= 500) statusEmoji = "\u2717 ";
74
+ else if (status >= 400) statusEmoji = "\u26A0 ";
75
+ else if (status >= 300) statusEmoji = "\u21AA ";
76
+ else statusEmoji = "\u2713 ";
77
+ }
78
+ const statusColor = status >= 500 ? "\x1B[31m" : status >= 400 ? "\x1B[33m" : status >= 300 ? "\x1B[36m" : "\x1B[32m";
79
+ const durationColor = isSlow ? "\x1B[31m" : duration < 100 ? "\x1B[32m" : "\x1B[33m";
80
+ const methodColors = {
81
+ GET: "\x1B[34m",
82
+ POST: "\x1B[32m",
83
+ PUT: "\x1B[33m",
84
+ PATCH: "\x1B[35m",
85
+ DELETE: "\x1B[31m"
86
+ };
87
+ const methodColor = methodColors[method] || "";
88
+ const reset = "\x1B[0m";
89
+ const dim = "\x1B[2m";
90
+ const bold = "\x1B[1m";
91
+ const timestamp = showTimestamp ? new Date(startTime).toISOString().slice(11, 23) + " " : "";
92
+ const slowIndicator = isSlow ? ` ${bold}[SLOW]${reset}` : "";
93
+ const requestIdDisplay = config.requestId ? `${dim}[${id}]${reset} ` : "";
94
+ const sizeDisplay = config.sizeTracking ? `${dim}${formatBytes(totalSize)}${reset} ` : "";
95
+ const parts = [
96
+ config.prefix ? `${dim}${config.prefix} ${reset}` : "",
97
+ requestIdDisplay,
98
+ `${dim}${timestamp}${reset}`,
99
+ `${methodColor}${method.padEnd(6)}${reset}`,
100
+ `${statusColor}${statusEmoji}${status}${reset}`,
101
+ `${durationColor}${duration}ms${reset}${slowIndicator}`,
102
+ sizeDisplay,
103
+ `${dim}${url}${reset}`
104
+ ].filter(Boolean);
105
+ if (error) parts.push(`
106
+ ${dim}Error: ${error}${reset}`);
107
+ if (requestBody) parts.push(`
108
+ ${dim}Request: ${requestBody}${reset}`);
109
+ if (responseBody) parts.push(`
110
+ ${dim}Response: ${responseBody}${reset}`);
111
+ console.log(parts.join(" "));
112
+ }
113
+
114
+ // src/hono.ts
115
+ function snapwyr(config = {}) {
116
+ return async function(c, next) {
117
+ if (config.enabled === false) {
118
+ await next();
119
+ return;
120
+ }
121
+ const id = generateRequestId();
122
+ const startTime = Date.now();
123
+ const method = c.req.method;
124
+ const queryObj = c.req.query();
125
+ const queryString = typeof queryObj === "object" && queryObj ? new URLSearchParams(queryObj).toString() : "";
126
+ const url = c.req.path + (queryString ? "?" + queryString : "");
127
+ if (config.requestId)
128
+ try {
129
+ c.header("X-Request-ID", id);
130
+ } catch {
131
+ }
132
+ let requestBody;
133
+ if (config.logBody) {
134
+ try {
135
+ const body = await c.req.raw.clone().text().catch(() => null);
136
+ if (body) requestBody = body.slice(0, config.bodySizeLimit || 500);
137
+ } catch {
138
+ }
139
+ }
140
+ await next();
141
+ const duration = Date.now() - startTime;
142
+ const status = c.res?.status ?? 200;
143
+ if (config.statusCodes && config.statusCodes.length > 0 && !config.statusCodes.includes(status))
144
+ return;
145
+ let responseBody;
146
+ if (config.logBody && c.res) {
147
+ try {
148
+ const resBody = await c.res.clone().text().catch(() => null);
149
+ if (resBody)
150
+ responseBody = resBody.slice(0, config.bodySizeLimit || 500);
151
+ } catch {
152
+ }
153
+ }
154
+ logRequest({
155
+ id,
156
+ method,
157
+ status,
158
+ duration,
159
+ url,
160
+ startTime,
161
+ config,
162
+ requestBody: config.logBody ? requestBody : void 0,
163
+ responseBody: config.logBody ? responseBody : void 0
164
+ });
165
+ };
166
+ }
167
+ export {
168
+ snapwyr
169
+ };
170
+ //# sourceMappingURL=hono.mjs.map