evlog 2.18.1 → 2.19.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 (190) hide show
  1. package/dist/adapters/axiom.d.mts +1 -1
  2. package/dist/adapters/axiom.mjs +2 -2
  3. package/dist/adapters/better-stack.d.mts +1 -1
  4. package/dist/adapters/better-stack.mjs +2 -2
  5. package/dist/adapters/datadog.d.mts +1 -1
  6. package/dist/adapters/datadog.mjs +2 -2
  7. package/dist/adapters/fs.d.mts +1 -1
  8. package/dist/adapters/fs.mjs +2 -2
  9. package/dist/adapters/hyperdx.d.mts +1 -1
  10. package/dist/adapters/hyperdx.mjs +1 -1
  11. package/dist/adapters/memory.d.mts +1 -1
  12. package/dist/adapters/memory.mjs +1 -1
  13. package/dist/adapters/otlp.d.mts +1 -1
  14. package/dist/adapters/otlp.mjs +4 -4
  15. package/dist/adapters/posthog.d.mts +1 -1
  16. package/dist/adapters/posthog.mjs +2 -2
  17. package/dist/adapters/sentry.d.mts +1 -1
  18. package/dist/adapters/sentry.mjs +3 -3
  19. package/dist/ai/index.d.mts +1 -1
  20. package/dist/{audit-BUI3af4w.mjs → audit-BFwTUxBJ.mjs} +357 -101
  21. package/dist/audit-BFwTUxBJ.mjs.map +1 -0
  22. package/dist/{audit-DVdkntSO.d.mts → audit-BUAajsPU.d.mts} +106 -35
  23. package/dist/audit-BUAajsPU.d.mts.map +1 -0
  24. package/dist/better-auth/index.d.mts +1 -1
  25. package/dist/browser.d.mts +1 -1
  26. package/dist/{define-D6OJdSUH.mjs → define-Bpaymi-h.mjs} +2 -1
  27. package/dist/define-Bpaymi-h.mjs.map +1 -0
  28. package/dist/{define-D-BVMf2l.d.mts → define-DGwZkZ7x.d.mts} +8 -3
  29. package/dist/define-DGwZkZ7x.d.mts.map +1 -0
  30. package/dist/dev-terminal-D4UaEm17.mjs +54 -0
  31. package/dist/dev-terminal-D4UaEm17.mjs.map +1 -0
  32. package/dist/{dist-H3GIh-KK.mjs → dist-DdQWiZn8.mjs} +1 -1
  33. package/dist/{dist-H3GIh-KK.mjs.map → dist-DdQWiZn8.mjs.map} +1 -1
  34. package/dist/{drain-7n3K6kPe.mjs → drain-D_fy7m0n.mjs} +3 -3
  35. package/dist/{drain-7n3K6kPe.mjs.map → drain-D_fy7m0n.mjs.map} +1 -1
  36. package/dist/elysia/index.d.mts +3 -3
  37. package/dist/elysia/index.d.mts.map +1 -1
  38. package/dist/elysia/index.mjs +8 -5
  39. package/dist/elysia/index.mjs.map +1 -1
  40. package/dist/enrich-drain-CG_2Nix-.mjs +122 -0
  41. package/dist/enrich-drain-CG_2Nix-.mjs.map +1 -0
  42. package/dist/{enricher-UW9npoB2.d.mts → enricher-CuMbbdqp.d.mts} +2 -2
  43. package/dist/{enricher-UW9npoB2.d.mts.map → enricher-CuMbbdqp.d.mts.map} +1 -1
  44. package/dist/{enricher-N0erZS87.mjs → enricher-DAWf2-Fx.mjs} +2 -2
  45. package/dist/{enricher-N0erZS87.mjs.map → enricher-DAWf2-Fx.mjs.map} +1 -1
  46. package/dist/enrichers.d.mts +2 -2
  47. package/dist/enrichers.mjs +2 -2
  48. package/dist/{error-CVtn5U7b.d.mts → error-DwajXSKM.d.mts} +2 -2
  49. package/dist/{error-CVtn5U7b.d.mts.map → error-DwajXSKM.d.mts.map} +1 -1
  50. package/dist/error.d.mts +1 -1
  51. package/dist/{errors-dEMNQCiL.d.mts → errors-CAq8pYpW.d.mts} +2 -2
  52. package/dist/{errors-dEMNQCiL.d.mts.map → errors-CAq8pYpW.d.mts.map} +1 -1
  53. package/dist/{errors-BQgyQ9xe.mjs → errors-DA0cyr8q.mjs} +1 -1
  54. package/dist/{errors-BQgyQ9xe.mjs.map → errors-DA0cyr8q.mjs.map} +1 -1
  55. package/dist/{event-1BMl7o0k.mjs → event-qwAv-7AZ.mjs} +1 -1
  56. package/dist/{event-1BMl7o0k.mjs.map → event-qwAv-7AZ.mjs.map} +1 -1
  57. package/dist/express/index.d.mts +2 -2
  58. package/dist/express/index.mjs +3 -3
  59. package/dist/fastify/index.d.mts +2 -2
  60. package/dist/fastify/index.mjs +2 -2
  61. package/dist/{fork-Bga8x-X4.mjs → fork-CYm453dq.mjs} +39 -14
  62. package/dist/fork-CYm453dq.mjs.map +1 -0
  63. package/dist/{headers-CU-QqnYg.mjs → headers-VtmnWcfn.mjs} +1 -1
  64. package/dist/{headers-CU-QqnYg.mjs.map → headers-VtmnWcfn.mjs.map} +1 -1
  65. package/dist/hono/index.d.mts +2 -2
  66. package/dist/hono/index.d.mts.map +1 -1
  67. package/dist/hono/index.mjs +10 -2
  68. package/dist/hono/index.mjs.map +1 -1
  69. package/dist/{http-B6YgAhyN.mjs → http-Bept5EIC.mjs} +2 -2
  70. package/dist/{http-B6YgAhyN.mjs.map → http-Bept5EIC.mjs.map} +1 -1
  71. package/dist/http.d.mts +1 -1
  72. package/dist/{index-ZSRQP_BI.d.mts → index-CE7kH0II.d.mts} +15 -8
  73. package/dist/index-CE7kH0II.d.mts.map +1 -0
  74. package/dist/index.d.mts +9 -9
  75. package/dist/index.mjs +9 -15
  76. package/dist/index.mjs.map +1 -1
  77. package/dist/{integration-Dhig7ae6.mjs → integration-CR601uyW.mjs} +3 -3
  78. package/dist/{integration-Dhig7ae6.mjs.map → integration-CR601uyW.mjs.map} +1 -1
  79. package/dist/{logger-CTcvd5Cc.d.mts → logger-BccCJUyD.d.mts} +8 -4
  80. package/dist/logger-BccCJUyD.d.mts.map +1 -0
  81. package/dist/logger.d.mts +2 -2
  82. package/dist/logger.mjs +2 -2
  83. package/dist/{middleware-31KhtiEF.d.mts → middleware-DQ6-h8h0.d.mts} +9 -2
  84. package/dist/middleware-DQ6-h8h0.d.mts.map +1 -0
  85. package/dist/nestjs/index.d.mts +2 -2
  86. package/dist/nestjs/index.mjs +4 -4
  87. package/dist/next/client.d.mts +1 -1
  88. package/dist/next/index.d.mts +4 -4
  89. package/dist/next/index.d.mts.map +1 -1
  90. package/dist/next/index.mjs +35 -37
  91. package/dist/next/index.mjs.map +1 -1
  92. package/dist/next/instrumentation.d.mts +1 -1
  93. package/dist/next/instrumentation.mjs +1 -1
  94. package/dist/nitro/errorHandler.mjs +10 -16
  95. package/dist/nitro/errorHandler.mjs.map +1 -1
  96. package/dist/nitro/module.d.mts +2 -2
  97. package/dist/nitro/module.d.mts.map +1 -1
  98. package/dist/nitro/module.mjs +2 -1
  99. package/dist/nitro/module.mjs.map +1 -1
  100. package/dist/nitro/plugin.mjs +36 -65
  101. package/dist/nitro/plugin.mjs.map +1 -1
  102. package/dist/nitro/v3/errorHandler.d.mts +0 -7
  103. package/dist/nitro/v3/errorHandler.mjs +13 -15
  104. package/dist/nitro/v3/errorHandler.mjs.map +1 -1
  105. package/dist/nitro/v3/index.d.mts +2 -2
  106. package/dist/nitro/v3/module.d.mts +1 -1
  107. package/dist/nitro/v3/module.d.mts.map +1 -1
  108. package/dist/nitro/v3/module.mjs +3 -3
  109. package/dist/nitro/v3/module.mjs.map +1 -1
  110. package/dist/nitro/v3/plugin.mjs +76 -44
  111. package/dist/nitro/v3/plugin.mjs.map +1 -1
  112. package/dist/nitro/v3/useLogger.d.mts +1 -1
  113. package/dist/nitro-ClRZLD1g.mjs +96 -0
  114. package/dist/nitro-ClRZLD1g.mjs.map +1 -0
  115. package/dist/{nitro-BRddgqSb.d.mts → nitro-zCXTylj4.d.mts} +7 -2
  116. package/dist/nitro-zCXTylj4.d.mts.map +1 -0
  117. package/dist/{nitroConfigBridge-NbFn-sIK.mjs → nitroConfigBridge-BkVWnSV3.mjs} +9 -2
  118. package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +1 -0
  119. package/dist/{nodeResponse-BkkionWl.mjs → nodeResponse-CIEEbrNE.mjs} +1 -1
  120. package/dist/{nodeResponse-BkkionWl.mjs.map → nodeResponse-CIEEbrNE.mjs.map} +1 -1
  121. package/dist/nuxt/module.d.mts +6 -1
  122. package/dist/nuxt/module.d.mts.map +1 -1
  123. package/dist/nuxt/module.mjs +11 -4
  124. package/dist/nuxt/module.mjs.map +1 -1
  125. package/dist/orpc/index.d.mts +2 -2
  126. package/dist/orpc/index.d.mts.map +1 -1
  127. package/dist/orpc/index.mjs +5 -4
  128. package/dist/orpc/index.mjs.map +1 -1
  129. package/dist/{package-B23bR3tK.mjs → package-CUhII9DA.mjs} +2 -2
  130. package/dist/package-CUhII9DA.mjs.map +1 -0
  131. package/dist/{parseError-D4PIxEWo.d.mts → parseError-Cagr-Ctc.d.mts} +2 -2
  132. package/dist/parseError-Cagr-Ctc.d.mts.map +1 -0
  133. package/dist/pretty-error-CVVgwlTn.mjs +278 -0
  134. package/dist/pretty-error-CVVgwlTn.mjs.map +1 -0
  135. package/dist/pretty-error-snippet.node-c_bzjg7g.mjs +47 -0
  136. package/dist/pretty-error-snippet.node-c_bzjg7g.mjs.map +1 -0
  137. package/dist/react-router/index.d.mts +2 -2
  138. package/dist/react-router/index.mjs +5 -6
  139. package/dist/react-router/index.mjs.map +1 -1
  140. package/dist/{routes-CnIgYWf8.mjs → routes-4rMzRyTk.mjs} +1 -1
  141. package/dist/{routes-CnIgYWf8.mjs.map → routes-4rMzRyTk.mjs.map} +1 -1
  142. package/dist/runtime/client/log.d.mts +1 -1
  143. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -1
  144. package/dist/runtime/server/useLogger.d.mts +1 -1
  145. package/dist/runtime/utils/parseError.d.mts +2 -2
  146. package/dist/runtime/utils/parseError.mjs +1 -1
  147. package/dist/{severity-R5Egq3qz.mjs → severity-CwXUSHt3.mjs} +1 -1
  148. package/dist/{severity-R5Egq3qz.mjs.map → severity-CwXUSHt3.mjs.map} +1 -1
  149. package/dist/{source-location-Dco0cRTz.mjs → source-location-xkDGiERl.mjs} +1 -1
  150. package/dist/{source-location-Dco0cRTz.mjs.map → source-location-xkDGiERl.mjs.map} +1 -1
  151. package/dist/{storage-BNubsWwz.mjs → storage-7X37OToT.mjs} +1 -1
  152. package/dist/{storage-BNubsWwz.mjs.map → storage-7X37OToT.mjs.map} +1 -1
  153. package/dist/stream.d.mts +1 -1
  154. package/dist/stream.mjs +1 -1
  155. package/dist/streamResponse-CmQ3qUbF.mjs +94 -0
  156. package/dist/streamResponse-CmQ3qUbF.mjs.map +1 -0
  157. package/dist/sveltekit/index.d.mts +2 -2
  158. package/dist/sveltekit/index.d.mts.map +1 -1
  159. package/dist/sveltekit/index.mjs +7 -8
  160. package/dist/sveltekit/index.mjs.map +1 -1
  161. package/dist/toolkit.d.mts +37 -6
  162. package/dist/toolkit.d.mts.map +1 -1
  163. package/dist/toolkit.mjs +15 -14
  164. package/dist/types.d.mts +2 -2
  165. package/dist/{useLogger-CqvH6qOf.d.mts → useLogger-Dv52PDpH.d.mts} +2 -2
  166. package/dist/{useLogger-CqvH6qOf.d.mts.map → useLogger-Dv52PDpH.d.mts.map} +1 -1
  167. package/dist/{utils-DxqvIOyR.d.mts → utils-DmNbZwBZ.d.mts} +11 -3
  168. package/dist/{utils-DxqvIOyR.d.mts.map → utils-DmNbZwBZ.d.mts.map} +1 -1
  169. package/dist/utils.d.mts +2 -2
  170. package/dist/utils.mjs +21 -8
  171. package/dist/utils.mjs.map +1 -1
  172. package/dist/vite/index.d.mts +1 -1
  173. package/dist/vite/index.mjs +1 -1
  174. package/dist/workers.d.mts +1 -1
  175. package/dist/workers.mjs +1 -1
  176. package/package.json +1 -1
  177. package/dist/audit-BUI3af4w.mjs.map +0 -1
  178. package/dist/audit-DVdkntSO.d.mts.map +0 -1
  179. package/dist/define-D-BVMf2l.d.mts.map +0 -1
  180. package/dist/define-D6OJdSUH.mjs.map +0 -1
  181. package/dist/fork-Bga8x-X4.mjs.map +0 -1
  182. package/dist/index-ZSRQP_BI.d.mts.map +0 -1
  183. package/dist/logger-CTcvd5Cc.d.mts.map +0 -1
  184. package/dist/middleware-31KhtiEF.d.mts.map +0 -1
  185. package/dist/nitro-BRddgqSb.d.mts.map +0 -1
  186. package/dist/nitro-DErMq_Zj.mjs +0 -34
  187. package/dist/nitro-DErMq_Zj.mjs.map +0 -1
  188. package/dist/nitroConfigBridge-NbFn-sIK.mjs.map +0 -1
  189. package/dist/package-B23bR3tK.mjs.map +0 -1
  190. package/dist/parseError-D4PIxEWo.d.mts.map +0 -1
