evlog 2.18.1 → 2.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/README.md +14 -16
  2. package/dist/adapters/axiom.d.mts +3 -3
  3. package/dist/adapters/axiom.d.mts.map +1 -1
  4. package/dist/adapters/axiom.mjs +10 -14
  5. package/dist/adapters/axiom.mjs.map +1 -1
  6. package/dist/adapters/better-stack.d.mts +2 -2
  7. package/dist/adapters/better-stack.d.mts.map +1 -1
  8. package/dist/adapters/better-stack.mjs +9 -13
  9. package/dist/adapters/better-stack.mjs.map +1 -1
  10. package/dist/adapters/datadog.d.mts +3 -3
  11. package/dist/adapters/datadog.mjs +9 -5
  12. package/dist/adapters/datadog.mjs.map +1 -1
  13. package/dist/adapters/fs.d.mts +1 -1
  14. package/dist/adapters/fs.d.mts.map +1 -1
  15. package/dist/adapters/fs.mjs +15 -2
  16. package/dist/adapters/fs.mjs.map +1 -1
  17. package/dist/adapters/hyperdx.d.mts +2 -2
  18. package/dist/adapters/hyperdx.mjs +3 -3
  19. package/dist/adapters/hyperdx.mjs.map +1 -1
  20. package/dist/adapters/memory.d.mts +2 -3
  21. package/dist/adapters/memory.d.mts.map +1 -1
  22. package/dist/adapters/memory.mjs +2 -3
  23. package/dist/adapters/memory.mjs.map +1 -1
  24. package/dist/adapters/otlp.d.mts +4 -4
  25. package/dist/adapters/otlp.mjs +19 -11
  26. package/dist/adapters/otlp.mjs.map +1 -1
  27. package/dist/adapters/posthog.d.mts +2 -2
  28. package/dist/adapters/posthog.mjs +5 -5
  29. package/dist/adapters/posthog.mjs.map +1 -1
  30. package/dist/adapters/sentry.d.mts +3 -3
  31. package/dist/adapters/sentry.mjs +6 -6
  32. package/dist/adapters/sentry.mjs.map +1 -1
  33. package/dist/ai/index.d.mts +1 -1
  34. package/dist/{audit-BUI3af4w.mjs → audit-BQt8yAHo.mjs} +376 -116
  35. package/dist/audit-BQt8yAHo.mjs.map +1 -0
  36. package/dist/{audit-DVdkntSO.d.mts → audit-D7v6JHj0.d.mts} +113 -35
  37. package/dist/audit-D7v6JHj0.d.mts.map +1 -0
  38. package/dist/better-auth/index.d.mts +1 -1
  39. package/dist/browser.d.mts +1 -1
  40. package/dist/deferred-drain-jeajC8QF.mjs +36 -0
  41. package/dist/deferred-drain-jeajC8QF.mjs.map +1 -0
  42. package/dist/{define-D6OJdSUH.mjs → define-Bpaymi-h.mjs} +2 -1
  43. package/dist/define-Bpaymi-h.mjs.map +1 -0
  44. package/dist/{define-D-BVMf2l.d.mts → define-DTQpu4f6.d.mts} +8 -3
  45. package/dist/define-DTQpu4f6.d.mts.map +1 -0
  46. package/dist/dev-terminal-D4UaEm17.mjs +54 -0
  47. package/dist/dev-terminal-D4UaEm17.mjs.map +1 -0
  48. package/dist/{dist-H3GIh-KK.mjs → dist-DdQWiZn8.mjs} +1 -1
  49. package/dist/{dist-H3GIh-KK.mjs.map → dist-DdQWiZn8.mjs.map} +1 -1
  50. package/dist/{drain-7n3K6kPe.mjs → drain-fDb-eNwz.mjs} +35 -4
  51. package/dist/drain-fDb-eNwz.mjs.map +1 -0
  52. package/dist/elysia/index.d.mts +3 -3
  53. package/dist/elysia/index.d.mts.map +1 -1
  54. package/dist/elysia/index.mjs +8 -5
  55. package/dist/elysia/index.mjs.map +1 -1
  56. package/dist/enrich-error-stack-next.node-Dgm_rCf5.mjs +120 -0
  57. package/dist/enrich-error-stack-next.node-Dgm_rCf5.mjs.map +1 -0
  58. package/dist/{enricher-UW9npoB2.d.mts → enricher-CBRmQw6e.d.mts} +2 -2
  59. package/dist/{enricher-UW9npoB2.d.mts.map → enricher-CBRmQw6e.d.mts.map} +1 -1
  60. package/dist/{enricher-N0erZS87.mjs → enricher-DAWf2-Fx.mjs} +2 -2
  61. package/dist/{enricher-N0erZS87.mjs.map → enricher-DAWf2-Fx.mjs.map} +1 -1
  62. package/dist/enrichers.d.mts +2 -2
  63. package/dist/enrichers.mjs +2 -2
  64. package/dist/{error-CVtn5U7b.d.mts → error-CpghjrkY.d.mts} +2 -2
  65. package/dist/{error-CVtn5U7b.d.mts.map → error-CpghjrkY.d.mts.map} +1 -1
  66. package/dist/error.d.mts +1 -1
  67. package/dist/{errors-dEMNQCiL.d.mts → errors-BLU4Tfpe.d.mts} +2 -2
  68. package/dist/{errors-dEMNQCiL.d.mts.map → errors-BLU4Tfpe.d.mts.map} +1 -1
  69. package/dist/{errors-BQgyQ9xe.mjs → errors-DA0cyr8q.mjs} +1 -1
  70. package/dist/{errors-BQgyQ9xe.mjs.map → errors-DA0cyr8q.mjs.map} +1 -1
  71. package/dist/{event-1BMl7o0k.mjs → event-qwAv-7AZ.mjs} +1 -1
  72. package/dist/{event-1BMl7o0k.mjs.map → event-qwAv-7AZ.mjs.map} +1 -1
  73. package/dist/express/index.d.mts +2 -2
  74. package/dist/express/index.mjs +3 -3
  75. package/dist/fastify/index.d.mts +2 -2
  76. package/dist/fastify/index.mjs +2 -2
  77. package/dist/{fork-Bga8x-X4.mjs → fork-CgGlAaHa.mjs} +39 -14
  78. package/dist/fork-CgGlAaHa.mjs.map +1 -0
  79. package/dist/{headers-CU-QqnYg.mjs → headers-VtmnWcfn.mjs} +1 -1
  80. package/dist/{headers-CU-QqnYg.mjs.map → headers-VtmnWcfn.mjs.map} +1 -1
  81. package/dist/hono/index.d.mts +2 -2
  82. package/dist/hono/index.d.mts.map +1 -1
  83. package/dist/hono/index.mjs +10 -2
  84. package/dist/hono/index.mjs.map +1 -1
  85. package/dist/{http-B6YgAhyN.mjs → http-ChVS9GYc.mjs} +2 -2
  86. package/dist/{http-B6YgAhyN.mjs.map → http-ChVS9GYc.mjs.map} +1 -1
  87. package/dist/http.d.mts +1 -1
  88. package/dist/{index-ZSRQP_BI.d.mts → index-EvnrXvQM.d.mts} +15 -8
  89. package/dist/index-EvnrXvQM.d.mts.map +1 -0
  90. package/dist/index.d.mts +9 -9
  91. package/dist/index.mjs +9 -15
  92. package/dist/index.mjs.map +1 -1
  93. package/dist/instrumentation-create-BrjQtSKD.d.mts +115 -0
  94. package/dist/instrumentation-create-BrjQtSKD.d.mts.map +1 -0
  95. package/dist/{integration-Dhig7ae6.mjs → integration-DYp2uw8O.mjs} +3 -3
  96. package/dist/{integration-Dhig7ae6.mjs.map → integration-DYp2uw8O.mjs.map} +1 -1
  97. package/dist/{logger-CTcvd5Cc.d.mts → logger-mHIWxBhJ.d.mts} +12 -4
  98. package/dist/logger-mHIWxBhJ.d.mts.map +1 -0
  99. package/dist/logger.d.mts +2 -2
  100. package/dist/logger.mjs +2 -2
  101. package/dist/{middleware-31KhtiEF.d.mts → middleware-B_k4Mrzg.d.mts} +9 -2
  102. package/dist/middleware-B_k4Mrzg.d.mts.map +1 -0
  103. package/dist/nestjs/index.d.mts +2 -2
  104. package/dist/nestjs/index.mjs +4 -4
  105. package/dist/next/client.d.mts +1 -1
  106. package/dist/next/index.d.mts +4 -4
  107. package/dist/next/index.d.mts.map +1 -1
  108. package/dist/next/index.mjs +49 -38
  109. package/dist/next/index.mjs.map +1 -1
  110. package/dist/next/instrumentation/create.d.mts +2 -0
  111. package/dist/next/instrumentation/create.mjs +155 -0
  112. package/dist/next/instrumentation/create.mjs.map +1 -0
  113. package/dist/next/instrumentation.d.mts +2 -77
  114. package/dist/next/instrumentation.mjs +32 -81
  115. package/dist/next/instrumentation.mjs.map +1 -1
  116. package/dist/next/stream.d.mts +1 -1
  117. package/dist/next/stream.mjs +2 -2
  118. package/dist/next/stream.mjs.map +1 -1
  119. package/dist/nitro/errorHandler.mjs +23 -18
  120. package/dist/nitro/errorHandler.mjs.map +1 -1
  121. package/dist/nitro/module.d.mts +2 -2
  122. package/dist/nitro/module.d.mts.map +1 -1
  123. package/dist/nitro/module.mjs +2 -1
  124. package/dist/nitro/module.mjs.map +1 -1
  125. package/dist/nitro/plugin.mjs +74 -18
  126. package/dist/nitro/plugin.mjs.map +1 -1
  127. package/dist/nitro/v3/errorHandler.d.mts +0 -7
  128. package/dist/nitro/v3/errorHandler.mjs +13 -15
  129. package/dist/nitro/v3/errorHandler.mjs.map +1 -1
  130. package/dist/nitro/v3/index.d.mts +2 -2
  131. package/dist/nitro/v3/module.d.mts +1 -1
  132. package/dist/nitro/v3/module.d.mts.map +1 -1
  133. package/dist/nitro/v3/module.mjs +3 -3
  134. package/dist/nitro/v3/module.mjs.map +1 -1
  135. package/dist/nitro/v3/plugin.mjs +76 -44
  136. package/dist/nitro/v3/plugin.mjs.map +1 -1
  137. package/dist/nitro/v3/useLogger.d.mts +1 -1
  138. package/dist/nitro-ClRZLD1g.mjs +96 -0
  139. package/dist/nitro-ClRZLD1g.mjs.map +1 -0
  140. package/dist/{nitro-BRddgqSb.d.mts → nitro-_Hda8Deo.d.mts} +7 -2
  141. package/dist/nitro-_Hda8Deo.d.mts.map +1 -0
  142. package/dist/{nitroConfigBridge-NbFn-sIK.mjs → nitroConfigBridge-BkVWnSV3.mjs} +9 -2
  143. package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +1 -0
  144. package/dist/{nodeResponse-BkkionWl.mjs → nodeResponse-CIEEbrNE.mjs} +1 -1
  145. package/dist/{nodeResponse-BkkionWl.mjs.map → nodeResponse-CIEEbrNE.mjs.map} +1 -1
  146. package/dist/nuxt/module.d.mts +6 -1
  147. package/dist/nuxt/module.d.mts.map +1 -1
  148. package/dist/nuxt/module.mjs +11 -4
  149. package/dist/nuxt/module.mjs.map +1 -1
  150. package/dist/orpc/index.d.mts +2 -2
  151. package/dist/orpc/index.d.mts.map +1 -1
  152. package/dist/orpc/index.mjs +5 -4
  153. package/dist/orpc/index.mjs.map +1 -1
  154. package/dist/{package-B23bR3tK.mjs → package-CNV_CXs8.mjs} +2 -2
  155. package/dist/package-CNV_CXs8.mjs.map +1 -0
  156. package/dist/{parseError-D4PIxEWo.d.mts → parseError-BeBXEd2V.d.mts} +2 -2
  157. package/dist/parseError-BeBXEd2V.d.mts.map +1 -0
  158. package/dist/pipeline.d.mts +0 -19
  159. package/dist/pipeline.d.mts.map +1 -1
  160. package/dist/pipeline.mjs +12 -0
  161. package/dist/pipeline.mjs.map +1 -1
  162. package/dist/pretty-error-THg0U0w9.mjs +288 -0
  163. package/dist/pretty-error-THg0U0w9.mjs.map +1 -0
  164. package/dist/pretty-error-snippet.node-itfCajBM.mjs +48 -0
  165. package/dist/pretty-error-snippet.node-itfCajBM.mjs.map +1 -0
  166. package/dist/react-router/index.d.mts +2 -2
  167. package/dist/react-router/index.mjs +5 -6
  168. package/dist/react-router/index.mjs.map +1 -1
  169. package/dist/{routes-CnIgYWf8.mjs → routes-4rMzRyTk.mjs} +1 -1
  170. package/dist/{routes-CnIgYWf8.mjs.map → routes-4rMzRyTk.mjs.map} +1 -1
  171. package/dist/runtime/client/log.d.mts +1 -1
  172. package/dist/runtime/server/routes/_evlog/ingest.post.d.mts +7 -0
  173. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +39 -3
  174. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
  175. package/dist/runtime/server/useLogger.d.mts +1 -1
  176. package/dist/runtime/utils/parseError.d.mts +2 -2
  177. package/dist/runtime/utils/parseError.mjs +1 -1
  178. package/dist/{severity-R5Egq3qz.mjs → severity-CwXUSHt3.mjs} +1 -1
  179. package/dist/{severity-R5Egq3qz.mjs.map → severity-CwXUSHt3.mjs.map} +1 -1
  180. package/dist/{source-location-Dco0cRTz.mjs → source-location-CHOPF2nd.mjs} +2 -1
  181. package/dist/{source-location-Dco0cRTz.mjs.map → source-location-CHOPF2nd.mjs.map} +1 -1
  182. package/dist/{storage-BNubsWwz.mjs → storage-7X37OToT.mjs} +1 -1
  183. package/dist/{storage-BNubsWwz.mjs.map → storage-7X37OToT.mjs.map} +1 -1
  184. package/dist/stream.d.mts +1 -1
  185. package/dist/stream.mjs +1 -1
  186. package/dist/streamResponse-CmQ3qUbF.mjs +94 -0
  187. package/dist/streamResponse-CmQ3qUbF.mjs.map +1 -0
  188. package/dist/sveltekit/index.d.mts +2 -2
  189. package/dist/sveltekit/index.d.mts.map +1 -1
  190. package/dist/sveltekit/index.mjs +7 -8
  191. package/dist/sveltekit/index.mjs.map +1 -1
  192. package/dist/toolkit.d.mts +51 -6
  193. package/dist/toolkit.d.mts.map +1 -1
  194. package/dist/toolkit.mjs +15 -14
  195. package/dist/types.d.mts +2 -2
  196. package/dist/{useLogger-CqvH6qOf.d.mts → useLogger-Cfv8Ck8b.d.mts} +2 -2
  197. package/dist/{useLogger-CqvH6qOf.d.mts.map → useLogger-Cfv8Ck8b.d.mts.map} +1 -1
  198. package/dist/{utils-DxqvIOyR.d.mts → utils-CJJG0ZYW.d.mts} +11 -3
  199. package/dist/{utils-DxqvIOyR.d.mts.map → utils-CJJG0ZYW.d.mts.map} +1 -1
  200. package/dist/utils.d.mts +2 -2
  201. package/dist/utils.mjs +23 -9
  202. package/dist/utils.mjs.map +1 -1
  203. package/dist/vite/index.d.mts +1 -1
  204. package/dist/vite/index.mjs +1 -1
  205. package/dist/workers.d.mts +1 -1
  206. package/dist/workers.mjs +1 -1
  207. package/package.json +12 -1
  208. package/dist/audit-BUI3af4w.mjs.map +0 -1
  209. package/dist/audit-DVdkntSO.d.mts.map +0 -1
  210. package/dist/define-D-BVMf2l.d.mts.map +0 -1
  211. package/dist/define-D6OJdSUH.mjs.map +0 -1
  212. package/dist/drain-7n3K6kPe.mjs.map +0 -1
  213. package/dist/fork-Bga8x-X4.mjs.map +0 -1
  214. package/dist/index-ZSRQP_BI.d.mts.map +0 -1
  215. package/dist/logger-CTcvd5Cc.d.mts.map +0 -1
  216. package/dist/middleware-31KhtiEF.d.mts.map +0 -1
  217. package/dist/next/instrumentation.d.mts.map +0 -1
  218. package/dist/nitro-BRddgqSb.d.mts.map +0 -1
  219. package/dist/nitro-DErMq_Zj.mjs +0 -34
  220. package/dist/nitro-DErMq_Zj.mjs.map +0 -1
  221. package/dist/nitroConfigBridge-NbFn-sIK.mjs.map +0 -1
  222. package/dist/package-B23bR3tK.mjs.map +0 -1
  223. package/dist/parseError-D4PIxEWo.d.mts.map +0 -1