@@ -1,8 +1,12 @@
1
- import { b as initLogger, g as createRequestLogger, j as normalizeRedactConfig, x as isEnabled, y as getGlobalPluginRunner } from "../audit-BUI3af4w.mjs";
1
+ import { n as readCodeSnippetFromDisk } from "../pretty-error-snippet.node-c_bzjg7g.mjs";
2
2
  import { filterSafeHeaders } from "../utils.mjs";
3
- import { t as extractErrorStatus } from "../errors-BQgyQ9xe.mjs";
4
- import { n as shouldLog, t as getServiceForPath } from "../routes-CnIgYWf8.mjs";
5
- import { n as resolveEvlogConfigForNitroPlugin, r as setActiveNitroRuntime } from "../nitroConfigBridge-NbFn-sIK.mjs";
3
+ import { N as normalizeRedactConfig, b as initLogger, g as createRequestLogger, x as isEnabled, y as getGlobalPluginRunner } from "../audit-BFwTUxBJ.mjs";
4
+ import { i as registerPrettyErrorSnippetReader } from "../pretty-error-CVVgwlTn.mjs";
5
+ import { t as extractErrorStatus } from "../errors-DA0cyr8q.mjs";
6
+ import { i as setActiveNitroRuntime, r as resolveEvlogConfigForNitroPlugin } from "../nitroConfigBridge-BkVWnSV3.mjs";
7
+ import { n as shouldLog, t as getServiceForPath } from "../routes-4rMzRyTk.mjs";
8
+ import { r as enrichErrorStackForDev, t as callEnrichAndDrain } from "../enrich-drain-CG_2Nix-.mjs";
9
+ import { r as shouldDeferEmitForResponse, t as bindStreamingResponseLifecycle } from "../streamResponse-CmQ3qUbF.mjs";
6
10
  import { startStreamServer } from "../stream.mjs";
7
11
  import { defineNitroPlugin } from "nitropack/runtime/internal/plugin";
8
12
  import { getHeaders } from "h3";
@@ -10,75 +14,22 @@ import { getHeaders } from "h3";
10
14
  function getSafeHeaders(event) {
11
15
  return filterSafeHeaders(getHeaders(event));
12
16
  }
13
- function getSafeResponseHeaders(event) {
14
- const headers = {};
15
- const nodeRes = event.node?.res;
16
- if (nodeRes?.getHeaders) for (const [key, value] of Object.entries(nodeRes.getHeaders())) {
17
- if (value === void 0) continue;
18
- headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
19
- }
20
- if (event.response?.headers) event.response.headers.forEach((value, key) => {
21
- headers[key] = value;
22
- });
23
- if (Object.keys(headers).length === 0) return void 0;
24
- return filterSafeHeaders(headers);
25
- }
26
17
  function getResponseStatus(event) {
27
18
  if (event.node?.res?.statusCode) return event.node.res.statusCode;
28
19
  if (event.response?.status) return event.response.status;
29
20
  if (typeof event.context.status === "number") return event.context.status;
30
21
  return 200;
31
22
  }