@@ -1,6 +1,6 @@
1
- import { t as extractSafeHeaders } from "../headers-CU-QqnYg.mjs";
2
- import { r as createMiddlewareLogger, t as attachForkToLogger } from "../fork-Bga8x-X4.mjs";
3
- import { t as createLoggerStorage } from "../storage-BNubsWwz.mjs";
1
+ import { t as extractSafeHeaders } from "../headers-VtmnWcfn.mjs";
2
+ import { r as createMiddlewareLogger, t as attachForkToLogger } from "../fork-CgGlAaHa.mjs";
3
+ import { t as createLoggerStorage } from "../storage-7X37OToT.mjs";
4
4
  import { createContext } from "react-router";
5
5
  //#region src/react-router/index.ts
6
6
  const { storage, useLogger } = createLoggerStorage("middleware context. Make sure the evlog middleware is added to your route.");
@@ -42,14 +42,13 @@ function evlog(options = {}) {
42
42
  headers: extractSafeHeaders(request.headers),
43
43
  ...options
44
44
  };
45
- const { logger, finish, skipped } = createMiddlewareLogger(middlewareOpts);
45
+ const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts);
46
46
  if (skipped) return next();
47
47
  attachForkToLogger(storage, logger, middlewareOpts);
48
48
  context.set(loggerContext, logger);
49
49
  try {
50
50
  const response = await storage.run(logger, () => next());
51
- await finish({ status: response.status });
52
- return response;
51
+ return finishResponse(response, { status: response.status });
53
52
  } catch (error) {
54
53
  await finish({ error });
55
54
  throw error;
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure the evlog middleware is added to your route.',\n)\n\n/**\n * Typed context key for accessing the evlog logger in loaders and actions.\n *\n * @example\n * ```ts\n * import { loggerContext } from 'evlog/react-router'\n *\n * export async function loader({ context }: Route.LoaderArgs) {\n * const log = context.get(loggerContext)\n * log.set({ user: { id: 'u-1' } })\n * return { ok: true }\n * }\n * ```\n */\nexport const loggerContext = createContext<RequestLogger>()\n\nexport type EvlogReactRouterOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * Create an evlog middleware for React Router.\n *\n * @example\n * ```ts\n * // app/root.tsx\n * import { evlog } from 'evlog/react-router'\n *\n * export const middleware: Route.MiddlewareFunction[] = [\n * evlog({ drain: createAxiomDrain() }),\n * ]\n * ```\n */\nexport function evlog(options: EvlogReactRouterOptions = {}) {\n return async (\n { request, context }: { request: Request; context: { set(ctx: unknown, value: unknown): void } },\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const url = new URL(request.url)\n const middlewareOpts = {\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n }\n const { logger, finish, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return next()\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n context.set(loggerContext, logger)\n\n try {\n const response = await storage.run(logger, () => next())\n await finish({ status: response.status })\n return response\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n}\n"],"mappings":";;;;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,6EACD;;;;;;;;;;;;;;;AAgBD,MAAa,gBAAgB,eAA8B;;;;;;;;;;;;;;AAmB3D,SAAgB,MAAM,UAAmC,EAAE,EAAE;AAC3D,QAAO,OACL,EAAE,SAAS,WACX,SACsB;EACtB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAChC,MAAM,iBAAiB;GACrB,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ;EACD,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB,eAAe;AAE1E,MAAI,QACF,QAAO,MAAM;AAGf,qBAAmB,SAAS,QAAQ,eAAe;AACnD,UAAQ,IAAI,eAAe,OAAO;AAElC,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,IAAI,cAAc,MAAM,CAAC;AACxD,SAAM,OAAO,EAAE,QAAQ,SAAS,QAAQ,CAAC;AACzC,UAAO;WACA,OAAO;AACd,SAAM,OAAO,EAAS,OAAgB,CAAC;AACvC,SAAM"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure the evlog middleware is added to your route.',\n)\n\n/**\n * Typed context key for accessing the evlog logger in loaders and actions.\n *\n * @example\n * ```ts\n * import { loggerContext } from 'evlog/react-router'\n *\n * export async function loader({ context }: Route.LoaderArgs) {\n * const log = context.get(loggerContext)\n * log.set({ user: { id: 'u-1' } })\n * return { ok: true }\n * }\n * ```\n */\nexport const loggerContext = createContext<RequestLogger>()\n\nexport type EvlogReactRouterOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * Create an evlog middleware for React Router.\n *\n * @example\n * ```ts\n * // app/root.tsx\n * import { evlog } from 'evlog/react-router'\n *\n * export const middleware: Route.MiddlewareFunction[] = [\n * evlog({ drain: createAxiomDrain() }),\n * ]\n * ```\n */\nexport function evlog(options: EvlogReactRouterOptions = {}) {\n return async (\n { request, context }: { request: Request; context: { set(ctx: unknown, value: unknown): void } },\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const url = new URL(request.url)\n const middlewareOpts = {\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return next()\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n context.set(loggerContext, logger)\n\n try {\n const response = await storage.run(logger, () => next())\n return finishResponse(response, { status: response.status })\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n}\n"],"mappings":";;;;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,6EACD;;;;;;;;;;;;;;;AAgBD,MAAa,gBAAgB,eAA8B;;;;;;;;;;;;;;AAmB3D,SAAgB,MAAM,UAAmC,EAAE,EAAE;AAC3D,QAAO,OACL,EAAE,SAAS,WACX,SACsB;EACtB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAChC,MAAM,iBAAiB;GACrB,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ;EACD,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,YAAY,uBAAuB,eAAe;AAE1F,MAAI,QACF,QAAO,MAAM;AAGf,qBAAmB,SAAS,QAAQ,eAAe;AACnD,UAAQ,IAAI,eAAe,OAAO;AAElC,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,IAAI,cAAc,MAAM,CAAC;AACxD,UAAO,eAAe,UAAU,EAAE,QAAQ,SAAS,QAAQ,CAAC;WACrD,OAAO;AACd,SAAM,OAAO,EAAS,OAAgB,CAAC;AACvC,SAAM"}
@@ -35,4 +35,4 @@ function getServiceForPath(path, routes) {
35
35
  //#endregion
36
36
  export { shouldLog as n, getServiceForPath as t };
37
37
 
38
- //# sourceMappingURL=routes-CnIgYWf8.mjs.map
38
+ //# sourceMappingURL=routes-4rMzRyTk.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes-CnIgYWf8.mjs","names":[],"sources":["../src/shared/routes.ts"],"sourcesContent":["import type { RouteConfig } from '../types'\nimport { matchesPattern } from '../utils'\n\nexport function shouldLog(path: string, include?: string[], exclude?: string[]): boolean {\n // Check exclusions first (they take precedence)\n if (exclude && exclude.length > 0) {\n if (exclude.some(pattern => matchesPattern(path, pattern))) {\n return false\n }\n }\n\n // If no include patterns, log everything (that wasn't excluded)\n if (!include || include.length === 0) {\n return true\n }\n\n // Log only if path matches at least one include pattern\n return include.some(pattern => matchesPattern(path, pattern))\n}\n\n/**\n * Find the service name for a given path based on route patterns.\n *\n * When multiple patterns match the same path, the first matching pattern wins\n * based on object iteration order. To ensure predictable behavior, order your\n * route patterns from most specific to most general.\n *\n * @param path - The request path to match\n * @param routes - Route configuration mapping patterns to service names\n * @returns The service name for the matching route, or undefined if no match\n *\n * @example\n * ```ts\n * // Good: specific patterns first, general patterns last\n * routes: {\n * '/api/auth/admin/**': { service: 'admin-service' },\n * '/api/auth/**': { service: 'auth-service' },\n * '/api/**': { service: 'api-service' },\n * }\n * ```\n */\nexport function getServiceForPath(path: string, routes?: Record<string, RouteConfig>): string | undefined {\n if (!routes) return undefined\n\n for (const [pattern, config] of Object.entries(routes)) {\n if (matchesPattern(path, pattern)) {\n return config.service\n }\n }\n\n return undefined\n}\n"],"mappings":";;AAGA,SAAgB,UAAU,MAAc,SAAoB,SAA6B;AAEvF,KAAI,WAAW,QAAQ,SAAS;MAC1B,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC,CACxD,QAAO;;AAKX,KAAI,CAAC,WAAW,QAAQ,WAAW,EACjC,QAAO;AAIT,QAAO,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;AAwB/D,SAAgB,kBAAkB,MAAc,QAA0D;AACxG,KAAI,CAAC,OAAQ,QAAO,KAAA;AAEpB,MAAK,MAAM,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,CACpD,KAAI,eAAe,MAAM,QAAQ,CAC/B,QAAO,OAAO"}
1
+ {"version":3,"file":"routes-4rMzRyTk.mjs","names":[],"sources":["../src/shared/routes.ts"],"sourcesContent":["import type { RouteConfig } from '../types'\nimport { matchesPattern } from '../utils'\n\nexport function shouldLog(path: string, include?: string[], exclude?: string[]): boolean {\n // Check exclusions first (they take precedence)\n if (exclude && exclude.length > 0) {\n if (exclude.some(pattern => matchesPattern(path, pattern))) {\n return false\n }\n }\n\n // If no include patterns, log everything (that wasn't excluded)\n if (!include || include.length === 0) {\n return true\n }\n\n // Log only if path matches at least one include pattern\n return include.some(pattern => matchesPattern(path, pattern))\n}\n\n/**\n * Find the service name for a given path based on route patterns.\n *\n * When multiple patterns match the same path, the first matching pattern wins\n * based on object iteration order. To ensure predictable behavior, order your\n * route patterns from most specific to most general.\n *\n * @param path - The request path to match\n * @param routes - Route configuration mapping patterns to service names\n * @returns The service name for the matching route, or undefined if no match\n *\n * @example\n * ```ts\n * // Good: specific patterns first, general patterns last\n * routes: {\n * '/api/auth/admin/**': { service: 'admin-service' },\n * '/api/auth/**': { service: 'auth-service' },\n * '/api/**': { service: 'api-service' },\n * }\n * ```\n */\nexport function getServiceForPath(path: string, routes?: Record<string, RouteConfig>): string | undefined {\n if (!routes) return undefined\n\n for (const [pattern, config] of Object.entries(routes)) {\n if (matchesPattern(path, pattern)) {\n return config.service\n }\n }\n\n return undefined\n}\n"],"mappings":";;AAGA,SAAgB,UAAU,MAAc,SAAoB,SAA6B;AAEvF,KAAI,WAAW,QAAQ,SAAS;MAC1B,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC,CACxD,QAAO;;AAKX,KAAI,CAAC,WAAW,QAAQ,WAAW,EACjC,QAAO;AAIT,QAAO,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;AAwB/D,SAAgB,kBAAkB,MAAc,QAA0D;AACxG,KAAI,CAAC,OAAQ,QAAO,KAAA;AAEpB,MAAK,MAAM,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,CACpD,KAAI,eAAe,MAAM,QAAQ,CAC/B,QAAO,OAAO"}
@@ -1,4 +1,4 @@
1
- import { G as Log, K as LogLevel, st as TransportConfig } from "../../audit-DVdkntSO.mjs";
1
+ import { X as LogLevel, Y as Log, dt as TransportConfig } from "../../audit-D7v6JHj0.mjs";
2
2
 
3
3
  //#region src/runtime/client/log.d.ts
4
4
  declare function setIdentity(identity: Record<string, unknown>): void;
@@ -1,6 +1,13 @@
1
1
  import * as _$h3 from "h3";
2
2
 
3
3
  //#region src/runtime/server/routes/_evlog/ingest.post.d.ts
4
+ /**
5
+ * Client log ingestion endpoint.
6
+ *
7
+ * The origin check is CSRF-level protection only: it blocks cross-site browser
8
+ * requests but is trivially satisfied by non-browser clients. Treat ingested
9
+ * events as untrusted input — this endpoint is intentionally unauthenticated.
10
+ */
4
11
  declare const _default: _$h3.EventHandler<_$h3.EventHandlerRequest, Promise<null>>;
5
12
  //#endregion
6
13
  export { _default as default };
@@ -1,6 +1,6 @@
1
- import { _ as getEnvironment, y as getGlobalPluginRunner } from "../../../../audit-BUI3af4w.mjs";
2
1
  import { filterSafeHeaders } from "../../../../utils.mjs";
3
- import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readBody, setResponseStatus } from "h3";
2
+ import { _ as getEnvironment, y as getGlobalPluginRunner } from "../../../../audit-BQt8yAHo.mjs";
3
+ import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readRawBody, setResponseStatus } from "h3";
4
4
  import { useNitroApp } from "nitropack/runtime";
5
5
  //#region src/runtime/server/routes/_evlog/ingest.post.ts
6
6
  const VALID_LEVELS = [
@@ -29,6 +29,35 @@ function validateOrigin(event) {
29
29
  message: "Invalid origin"
30
30
  });
31
31
  }
32
+ /**
33
+ * Maximum accepted ingest body size in bytes. Client wide events are small;
34
+ * anything larger is rejected before it reaches the enrich/drain pipeline.
35
+ */
36
+ const MAX_BODY_BYTES = 32 * 1024;
37
+ async function readJsonBody(event) {
38
+ const contentLength = Number(getHeader(event, "content-length"));
39
+ if (Number.isFinite(contentLength) && contentLength > MAX_BODY_BYTES) throw createError({
40
+ statusCode: 413,
41
+ message: "Payload too large"
42
+ });
43
+ const raw = await readRawBody(event, "utf8");
44
+ if (!raw) throw createError({
45
+ statusCode: 400,
46
+ message: "Invalid request body"
47
+ });
48
+ if (new TextEncoder().encode(raw).byteLength > MAX_BODY_BYTES) throw createError({
49
+ statusCode: 413,
50
+ message: "Payload too large"
51
+ });
52
+ try {
53
+ return JSON.parse(raw);
54
+ } catch {
55
+ throw createError({
56
+ statusCode: 400,
57
+ message: "Invalid request body"
58
+ });
59
+ }
60
+ }
32
61
  const ISO_8601_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;
33
62
  function isValidISOTimestamp(value) {
34
63
  if (!ISO_8601_REGEX.test(value)) return false;
@@ -93,9 +122,16 @@ function resolveWaitUntilContext(event) {
93
122
  if (isRecord(cloudflare) && isRecord(cloudflare.context)) return cloudflare.context;
94
123
  return context;
95
124
  }
125
+ /**
126
+ * Client log ingestion endpoint.
127
+ *
128
+ * The origin check is CSRF-level protection only: it blocks cross-site browser
129
+ * requests but is trivially satisfied by non-browser clients. Treat ingested
130
+ * events as untrusted input — this endpoint is intentionally unauthenticated.
131
+ */
96
132
  var ingest_post_default = defineEventHandler(async (event) => {
97
133
  validateOrigin(event);
98
- const payload = validatePayload(await readBody(event));
134
+ const payload = validatePayload(await readJsonBody(event));
99
135
  const nitroApp = useNitroApp();
100
136
  const env = getEnvironment();
101
137
  const { service: _clientService, ...sanitizedPayload } = payload;
@@ -1 +1 @@
1
- {"version":3,"file":"ingest.post.mjs","names":[],"sources":["../../../../../src/runtime/server/routes/_evlog/ingest.post.ts"],"sourcesContent":["import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readBody, setResponseStatus } from 'h3'\nimport { useNitroApp } from 'nitropack/runtime'\nimport type { IngestPayload, WideEvent } from '../../../../types'\nimport { getEnvironment, getGlobalPluginRunner } from '../../../../logger'\nimport { filterSafeHeaders } from '../../../../utils'\n\nconst VALID_LEVELS = ['info', 'error', 'warn', 'debug'] as const\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isLogLevel(value: string): value is IngestPayload['level'] {\n return (VALID_LEVELS as readonly string[]).includes(value)\n}\n\nfunction validateOrigin(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): void {\n const origin = getHeader(event, 'origin')\n const referer = getHeader(event, 'referer')\n const host = getRequestHost(event)\n\n const requestOrigin = origin || (referer ? new URL(referer).origin : null)\n\n if (!requestOrigin) {\n throw createError({ statusCode: 403, message: 'Missing origin header' })\n }\n\n const originHost = new URL(requestOrigin).host\n\n if (originHost !== host) {\n throw createError({ statusCode: 403, message: 'Invalid origin' })\n }\n}\n\n// ISO 8601 datetime pattern (e.g., 2024-01-31T14:00:00.000Z)\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/\n\nfunction isValidISOTimestamp(value: string): boolean {\n if (!ISO_8601_REGEX.test(value)) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nfunction validatePayload(body: unknown): IngestPayload {\n if (!isRecord(body)) {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n\n if (body.timestamp === undefined || body.timestamp === null) {\n throw createError({ statusCode: 400, message: 'Missing required field: timestamp' })\n }\n\n const { timestamp: rawTimestamp } = body\n let timestamp: string\n if (typeof rawTimestamp === 'number') {\n const minTimestamp = new Date('2000-01-01').getTime()\n const maxTimestamp = Date.now() + 24 * 60 * 60 * 1000 // 1 day in the future\n if (rawTimestamp < minTimestamp || rawTimestamp > maxTimestamp) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: value out of reasonable range' })\n }\n timestamp = new Date(rawTimestamp).toISOString()\n } else if (typeof rawTimestamp === 'string') {\n if (!isValidISOTimestamp(rawTimestamp)) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be a valid ISO 8601 datetime string' })\n }\n timestamp = rawTimestamp\n } else {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be string or number' })\n }\n\n if (!body.level || typeof body.level !== 'string') {\n throw createError({ statusCode: 400, message: 'Missing required field: level' })\n }\n\n if (!isLogLevel(body.level)) {\n throw createError({ statusCode: 400, message: `Invalid level: must be one of ${VALID_LEVELS.join(', ')}` })\n }\n\n return {\n ...body,\n timestamp,\n level: body.level,\n }\n}\n\nfunction getSafeHeaders(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\ninterface WaitUntilHost {\n waitUntil?: (promise: Promise<unknown>) => void\n}\n\nfunction hasWaitUntil(value: unknown): value is WaitUntilHost & { waitUntil: (promise: Promise<unknown>) => void } {\n return isRecord(value) && typeof value.waitUntil === 'function'\n}\n\n/** Resolve platform waitUntil from Nitro event context (Cloudflare Workers, Vercel Edge). */\nfunction resolveWaitUntilContext(event: unknown): WaitUntilHost | undefined {\n if (!isRecord(event)) return undefined\n const { context } = event\n if (!isRecord(context)) return undefined\n const { cloudflare } = context\n if (isRecord(cloudflare) && isRecord(cloudflare.context)) {\n return cloudflare.context\n }\n return context\n}\n\nexport default defineEventHandler(async (event) => {\n validateOrigin(event)\n\n const body = await readBody(event)\n const payload = validatePayload(body)\n const nitroApp = useNitroApp()\n const env = getEnvironment()\n\n const { service: _clientService, ...sanitizedPayload } = payload\n\n const wideEvent: WideEvent = {\n ...sanitizedPayload,\n ...env,\n source: 'client',\n }\n\n const headers = getSafeHeaders(event)\n const request = { method: 'POST' as const, path: event.path }\n const runner = getGlobalPluginRunner()\n\n if (runner.hasClientLog) {\n runner.runOnClientLog({\n payload,\n request,\n headers,\n })\n }\n\n const enrichCtx = {\n event: wideEvent,\n request,\n headers,\n response: { status: 204 },\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: wideEvent,\n request,\n 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)\n // Otherwise, await the drain to prevent lost logs in serverless environments\n const waitUntilCtx = resolveWaitUntilContext(event)\n if (waitUntilCtx && hasWaitUntil(waitUntilCtx)) {\n waitUntilCtx.waitUntil(drainPromise)\n } else {\n await drainPromise\n }\n\n setResponseStatus(event, 204)\n return null\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"ingest.post.mjs","names":[],"sources":["../../../../../src/runtime/server/routes/_evlog/ingest.post.ts"],"sourcesContent":["import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readRawBody, setResponseStatus } from 'h3'\nimport { useNitroApp } from 'nitropack/runtime'\nimport type { IngestPayload, WideEvent } from '../../../../types'\nimport { getEnvironment, getGlobalPluginRunner } from '../../../../logger'\nimport { filterSafeHeaders } from '../../../../utils'\n\nconst VALID_LEVELS = ['info', 'error', 'warn', 'debug'] as const\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isLogLevel(value: string): value is IngestPayload['level'] {\n return (VALID_LEVELS as readonly string[]).includes(value)\n}\n\nfunction validateOrigin(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): void {\n const origin = getHeader(event, 'origin')\n const referer = getHeader(event, 'referer')\n const host = getRequestHost(event)\n\n const requestOrigin = origin || (referer ? new URL(referer).origin : null)\n\n if (!requestOrigin) {\n throw createError({ statusCode: 403, message: 'Missing origin header' })\n }\n\n const originHost = new URL(requestOrigin).host\n\n if (originHost !== host) {\n throw createError({ statusCode: 403, message: 'Invalid origin' })\n }\n}\n\n/**\n * Maximum accepted ingest body size in bytes. Client wide events are small;\n * anything larger is rejected before it reaches the enrich/drain pipeline.\n */\nconst MAX_BODY_BYTES = 32 * 1024\n\nasync function readJsonBody(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): Promise<unknown> {\n const contentLength = Number(getHeader(event, 'content-length'))\n if (Number.isFinite(contentLength) && contentLength > MAX_BODY_BYTES) {\n throw createError({ statusCode: 413, message: 'Payload too large' })\n }\n\n const raw = await readRawBody(event, 'utf8')\n if (!raw) {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n // Measure actual UTF-8 bytes so multi-byte payloads can't slip past the cap.\n if (new TextEncoder().encode(raw).byteLength > MAX_BODY_BYTES) {\n throw createError({ statusCode: 413, message: 'Payload too large' })\n }\n\n try {\n return JSON.parse(raw)\n } catch {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n}\n\n// ISO 8601 datetime pattern (e.g., 2024-01-31T14:00:00.000Z)\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/\n\nfunction isValidISOTimestamp(value: string): boolean {\n if (!ISO_8601_REGEX.test(value)) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nfunction validatePayload(body: unknown): IngestPayload {\n if (!isRecord(body)) {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n\n if (body.timestamp === undefined || body.timestamp === null) {\n throw createError({ statusCode: 400, message: 'Missing required field: timestamp' })\n }\n\n const { timestamp: rawTimestamp } = body\n let timestamp: string\n if (typeof rawTimestamp === 'number') {\n const minTimestamp = new Date('2000-01-01').getTime()\n const maxTimestamp = Date.now() + 24 * 60 * 60 * 1000 // 1 day in the future\n if (rawTimestamp < minTimestamp || rawTimestamp > maxTimestamp) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: value out of reasonable range' })\n }\n timestamp = new Date(rawTimestamp).toISOString()\n } else if (typeof rawTimestamp === 'string') {\n if (!isValidISOTimestamp(rawTimestamp)) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be a valid ISO 8601 datetime string' })\n }\n timestamp = rawTimestamp\n } else {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be string or number' })\n }\n\n if (!body.level || typeof body.level !== 'string') {\n throw createError({ statusCode: 400, message: 'Missing required field: level' })\n }\n\n if (!isLogLevel(body.level)) {\n throw createError({ statusCode: 400, message: `Invalid level: must be one of ${VALID_LEVELS.join(', ')}` })\n }\n\n return {\n ...body,\n timestamp,\n level: body.level,\n }\n}\n\nfunction getSafeHeaders(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\ninterface WaitUntilHost {\n waitUntil?: (promise: Promise<unknown>) => void\n}\n\nfunction hasWaitUntil(value: unknown): value is WaitUntilHost & { waitUntil: (promise: Promise<unknown>) => void } {\n return isRecord(value) && typeof value.waitUntil === 'function'\n}\n\n/** Resolve platform waitUntil from Nitro event context (Cloudflare Workers, Vercel Edge). */\nfunction resolveWaitUntilContext(event: unknown): WaitUntilHost | undefined {\n if (!isRecord(event)) return undefined\n const { context } = event\n if (!isRecord(context)) return undefined\n const { cloudflare } = context\n if (isRecord(cloudflare) && isRecord(cloudflare.context)) {\n return cloudflare.context\n }\n return context\n}\n\n/**\n * Client log ingestion endpoint.\n *\n * The origin check is CSRF-level protection only: it blocks cross-site browser\n * requests but is trivially satisfied by non-browser clients. Treat ingested\n * events as untrusted input — this endpoint is intentionally unauthenticated.\n */\nexport default defineEventHandler(async (event) => {\n validateOrigin(event)\n\n const body = await readJsonBody(event)\n const payload = validatePayload(body)\n const nitroApp = useNitroApp()\n const env = getEnvironment()\n\n const { service: _clientService, ...sanitizedPayload } = payload\n\n const wideEvent: WideEvent = {\n ...sanitizedPayload,\n ...env,\n source: 'client',\n }\n\n const headers = getSafeHeaders(event)\n const request = { method: 'POST' as const, path: event.path }\n const runner = getGlobalPluginRunner()\n\n if (runner.hasClientLog) {\n runner.runOnClientLog({\n payload,\n request,\n headers,\n })\n }\n\n const enrichCtx = {\n event: wideEvent,\n request,\n headers,\n response: { status: 204 },\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: wideEvent,\n request,\n 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)\n // Otherwise, await the drain to prevent lost logs in serverless environments\n const waitUntilCtx = resolveWaitUntilContext(event)\n if (waitUntilCtx && hasWaitUntil(waitUntilCtx)) {\n waitUntilCtx.waitUntil(drainPromise)\n } else {\n await drainPromise\n }\n\n setResponseStatus(event, 204)\n return null\n})\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { t as useLogger } from "../../useLogger-CqvH6qOf.mjs";
1
+ import { t as useLogger } from "../../useLogger-Cfv8Ck8b.mjs";
2
2
  export { useLogger };
@@ -1,3 +1,3 @@
1
- import { J as ParsedError } from "../../audit-DVdkntSO.mjs";
2
- import { t as parseError } from "../../parseError-D4PIxEWo.mjs";
1
+ import { Q as ParsedError } from "../../audit-D7v6JHj0.mjs";
2
+ import { t as parseError } from "../../parseError-BeBXEd2V.mjs";
3
3
  export { ParsedError, parseError };
@@ -1,4 +1,4 @@
1
- import { t as extractErrorStatus } from "../../errors-BQgyQ9xe.mjs";
1
+ import { t as extractErrorStatus } from "../../errors-DA0cyr8q.mjs";
2
2
  //#region src/runtime/utils/parseError.ts
3
3
  function pickCode(value) {
4
4
  if (value && typeof value === "object" && "code" in value) {
@@ -18,4 +18,4 @@ const OTEL_SEVERITY_TEXT = {
18
18
  //#endregion
19
19
  export { OTEL_SEVERITY_TEXT as n, OTEL_SEVERITY_NUMBER as t };
20
20
 
21
- //# sourceMappingURL=severity-R5Egq3qz.mjs.map
21
+ //# sourceMappingURL=severity-CwXUSHt3.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"severity-R5Egq3qz.mjs","names":[],"sources":["../src/shared/severity.ts"],"sourcesContent":["import type { LogLevel } from '../types'\n\n/**\n * OpenTelemetry severity numbers per evlog log level.\n * @see https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber\n */\nexport const OTEL_SEVERITY_NUMBER: Record<LogLevel, number> = {\n debug: 5,\n info: 9,\n warn: 13,\n error: 17,\n}\n\nexport const OTEL_SEVERITY_TEXT: Record<LogLevel, string> = {\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARN',\n error: 'ERROR',\n}\n"],"mappings":";;;;;AAMA,MAAa,uBAAiD;CAC5D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,MAAa,qBAA+C;CAC1D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR"}
1
+ {"version":3,"file":"severity-CwXUSHt3.mjs","names":[],"sources":["../src/shared/severity.ts"],"sourcesContent":["import type { LogLevel } from '../types'\n\n/**\n * OpenTelemetry severity numbers per evlog log level.\n * @see https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber\n */\nexport const OTEL_SEVERITY_NUMBER: Record<LogLevel, number> = {\n debug: 5,\n info: 9,\n warn: 13,\n error: 17,\n}\n\nexport const OTEL_SEVERITY_TEXT: Record<LogLevel, string> = {\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARN',\n error: 'ERROR',\n}\n"],"mappings":";;;;;AAMA,MAAa,uBAAiD;CAC5D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,MAAa,qBAA+C;CAC1D,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR"}
@@ -1115,6 +1115,7 @@ function createSourceLocationPlugin(enabled) {
1115
1115
  configResolved({ command, root: configRoot }) {
1116
1116
  active = enabled ?? command === "serve";
1117
1117
  root = configRoot;
1118
+ if (enabled === true && command === "build") console.warn("[evlog] sourceLocation is enabled for a production build: source file paths will be embedded in the client bundle.");
1118
1119
  },
1119
1120
  transform: {
1120
1121
  filter: {
@@ -1162,4 +1163,4 @@ function createSourceLocationPlugin(enabled) {
1162
1163
  //#endregion
1163
1164
  export { walk as a, shouldTransform as i, createStripPlugin as n, MagicString as o, TRANSFORM_FILTER as r, createSourceLocationPlugin as t };
1164
1165
 
1165
- //# sourceMappingURL=source-location-Dco0cRTz.mjs.map
1166
+ //# sourceMappingURL=source-location-CHOPF2nd.mjs.map