32
- function buildHookContext(event) {
33
- const responseHeaders = getSafeResponseHeaders(event);
34
- return {
35
- request: {
36
- method: event.method,
37
- path: event.path
38
- },
39
- headers: getSafeHeaders(event),
40
- response: {
41
- status: getResponseStatus(event),
42
- headers: responseHeaders
43
- }
44
- };
45
- }
46
- async function callEnrichAndDrain(nitroApp, emittedEvent, event) {
47
- if (!emittedEvent) return;
48
- const hookContext = buildHookContext(event);
49
- const enrichCtx = {
50
- event: emittedEvent,
51
- ...hookContext
52
- };
53
- const runner = getGlobalPluginRunner();
54
- try {
55
- await nitroApp.hooks.callHook("evlog:enrich", enrichCtx);
56
- } catch (err) {
57
- console.error("[evlog] enrich failed:", err);
58
- }
59
- if (runner.hasEnrich) await runner.runEnrich(enrichCtx);
60
- const drainCtx = {
61
- event: emittedEvent,
62
- request: hookContext.request,
63
- headers: hookContext.headers
64
- };
65
- const drainTasks = [nitroApp.hooks.callHook("evlog:drain", drainCtx).catch((err) => {
66
- console.error("[evlog] drain failed:", err);
67
- })];
68
- if (runner.hasDrain) drainTasks.push(runner.runDrain(drainCtx));
69
- const drainPromise = Promise.all(drainTasks);
70
- const waitUntilCtx = event.context.cloudflare?.context ?? event.context;
71
- if (typeof waitUntilCtx?.waitUntil === "function") waitUntilCtx.waitUntil(drainPromise);
72
- else await drainPromise;
73
- }
74
23
  var plugin_default = defineNitroPlugin(async (nitroApp) => {
75
24
  setActiveNitroRuntime("v2");
76
25
  const evlogConfig = await resolveEvlogConfigForNitroPlugin();
77
26
  const redact = normalizeRedactConfig(evlogConfig?.redact);
27
+ registerPrettyErrorSnippetReader(readCodeSnippetFromDisk);
78
28
  initLogger({
79
29
  enabled: evlogConfig?.enabled,
80
30
  env: evlogConfig?.env,
81
31
  pretty: evlogConfig?.pretty,
32
+ dev: evlogConfig?.dev,
82
33
  silent: evlogConfig?.silent,
83
34
  sampling: evlogConfig?.sampling,
84
35
  minLevel: evlogConfig?.minLevel,
@@ -132,8 +83,12 @@ var plugin_default = defineNitroPlugin(async (nitroApp) => {
132
83
  if (!e) return;
133
84
  if (!e.context._evlogShouldEmit) return;
134
85
  const requestLog = e.context.log;
135
- if (requestLog) {
136
- requestLog.error(error);
86
+ if (!requestLog) return;
87
+ e.context._evlogEmitting = true;
88
+ try {
89
+ const err = error;
90
+ enrichErrorStackForDev(err, { pretty: evlogConfig?.pretty });
91
+ requestLog.error(err);
137
92
  const errorStatus = extractErrorStatus(error);
138
93
  requestLog.set({ status: errorStatus });
139
94
  const startTime = e.context._evlogStartTime;
@@ -148,15 +103,23 @@ var plugin_default = defineNitroPlugin(async (nitroApp) => {
148
103
  await nitroApp.hooks.callHook("evlog:emit:keep", tailCtx);
149
104
  const runner = getGlobalPluginRunner();
150
105
  if (runner.hasKeep) await runner.runKeep(tailCtx);
151
- e.context._evlogEmitted = true;
152
- await callEnrichAndDrain(nitroApp, requestLog.emit({ _forceKeep: tailCtx.shouldKeep }), e);
106
+ const emittedEvent = requestLog.emit({ _forceKeep: tailCtx.shouldKeep });
107
+ if (emittedEvent) {
108
+ e.context._evlogEmitted = true;
109
+ callEnrichAndDrain(nitroApp, emittedEvent, e, { deferDrain: true }).catch((err) => {
110
+ console.error("[evlog] background enrich/drain failed:", err);
111
+ });
112
+ }
113
+ } finally {
114
+ delete e.context._evlogEmitting;
153
115
  }
154
116
  });
155
117
  nitroApp.hooks.hook("afterResponse", async (event) => {
156
118
  const e = event;
157
- if (e.context._evlogEmitted || !e.context._evlogShouldEmit) return;
119
+ if (e.context._evlogEmitted || e.context._evlogEmitting || !e.context._evlogShouldEmit) return;
158
120
  const requestLog = e.context.log;
159
- if (requestLog) {
121
+ if (!requestLog) return;
122
+ const emitSuccessResponse = async () => {
160
123
  const status = getResponseStatus(e);
161
124
  requestLog.set({ status });
162
125
  const startTime = e.context._evlogStartTime;
@@ -172,7 +135,15 @@ var plugin_default = defineNitroPlugin(async (nitroApp) => {
172
135
  const runner = getGlobalPluginRunner();
173
136
  if (runner.hasKeep) await runner.runKeep(tailCtx);
174
137
  await callEnrichAndDrain(nitroApp, requestLog.emit({ _forceKeep: tailCtx.shouldKeep }), e);
138
+ };
139
+ if (e.response && shouldDeferEmitForResponse(e.response)) {
140
+ e.response = bindStreamingResponseLifecycle(e.response, async (meta) => {
141
+ if (meta.error) requestLog.error(meta.error);
142
+ await emitSuccessResponse();
143
+ });
144
+ return;
175
145
  }
146
+ await emitSuccessResponse();
176
147
  });
177
148
  });
178
149
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../../src/nitro/plugin.ts"],"sourcesContent":["import type { NitroApp } from 'nitropack/types'\n// Import from specific subpaths to avoid the barrel 'nitropack/runtime' which\n// re-exports from internal/app.mjs — that file imports #nitro-internal-virtual/*\n// modules that only exist inside rollup builds and crash when loaded externally\n// (nitropack dev loads plugins outside the bundle via Worker threads).\nimport { defineNitroPlugin } from 'nitropack/runtime/internal/plugin'\nimport { getHeaders } from 'h3'\nimport { createRequestLogger, getGlobalPluginRunner, initLogger, isEnabled } from '../logger'\nimport { shouldLog, getServiceForPath, extractErrorStatus } from '../nitro'\nimport { normalizeRedactConfig } from '../redact'\nimport { resolveEvlogConfigForNitroPlugin, setActiveNitroRuntime } from '../shared/nitroConfigBridge'\nimport { startStreamServer, type StreamServerOptions } from '../stream'\nimport type { EnrichContext, RequestLogger, ServerEvent, TailSamplingContext, WideEvent } from '../types'\nimport { filterSafeHeaders } from '../utils'\n\nfunction getSafeHeaders(event: ServerEvent): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\nfunction getSafeResponseHeaders(event: ServerEvent): Record<string, string> | undefined {\n const headers: Record<string, string> = {}\n const nodeRes = event.node?.res as { getHeaders?: () => Record<string, unknown> } | undefined\n\n if (nodeRes?.getHeaders) {\n for (const [key, value] of Object.entries(nodeRes.getHeaders())) {\n if (value === undefined) continue\n headers[key] = Array.isArray(value) ? value.join(', ') : String(value)\n }\n }\n\n if (event.response?.headers) {\n event.response.headers.forEach((value, key) => {\n headers[key] = value\n })\n }\n\n if (Object.keys(headers).length === 0) return undefined\n return filterSafeHeaders(headers)\n}\n\nfunction getResponseStatus(event: ServerEvent): number {\n // Node.js style\n if (event.node?.res?.statusCode) {\n return event.node.res.statusCode\n }\n\n // Web Standard\n if (event.response?.status) {\n return event.response.status\n }\n\n // Context-based\n if (typeof event.context.status === 'number') {\n return event.context.status\n }\n\n return 200\n}\n\nfunction buildHookContext(event: ServerEvent): Omit<EnrichContext, 'event'> {\n const responseHeaders = getSafeResponseHeaders(event)\n return {\n request: { method: event.method, path: event.path },\n headers: getSafeHeaders(event),\n response: {\n status: getResponseStatus(event),\n headers: responseHeaders,\n },\n }\n}\n\nasync function callEnrichAndDrain(\n nitroApp: NitroApp,\n emittedEvent: WideEvent | null,\n event: ServerEvent,\n): Promise<void> {\n if (!emittedEvent) return\n\n const hookContext = buildHookContext(event)\n const enrichCtx: EnrichContext = { event: emittedEvent, ...hookContext }\n const runner = getGlobalPluginRunner()\n\n try {\n await nitroApp.hooks.callHook('evlog:enrich', enrichCtx)\n } catch (err) {\n console.error('[evlog] enrich failed:', err)\n }\n if (runner.hasEnrich) {\n await runner.runEnrich(enrichCtx)\n }\n\n const drainCtx = {\n event: emittedEvent,\n request: hookContext.request,\n headers: hookContext.headers,\n }\n const drainTasks: Array<Promise<unknown>> = [\n nitroApp.hooks.callHook('evlog:drain', drainCtx).catch((err) => {\n console.error('[evlog] drain failed:', err)\n }),\n ]\n if (runner.hasDrain) {\n drainTasks.push(runner.runDrain(drainCtx))\n }\n const drainPromise = Promise.all(drainTasks)\n\n // Use waitUntil if available (Cloudflare Workers, Vercel Edge, etc.)\n // This keeps the runtime alive for background work without blocking the response\n const waitUntilCtx = event.context.cloudflare?.context ?? event.context\n if (typeof waitUntilCtx?.waitUntil === 'function') {\n waitUntilCtx.waitUntil(drainPromise)\n } else {\n // Fallback: await drain to prevent lost logs in serverless environments\n // (e.g. Vercel Fluid Compute). On the normal path this runs from\n // afterResponse (response already sent); on the error path it may run\n // before the error response is finalized.\n await drainPromise\n }\n}\n\nexport default defineNitroPlugin(async (nitroApp) => {\n setActiveNitroRuntime('v2')\n const evlogConfig = await resolveEvlogConfigForNitroPlugin()\n\n const redact = normalizeRedactConfig(evlogConfig?.redact as boolean | Record<string, unknown> | undefined)\n\n initLogger({\n enabled: evlogConfig?.enabled,\n env: evlogConfig?.env,\n pretty: evlogConfig?.pretty,\n silent: evlogConfig?.silent,\n sampling: evlogConfig?.sampling,\n minLevel: evlogConfig?.minLevel,\n redact,\n _suppressDrainWarning: true,\n })\n\n // When `evlog.stream` is set (or auto-on in dev), boot the mini stream\n // server and hook every drained event into it. The server runs on its\n // own ephemeral port — the user's API surface is untouched.\n const streamSetting = (evlogConfig as { stream?: boolean | StreamServerOptions } | undefined)?.stream\n if (streamSetting === true || (streamSetting && typeof streamSetting === 'object')) {\n const streamOpts: StreamServerOptions = streamSetting === true ? {} : streamSetting\n startStreamServer(streamOpts).then((server) => {\n nitroApp.hooks.hook('evlog:drain', (ctx) => {\n if (ctx?.event) server.drain(ctx)\n })\n }).catch((err) => {\n console.error('[evlog] failed to start stream server:', err)\n })\n }\n\n // When globally disabled, createRequestLogger returns a no-op logger — still\n // attach it so handlers can call useLogger(event) without throwing.\n if (!isEnabled()) {\n nitroApp.hooks.hook('request', (event) => {\n const e = event as ServerEvent\n let requestIdOverride: string | undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = getSafeHeaders(e)?.['cf-ray']\n if (cfRay) requestIdOverride = cfRay\n }\n e.context.log = createRequestLogger({\n method: e.method,\n path: e.path,\n requestId: requestIdOverride || e.context.requestId || crypto.randomUUID(),\n }, { _deferDrain: true })\n })\n return\n }\n\n nitroApp.hooks.hook('request', (event) => {\n const e = event as ServerEvent\n\n // Evaluate route filtering but always create the logger so that server\n // middleware (which runs for every request) can call useLogger(event)\n // without throwing. Filtering is enforced at emit time instead.\n e.context._evlogShouldEmit = shouldLog(e.path, evlogConfig?.include, evlogConfig?.exclude)\n\n // Store start time for duration calculation in tail sampling\n e.context._evlogStartTime = Date.now()\n\n let requestIdOverride: string | undefined = undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = getSafeHeaders(e)?.['cf-ray']\n if (cfRay) requestIdOverride = cfRay\n }\n\n const requestLog = createRequestLogger({\n method: e.method,\n path: e.path,\n requestId: requestIdOverride || e.context.requestId || crypto.randomUUID(),\n }, { _deferDrain: true })\n\n // Apply route-based service configuration if a matching route is found\n const routeService = getServiceForPath(e.path, evlogConfig?.routes)\n if (routeService) {\n requestLog.set({ service: routeService })\n }\n\n e.context.log = requestLog\n })\n\n nitroApp.hooks.hook('error', async (error, { event }) => {\n const e = event as ServerEvent | undefined\n if (!e) return\n if (!e.context._evlogShouldEmit) return\n\n const requestLog = e.context.log as RequestLogger | undefined\n if (requestLog) {\n requestLog.error(error as Error)\n\n const errorStatus = extractErrorStatus(error)\n requestLog.set({ status: errorStatus })\n\n // Build tail sampling context\n const startTime = e.context._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status: errorStatus,\n duration: durationMs,\n path: e.path,\n method: e.method,\n context: requestLog.getContext(),\n shouldKeep: false,\n }\n\n // Call evlog:emit:keep hook + plugin runner keep hook\n await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n e.context._evlogEmitted = true\n\n const emittedEvent = requestLog.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(nitroApp, emittedEvent, e)\n }\n })\n\n nitroApp.hooks.hook('afterResponse', async (event) => {\n const e = event as ServerEvent\n // Skip if already emitted by error hook or route was filtered out\n if (e.context._evlogEmitted || !e.context._evlogShouldEmit) return\n\n const requestLog = e.context.log as RequestLogger | undefined\n if (requestLog) {\n const status = getResponseStatus(e)\n requestLog.set({ status })\n\n const startTime = e.context._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status,\n duration: durationMs,\n path: e.path,\n method: e.method,\n context: requestLog.getContext(),\n shouldKeep: false,\n }\n\n await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = requestLog.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(nitroApp, emittedEvent, e)\n }\n })\n})\n"],"mappings":";;;;;;;;;AAeA,SAAS,eAAe,OAA4C;AAElE,QAAO,kBADY,WAAW,MACK,CAAC;;AAGtC,SAAS,uBAAuB,OAAwD;CACtF,MAAM,UAAkC,EAAE;CAC1C,MAAM,UAAU,MAAM,MAAM;AAE5B,KAAI,SAAS,WACX,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,YAAY,CAAC,EAAE;AAC/D,MAAI,UAAU,KAAA,EAAW;AACzB,UAAQ,OAAO,MAAM,QAAQ,MAAM,GAAG,MAAM,KAAK,KAAK,GAAG,OAAO,MAAM;;AAI1E,KAAI,MAAM,UAAU,QAClB,OAAM,SAAS,QAAQ,SAAS,OAAO,QAAQ;AAC7C,UAAQ,OAAO;GACf;AAGJ,KAAI,OAAO,KAAK,QAAQ,CAAC,WAAW,EAAG,QAAO,KAAA;AAC9C,QAAO,kBAAkB,QAAQ;;AAGnC,SAAS,kBAAkB,OAA4B;AAErD,KAAI,MAAM,MAAM,KAAK,WACnB,QAAO,MAAM,KAAK,IAAI;AAIxB,KAAI,MAAM,UAAU,OAClB,QAAO,MAAM,SAAS;AAIxB,KAAI,OAAO,MAAM,QAAQ,WAAW,SAClC,QAAO,MAAM,QAAQ;AAGvB,QAAO;;AAGT,SAAS,iBAAiB,OAAkD;CAC1E,MAAM,kBAAkB,uBAAuB,MAAM;AACrD,QAAO;EACL,SAAS;GAAE,QAAQ,MAAM;GAAQ,MAAM,MAAM;GAAM;EACnD,SAAS,eAAe,MAAM;EAC9B,UAAU;GACR,QAAQ,kBAAkB,MAAM;GAChC,SAAS;GACV;EACF;;AAGH,eAAe,mBACb,UACA,cACA,OACe;AACf,KAAI,CAAC,aAAc;CAEnB,MAAM,cAAc,iBAAiB,MAAM;CAC3C,MAAM,YAA2B;EAAE,OAAO;EAAc,GAAG;EAAa;CACxE,MAAM,SAAS,uBAAuB;AAEtC,KAAI;AACF,QAAM,SAAS,MAAM,SAAS,gBAAgB,UAAU;UACjD,KAAK;AACZ,UAAQ,MAAM,0BAA0B,IAAI;;AAE9C,KAAI,OAAO,UACT,OAAM,OAAO,UAAU,UAAU;CAGnC,MAAM,WAAW;EACf,OAAO;EACP,SAAS,YAAY;EACrB,SAAS,YAAY;EACtB;CACD,MAAM,aAAsC,CAC1C,SAAS,MAAM,SAAS,eAAe,SAAS,CAAC,OAAO,QAAQ;AAC9D,UAAQ,MAAM,yBAAyB,IAAI;GAC3C,CACH;AACD,KAAI,OAAO,SACT,YAAW,KAAK,OAAO,SAAS,SAAS,CAAC;CAE5C,MAAM,eAAe,QAAQ,IAAI,WAAW;CAI5C,MAAM,eAAe,MAAM,QAAQ,YAAY,WAAW,MAAM;AAChE,KAAI,OAAO,cAAc,cAAc,WACrC,cAAa,UAAU,aAAa;KAMpC,OAAM;;AAIV,IAAA,iBAAe,kBAAkB,OAAO,aAAa;AACnD,uBAAsB,KAAK;CAC3B,MAAM,cAAc,MAAM,kCAAkC;CAE5D,MAAM,SAAS,sBAAsB,aAAa,OAAwD;AAE1G,YAAW;EACT,SAAS,aAAa;EACtB,KAAK,aAAa;EAClB,QAAQ,aAAa;EACrB,QAAQ,aAAa;EACrB,UAAU,aAAa;EACvB,UAAU,aAAa;EACvB;EACA,uBAAuB;EACxB,CAAC;CAKF,MAAM,gBAAiB,aAAwE;AAC/F,KAAI,kBAAkB,QAAS,iBAAiB,OAAO,kBAAkB,SAEvE,mBADwC,kBAAkB,OAAO,EAAE,GAAG,cACzC,CAAC,MAAM,WAAW;AAC7C,WAAS,MAAM,KAAK,gBAAgB,QAAQ;AAC1C,OAAI,KAAK,MAAO,QAAO,MAAM,IAAI;IACjC;GACF,CAAC,OAAO,QAAQ;AAChB,UAAQ,MAAM,0CAA0C,IAAI;GAC5D;AAKJ,KAAI,CAAC,WAAW,EAAE;AAChB,WAAS,MAAM,KAAK,YAAY,UAAU;GACxC,MAAM,IAAI;GACV,IAAI;AACJ,OAAI,WAAW,WAAW,cAAc,sBAAsB;IAC5D,MAAM,QAAQ,eAAe,EAAE,GAAG;AAClC,QAAI,MAAO,qBAAoB;;AAEjC,KAAE,QAAQ,MAAM,oBAAoB;IAClC,QAAQ,EAAE;IACV,MAAM,EAAE;IACR,WAAW,qBAAqB,EAAE,QAAQ,aAAa,OAAO,YAAY;IAC3E,EAAE,EAAE,aAAa,MAAM,CAAC;IACzB;AACF;;AAGF,UAAS,MAAM,KAAK,YAAY,UAAU;EACxC,MAAM,IAAI;AAKV,IAAE,QAAQ,mBAAmB,UAAU,EAAE,MAAM,aAAa,SAAS,aAAa,QAAQ;AAG1F,IAAE,QAAQ,kBAAkB,KAAK,KAAK;EAEtC,IAAI,oBAAwC,KAAA;AAC5C,MAAI,WAAW,WAAW,cAAc,sBAAsB;GAC5D,MAAM,QAAQ,eAAe,EAAE,GAAG;AAClC,OAAI,MAAO,qBAAoB;;EAGjC,MAAM,aAAa,oBAAoB;GACrC,QAAQ,EAAE;GACV,MAAM,EAAE;GACR,WAAW,qBAAqB,EAAE,QAAQ,aAAa,OAAO,YAAY;GAC3E,EAAE,EAAE,aAAa,MAAM,CAAC;EAGzB,MAAM,eAAe,kBAAkB,EAAE,MAAM,aAAa,OAAO;AACnE,MAAI,aACF,YAAW,IAAI,EAAE,SAAS,cAAc,CAAC;AAG3C,IAAE,QAAQ,MAAM;GAChB;AAEF,UAAS,MAAM,KAAK,SAAS,OAAO,OAAO,EAAE,YAAY;EACvD,MAAM,IAAI;AACV,MAAI,CAAC,EAAG;AACR,MAAI,CAAC,EAAE,QAAQ,iBAAkB;EAEjC,MAAM,aAAa,EAAE,QAAQ;AAC7B,MAAI,YAAY;AACd,cAAW,MAAM,MAAe;GAEhC,MAAM,cAAc,mBAAmB,MAAM;AAC7C,cAAW,IAAI,EAAE,QAAQ,aAAa,CAAC;GAGvC,MAAM,YAAY,EAAE,QAAQ;GAG5B,MAAM,UAA+B;IACnC,QAAQ;IACR,UAJiB,YAAY,KAAK,KAAK,GAAG,YAAY,KAAA;IAKtD,MAAM,EAAE;IACR,QAAQ,EAAE;IACV,SAAS,WAAW,YAAY;IAChC,YAAY;IACb;AAGD,SAAM,SAAS,MAAM,SAAS,mBAAmB,QAAQ;GACzD,MAAM,SAAS,uBAAuB;AACtC,OAAI,OAAO,QAAS,OAAM,OAAO,QAAQ,QAAQ;AAEjD,KAAE,QAAQ,gBAAgB;AAG1B,SAAM,mBAAmB,UADJ,WAAW,KAAK,EAAE,YAAY,QAAQ,YAAY,CACxB,EAAE,EAAE;;GAErD;AAEF,UAAS,MAAM,KAAK,iBAAiB,OAAO,UAAU;EACpD,MAAM,IAAI;AAEV,MAAI,EAAE,QAAQ,iBAAiB,CAAC,EAAE,QAAQ,iBAAkB;EAE5D,MAAM,aAAa,EAAE,QAAQ;AAC7B,MAAI,YAAY;GACd,MAAM,SAAS,kBAAkB,EAAE;AACnC,cAAW,IAAI,EAAE,QAAQ,CAAC;GAE1B,MAAM,YAAY,EAAE,QAAQ;GAG5B,MAAM,UAA+B;IACnC;IACA,UAJiB,YAAY,KAAK,KAAK,GAAG,YAAY,KAAA;IAKtD,MAAM,EAAE;IACR,QAAQ,EAAE;IACV,SAAS,WAAW,YAAY;IAChC,YAAY;IACb;AAED,SAAM,SAAS,MAAM,SAAS,mBAAmB,QAAQ;GACzD,MAAM,SAAS,uBAAuB;AACtC,OAAI,OAAO,QAAS,OAAM,OAAO,QAAQ,QAAQ;AAGjD,SAAM,mBAAmB,UADJ,WAAW,KAAK,EAAE,YAAY,QAAQ,YAAY,CACxB,EAAE,EAAE;;GAErD;EACF"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../src/nitro/plugin.ts"],"sourcesContent":["// Import from specific subpaths to avoid the barrel 'nitropack/runtime' which\n// re-exports from internal/app.mjs — that file imports #nitro-internal-virtual/*\n// modules that only exist inside rollup builds and crash when loaded externally\n// (nitropack dev loads plugins outside the bundle via Worker threads).\nimport { defineNitroPlugin } from 'nitropack/runtime/internal/plugin'\nimport { getHeaders } from 'h3'\nimport { createRequestLogger, getGlobalPluginRunner, initLogger, isEnabled, markWideEventDrainStarted } from '../logger'\nimport { registerPrettyErrorSnippetReader } from '../shared/pretty-error'\nimport { readCodeSnippetFromDisk } from '../shared/pretty-error-snippet.node'\nimport { enrichErrorStackForDev } from '../shared/enrich-error-stack.node'\nimport { shouldLog, getServiceForPath, extractErrorStatus } from '../nitro'\nimport { normalizeRedactConfig } from '../redact'\nimport { resolveEvlogConfigForNitroPlugin, setActiveNitroRuntime } from '../shared/nitroConfigBridge'\nimport { bindStreamingResponseLifecycle, shouldDeferEmitForResponse } from '../shared/streamResponse'\nimport { startStreamServer, type StreamServerOptions } from '../stream'\nimport type { RequestLogger, ServerEvent, TailSamplingContext } from '../types'\nimport { filterSafeHeaders } from '../utils'\nimport { callEnrichAndDrain } from './enrich-drain'\n\nfunction getSafeHeaders(event: ServerEvent): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\nfunction getResponseStatus(event: ServerEvent): number {\n // Node.js style\n if (event.node?.res?.statusCode) {\n return event.node.res.statusCode\n }\n\n // Web Standard\n if (event.response?.status) {\n return event.response.status\n }\n\n // Context-based\n if (typeof event.context.status === 'number') {\n return event.context.status\n }\n\n return 200\n}\n\n\nexport default defineNitroPlugin(async (nitroApp) => {\n setActiveNitroRuntime('v2')\n const evlogConfig = await resolveEvlogConfigForNitroPlugin()\n\n const redact = normalizeRedactConfig(evlogConfig?.redact as boolean | Record<string, unknown> | undefined)\n\n registerPrettyErrorSnippetReader(readCodeSnippetFromDisk)\n\n initLogger({\n enabled: evlogConfig?.enabled,\n env: evlogConfig?.env,\n pretty: evlogConfig?.pretty,\n dev: evlogConfig?.dev,\n silent: evlogConfig?.silent,\n sampling: evlogConfig?.sampling,\n minLevel: evlogConfig?.minLevel,\n redact,\n _suppressDrainWarning: true,\n })\n\n // When `evlog.stream` is set (or auto-on in dev), boot the mini stream\n // server and hook every drained event into it. The server runs on its\n // own ephemeral port — the user's API surface is untouched.\n const streamSetting = (evlogConfig as { stream?: boolean | StreamServerOptions } | undefined)?.stream\n if (streamSetting === true || (streamSetting && typeof streamSetting === 'object')) {\n const streamOpts: StreamServerOptions = streamSetting === true ? {} : streamSetting\n startStreamServer(streamOpts).then((server) => {\n nitroApp.hooks.hook('evlog:drain', (ctx) => {\n if (ctx?.event) server.drain(ctx)\n })\n }).catch((err) => {\n console.error('[evlog] failed to start stream server:', err)\n })\n }\n\n // When globally disabled, createRequestLogger returns a no-op logger — still\n // attach it so handlers can call useLogger(event) without throwing.\n if (!isEnabled()) {\n nitroApp.hooks.hook('request', (event) => {\n const e = event as ServerEvent\n let requestIdOverride: string | undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = getSafeHeaders(e)?.['cf-ray']\n if (cfRay) requestIdOverride = cfRay\n }\n e.context.log = createRequestLogger({\n method: e.method,\n path: e.path,\n requestId: requestIdOverride || e.context.requestId || crypto.randomUUID(),\n }, { _deferDrain: true })\n })\n return\n }\n\n nitroApp.hooks.hook('request', (event) => {\n const e = event as ServerEvent\n\n // Evaluate route filtering but always create the logger so that server\n // middleware (which runs for every request) can call useLogger(event)\n // without throwing. Filtering is enforced at emit time instead.\n e.context._evlogShouldEmit = shouldLog(e.path, evlogConfig?.include, evlogConfig?.exclude)\n\n // Store start time for duration calculation in tail sampling\n e.context._evlogStartTime = Date.now()\n\n let requestIdOverride: string | undefined = undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = getSafeHeaders(e)?.['cf-ray']\n if (cfRay) requestIdOverride = cfRay\n }\n\n const requestLog = createRequestLogger({\n method: e.method,\n path: e.path,\n requestId: requestIdOverride || e.context.requestId || crypto.randomUUID(),\n }, { _deferDrain: true })\n\n // Apply route-based service configuration if a matching route is found\n const routeService = getServiceForPath(e.path, evlogConfig?.routes)\n if (routeService) {\n requestLog.set({ service: routeService })\n }\n\n e.context.log = requestLog\n })\n\n nitroApp.hooks.hook('error', async (error, { event }) => {\n const e = event as ServerEvent | undefined\n if (!e) return\n if (!e.context._evlogShouldEmit) return\n\n const requestLog = e.context.log as RequestLogger | undefined\n if (!requestLog) return\n\n e.context._evlogEmitting = true\n try {\n const err = error as Error\n void enrichErrorStackForDev(err, { pretty: evlogConfig?.pretty })\n requestLog.error(err)\n\n const errorStatus = extractErrorStatus(error)\n requestLog.set({ status: errorStatus })\n\n const startTime = e.context._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status: errorStatus,\n duration: durationMs,\n path: e.path,\n method: e.method,\n context: requestLog.getContext(),\n shouldKeep: false,\n }\n\n await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = requestLog.emit({ _forceKeep: tailCtx.shouldKeep })\n if (emittedEvent) {\n e.context._evlogEmitted = true\n void callEnrichAndDrain(nitroApp, emittedEvent, e, { deferDrain: true }).catch((err) => {\n console.error('[evlog] background enrich/drain failed:', err)\n })\n }\n } finally {\n delete e.context._evlogEmitting\n }\n })\n\n nitroApp.hooks.hook('afterResponse', async (event) => {\n const e = event as ServerEvent\n if (e.context._evlogEmitted || e.context._evlogEmitting || !e.context._evlogShouldEmit) return\n\n const requestLog = e.context.log as RequestLogger | undefined\n if (!requestLog) return\n\n const emitSuccessResponse = async () => {\n const status = getResponseStatus(e)\n requestLog.set({ status })\n\n const startTime = e.context._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status,\n duration: durationMs,\n path: e.path,\n method: e.method,\n context: requestLog.getContext(),\n shouldKeep: false,\n }\n\n await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = requestLog.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(nitroApp, emittedEvent, e)\n }\n\n if (e.response && shouldDeferEmitForResponse(e.response)) {\n e.response = bindStreamingResponseLifecycle(e.response, async (meta) => {\n if (meta.error) {\n requestLog.error(meta.error)\n }\n await emitSuccessResponse()\n })\n return\n }\n\n await emitSuccessResponse()\n })\n})\n"],"mappings":"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"}
@@ -6,16 +6,9 @@ import * as _$nitro_types0 from "nitro/types";
6
6
  * This ensures that 'data' (containing 'why', 'fix', 'link') is preserved
7
7
  * in the JSON response regardless of the underlying HTTP framework.
8
8
  *
9
- * For non-EvlogError, returns undefined to let Nitro's default handler take over.
10
- *
11
9
  * Usage in nitro.config.ts:
12
10
  * ```ts
13
- * // errorHandler.ts
14
11
  * export { default } from 'evlog/nitro/v3/errorHandler'
15
- * // nitro.config.ts
16
- * export default defineConfig({
17
- * errorHandler: './errorHandler',
18
- * })
19
12
  * ```
20
13
  */
21
14
  declare const _default: _$nitro_types0.NitroErrorHandler;
@@ -1,6 +1,6 @@
1
- import { t as extractErrorStatus } from "../../errors-BQgyQ9xe.mjs";
2
- import { n as serializeEvlogErrorResponse, t as resolveEvlogError } from "../../nitro-DErMq_Zj.mjs";
3
- import { t as parseURL } from "../../dist-H3GIh-KK.mjs";
1
+ import { t as extractErrorStatus } from "../../errors-DA0cyr8q.mjs";
2
+ import { a as serializeEvlogErrorResponse, i as resolveEvlogError, n as markH3ErrorHandled, o as shouldSuppressNitroDevOverlay, s as suppressNitroDevOverlay, t as buildPlainNitroErrorBody } from "../../nitro-ClRZLD1g.mjs";
3
+ import { t as parseURL } from "../../dist-DdQWiZn8.mjs";
4
4
  import { defineErrorHandler } from "nitro";
5
5
  //#region src/nitro-v3/errorHandler.ts
6
6
  /**
@@ -8,24 +8,22 @@ import { defineErrorHandler } from "nitro";
8
8
  * This ensures that 'data' (containing 'why', 'fix', 'link') is preserved
9
9
  * in the JSON response regardless of the underlying HTTP framework.
10
10
  *
11
- * For non-EvlogError, returns undefined to let Nitro's default handler take over.
12
- *
13
11
  * Usage in nitro.config.ts:
14
12
  * ```ts
15
- * // errorHandler.ts
16
13
  * export { default } from 'evlog/nitro/v3/errorHandler'
17
- * // nitro.config.ts
18
- * export default defineConfig({
19
- * errorHandler: './errorHandler',
20
- * })
21
14
  * ```
22
15
  */
23
- var errorHandler_default = defineErrorHandler((error, event) => {
24
- const evlogError = resolveEvlogError(error);
25
- if (!evlogError) return;
16
+ var errorHandler_default = defineErrorHandler(async (error, event, ctx) => {
17
+ const suppressOverlay = shouldSuppressNitroDevOverlay();
18
+ if (!suppressOverlay) await ctx.defaultHandler(error, event, { silent: false });
19
+ markH3ErrorHandled(event);
20
+ if (suppressOverlay) suppressNitroDevOverlay(error);
26
21
  const url = parseURL(event.req.url).pathname;
27
- const status = extractErrorStatus(evlogError);
28
- return new Response(JSON.stringify(serializeEvlogErrorResponse(evlogError, url)), {
22
+ const isDev = process.env.NODE_ENV === "development";
23
+ const evlogError = resolveEvlogError(error);
24
+ const body = evlogError ? serializeEvlogErrorResponse(evlogError, url) : buildPlainNitroErrorBody(error, url, isDev);
25
+ const status = extractErrorStatus(evlogError ?? error);
26
+ return new Response(JSON.stringify(body), {
29
27
  status,
30
28
  headers: { "Content-Type": "application/json" }
31
29
  });
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandler.mjs","names":[],"sources":["../../../src/nitro-v3/errorHandler.ts"],"sourcesContent":["import { parseURL } from 'ufo'\nimport { defineErrorHandler } from 'nitro'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\n\n/**\n * Custom Nitro v3 error handler that properly serializes EvlogError.\n * This ensures that 'data' (containing 'why', 'fix', 'link') is preserved\n * in the JSON response regardless of the underlying HTTP framework.\n *\n * For non-EvlogError, returns undefined to let Nitro's default handler take over.\n *\n * Usage in nitro.config.ts:\n * ```ts\n * // errorHandler.ts\n * export { default } from 'evlog/nitro/v3/errorHandler'\n * // nitro.config.ts\n * export default defineConfig({\n * errorHandler: './errorHandler',\n * })\n * ```\n */\nexport default defineErrorHandler((error, event) => {\n const evlogError = resolveEvlogError(error)\n\n if (!evlogError) return\n\n const url = parseURL(event.req.url).pathname\n const status = extractErrorStatus(evlogError)\n\n return new Response(JSON.stringify(serializeEvlogErrorResponse(evlogError, url)), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAA,uBAAe,oBAAoB,OAAO,UAAU;CAClD,MAAM,aAAa,kBAAkB,MAAM;AAE3C,KAAI,CAAC,WAAY;CAEjB,MAAM,MAAM,SAAS,MAAM,IAAI,IAAI,CAAC;CACpC,MAAM,SAAS,mBAAmB,WAAW;AAE7C,QAAO,IAAI,SAAS,KAAK,UAAU,4BAA4B,YAAY,IAAI,CAAC,EAAE;EAChF;EACA,SAAS,EAAE,gBAAgB,oBAAoB;EAChD,CAAC;EACF"}
1
+ {"version":3,"file":"errorHandler.mjs","names":[],"sources":["../../../src/nitro-v3/errorHandler.ts"],"sourcesContent":["import { parseURL } from 'ufo'\nimport { defineErrorHandler } from 'nitro'\nimport {\n resolveEvlogError,\n extractErrorStatus,\n buildPlainNitroErrorBody,\n serializeEvlogErrorResponse,\n shouldSuppressNitroDevOverlay,\n suppressNitroDevOverlay,\n markH3ErrorHandled,\n} from '../nitro'\nimport type { NitroErrorHandlerContext } from '../shared/nitro-types'\n\n/**\n * Custom Nitro v3 error handler that properly serializes EvlogError.\n * This ensures that 'data' (containing 'why', 'fix', 'link') is preserved\n * in the JSON response regardless of the underlying HTTP framework.\n *\n * Usage in nitro.config.ts:\n * ```ts\n * export { default } from 'evlog/nitro/v3/errorHandler'\n * ```\n */\nexport default defineErrorHandler(async (error, event, ctx: NitroErrorHandlerContext) => {\n const suppressOverlay = shouldSuppressNitroDevOverlay()\n\n if (!suppressOverlay) {\n await ctx.defaultHandler(error, event, { silent: false })\n }\n\n markH3ErrorHandled(event)\n\n if (suppressOverlay) {\n suppressNitroDevOverlay(error)\n }\n\n const url = parseURL(event.req.url).pathname\n const isDev = process.env.NODE_ENV === 'development'\n const evlogError = resolveEvlogError(error)\n\n const body = evlogError\n ? serializeEvlogErrorResponse(evlogError, url)\n : buildPlainNitroErrorBody(error, url, isDev)\n const status = extractErrorStatus(evlogError ?? error)\n\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n})\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,IAAA,uBAAe,mBAAmB,OAAO,OAAO,OAAO,QAAkC;CACvF,MAAM,kBAAkB,+BAA+B;AAEvD,KAAI,CAAC,gBACH,OAAM,IAAI,eAAe,OAAO,OAAO,EAAE,QAAQ,OAAO,CAAC;AAG3D,oBAAmB,MAAM;AAEzB,KAAI,gBACF,yBAAwB,MAAM;CAGhC,MAAM,MAAM,SAAS,MAAM,IAAI,IAAI,CAAC;CACpC,MAAM,QAAQ,QAAQ,IAAI,aAAa;CACvC,MAAM,aAAa,kBAAkB,MAAM;CAE3C,MAAM,OAAO,aACT,4BAA4B,YAAY,IAAI,GAC5C,yBAAyB,OAAO,KAAK,MAAM;CAC/C,MAAM,SAAS,mBAAmB,cAAc,MAAM;AAEtD,QAAO,IAAI,SAAS,KAAK,UAAU,KAAK,EAAE;EACxC;EACA,SAAS,EAAE,gBAAgB,oBAAoB;EAChD,CAAC;EACF"}
@@ -1,5 +1,5 @@
1
- import { n as createError, t as EvlogError } from "../../error-CVtn5U7b.mjs";
2
- import { t as parseError } from "../../parseError-D4PIxEWo.mjs";
1
+ import { n as createError, t as EvlogError } from "../../error-DwajXSKM.mjs";
2
+ import { t as parseError } from "../../parseError-Cagr-Ctc.mjs";
3
3
  import evlog from "./module.mjs";
4
4
  import { useLogger } from "./useLogger.mjs";
5
5
  import { evlogErrorHandler } from "./middleware.mjs";
@@ -1,4 +1,4 @@
1
- import { t as NitroModuleOptions } from "../../nitro-BRddgqSb.mjs";
1
+ import { t as NitroModuleOptions } from "../../nitro-zCXTylj4.mjs";
2
2
  import { Nitro } from "nitro/types";
3
3
 
4
4
  //#region src/nitro-v3/module.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.mts","names":[],"sources":["../../../src/nitro-v3/module.ts"],"mappings":";;;;iBAiBwB,KAAA,CAAM,OAAA,GAAU,kBAAA;;eAGvB,KAAA;AAAA"}
1
+ {"version":3,"file":"module.d.mts","names":[],"sources":["../../../src/nitro-v3/module.ts"],"mappings":";;;;iBAkBwB,KAAA,CAAM,OAAA,GAAU,kBAAA;;eAGvB,KAAA;AAAA"}
@@ -1,3 +1,4 @@
1
+ import { r as prependNitroErrorHandler } from "../../nitro-ClRZLD1g.mjs";
1
2
  import { dirname, resolve } from "node:path";
2
3
  import { fileURLToPath } from "node:url";
3
4
  //#region src/nitro-v3/module.ts
@@ -13,9 +14,8 @@ function evlog(options) {
13
14
  nitro.options.plugins.push(resolveModulePath("plugin"));
14
15
  if (!nitro.options.noExternals) nitro.options.noExternals = ["evlog"];
15
16
  else if (Array.isArray(nitro.options.noExternals)) nitro.options.noExternals.push("evlog");
16
- if (!nitro.options.errorHandler) nitro.options.errorHandler = [resolveModulePath("errorHandler")];
17
- else if (Array.isArray(nitro.options.errorHandler)) nitro.options.errorHandler.unshift(resolveModulePath("errorHandler"));
18
- else if (typeof nitro.options.errorHandler === "string") nitro.options.errorHandler = [resolveModulePath("errorHandler"), nitro.options.errorHandler];
17
+ const handlers = prependNitroErrorHandler(nitro.options.errorHandler, resolveModulePath("errorHandler"));
18
+ nitro.options.errorHandler = Array.isArray(handlers) ? handlers : [handlers];
19
19
  nitro.options.runtimeConfig = nitro.options.runtimeConfig || {};
20
20
  nitro.options.runtimeConfig.evlog = options || {};
21
21
  nitro.options.replace = nitro.options.replace || {};
@@ -1 +1 @@
1
- {"version":3,"file":"module.mjs","names":[],"sources":["../../../src/nitro-v3/module.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Nitro } from 'nitro/types'\nimport type { NitroModuleOptions } from '../nitro'\n\nexport type { NitroModuleOptions }\n\nconst _dir = dirname(fileURLToPath(import.meta.url))\n\n// Nitro raw-interpolates these paths into JS string literals when generating\n// the #nitro/virtual/plugins and #nitro/virtual/error-handler modules, so\n// Windows backslashes would be parsed as escape sequences (\\n, \\v, …) and\n// break module resolution. Normalize to POSIX separators.\nfunction resolveModulePath(name: string): string {\n return resolve(_dir, name).replace(/\\\\/g, '/')\n}\n\nexport default function evlog(options?: NitroModuleOptions) {\n return {\n name: 'evlog',\n setup(nitro: Nitro) {\n // Push the plugin (no extension — Nitro's bundler resolves it)\n nitro.options.plugins = nitro.options.plugins || []\n nitro.options.plugins.push(resolveModulePath('plugin'))\n\n // explicitly tell nitro to bundle evlog's files to correctly resolve nitro dependencies\n if (!nitro.options.noExternals) {\n nitro.options.noExternals = ['evlog']\n } else if (Array.isArray(nitro.options.noExternals)) {\n nitro.options.noExternals.push('evlog')\n }\n\n\n // Set error handler only if not already configured by user\n if (!nitro.options.errorHandler) {\n nitro.options.errorHandler = [resolveModulePath('errorHandler')]\n } else if (Array.isArray(nitro.options.errorHandler)) {\n nitro.options.errorHandler.unshift(resolveModulePath('errorHandler'))\n } else if (typeof nitro.options.errorHandler === 'string') {\n nitro.options.errorHandler = [resolveModulePath('errorHandler'), nitro.options.errorHandler]\n }\n\n // Inject config into runtimeConfig — works in production where the\n // plugin is bundled through Nitro's builder and the virtual\n // runtime-config module resolves correctly.\n nitro.options.runtimeConfig = nitro.options.runtimeConfig || {}\n nitro.options.runtimeConfig.evlog = options || {}\n\n // Bake the config into the bundle as a literal so the plugin never has\n // to do a runtime `import('nitro/runtime-config')` to discover it. That\n // dynamic import resolves to a module which itself imports the build-only\n // virtual `#nitro/virtual/runtime-config` — fine inside the Nitro build,\n // but on Vercel + Bun the missing virtual triggers Bun's auto-installer\n // and crashes with `ReadOnlyFileSystem` (see issue #312).\n nitro.options.replace = nitro.options.replace || {}\n nitro.options.replace.__EVLOG_CONFIG__ = JSON.stringify(options || {})\n\n // In dev mode, Nitro loads plugins externally (not bundled), so the\n // virtual runtime-config module is unreachable and useRuntimeConfig()\n // returns a stub without our values. process.env is inherited by the\n // Worker Threads that run the dev server, making it a reliable bridge.\n // The plugin reads: useRuntimeConfig().evlog ?? process.env.__EVLOG_CONFIG\n process.env.__EVLOG_CONFIG = JSON.stringify(options || {})\n },\n }\n}\n"],"mappings":";;;AAOA,MAAM,OAAO,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAMpD,SAAS,kBAAkB,MAAsB;AAC/C,QAAO,QAAQ,MAAM,KAAK,CAAC,QAAQ,OAAO,IAAI;;AAGhD,SAAwB,MAAM,SAA8B;AAC1D,QAAO;EACL,MAAM;EACN,MAAM,OAAc;AAElB,SAAM,QAAQ,UAAU,MAAM,QAAQ,WAAW,EAAE;AACnD,SAAM,QAAQ,QAAQ,KAAK,kBAAkB,SAAS,CAAC;AAGvD,OAAI,CAAC,MAAM,QAAQ,YACjB,OAAM,QAAQ,cAAc,CAAC,QAAQ;YAC5B,MAAM,QAAQ,MAAM,QAAQ,YAAY,CACjD,OAAM,QAAQ,YAAY,KAAK,QAAQ;AAKzC,OAAI,CAAC,MAAM,QAAQ,aACjB,OAAM,QAAQ,eAAe,CAAC,kBAAkB,eAAe,CAAC;YACvD,MAAM,QAAQ,MAAM,QAAQ,aAAa,CAClD,OAAM,QAAQ,aAAa,QAAQ,kBAAkB,eAAe,CAAC;YAC5D,OAAO,MAAM,QAAQ,iBAAiB,SAC/C,OAAM,QAAQ,eAAe,CAAC,kBAAkB,eAAe,EAAE,MAAM,QAAQ,aAAa;AAM9F,SAAM,QAAQ,gBAAgB,MAAM,QAAQ,iBAAiB,EAAE;AAC/D,SAAM,QAAQ,cAAc,QAAQ,WAAW,EAAE;AAQjD,SAAM,QAAQ,UAAU,MAAM,QAAQ,WAAW,EAAE;AACnD,SAAM,QAAQ,QAAQ,mBAAmB,KAAK,UAAU,WAAW,EAAE,CAAC;AAOtE,WAAQ,IAAI,iBAAiB,KAAK,UAAU,WAAW,EAAE,CAAC;;EAE7D"}
1
+ {"version":3,"file":"module.mjs","names":[],"sources":["../../../src/nitro-v3/module.ts"],"sourcesContent":["import { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Nitro } from 'nitro/types'\nimport type { NitroModuleOptions } from '../nitro'\nimport { prependNitroErrorHandler } from '../nitro'\n\nexport type { NitroModuleOptions }\n\nconst _dir = dirname(fileURLToPath(import.meta.url))\n\n// Nitro raw-interpolates these paths into JS string literals when generating\n// the #nitro/virtual/plugins and #nitro/virtual/error-handler modules, so\n// Windows backslashes would be parsed as escape sequences (\\n, \\v, …) and\n// break module resolution. Normalize to POSIX separators.\nfunction resolveModulePath(name: string): string {\n return resolve(_dir, name).replace(/\\\\/g, '/')\n}\n\nexport default function evlog(options?: NitroModuleOptions) {\n return {\n name: 'evlog',\n setup(nitro: Nitro) {\n // Push the plugin (no extension — Nitro's bundler resolves it)\n nitro.options.plugins = nitro.options.plugins || []\n nitro.options.plugins.push(resolveModulePath('plugin'))\n\n // explicitly tell nitro to bundle evlog's files to correctly resolve nitro dependencies\n if (!nitro.options.noExternals) {\n nitro.options.noExternals = ['evlog']\n } else if (Array.isArray(nitro.options.noExternals)) {\n nitro.options.noExternals.push('evlog')\n }\n\n\n const handlers = prependNitroErrorHandler(\n nitro.options.errorHandler,\n resolveModulePath('errorHandler'),\n )\n nitro.options.errorHandler = Array.isArray(handlers) ? handlers : [handlers]\n\n // Inject config into runtimeConfig — works in production where the\n // plugin is bundled through Nitro's builder and the virtual\n // runtime-config module resolves correctly.\n nitro.options.runtimeConfig = nitro.options.runtimeConfig || {}\n nitro.options.runtimeConfig.evlog = options || {}\n\n // Bake the config into the bundle as a literal so the plugin never has\n // to do a runtime `import('nitro/runtime-config')` to discover it. That\n // dynamic import resolves to a module which itself imports the build-only\n // virtual `#nitro/virtual/runtime-config` — fine inside the Nitro build,\n // but on Vercel + Bun the missing virtual triggers Bun's auto-installer\n // and crashes with `ReadOnlyFileSystem` (see issue #312).\n nitro.options.replace = nitro.options.replace || {}\n nitro.options.replace.__EVLOG_CONFIG__ = JSON.stringify(options || {})\n\n // In dev mode, Nitro loads plugins externally (not bundled), so the\n // virtual runtime-config module is unreachable and useRuntimeConfig()\n // returns a stub without our values. process.env is inherited by the\n // Worker Threads that run the dev server, making it a reliable bridge.\n // The plugin reads: useRuntimeConfig().evlog ?? process.env.__EVLOG_CONFIG\n process.env.__EVLOG_CONFIG = JSON.stringify(options || {})\n },\n }\n}\n"],"mappings":";;;;AAQA,MAAM,OAAO,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAMpD,SAAS,kBAAkB,MAAsB;AAC/C,QAAO,QAAQ,MAAM,KAAK,CAAC,QAAQ,OAAO,IAAI;;AAGhD,SAAwB,MAAM,SAA8B;AAC1D,QAAO;EACL,MAAM;EACN,MAAM,OAAc;AAElB,SAAM,QAAQ,UAAU,MAAM,QAAQ,WAAW,EAAE;AACnD,SAAM,QAAQ,QAAQ,KAAK,kBAAkB,SAAS,CAAC;AAGvD,OAAI,CAAC,MAAM,QAAQ,YACjB,OAAM,QAAQ,cAAc,CAAC,QAAQ;YAC5B,MAAM,QAAQ,MAAM,QAAQ,YAAY,CACjD,OAAM,QAAQ,YAAY,KAAK,QAAQ;GAIzC,MAAM,WAAW,yBACf,MAAM,QAAQ,cACd,kBAAkB,eAAe,CAClC;AACD,SAAM,QAAQ,eAAe,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS;AAK5E,SAAM,QAAQ,gBAAgB,MAAM,QAAQ,iBAAiB,EAAE;AAC/D,SAAM,QAAQ,cAAc,QAAQ,WAAW,EAAE;AAQjD,SAAM,QAAQ,UAAU,MAAM,QAAQ,WAAW,EAAE;AACnD,SAAM,QAAQ,QAAQ,mBAAmB,KAAK,UAAU,WAAW,EAAE,CAAC;AAOtE,WAAQ,IAAI,iBAAiB,KAAK,UAAU,WAAW,EAAE,CAAC;;EAE7D"}
@@ -1,9 +1,13 @@
1
- import { b as initLogger, g as createRequestLogger, j as normalizeRedactConfig, x as isEnabled, y as getGlobalPluginRunner } from "../../audit-BUI3af4w.mjs";
1
+ import { n as readCodeSnippetFromDisk } from "../../pretty-error-snippet.node-c_bzjg7g.mjs";
2
2
  import { filterSafeHeaders } from "../../utils.mjs";
3
- import { t as extractErrorStatus } from "../../errors-BQgyQ9xe.mjs";
4
- import { n as shouldLog, t as getServiceForPath } from "../../routes-CnIgYWf8.mjs";
5
- import { n as resolveEvlogConfigForNitroPlugin, r as setActiveNitroRuntime } from "../../nitroConfigBridge-NbFn-sIK.mjs";
6
- import { t as parseURL } from "../../dist-H3GIh-KK.mjs";
3
+ import { N as normalizeRedactConfig, b as initLogger, g as createRequestLogger, w as markWideEventDrainStarted, x as isEnabled, y as getGlobalPluginRunner } from "../../audit-BFwTUxBJ.mjs";
4
+ import { i as registerPrettyErrorSnippetReader } from "../../pretty-error-CVVgwlTn.mjs";
5
+ import { t as extractErrorStatus } from "../../errors-DA0cyr8q.mjs";
6
+ import { i as setActiveNitroRuntime, r as resolveEvlogConfigForNitroPlugin } from "../../nitroConfigBridge-BkVWnSV3.mjs";
7
+ import { n as shouldLog, t as getServiceForPath } from "../../routes-4rMzRyTk.mjs";
8
+ import { n as extendDeferredDrain, r as enrichErrorStackForDev } from "../../enrich-drain-CG_2Nix-.mjs";
9
+ import { r as shouldDeferEmitForResponse, t as bindStreamingResponseLifecycle } from "../../streamResponse-CmQ3qUbF.mjs";
10
+ import { t as parseURL } from "../../dist-DdQWiZn8.mjs";
7
11
  import { definePlugin } from "nitro";
8
12
  //#region src/nitro-v3/plugin.ts
9
13
  function getContext(event) {
@@ -40,7 +44,7 @@ function buildHookContext(event, res) {
40
44
  }
41
45
  };
42
46
  }
43
- async function callDrainHook(hooks, emittedEvent, event, hookContext) {
47
+ async function callDrainHook(hooks, emittedEvent, event, hookContext, options) {
44
48
  if (!emittedEvent) return;
45
49
  const drainCtx = {
46
50
  event: emittedEvent,
@@ -60,10 +64,14 @@ async function callDrainHook(hooks, emittedEvent, event, hookContext) {
60
64
  if (runner.hasDrain) drainTasks.push(runner.runDrain(drainCtx));
61
65
  if (drainTasks.length === 0) return;
62
66
  const drainPromise = Promise.all(drainTasks);
67
+ if (options?.deferDrain) {
68
+ extendDeferredDrain(drainPromise, globalThis.navigator?.userAgent === "Cloudflare-Workers" && typeof event.req.waitUntil === "function" ? event.req.waitUntil.bind(event.req) : void 0);
69
+ return;
70
+ }
63
71
  if (typeof event.req.waitUntil === "function") event.req.waitUntil(drainPromise);
64
72
  else await drainPromise;
65
73
  }
66
- async function callEnrichAndDrain(hooks, emittedEvent, event, res) {
74
+ async function callEnrichAndDrain(hooks, emittedEvent, event, res, options) {
67
75
  if (!emittedEvent) return;
68
76
  const hookContext = buildHookContext(event, res);
69
77
  const enrichCtx = {
@@ -77,7 +85,8 @@ async function callEnrichAndDrain(hooks, emittedEvent, event, res) {
77
85
  }
78
86
  const runner = getGlobalPluginRunner();
79
87
  if (runner.hasEnrich) await runner.runEnrich(enrichCtx);
80
- await callDrainHook(hooks, emittedEvent, event, hookContext);
88
+ markWideEventDrainStarted(emittedEvent);
89
+ await callDrainHook(hooks, emittedEvent, event, hookContext, options);
81
90
  }
82
91
  /**
83
92
  * Nitro v3 plugin entry point.
@@ -92,10 +101,12 @@ var plugin_default = definePlugin(async (nitroApp) => {
92
101
  setActiveNitroRuntime("v3");
93
102
  const evlogConfig = await resolveEvlogConfigForNitroPlugin();
94
103
  const redact = normalizeRedactConfig(evlogConfig?.redact);
104
+ registerPrettyErrorSnippetReader(readCodeSnippetFromDisk);
95
105
  initLogger({
96
106
  enabled: evlogConfig?.enabled,
97
107
  env: evlogConfig?.env,
98
108
  pretty: evlogConfig?.pretty,
109
+ dev: evlogConfig?.dev,
99
110
  silent: evlogConfig?.silent,
100
111
  sampling: evlogConfig?.sampling,
101
112
  minLevel: evlogConfig?.minLevel,
@@ -141,26 +152,36 @@ var plugin_default = definePlugin(async (nitroApp) => {
141
152
  });
142
153
  hooks.hook("response", async (res, event) => {
143
154
  const ctx = event.req.context;
144
- if (ctx?._evlogEmitted || !ctx?._evlogShouldEmit) return;
155
+ if (ctx?._evlogEmitted || ctx?._evlogEmitting || !ctx?._evlogShouldEmit) return;
145
156
  const log = ctx?.log;
146
157
  if (!log || !ctx) return;
147
- const { status } = res;
148
- log.set({ status });
149
- const startTime = ctx._evlogStartTime;
150
- const durationMs = startTime ? Date.now() - startTime : void 0;
151
- const { pathname } = parseURL(event.req.url);
152
- const tailCtx = {
153
- status,
154
- duration: durationMs,
155
- path: pathname,
156
- method: event.req.method,
157
- context: log.getContext(),
158
- shouldKeep: false
158
+ const emitSuccessResponse = async (responseStatus) => {
159
+ log.set({ status: responseStatus });
160
+ const startTime = ctx._evlogStartTime;
161
+ const durationMs = startTime ? Date.now() - startTime : void 0;
162
+ const { pathname } = parseURL(event.req.url);
163
+ const tailCtx = {
164
+ status: responseStatus,
165
+ duration: durationMs,
166
+ path: pathname,
167
+ method: event.req.method,
168
+ context: log.getContext(),
169
+ shouldKeep: false
170
+ };
171
+ await hooks.callHook("evlog:emit:keep", tailCtx);
172
+ const runner = getGlobalPluginRunner();
173
+ if (runner.hasKeep) await runner.runKeep(tailCtx);
174
+ await callEnrichAndDrain(hooks, log.emit({ _forceKeep: tailCtx.shouldKeep }), event, res);
159
175
  };
160
- await hooks.callHook("evlog:emit:keep", tailCtx);
161
- const runner = getGlobalPluginRunner();
162
- if (runner.hasKeep) await runner.runKeep(tailCtx);
163
- await callEnrichAndDrain(hooks, log.emit({ _forceKeep: tailCtx.shouldKeep }), event, res);
176
+ if (shouldDeferEmitForResponse(res)) {
177
+ const wrapped = bindStreamingResponseLifecycle(res, async (meta) => {
178
+ if (meta.error) log.error(meta.error);
179
+ await emitSuccessResponse(meta.status ?? res.status);
180
+ });
181
+ if (wrapped !== res && "res" in event) event.res = wrapped;
182
+ return;
183
+ }
184
+ await emitSuccessResponse(res.status);
164
185
  });
165
186
  hooks.hook("error", async (error, { event }) => {
166
187
  if (!event) return;
@@ -169,25 +190,36 @@ var plugin_default = definePlugin(async (nitroApp) => {
169
190
  if (!ctx?._evlogShouldEmit) return;
170
191
  const log = ctx.log;
171
192
  if (!log) return;
172
- const actualError = error.cause?.name === "EvlogError" ? error.cause : error;
173
- log.error(actualError);
174
- const errorStatus = extractErrorStatus(actualError);
175
- log.set({ status: errorStatus });
176
- const { pathname } = parseURL(e.req.url);
177
- const startTime = ctx._evlogStartTime;
178
- const tailCtx = {
179
- status: errorStatus,
180
- duration: startTime ? Date.now() - startTime : void 0,
181
- path: pathname,
182
- method: e.req.method,
183
- context: log.getContext(),
184
- shouldKeep: false
185
- };
186
- await hooks.callHook("evlog:emit:keep", tailCtx);
187
- const runner = getGlobalPluginRunner();
188
- if (runner.hasKeep) await runner.runKeep(tailCtx);
189
- ctx._evlogEmitted = true;
190
- await callEnrichAndDrain(hooks, log.emit({ _forceKeep: tailCtx.shouldKeep }), e);
193
+ ctx._evlogEmitting = true;
194
+ try {
195
+ const actualError = error.cause?.name === "EvlogError" ? error.cause : error;
196
+ enrichErrorStackForDev(actualError, { pretty: evlogConfig?.pretty });
197
+ log.error(actualError);
198
+ const errorStatus = extractErrorStatus(actualError);
199
+ log.set({ status: errorStatus });
200
+ const { pathname } = parseURL(e.req.url);
201
+ const startTime = ctx._evlogStartTime;
202
+ const tailCtx = {
203
+ status: errorStatus,
204
+ duration: startTime ? Date.now() - startTime : void 0,
205
+ path: pathname,
206
+ method: e.req.method,
207
+ context: log.getContext(),
208
+ shouldKeep: false
209
+ };
210
+ await hooks.callHook("evlog:emit:keep", tailCtx);
211
+ const runner = getGlobalPluginRunner();
212
+ if (runner.hasKeep) await runner.runKeep(tailCtx);
213
+ const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep });
214
+ if (emittedEvent) {
215
+ ctx._evlogEmitted = true;
216
+ callEnrichAndDrain(hooks, emittedEvent, e, void 0, { deferDrain: true }).catch((err) => {
217
+ console.error("[evlog] background enrich/drain failed:", err);
218
+ });
219
+ }
220
+ } finally {
221
+ delete ctx._evlogEmitting;
222
+ }
191
223
  });
192
224
  });
193
225
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/nitro-v3/plugin.ts"],"sourcesContent":["import { definePlugin } from 'nitro'\nimport type { CaptureError } from 'nitro/types'\nimport type { HTTPEvent } from 'nitro/h3'\nimport { parseURL } from 'ufo'\nimport { createRequestLogger, getGlobalPluginRunner, initLogger, isEnabled } from '../logger'\nimport { shouldLog, getServiceForPath, extractErrorStatus } from '../nitro'\nimport { normalizeRedactConfig } from '../redact'\nimport { resolveEvlogConfigForNitroPlugin, setActiveNitroRuntime } from '../shared/nitroConfigBridge'\nimport type { EnrichContext, RequestLogger, TailSamplingContext, WideEvent } from '../types'\nimport { filterSafeHeaders } from '../utils'\n\n// Nitro v3 doesn't fully export hook types yet\n// https://github.com/nitrojs/nitro/blob/8882bc9e1dbf2d342e73097f22a2156f70f50575/src/types/runtime/nitro.ts#L48-L53\ninterface NitroV3Hooks {\n close: () => void\n error: CaptureError\n request: (event: HTTPEvent) => void | Promise<void>\n response: (res: Response, event: HTTPEvent) => void | Promise<void>\n 'evlog:emit:keep': (ctx: TailSamplingContext) => void | Promise<void>\n 'evlog:enrich': (ctx: EnrichContext) => void | Promise<void>\n 'evlog:drain': (ctx: { event: WideEvent; request?: { method?: string; path: string; requestId?: string }; headers?: Record<string, string> }) => void | Promise<void>\n}\n\ntype Hooks = {\n hook: <T extends keyof NitroV3Hooks>(name: T, listener: NitroV3Hooks[T]) => void\n callHook: <T extends keyof NitroV3Hooks>(name: T, ...args: Parameters<NitroV3Hooks[T]>) => Promise<void>\n}\n\nfunction getContext(event: HTTPEvent): Record<string, unknown> {\n if (!event.req.context) {\n event.req.context = {}\n }\n return event.req.context\n}\n\nfunction getSafeRequestHeaders(event: HTTPEvent): Record<string, string> {\n const headers: Record<string, string> = {}\n event.req.headers.forEach((value, key) => {\n headers[key] = value\n })\n return filterSafeHeaders(headers)\n}\n\nfunction getSafeResponseHeaders(res: Response): Record<string, string> | undefined {\n const headers: Record<string, string> = {}\n res.headers.forEach((value, key) => {\n headers[key] = value\n })\n if (Object.keys(headers).length === 0) return undefined\n return filterSafeHeaders(headers)\n}\n\nfunction buildHookContext(\n event: HTTPEvent,\n res?: Response,\n): Omit<EnrichContext, 'event'> {\n const { pathname } = parseURL(event.req.url)\n const responseHeaders = res ? getSafeResponseHeaders(res) : undefined\n return {\n request: { method: event.req.method, path: pathname },\n headers: getSafeRequestHeaders(event),\n response: {\n status: res?.status ?? 200,\n headers: responseHeaders,\n },\n }\n}\n\nasync function callDrainHook(\n hooks: Hooks,\n emittedEvent: WideEvent | null,\n event: HTTPEvent,\n hookContext: Omit<EnrichContext, 'event'>,\n): Promise<void> {\n if (!emittedEvent) return\n\n const drainCtx = {\n event: emittedEvent,\n request: hookContext.request,\n headers: hookContext.headers,\n }\n\n const drainTasks: Array<Promise<unknown>> = []\n try {\n const result = hooks.callHook('evlog:drain', drainCtx)\n if (result?.catch) {\n drainTasks.push(\n result.catch((err: unknown) => {\n console.error('[evlog] drain failed:', err)\n }),\n )\n }\n } catch (err) {\n console.error('[evlog] drain failed:', err)\n }\n\n const runner = getGlobalPluginRunner()\n if (runner.hasDrain) {\n drainTasks.push(runner.runDrain(drainCtx))\n }\n\n if (drainTasks.length === 0) return\n const drainPromise = Promise.all(drainTasks)\n\n // Use waitUntil if available (srvx native — Cloudflare Workers, Vercel Edge, etc.)\n // This keeps the runtime alive for background work without blocking the response\n if (typeof event.req.waitUntil === 'function') {\n event.req.waitUntil(drainPromise)\n } else {\n // Fallback: await drain to prevent lost logs in serverless environments\n // (e.g. Vercel Fluid Compute). On the normal path this runs from the\n // response hook (response already sent); on the error path it may run\n // before the error response is finalized.\n await drainPromise\n }\n}\n\nasync function callEnrichAndDrain(\n hooks: Hooks,\n emittedEvent: WideEvent | null,\n event: HTTPEvent,\n res?: Response,\n): Promise<void> {\n if (!emittedEvent) return\n\n const hookContext = buildHookContext(event, res)\n const enrichCtx: EnrichContext = { event: emittedEvent, ...hookContext }\n\n try {\n await hooks.callHook('evlog:enrich', enrichCtx)\n } catch (err) {\n console.error('[evlog] enrich failed:', err)\n }\n\n const runner = getGlobalPluginRunner()\n if (runner.hasEnrich) {\n await runner.runEnrich(enrichCtx)\n }\n\n await callDrainHook(hooks, emittedEvent, event, hookContext)\n}\n\n/**\n * Nitro v3 plugin entry point.\n *\n * Usage in Nitro v3:\n * ```ts\n * // plugins/evlog.ts\n * export { default } from 'evlog/nitro/v3'\n * ```\n */\nexport default definePlugin(async (nitroApp) => {\n setActiveNitroRuntime('v3')\n const evlogConfig = await resolveEvlogConfigForNitroPlugin()\n\n const redact = normalizeRedactConfig(evlogConfig?.redact as boolean | Record<string, unknown> | undefined)\n\n initLogger({\n enabled: evlogConfig?.enabled,\n env: evlogConfig?.env,\n pretty: evlogConfig?.pretty,\n silent: evlogConfig?.silent,\n sampling: evlogConfig?.sampling,\n minLevel: evlogConfig?.minLevel,\n redact,\n _suppressDrainWarning: true,\n })\n\n const hooks = nitroApp.hooks as unknown as Hooks\n\n // When globally disabled, createRequestLogger returns a no-op logger — still\n // attach it so handlers can call useLogger without throwing.\n if (!isEnabled()) {\n hooks.hook('request', (event) => {\n const { pathname } = parseURL(event.req.url)\n const ctx = getContext(event)\n let requestIdOverride: string | undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = event.req.headers.get('cf-ray')\n if (cfRay) requestIdOverride = cfRay\n }\n ctx.log = createRequestLogger({\n method: event.req.method,\n path: pathname,\n requestId: requestIdOverride || ctx.requestId as string | undefined || crypto.randomUUID(),\n }, { _deferDrain: true })\n })\n return\n }\n\n hooks.hook('request', (event) => {\n const { pathname } = parseURL(event.req.url)\n const ctx = getContext(event)\n\n // Evaluate route filtering but always create the logger so that server\n // middleware (which runs for every request) can call useLogger(event)\n // without throwing. Filtering is enforced at emit time instead.\n ctx._evlogShouldEmit = shouldLog(pathname, evlogConfig?.include, evlogConfig?.exclude)\n\n // Store start time for duration calculation in tail sampling\n ctx._evlogStartTime = Date.now()\n\n let requestIdOverride: string | undefined = undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = event.req.headers.get('cf-ray')\n if (cfRay) requestIdOverride = cfRay\n }\n\n const log = createRequestLogger({\n method: event.req.method,\n path: pathname,\n requestId: requestIdOverride || ctx.requestId as string | undefined || crypto.randomUUID(),\n }, { _deferDrain: true })\n\n // Apply route-based service configuration if a matching route is found\n const routeService = getServiceForPath(pathname, evlogConfig?.routes)\n if (routeService) {\n log.set({ service: routeService })\n }\n\n ctx.log = log\n })\n\n hooks.hook('response', async (res, event) => {\n const ctx = event.req.context\n // Skip if already emitted by error hook or route was filtered out\n if (ctx?._evlogEmitted || !ctx?._evlogShouldEmit) return\n\n const log = ctx?.log as RequestLogger | undefined\n if (!log || !ctx) return\n\n const { status } = res\n log.set({ status })\n\n const startTime = ctx._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const { pathname } = parseURL(event.req.url)\n\n const tailCtx: TailSamplingContext = {\n status,\n duration: durationMs,\n path: pathname,\n method: event.req.method,\n context: log.getContext(),\n shouldKeep: false,\n }\n\n await hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(hooks, emittedEvent, event, res)\n })\n\n hooks.hook('error', async (error, { event }) => {\n if (!event) return\n const e = event as HTTPEvent\n\n const ctx = e.req.context\n if (!ctx?._evlogShouldEmit) return\n const log = ctx.log as RequestLogger | undefined\n if (!log) return\n\n // Check if error.cause is an EvlogError (thrown errors get wrapped in HTTPError by nitro)\n const actualError = (error.cause as Error)?.name === 'EvlogError' \n ? error.cause as Error \n : error as Error\n\n log.error(actualError)\n\n const errorStatus = extractErrorStatus(actualError)\n log.set({ status: errorStatus })\n\n const { pathname } = parseURL(e.req.url)\n const startTime = ctx._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status: errorStatus,\n duration: durationMs,\n path: pathname,\n method: e.req.method,\n context: log.getContext(),\n shouldKeep: false,\n }\n\n await hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n ctx._evlogEmitted = true\n\n const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(hooks, emittedEvent, e)\n })\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/nitro-v3/plugin.ts"],"sourcesContent":["import { definePlugin } from 'nitro'\nimport type { CaptureError } from 'nitro/types'\nimport type { HTTPEvent } from 'nitro/h3'\nimport { parseURL } from 'ufo'\nimport { createRequestLogger, getGlobalPluginRunner, initLogger, isEnabled, markWideEventDrainStarted } from '../logger'\nimport { registerPrettyErrorSnippetReader } from '../shared/pretty-error'\nimport { readCodeSnippetFromDisk } from '../shared/pretty-error-snippet.node'\nimport { enrichErrorStackForDev } from '../shared/enrich-error-stack.node'\nimport { shouldLog, getServiceForPath, extractErrorStatus } from '../nitro'\nimport { extendDeferredDrain } from '../nitro/enrich-drain'\nimport { normalizeRedactConfig } from '../redact'\nimport { resolveEvlogConfigForNitroPlugin, setActiveNitroRuntime } from '../shared/nitroConfigBridge'\nimport { bindStreamingResponseLifecycle, shouldDeferEmitForResponse } from '../shared/streamResponse'\nimport type { EnrichContext, RequestLogger, TailSamplingContext, WideEvent } from '../types'\nimport { filterSafeHeaders } from '../utils'\n\n// Nitro v3 doesn't fully export hook types yet\n// https://github.com/nitrojs/nitro/blob/8882bc9e1dbf2d342e73097f22a2156f70f50575/src/types/runtime/nitro.ts#L48-L53\ninterface NitroV3Hooks {\n close: () => void\n error: CaptureError\n request: (event: HTTPEvent) => void | Promise<void>\n response: (res: Response, event: HTTPEvent) => void | Promise<void>\n 'evlog:emit:keep': (ctx: TailSamplingContext) => void | Promise<void>\n 'evlog:enrich': (ctx: EnrichContext) => void | Promise<void>\n 'evlog:drain': (ctx: { event: WideEvent; request?: { method?: string; path: string; requestId?: string }; headers?: Record<string, string> }) => void | Promise<void>\n}\n\ntype Hooks = {\n hook: <T extends keyof NitroV3Hooks>(name: T, listener: NitroV3Hooks[T]) => void\n callHook: <T extends keyof NitroV3Hooks>(name: T, ...args: Parameters<NitroV3Hooks[T]>) => Promise<void>\n}\n\nfunction getContext(event: HTTPEvent): Record<string, unknown> {\n if (!event.req.context) {\n event.req.context = {}\n }\n return event.req.context\n}\n\nfunction getSafeRequestHeaders(event: HTTPEvent): Record<string, string> {\n const headers: Record<string, string> = {}\n event.req.headers.forEach((value, key) => {\n headers[key] = value\n })\n return filterSafeHeaders(headers)\n}\n\nfunction getSafeResponseHeaders(res: Response): Record<string, string> | undefined {\n const headers: Record<string, string> = {}\n res.headers.forEach((value, key) => {\n headers[key] = value\n })\n if (Object.keys(headers).length === 0) return undefined\n return filterSafeHeaders(headers)\n}\n\nfunction buildHookContext(\n event: HTTPEvent,\n res?: Response,\n): Omit<EnrichContext, 'event'> {\n const { pathname } = parseURL(event.req.url)\n const responseHeaders = res ? getSafeResponseHeaders(res) : undefined\n return {\n request: { method: event.req.method, path: pathname },\n headers: getSafeRequestHeaders(event),\n response: {\n status: res?.status ?? 200,\n headers: responseHeaders,\n },\n }\n}\n\nasync function callDrainHook(\n hooks: Hooks,\n emittedEvent: WideEvent | null,\n event: HTTPEvent,\n hookContext: Omit<EnrichContext, 'event'>,\n options?: { deferDrain?: boolean },\n): Promise<void> {\n if (!emittedEvent) return\n\n const drainCtx = {\n event: emittedEvent,\n request: hookContext.request,\n headers: hookContext.headers,\n }\n\n const drainTasks: Array<Promise<unknown>> = []\n try {\n const result = hooks.callHook('evlog:drain', drainCtx)\n if (result?.catch) {\n drainTasks.push(\n result.catch((err: unknown) => {\n console.error('[evlog] drain failed:', err)\n }),\n )\n }\n } catch (err) {\n console.error('[evlog] drain failed:', err)\n }\n\n const runner = getGlobalPluginRunner()\n if (runner.hasDrain) {\n drainTasks.push(runner.runDrain(drainCtx))\n }\n\n if (drainTasks.length === 0) return\n const drainPromise = Promise.all(drainTasks)\n\n // deferDrain: never block Nitro Node responses; extend lifetime on Cloudflare only.\n if (options?.deferDrain) {\n const waitUntil = globalThis.navigator?.userAgent === 'Cloudflare-Workers' && typeof event.req.waitUntil === 'function'\n ? event.req.waitUntil.bind(event.req)\n : undefined\n extendDeferredDrain(drainPromise, waitUntil)\n return\n }\n\n if (typeof event.req.waitUntil === 'function') {\n event.req.waitUntil(drainPromise)\n } else {\n await drainPromise\n }\n}\n\nasync function callEnrichAndDrain(\n hooks: Hooks,\n emittedEvent: WideEvent | null,\n event: HTTPEvent,\n res?: Response,\n options?: { deferDrain?: boolean },\n): Promise<void> {\n if (!emittedEvent) return\n\n const hookContext = buildHookContext(event, res)\n const enrichCtx: EnrichContext = { event: emittedEvent, ...hookContext }\n\n try {\n await hooks.callHook('evlog:enrich', enrichCtx)\n } catch (err) {\n console.error('[evlog] enrich failed:', err)\n }\n\n const runner = getGlobalPluginRunner()\n if (runner.hasEnrich) {\n await runner.runEnrich(enrichCtx)\n }\n\n markWideEventDrainStarted(emittedEvent)\n\n await callDrainHook(hooks, emittedEvent, event, hookContext, options)\n}\n\n/**\n * Nitro v3 plugin entry point.\n *\n * Usage in Nitro v3:\n * ```ts\n * // plugins/evlog.ts\n * export { default } from 'evlog/nitro/v3'\n * ```\n */\nexport default definePlugin(async (nitroApp) => {\n setActiveNitroRuntime('v3')\n const evlogConfig = await resolveEvlogConfigForNitroPlugin()\n\n const redact = normalizeRedactConfig(evlogConfig?.redact as boolean | Record<string, unknown> | undefined)\n\n registerPrettyErrorSnippetReader(readCodeSnippetFromDisk)\n\n initLogger({\n enabled: evlogConfig?.enabled,\n env: evlogConfig?.env,\n pretty: evlogConfig?.pretty,\n dev: evlogConfig?.dev,\n silent: evlogConfig?.silent,\n sampling: evlogConfig?.sampling,\n minLevel: evlogConfig?.minLevel,\n redact,\n _suppressDrainWarning: true,\n })\n\n const hooks = nitroApp.hooks as unknown as Hooks\n\n // When globally disabled, createRequestLogger returns a no-op logger — still\n // attach it so handlers can call useLogger without throwing.\n if (!isEnabled()) {\n hooks.hook('request', (event) => {\n const { pathname } = parseURL(event.req.url)\n const ctx = getContext(event)\n let requestIdOverride: string | undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = event.req.headers.get('cf-ray')\n if (cfRay) requestIdOverride = cfRay\n }\n ctx.log = createRequestLogger({\n method: event.req.method,\n path: pathname,\n requestId: requestIdOverride || ctx.requestId as string | undefined || crypto.randomUUID(),\n }, { _deferDrain: true })\n })\n return\n }\n\n hooks.hook('request', (event) => {\n const { pathname } = parseURL(event.req.url)\n const ctx = getContext(event)\n\n // Evaluate route filtering but always create the logger so that server\n // middleware (which runs for every request) can call useLogger(event)\n // without throwing. Filtering is enforced at emit time instead.\n ctx._evlogShouldEmit = shouldLog(pathname, evlogConfig?.include, evlogConfig?.exclude)\n\n // Store start time for duration calculation in tail sampling\n ctx._evlogStartTime = Date.now()\n\n let requestIdOverride: string | undefined = undefined\n if (globalThis.navigator?.userAgent === 'Cloudflare-Workers') {\n const cfRay = event.req.headers.get('cf-ray')\n if (cfRay) requestIdOverride = cfRay\n }\n\n const log = createRequestLogger({\n method: event.req.method,\n path: pathname,\n requestId: requestIdOverride || ctx.requestId as string | undefined || crypto.randomUUID(),\n }, { _deferDrain: true })\n\n // Apply route-based service configuration if a matching route is found\n const routeService = getServiceForPath(pathname, evlogConfig?.routes)\n if (routeService) {\n log.set({ service: routeService })\n }\n\n ctx.log = log\n })\n\n hooks.hook('response', async (res, event) => {\n const ctx = event.req.context\n // Skip if already emitted by error hook or route was filtered out\n if (ctx?._evlogEmitted || ctx?._evlogEmitting || !ctx?._evlogShouldEmit) return\n\n const log = ctx?.log as RequestLogger | undefined\n if (!log || !ctx) return\n\n const emitSuccessResponse = async (responseStatus: number) => {\n log.set({ status: responseStatus })\n\n const startTime = ctx._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const { pathname } = parseURL(event.req.url)\n\n const tailCtx: TailSamplingContext = {\n status: responseStatus,\n duration: durationMs,\n path: pathname,\n method: event.req.method,\n context: log.getContext(),\n shouldKeep: false,\n }\n\n await hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep })\n await callEnrichAndDrain(hooks, emittedEvent, event, res)\n }\n\n if (shouldDeferEmitForResponse(res)) {\n const wrapped = bindStreamingResponseLifecycle(res, async (meta) => {\n if (meta.error) {\n log.error(meta.error)\n }\n await emitSuccessResponse(meta.status ?? res.status)\n })\n if (wrapped !== res && 'res' in event) {\n (event as { res: Response }).res = wrapped\n }\n return\n }\n\n await emitSuccessResponse(res.status)\n })\n\n hooks.hook('error', async (error, { event }) => {\n if (!event) return\n const e = event as HTTPEvent\n\n const ctx = e.req.context\n if (!ctx?._evlogShouldEmit) return\n const log = ctx.log as RequestLogger | undefined\n if (!log) return\n\n ctx._evlogEmitting = true\n try {\n const actualError = (error.cause as Error)?.name === 'EvlogError'\n ? error.cause as Error\n : error as Error\n\n void enrichErrorStackForDev(actualError, { pretty: evlogConfig?.pretty })\n log.error(actualError)\n\n const errorStatus = extractErrorStatus(actualError)\n log.set({ status: errorStatus })\n\n const { pathname } = parseURL(e.req.url)\n const startTime = ctx._evlogStartTime as number | undefined\n const durationMs = startTime ? Date.now() - startTime : undefined\n\n const tailCtx: TailSamplingContext = {\n status: errorStatus,\n duration: durationMs,\n path: pathname,\n method: e.req.method,\n context: log.getContext(),\n shouldKeep: false,\n }\n\n await hooks.callHook('evlog:emit:keep', tailCtx)\n const runner = getGlobalPluginRunner()\n if (runner.hasKeep) await runner.runKeep(tailCtx)\n\n const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep })\n if (emittedEvent) {\n ctx._evlogEmitted = true\n void callEnrichAndDrain(hooks, emittedEvent, e, undefined, { deferDrain: true }).catch((err) => {\n console.error('[evlog] background enrich/drain failed:', err)\n })\n }\n } finally {\n delete ctx._evlogEmitting\n }\n })\n})\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { $ as RequestLogger } from "../../audit-DVdkntSO.mjs";
1
+ import { rt as RequestLogger } from "../../audit-BUAajsPU.mjs";
2
2
  import { HTTPEvent } from "nitro/h3";
3
3
 
4
4
  //#region src/nitro-v3/useLogger.d.ts