evlog 2.17.0 → 2.18.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.
- package/README.md +95 -2
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +2 -2
- package/dist/adapters/axiom.mjs.map +1 -1
- package/dist/adapters/better-stack.d.mts +1 -1
- package/dist/adapters/better-stack.mjs +2 -2
- package/dist/adapters/datadog.d.mts +1 -1
- package/dist/adapters/datadog.mjs +2 -2
- package/dist/adapters/fs.d.mts +1 -1
- package/dist/adapters/fs.mjs +1 -1
- package/dist/adapters/hyperdx.d.mts +1 -1
- package/dist/adapters/hyperdx.mjs +1 -1
- package/dist/adapters/memory.d.mts +116 -0
- package/dist/adapters/memory.d.mts.map +1 -0
- package/dist/adapters/memory.mjs +191 -0
- package/dist/adapters/memory.mjs.map +1 -0
- package/dist/adapters/otlp.d.mts +1 -1
- package/dist/adapters/otlp.mjs +2 -2
- package/dist/adapters/posthog.d.mts +1 -1
- package/dist/adapters/posthog.mjs +2 -2
- package/dist/adapters/sentry.d.mts +1 -1
- package/dist/adapters/sentry.mjs +2 -2
- package/dist/ai/index.d.mts +1 -1
- package/dist/{audit-pV5aLGP0.mjs → audit-BUI3af4w.mjs} +121 -53
- package/dist/audit-BUI3af4w.mjs.map +1 -0
- package/dist/{audit-CC8nfazi.d.mts → audit-DVdkntSO.d.mts} +21 -1
- package/dist/audit-DVdkntSO.d.mts.map +1 -0
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{define-MSdhzmXn.d.mts → define-D-BVMf2l.d.mts} +3 -3
- package/dist/{define-MSdhzmXn.d.mts.map → define-D-BVMf2l.d.mts.map} +1 -1
- package/dist/define-D6OJdSUH.mjs.map +1 -1
- package/dist/{drain-X7_5szSI.mjs → drain-7n3K6kPe.mjs} +3 -3
- package/dist/drain-7n3K6kPe.mjs.map +1 -0
- package/dist/elysia/index.d.mts +2 -2
- package/dist/elysia/index.mjs +2 -2
- package/dist/{enricher-DxgML6IC.d.mts → enricher-UW9npoB2.d.mts} +2 -2
- package/dist/{enricher-DxgML6IC.d.mts.map → enricher-UW9npoB2.d.mts.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/{error-CpbbtyXL.d.mts → error-CVtn5U7b.d.mts} +2 -2
- package/dist/{error-CpbbtyXL.d.mts.map → error-CVtn5U7b.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-DySW1F9_.d.mts → errors-dEMNQCiL.d.mts} +2 -2
- package/dist/{errors-DySW1F9_.d.mts.map → errors-dEMNQCiL.d.mts.map} +1 -1
- package/dist/express/index.d.mts +3 -3
- package/dist/express/index.d.mts.map +1 -1
- package/dist/express/index.mjs +2 -2
- package/dist/express/index.mjs.map +1 -1
- package/dist/fastify/index.d.mts +9 -4
- package/dist/fastify/index.d.mts.map +1 -1
- package/dist/fastify/index.mjs +10 -8
- package/dist/fastify/index.mjs.map +1 -1
- package/dist/{fork-8u_zFOJq.mjs → fork-Bga8x-X4.mjs} +3 -2
- package/dist/fork-Bga8x-X4.mjs.map +1 -0
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.mjs +1 -1
- package/dist/{http-6umVAKDW.mjs → http-B6YgAhyN.mjs} +2 -2
- package/dist/{http-6umVAKDW.mjs.map → http-B6YgAhyN.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/{index-o1_z4phv.d.mts → index-ZSRQP_BI.d.mts} +3 -3
- package/dist/{index-o1_z4phv.d.mts.map → index-ZSRQP_BI.d.mts.map} +1 -1
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{integration-DTZtjSqh.mjs → integration-Dhig7ae6.mjs} +2 -2
- package/dist/{integration-DTZtjSqh.mjs.map → integration-Dhig7ae6.mjs.map} +1 -1
- package/dist/{logger-DntcxxHg.d.mts → logger-CTcvd5Cc.d.mts} +7 -3
- package/dist/logger-CTcvd5Cc.d.mts.map +1 -0
- package/dist/logger.d.mts +2 -2
- package/dist/logger.mjs +2 -2
- package/dist/{middleware-U-lIAzHg.d.mts → middleware-31KhtiEF.d.mts} +2 -2
- package/dist/{middleware-U-lIAzHg.d.mts.map → middleware-31KhtiEF.d.mts.map} +1 -1
- package/dist/nestjs/index.d.mts +2 -2
- package/dist/nestjs/index.mjs +2 -2
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +6 -5
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +3 -3
- package/dist/next/index.mjs.map +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/instrumentation.mjs +1 -1
- package/dist/next/instrumentation.mjs.map +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/module.d.mts.map +1 -1
- package/dist/nitro/module.mjs +7 -2
- package/dist/nitro/module.mjs.map +1 -1
- package/dist/nitro/plugin.mjs +3 -2
- package/dist/nitro/plugin.mjs.map +1 -1
- package/dist/nitro/v3/index.d.mts +2 -2
- package/dist/nitro/v3/module.d.mts +1 -1
- package/dist/nitro/v3/module.d.mts.map +1 -1
- package/dist/nitro/v3/module.mjs +9 -4
- package/dist/nitro/v3/module.mjs.map +1 -1
- package/dist/nitro/v3/plugin.mjs +3 -2
- package/dist/nitro/v3/plugin.mjs.map +1 -1
- package/dist/nitro/v3/useLogger.d.mts +1 -1
- package/dist/{nitro-oZre8ab3.d.mts → nitro-BRddgqSb.d.mts} +2 -2
- package/dist/{nitro-oZre8ab3.d.mts.map → nitro-BRddgqSb.d.mts.map} +1 -1
- package/dist/nitroConfigBridge-NbFn-sIK.mjs +157 -0
- package/dist/nitroConfigBridge-NbFn-sIK.mjs.map +1 -0
- package/dist/nuxt/module.d.mts +8 -4
- package/dist/nuxt/module.d.mts.map +1 -1
- package/dist/nuxt/module.mjs +1 -1
- package/dist/nuxt/module.mjs.map +1 -1
- package/dist/orpc/index.d.mts +115 -0
- package/dist/orpc/index.d.mts.map +1 -0
- package/dist/orpc/index.mjs +144 -0
- package/dist/orpc/index.mjs.map +1 -0
- package/dist/{package-v_MmOZeA.mjs → package-B23bR3tK.mjs} +2 -2
- package/dist/package-B23bR3tK.mjs.map +1 -0
- package/dist/{parseError-yVZ58wIK.d.mts → parseError-D4PIxEWo.d.mts} +2 -2
- package/dist/parseError-D4PIxEWo.d.mts.map +1 -0
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +2 -2
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +28 -12
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/{storage-Dwinmg8P.mjs → storage-BNubsWwz.mjs} +2 -1
- package/dist/{storage-Dwinmg8P.mjs.map → storage-BNubsWwz.mjs.map} +1 -1
- package/dist/stream.d.mts +1 -1
- package/dist/stream.mjs +1 -1
- package/dist/sveltekit/index.d.mts +3 -3
- package/dist/sveltekit/index.d.mts.map +1 -1
- package/dist/sveltekit/index.mjs +43 -10
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +6 -6
- package/dist/toolkit.mjs +6 -6
- package/dist/types.d.mts +1 -1
- package/dist/{useLogger-BsPL4AQm.d.mts → useLogger-CqvH6qOf.d.mts} +2 -2
- package/dist/{useLogger-BsPL4AQm.d.mts.map → useLogger-CqvH6qOf.d.mts.map} +1 -1
- package/dist/{utils-DLCeShxL.d.mts → utils-DxqvIOyR.d.mts} +12 -3
- package/dist/{utils-DLCeShxL.d.mts.map → utils-DxqvIOyR.d.mts.map} +1 -1
- package/dist/utils.d.mts +1 -1
- package/dist/utils.mjs +10 -1
- package/dist/utils.mjs.map +1 -1
- package/dist/vite/index.d.mts +1 -1
- package/dist/workers.d.mts +1 -1
- package/dist/workers.mjs +1 -1
- package/package.json +48 -15
- package/dist/audit-CC8nfazi.d.mts.map +0 -1
- package/dist/audit-pV5aLGP0.mjs.map +0 -1
- package/dist/drain-X7_5szSI.mjs.map +0 -1
- package/dist/fork-8u_zFOJq.mjs.map +0 -1
- package/dist/logger-DntcxxHg.d.mts.map +0 -1
- package/dist/nitroConfigBridge-DKk7eOn-.mjs +0 -92
- package/dist/nitroConfigBridge-DKk7eOn-.mjs.map +0 -1
- package/dist/package-v_MmOZeA.mjs.map +0 -1
- package/dist/parseError-yVZ58wIK.d.mts.map +0 -1
|
@@ -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 } 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 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":"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"}
|
|
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":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as createError, t as EvlogError } from "../../error-
|
|
2
|
-
import { t as parseError } from "../../parseError-
|
|
1
|
+
import { n as createError, t as EvlogError } from "../../error-CVtn5U7b.mjs";
|
|
2
|
+
import { t as parseError } from "../../parseError-D4PIxEWo.mjs";
|
|
3
3
|
import evlog from "./module.mjs";
|
|
4
4
|
import { useLogger } from "./useLogger.mjs";
|
|
5
5
|
import { evlogErrorHandler } from "./middleware.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.mts","names":[],"sources":["../../../src/nitro-v3/module.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"module.d.mts","names":[],"sources":["../../../src/nitro-v3/module.ts"],"mappings":";;;;iBAiBwB,KAAA,CAAM,OAAA,GAAU,kBAAA;;eAGvB,KAAA;AAAA"}
|
package/dist/nitro/v3/module.mjs
CHANGED
|
@@ -2,19 +2,24 @@ import { dirname, resolve } from "node:path";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
//#region src/nitro-v3/module.ts
|
|
4
4
|
const _dir = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
function resolveModulePath(name) {
|
|
6
|
+
return resolve(_dir, name).replace(/\\/g, "/");
|
|
7
|
+
}
|
|
5
8
|
function evlog(options) {
|
|
6
9
|
return {
|
|
7
10
|
name: "evlog",
|
|
8
11
|
setup(nitro) {
|
|
9
12
|
nitro.options.plugins = nitro.options.plugins || [];
|
|
10
|
-
nitro.options.plugins.push(
|
|
13
|
+
nitro.options.plugins.push(resolveModulePath("plugin"));
|
|
11
14
|
if (!nitro.options.noExternals) nitro.options.noExternals = ["evlog"];
|
|
12
15
|
else if (Array.isArray(nitro.options.noExternals)) nitro.options.noExternals.push("evlog");
|
|
13
|
-
if (!nitro.options.errorHandler) nitro.options.errorHandler = [
|
|
14
|
-
else if (Array.isArray(nitro.options.errorHandler)) nitro.options.errorHandler.unshift(
|
|
15
|
-
else if (typeof nitro.options.errorHandler === "string") nitro.options.errorHandler = [
|
|
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];
|
|
16
19
|
nitro.options.runtimeConfig = nitro.options.runtimeConfig || {};
|
|
17
20
|
nitro.options.runtimeConfig.evlog = options || {};
|
|
21
|
+
nitro.options.replace = nitro.options.replace || {};
|
|
22
|
+
nitro.options.replace.__EVLOG_CONFIG__ = JSON.stringify(options || {});
|
|
18
23
|
process.env.__EVLOG_CONFIG = JSON.stringify(options || {});
|
|
19
24
|
}
|
|
20
25
|
};
|
|
@@ -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\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(
|
|
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"}
|
package/dist/nitro/v3/plugin.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as initLogger, g as createRequestLogger, j as normalizeRedactConfig, x as isEnabled, y as getGlobalPluginRunner } from "../../audit-BUI3af4w.mjs";
|
|
2
2
|
import { filterSafeHeaders } from "../../utils.mjs";
|
|
3
3
|
import { t as extractErrorStatus } from "../../errors-BQgyQ9xe.mjs";
|
|
4
4
|
import { n as shouldLog, t as getServiceForPath } from "../../routes-CnIgYWf8.mjs";
|
|
5
|
-
import { n as resolveEvlogConfigForNitroPlugin } from "../../nitroConfigBridge-
|
|
5
|
+
import { n as resolveEvlogConfigForNitroPlugin, r as setActiveNitroRuntime } from "../../nitroConfigBridge-NbFn-sIK.mjs";
|
|
6
6
|
import { t as parseURL } from "../../dist-H3GIh-KK.mjs";
|
|
7
7
|
import { definePlugin } from "nitro";
|
|
8
8
|
//#region src/nitro-v3/plugin.ts
|
|
@@ -89,6 +89,7 @@ async function callEnrichAndDrain(hooks, emittedEvent, event, res) {
|
|
|
89
89
|
* ```
|
|
90
90
|
*/
|
|
91
91
|
var plugin_default = definePlugin(async (nitroApp) => {
|
|
92
|
+
setActiveNitroRuntime("v3");
|
|
92
93
|
const evlogConfig = await resolveEvlogConfigForNitroPlugin();
|
|
93
94
|
const redact = normalizeRedactConfig(evlogConfig?.redact);
|
|
94
95
|
initLogger({
|
|
@@ -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 } 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 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 } 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":";;;;;;;;AA4BA,SAAS,WAAW,OAA2C;AAC7D,KAAI,CAAC,MAAM,IAAI,QACb,OAAM,IAAI,UAAU,EAAE;AAExB,QAAO,MAAM,IAAI;;AAGnB,SAAS,sBAAsB,OAA0C;CACvE,MAAM,UAAkC,EAAE;AAC1C,OAAM,IAAI,QAAQ,SAAS,OAAO,QAAQ;AACxC,UAAQ,OAAO;GACf;AACF,QAAO,kBAAkB,QAAQ;;AAGnC,SAAS,uBAAuB,KAAmD;CACjF,MAAM,UAAkC,EAAE;AAC1C,KAAI,QAAQ,SAAS,OAAO,QAAQ;AAClC,UAAQ,OAAO;GACf;AACF,KAAI,OAAO,KAAK,QAAQ,CAAC,WAAW,EAAG,QAAO,KAAA;AAC9C,QAAO,kBAAkB,QAAQ;;AAGnC,SAAS,iBACP,OACA,KAC8B;CAC9B,MAAM,EAAE,aAAa,SAAS,MAAM,IAAI,IAAI;CAC5C,MAAM,kBAAkB,MAAM,uBAAuB,IAAI,GAAG,KAAA;AAC5D,QAAO;EACL,SAAS;GAAE,QAAQ,MAAM,IAAI;GAAQ,MAAM;GAAU;EACrD,SAAS,sBAAsB,MAAM;EACrC,UAAU;GACR,QAAQ,KAAK,UAAU;GACvB,SAAS;GACV;EACF;;AAGH,eAAe,cACb,OACA,cACA,OACA,aACe;AACf,KAAI,CAAC,aAAc;CAEnB,MAAM,WAAW;EACf,OAAO;EACP,SAAS,YAAY;EACrB,SAAS,YAAY;EACtB;CAED,MAAM,aAAsC,EAAE;AAC9C,KAAI;EACF,MAAM,SAAS,MAAM,SAAS,eAAe,SAAS;AACtD,MAAI,QAAQ,MACV,YAAW,KACT,OAAO,OAAO,QAAiB;AAC7B,WAAQ,MAAM,yBAAyB,IAAI;IAC3C,CACH;UAEI,KAAK;AACZ,UAAQ,MAAM,yBAAyB,IAAI;;CAG7C,MAAM,SAAS,uBAAuB;AACtC,KAAI,OAAO,SACT,YAAW,KAAK,OAAO,SAAS,SAAS,CAAC;AAG5C,KAAI,WAAW,WAAW,EAAG;CAC7B,MAAM,eAAe,QAAQ,IAAI,WAAW;AAI5C,KAAI,OAAO,MAAM,IAAI,cAAc,WACjC,OAAM,IAAI,UAAU,aAAa;KAMjC,OAAM;;AAIV,eAAe,mBACb,OACA,cACA,OACA,KACe;AACf,KAAI,CAAC,aAAc;CAEnB,MAAM,cAAc,iBAAiB,OAAO,IAAI;CAChD,MAAM,YAA2B;EAAE,OAAO;EAAc,GAAG;EAAa;AAExE,KAAI;AACF,QAAM,MAAM,SAAS,gBAAgB,UAAU;UACxC,KAAK;AACZ,UAAQ,MAAM,0BAA0B,IAAI;;CAG9C,MAAM,SAAS,uBAAuB;AACtC,KAAI,OAAO,UACT,OAAM,OAAO,UAAU,UAAU;AAGnC,OAAM,cAAc,OAAO,cAAc,OAAO,YAAY;;;;;;;;;;;AAY9D,IAAA,iBAAe,aAAa,OAAO,aAAa;AAC9C,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;CAEF,MAAM,QAAQ,SAAS;AAIvB,KAAI,CAAC,WAAW,EAAE;AAChB,QAAM,KAAK,YAAY,UAAU;GAC/B,MAAM,EAAE,aAAa,SAAS,MAAM,IAAI,IAAI;GAC5C,MAAM,MAAM,WAAW,MAAM;GAC7B,IAAI;AACJ,OAAI,WAAW,WAAW,cAAc,sBAAsB;IAC5D,MAAM,QAAQ,MAAM,IAAI,QAAQ,IAAI,SAAS;AAC7C,QAAI,MAAO,qBAAoB;;AAEjC,OAAI,MAAM,oBAAoB;IAC5B,QAAQ,MAAM,IAAI;IAClB,MAAM;IACN,WAAW,qBAAqB,IAAI,aAAmC,OAAO,YAAY;IAC3F,EAAE,EAAE,aAAa,MAAM,CAAC;IACzB;AACF;;AAGF,OAAM,KAAK,YAAY,UAAU;EAC/B,MAAM,EAAE,aAAa,SAAS,MAAM,IAAI,IAAI;EAC5C,MAAM,MAAM,WAAW,MAAM;AAK7B,MAAI,mBAAmB,UAAU,UAAU,aAAa,SAAS,aAAa,QAAQ;AAGtF,MAAI,kBAAkB,KAAK,KAAK;EAEhC,IAAI,oBAAwC,KAAA;AAC5C,MAAI,WAAW,WAAW,cAAc,sBAAsB;GAC5D,MAAM,QAAQ,MAAM,IAAI,QAAQ,IAAI,SAAS;AAC7C,OAAI,MAAO,qBAAoB;;EAGjC,MAAM,MAAM,oBAAoB;GAC9B,QAAQ,MAAM,IAAI;GAClB,MAAM;GACN,WAAW,qBAAqB,IAAI,aAAmC,OAAO,YAAY;GAC3F,EAAE,EAAE,aAAa,MAAM,CAAC;EAGzB,MAAM,eAAe,kBAAkB,UAAU,aAAa,OAAO;AACrE,MAAI,aACF,KAAI,IAAI,EAAE,SAAS,cAAc,CAAC;AAGpC,MAAI,MAAM;GACV;AAEF,OAAM,KAAK,YAAY,OAAO,KAAK,UAAU;EAC3C,MAAM,MAAM,MAAM,IAAI;AAEtB,MAAI,KAAK,iBAAiB,CAAC,KAAK,iBAAkB;EAElD,MAAM,MAAM,KAAK;AACjB,MAAI,CAAC,OAAO,CAAC,IAAK;EAElB,MAAM,EAAE,WAAW;AACnB,MAAI,IAAI,EAAE,QAAQ,CAAC;EAEnB,MAAM,YAAY,IAAI;EACtB,MAAM,aAAa,YAAY,KAAK,KAAK,GAAG,YAAY,KAAA;EAExD,MAAM,EAAE,aAAa,SAAS,MAAM,IAAI,IAAI;EAE5C,MAAM,UAA+B;GACnC;GACA,UAAU;GACV,MAAM;GACN,QAAQ,MAAM,IAAI;GAClB,SAAS,IAAI,YAAY;GACzB,YAAY;GACb;AAED,QAAM,MAAM,SAAS,mBAAmB,QAAQ;EAChD,MAAM,SAAS,uBAAuB;AACtC,MAAI,OAAO,QAAS,OAAM,OAAO,QAAQ,QAAQ;AAGjD,QAAM,mBAAmB,OADJ,IAAI,KAAK,EAAE,YAAY,QAAQ,YAAY,CACpB,EAAE,OAAO,IAAI;GACzD;AAEF,OAAM,KAAK,SAAS,OAAO,OAAO,EAAE,YAAY;AAC9C,MAAI,CAAC,MAAO;EACZ,MAAM,IAAI;EAEV,MAAM,MAAM,EAAE,IAAI;AAClB,MAAI,CAAC,KAAK,iBAAkB;EAC5B,MAAM,MAAM,IAAI;AAChB,MAAI,CAAC,IAAK;EAGV,MAAM,cAAe,MAAM,OAAiB,SAAS,eACjD,MAAM,QACN;AAEJ,MAAI,MAAM,YAAY;EAEtB,MAAM,cAAc,mBAAmB,YAAY;AACnD,MAAI,IAAI,EAAE,QAAQ,aAAa,CAAC;EAEhC,MAAM,EAAE,aAAa,SAAS,EAAE,IAAI,IAAI;EACxC,MAAM,YAAY,IAAI;EAGtB,MAAM,UAA+B;GACnC,QAAQ;GACR,UAJiB,YAAY,KAAK,KAAK,GAAG,YAAY,KAAA;GAKtD,MAAM;GACN,QAAQ,EAAE,IAAI;GACd,SAAS,IAAI,YAAY;GACzB,YAAY;GACb;AAED,QAAM,MAAM,SAAS,mBAAmB,QAAQ;EAChD,MAAM,SAAS,uBAAuB;AACtC,MAAI,OAAO,QAAS,OAAM,OAAO,QAAQ,QAAQ;AAEjD,MAAI,gBAAgB;AAGpB,QAAM,mBAAmB,OADJ,IAAI,KAAK,EAAE,YAAY,QAAQ,YAAY,CACpB,EAAE,EAAE;GAChD;EACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as LogLevel, R as EnvironmentContext, Y as RedactConfig, nt as SamplingConfig, tt as RouteConfig } from "./audit-
|
|
1
|
+
import { K as LogLevel, R as EnvironmentContext, Y as RedactConfig, nt as SamplingConfig, tt as RouteConfig } from "./audit-DVdkntSO.mjs";
|
|
2
2
|
//#region src/nitro.d.ts
|
|
3
3
|
interface NitroModuleOptions {
|
|
4
4
|
/**
|
|
@@ -57,4 +57,4 @@ interface NitroModuleOptions {
|
|
|
57
57
|
}
|
|
58
58
|
//#endregion
|
|
59
59
|
export { NitroModuleOptions as t };
|
|
60
|
-
//# sourceMappingURL=nitro-
|
|
60
|
+
//# sourceMappingURL=nitro-BRddgqSb.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nitro-
|
|
1
|
+
{"version":3,"file":"nitro-BRddgqSb.d.mts","names":[],"sources":["../src/nitro.ts"],"mappings":";;UAKiB,kBAAA;;AAAjB;;;EAKE,OAAA;EAKM;;;EAAN,GAAA,GAAM,OAAA,CAAQ,kBAAA;EA8CH;;;;EAxCX,MAAA;EANA;;;;;;;EAeA,MAAA;EAmBS;;;;;EAZT,OAAA;EA8BA;;;;;EAvBA,OAAA;;;;EAKA,MAAA,GAAS,MAAA,SAAe,WAAA;;;;EAKxB,QAAA,GAAW,cAAA;;;;;;EAOX,QAAA,GAAW,QAAA;;;;;EAMX,MAAA,aAAmB,YAAA;AAAA"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
//#region src/shared/nitroConfigBridge.ts
|
|
2
|
+
const EVLOG_NITRO_ENV = "__EVLOG_CONFIG";
|
|
3
|
+
/** Build-time inlined config, or `undefined` if the bundle was not produced by an evlog Nitro module. */
|
|
4
|
+
function readEvlogConfigFromInline() {
|
|
5
|
+
if (typeof __EVLOG_CONFIG__ === "undefined") return void 0;
|
|
6
|
+
if (__EVLOG_CONFIG__ === null || typeof __EVLOG_CONFIG__ !== "object") return void 0;
|
|
7
|
+
return __EVLOG_CONFIG__;
|
|
8
|
+
}
|
|
9
|
+
let activeNitroRuntime;
|
|
10
|
+
/**
|
|
11
|
+
* Declare the active Nitro major version so adapters never probe the other
|
|
12
|
+
* version's modules at runtime. The evlog Nitro plugins call this in their
|
|
13
|
+
* first synchronous statement.
|
|
14
|
+
*
|
|
15
|
+
* Bun's auto-install behavior writes to `node_modules/.cache` whenever a
|
|
16
|
+
* dynamic import targets a missing package, which crashes on Vercel's
|
|
17
|
+
* read-only function filesystem. Restricting probes to the runtime that is
|
|
18
|
+
* actually installed avoids that path entirely.
|
|
19
|
+
*/
|
|
20
|
+
function setActiveNitroRuntime(version) {
|
|
21
|
+
activeNitroRuntime = version;
|
|
22
|
+
}
|
|
23
|
+
function nitroV3RuntimeConfigSpecifier() {
|
|
24
|
+
return ["nitro", "runtime-config"].join("/");
|
|
25
|
+
}
|
|
26
|
+
function nitropackRuntimeSpecifier() {
|
|
27
|
+
return ["nitropack", "runtime"].join("/");
|
|
28
|
+
}
|
|
29
|
+
function nitropackInternalRuntimeConfigSpecifier() {
|
|
30
|
+
return [
|
|
31
|
+
"nitropack",
|
|
32
|
+
"runtime",
|
|
33
|
+
"internal",
|
|
34
|
+
"config"
|
|
35
|
+
].join("/");
|
|
36
|
+
}
|
|
37
|
+
async function importOrNull(specifier) {
|
|
38
|
+
try {
|
|
39
|
+
return await import(specifier);
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isRuntimeConfigModule(mod) {
|
|
45
|
+
return typeof mod === "object" && mod !== null && "useRuntimeConfig" in mod && typeof mod.useRuntimeConfig === "function";
|
|
46
|
+
}
|
|
47
|
+
/** Snapshot from env, or `undefined` if unset / invalid JSON. */
|
|
48
|
+
function readEvlogConfigFromNitroEnv() {
|
|
49
|
+
const raw = process.env[EVLOG_NITRO_ENV];
|
|
50
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(raw);
|
|
53
|
+
} catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
let cachedNitropackRuntime;
|
|
58
|
+
let cachedNitroV3Runtime;
|
|
59
|
+
let cachedNitropackInternalConfig;
|
|
60
|
+
async function getNitropackRuntime() {
|
|
61
|
+
if (cachedNitropackRuntime !== void 0) return cachedNitropackRuntime;
|
|
62
|
+
const mod = await importOrNull(nitropackRuntimeSpecifier());
|
|
63
|
+
cachedNitropackRuntime = isRuntimeConfigModule(mod) ? mod : null;
|
|
64
|
+
return cachedNitropackRuntime;
|
|
65
|
+
}
|
|
66
|
+
async function getNitroV3Runtime() {
|
|
67
|
+
if (cachedNitroV3Runtime !== void 0) return cachedNitroV3Runtime;
|
|
68
|
+
const mod = await importOrNull(nitroV3RuntimeConfigSpecifier());
|
|
69
|
+
cachedNitroV3Runtime = isRuntimeConfigModule(mod) ? mod : null;
|
|
70
|
+
return cachedNitroV3Runtime;
|
|
71
|
+
}
|
|
72
|
+
async function getNitropackInternalRuntimeConfig() {
|
|
73
|
+
if (cachedNitropackInternalConfig !== void 0) return cachedNitropackInternalConfig;
|
|
74
|
+
const mod = await importOrNull(nitropackInternalRuntimeConfigSpecifier());
|
|
75
|
+
cachedNitropackInternalConfig = isRuntimeConfigModule(mod) ? mod : null;
|
|
76
|
+
return cachedNitropackInternalConfig;
|
|
77
|
+
}
|
|
78
|
+
function evlogSlice(config) {
|
|
79
|
+
const { evlog } = config;
|
|
80
|
+
if (evlog && typeof evlog === "object") return evlog;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Options for evlog Nitro plugins (nitropack v2 and Nitro v3).
|
|
84
|
+
*
|
|
85
|
+
* Lookup order:
|
|
86
|
+
* 1. `__EVLOG_CONFIG__` — inlined at build time by the evlog Nitro module.
|
|
87
|
+
* Hits in every deployed bundle and skips runtime probing entirely.
|
|
88
|
+
* 2. `process.env.__EVLOG_CONFIG`
|
|
89
|
+
* 3. The active runtime declared by {@link setActiveNitroRuntime} — either
|
|
90
|
+
* Nitro v3 `runtime-config` or nitropack internal config, never both.
|
|
91
|
+
* 4. When no active runtime has been declared (standalone use): probe v3 then
|
|
92
|
+
* nitropack v2 as a best-effort fallback.
|
|
93
|
+
*/
|
|
94
|
+
async function resolveEvlogConfigForNitroPlugin() {
|
|
95
|
+
const fromInline = readEvlogConfigFromInline();
|
|
96
|
+
if (fromInline !== void 0) return fromInline;
|
|
97
|
+
const fromEnv = readEvlogConfigFromNitroEnv();
|
|
98
|
+
if (fromEnv !== void 0) return fromEnv;
|
|
99
|
+
if (activeNitroRuntime === "v3") {
|
|
100
|
+
const v3 = await getNitroV3Runtime();
|
|
101
|
+
if (v3) {
|
|
102
|
+
const slice = evlogSlice(v3.useRuntimeConfig());
|
|
103
|
+
if (slice !== void 0) return slice;
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (activeNitroRuntime === "v2") {
|
|
108
|
+
const internal = await getNitropackInternalRuntimeConfig();
|
|
109
|
+
if (internal) {
|
|
110
|
+
const slice = evlogSlice(internal.useRuntimeConfig());
|
|
111
|
+
if (slice !== void 0) return slice;
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const v3 = await getNitroV3Runtime();
|
|
116
|
+
if (v3) {
|
|
117
|
+
const slice = evlogSlice(v3.useRuntimeConfig());
|
|
118
|
+
if (slice !== void 0) return slice;
|
|
119
|
+
}
|
|
120
|
+
const internal = await getNitropackInternalRuntimeConfig();
|
|
121
|
+
if (internal) {
|
|
122
|
+
const slice = evlogSlice(internal.useRuntimeConfig());
|
|
123
|
+
if (slice !== void 0) return slice;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Full `useRuntimeConfig()` object for drain adapters.
|
|
128
|
+
*
|
|
129
|
+
* Honors {@link setActiveNitroRuntime}: when a Nitro plugin has declared its
|
|
130
|
+
* version, only that version's runtime module is probed. When no version has
|
|
131
|
+
* been declared (standalone use outside Nitro), falls back to the historical
|
|
132
|
+
* order: nitropack v2 first, then Nitro v3.
|
|
133
|
+
*
|
|
134
|
+
* When `__EVLOG_CONFIG__` was inlined at build time, returns a synthetic
|
|
135
|
+
* `{ evlog: <inlined> }` record so adapters can read `runtimeConfig.evlog.*`
|
|
136
|
+
* without triggering the dynamic import (issue #312).
|
|
137
|
+
*/
|
|
138
|
+
async function getNitroRuntimeConfigRecord() {
|
|
139
|
+
const inline = readEvlogConfigFromInline();
|
|
140
|
+
if (inline !== void 0) return { evlog: inline };
|
|
141
|
+
if (activeNitroRuntime === "v3") {
|
|
142
|
+
const v3 = await getNitroV3Runtime();
|
|
143
|
+
return v3 ? v3.useRuntimeConfig() : void 0;
|
|
144
|
+
}
|
|
145
|
+
if (activeNitroRuntime === "v2") {
|
|
146
|
+
const nitropack = await getNitropackRuntime();
|
|
147
|
+
return nitropack ? nitropack.useRuntimeConfig() : void 0;
|
|
148
|
+
}
|
|
149
|
+
const nitropack = await getNitropackRuntime();
|
|
150
|
+
if (nitropack) return nitropack.useRuntimeConfig();
|
|
151
|
+
const v3 = await getNitroV3Runtime();
|
|
152
|
+
if (v3) return v3.useRuntimeConfig();
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
155
|
+
export { resolveEvlogConfigForNitroPlugin as n, setActiveNitroRuntime as r, getNitroRuntimeConfigRecord as t };
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=nitroConfigBridge-NbFn-sIK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nitroConfigBridge-NbFn-sIK.mjs","names":[],"sources":["../src/shared/nitroConfigBridge.ts"],"sourcesContent":["/**\n * How evlog reads Nitro runtime config from **published** ESM.\n *\n * **Why not** `import('nitro/runtime-config')` as a string literal in source?\n * Those subpaths are virtual or specially resolved. App Rollup can resolve them\n * for first-party code; for dependency chunks (`node_modules/evlog/dist/...`),\n * strict presets (e.g. `cloudflare-durable`) may fail with “externals are not\n * allowed”. A literal dynamic import is enough for Rollup to pre-resolve.\n *\n * **Strategy**\n *\n * 1. `__EVLOG_CONFIG__` — build-time literal baked in by the evlog Nitro\n * modules via `nitro.options.replace`. When present, all runtime probing is\n * skipped (see issue #312: Vercel + Bun crashes if the v3 probe runs).\n * 2. `process.env.__EVLOG_CONFIG` — JSON set by evlog Nitro modules during\n * build; survives into runtime on platforms that propagate build env vars.\n * 3. Computed module IDs — `['a','b'].join('/')` passed to `import()` so emitted\n * JS does not contain a static `import(\"a/b\")`.\n * 4. Plugins call {@link setActiveNitroRuntime} so adapters never probe modules\n * from the other major version.\n * 5. When the active runtime is unknown (standalone use outside a Nitro\n * plugin), the bridge falls back to the historical probe order.\n *\n * Not exported from `evlog/toolkit` — package-internal only.\n */\n\nimport type { NitroPluginEvlogConfig } from '../nitro'\n\ntype EvlogConfig = NitroPluginEvlogConfig\n\nconst EVLOG_NITRO_ENV = '__EVLOG_CONFIG' as const\n\n// Replaced at build time by `nitro.options.replace` in the evlog Nitro\n// modules. Outside of a Nitro build, this identifier is undeclared and the\n// `typeof` guard below evaluates safely.\n// eslint-disable-next-line @typescript-eslint/naming-convention\ndeclare const __EVLOG_CONFIG__: EvlogConfig | undefined\n\n/** Build-time inlined config, or `undefined` if the bundle was not produced by an evlog Nitro module. */\nexport function readEvlogConfigFromInline(): EvlogConfig | undefined {\n if (typeof __EVLOG_CONFIG__ === 'undefined') return undefined\n if (__EVLOG_CONFIG__ === null || typeof __EVLOG_CONFIG__ !== 'object') return undefined\n return __EVLOG_CONFIG__\n}\n\ntype NitroMajor = 'v2' | 'v3'\n\nlet activeNitroRuntime: NitroMajor | undefined\n\n/**\n * Declare the active Nitro major version so adapters never probe the other\n * version's modules at runtime. The evlog Nitro plugins call this in their\n * first synchronous statement.\n *\n * Bun's auto-install behavior writes to `node_modules/.cache` whenever a\n * dynamic import targets a missing package, which crashes on Vercel's\n * read-only function filesystem. Restricting probes to the runtime that is\n * actually installed avoids that path entirely.\n */\nexport function setActiveNitroRuntime(version: NitroMajor): void {\n activeNitroRuntime = version\n}\n\n/** @internal Reset the active runtime declaration. Used by tests only. */\nexport function resetActiveNitroRuntime(): void {\n activeNitroRuntime = undefined\n}\n\ntype NitroRuntimeConfigModule = {\n useRuntimeConfig: () => Record<string, any>\n}\n\nfunction nitroV3RuntimeConfigSpecifier(): string {\n return ['nitro', 'runtime-config'].join('/')\n}\n\nfunction nitropackRuntimeSpecifier(): string {\n return ['nitropack', 'runtime'].join('/')\n}\n\nfunction nitropackInternalRuntimeConfigSpecifier(): string {\n return ['nitropack', 'runtime', 'internal', 'config'].join('/')\n}\n\nasync function importOrNull(specifier: string): Promise<unknown> {\n try {\n return await import(specifier)\n } catch {\n return null\n }\n}\n\nfunction isRuntimeConfigModule(mod: unknown): mod is NitroRuntimeConfigModule {\n return (\n typeof mod === 'object'\n && mod !== null\n && 'useRuntimeConfig' in mod\n && typeof (mod as NitroRuntimeConfigModule).useRuntimeConfig === 'function'\n )\n}\n\n/** Snapshot from env, or `undefined` if unset / invalid JSON. */\nexport function readEvlogConfigFromNitroEnv(): EvlogConfig | undefined {\n const raw = process.env[EVLOG_NITRO_ENV]\n if (raw === undefined || raw === '') return undefined\n try {\n return JSON.parse(raw) as EvlogConfig\n } catch {\n return undefined\n }\n}\n\nlet cachedNitropackRuntime: NitroRuntimeConfigModule | null | undefined\nlet cachedNitroV3Runtime: NitroRuntimeConfigModule | null | undefined\nlet cachedNitropackInternalConfig: NitroRuntimeConfigModule | null | undefined\n\nasync function getNitropackRuntime(): Promise<NitroRuntimeConfigModule | null> {\n if (cachedNitropackRuntime !== undefined) return cachedNitropackRuntime\n const mod = await importOrNull(nitropackRuntimeSpecifier())\n cachedNitropackRuntime = isRuntimeConfigModule(mod) ? mod : null\n return cachedNitropackRuntime\n}\n\nasync function getNitroV3Runtime(): Promise<NitroRuntimeConfigModule | null> {\n if (cachedNitroV3Runtime !== undefined) return cachedNitroV3Runtime\n const mod = await importOrNull(nitroV3RuntimeConfigSpecifier())\n cachedNitroV3Runtime = isRuntimeConfigModule(mod) ? mod : null\n return cachedNitroV3Runtime\n}\n\nasync function getNitropackInternalRuntimeConfig(): Promise<NitroRuntimeConfigModule | null> {\n if (cachedNitropackInternalConfig !== undefined) return cachedNitropackInternalConfig\n const mod = await importOrNull(nitropackInternalRuntimeConfigSpecifier())\n cachedNitropackInternalConfig = isRuntimeConfigModule(mod) ? mod : null\n return cachedNitropackInternalConfig\n}\n\nfunction evlogSlice(config: Record<string, any>): EvlogConfig | undefined {\n const { evlog } = config\n if (evlog && typeof evlog === 'object') return evlog as EvlogConfig\n return undefined\n}\n\n/**\n * Options for evlog Nitro plugins (nitropack v2 and Nitro v3).\n *\n * Lookup order:\n * 1. `__EVLOG_CONFIG__` — inlined at build time by the evlog Nitro module.\n * Hits in every deployed bundle and skips runtime probing entirely.\n * 2. `process.env.__EVLOG_CONFIG`\n * 3. The active runtime declared by {@link setActiveNitroRuntime} — either\n * Nitro v3 `runtime-config` or nitropack internal config, never both.\n * 4. When no active runtime has been declared (standalone use): probe v3 then\n * nitropack v2 as a best-effort fallback.\n */\nexport async function resolveEvlogConfigForNitroPlugin(): Promise<EvlogConfig | undefined> {\n const fromInline = readEvlogConfigFromInline()\n if (fromInline !== undefined) return fromInline\n\n const fromEnv = readEvlogConfigFromNitroEnv()\n if (fromEnv !== undefined) return fromEnv\n\n if (activeNitroRuntime === 'v3') {\n const v3 = await getNitroV3Runtime()\n if (v3) {\n const slice = evlogSlice(v3.useRuntimeConfig())\n if (slice !== undefined) return slice\n }\n return undefined\n }\n\n if (activeNitroRuntime === 'v2') {\n const internal = await getNitropackInternalRuntimeConfig()\n if (internal) {\n const slice = evlogSlice(internal.useRuntimeConfig())\n if (slice !== undefined) return slice\n }\n return undefined\n }\n\n const v3 = await getNitroV3Runtime()\n if (v3) {\n const slice = evlogSlice(v3.useRuntimeConfig())\n if (slice !== undefined) return slice\n }\n\n const internal = await getNitropackInternalRuntimeConfig()\n if (internal) {\n const slice = evlogSlice(internal.useRuntimeConfig())\n if (slice !== undefined) return slice\n }\n\n return undefined\n}\n\n/**\n * Full `useRuntimeConfig()` object for drain adapters.\n *\n * Honors {@link setActiveNitroRuntime}: when a Nitro plugin has declared its\n * version, only that version's runtime module is probed. When no version has\n * been declared (standalone use outside Nitro), falls back to the historical\n * order: nitropack v2 first, then Nitro v3.\n *\n * When `__EVLOG_CONFIG__` was inlined at build time, returns a synthetic\n * `{ evlog: <inlined> }` record so adapters can read `runtimeConfig.evlog.*`\n * without triggering the dynamic import (issue #312).\n */\nexport async function getNitroRuntimeConfigRecord(): Promise<Record<string, any> | undefined> {\n const inline = readEvlogConfigFromInline()\n if (inline !== undefined) return { evlog: inline }\n\n if (activeNitroRuntime === 'v3') {\n const v3 = await getNitroV3Runtime()\n return v3 ? v3.useRuntimeConfig() : undefined\n }\n\n if (activeNitroRuntime === 'v2') {\n const nitropack = await getNitropackRuntime()\n return nitropack ? nitropack.useRuntimeConfig() : undefined\n }\n\n const nitropack = await getNitropackRuntime()\n if (nitropack) return nitropack.useRuntimeConfig()\n\n const v3 = await getNitroV3Runtime()\n if (v3) return v3.useRuntimeConfig()\n\n return undefined\n}\n"],"mappings":"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"}
|
package/dist/nuxt/module.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as LogLevel, R as EnvironmentContext, Y as RedactConfig, nt as SamplingConfig, st as TransportConfig, tt as RouteConfig } from "../audit-
|
|
1
|
+
import { K as LogLevel, R as EnvironmentContext, Y as RedactConfig, nt as SamplingConfig, st as TransportConfig, tt as RouteConfig } from "../audit-DVdkntSO.mjs";
|
|
2
2
|
import { StreamServerOptions } from "../stream.mjs";
|
|
3
3
|
import * as _$_nuxt_schema0 from "@nuxt/schema";
|
|
4
4
|
|
|
@@ -6,8 +6,12 @@ import * as _$_nuxt_schema0 from "@nuxt/schema";
|
|
|
6
6
|
interface ModuleAxiomBaseConfig {
|
|
7
7
|
/** Axiom dataset name */
|
|
8
8
|
dataset: string;
|
|
9
|
-
/** Axiom API token */
|
|
10
|
-
|
|
9
|
+
/** Axiom API token (evlog field `apiKey`) */
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Renamed to `apiKey`. Will be removed in the next major version.
|
|
13
|
+
*/
|
|
14
|
+
token?: string;
|
|
11
15
|
/** Organization ID (required for Personal Access Tokens) */
|
|
12
16
|
orgId?: string;
|
|
13
17
|
/** Request timeout in milliseconds. Default: 5000 */
|
|
@@ -159,7 +163,7 @@ interface ModuleOptions {
|
|
|
159
163
|
* ```ts
|
|
160
164
|
* axiom: {
|
|
161
165
|
* dataset: 'my-app-logs',
|
|
162
|
-
*
|
|
166
|
+
* apiKey: process.env.AXIOM_API_KEY,
|
|
163
167
|
* }
|
|
164
168
|
* ```
|
|
165
169
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.mts","names":[],"sources":["../../src/nuxt/module.ts"],"mappings":";;;;;UAgBU,qBAAA;;EAER,OAAA;;EAEA,
|
|
1
|
+
{"version":3,"file":"module.d.mts","names":[],"sources":["../../src/nuxt/module.ts"],"mappings":";;;;;UAgBU,qBAAA;;EAER,OAAA;;EAEA,MAAA;EAJ6B;;;EAQ7B,KAAA;EAJA;EAMA,KAAA;EAAA;EAEA,OAAA;AAAA;AAAA,UAGQ,qBAAA;EAAA;;;;;EAMR,OAAA;EAKiC;EAHjC,OAAA;AAAA;AAAA,UAGQ,yBAAA;EAOL;EALH,OAAA;;EAEA,OAAA;AAAA;AAAA,KAGG,iBAAA,GAAoB,qBAAA,IAAyB,qBAAA,GAAwB,yBAAA;AAAA,UAEzD,aAAA;EAFkF;;;;;EAQjG,OAAA;EANe;;;EAWf,GAAA,GAAM,OAAA,CAAQ,kBAAA;EAAR;;;;;;EAQN,OAAA;EA8HQ;;;;EAxHR,MAAA;EA0NQ;;;;;;;EAjNR,MAAA;EATA;;;;;;EAiBA,OAAA;EAyCA;;;;;;EAjCA,OAAA;EAiFM;;;;;;;;;;;;;EAlEN,MAAA,GAAS,MAAA,SAAe,WAAA;EA+HtB;;;;;;;;;;;;;;;;EA7GF,QAAA,GAAW,cAAA;;;;;;EAOX,QAAA,GAAW,QAAA;;;;;;;;;;;;;EAcX,SAAA,GAAY,eAAA;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BZ,MAAA,aA3B2B,mBAAA;;;;;;;;;;;;;EAyC3B,KAAA,GAAQ,iBAAA;;;;;;;;;;;;;;;EAgBR,IAAA;2DAEE,QAAA;IAEA,WAAA;IAEA,kBAAA,GAAqB,MAAA;IAErB,OAAA,GAAU,MAAA;IAEV,OAAA;EAAA;;;;;;;;;;;;;EAeF,OAAA;kCAEE,MAAA;IAEA,IAAA;IAEA,OAAA;EAAA;;;;;;;;;;;;EAcF,MAAA;qBAEE,GAAA;IAEA,WAAA;IAEA,OAAA;IAEA,IAAA,GAAO,MAAA;IAEP,OAAA;EAAA;;;;;;;;;;;;;;;;;;;EAqBF,MAAA,aAAmB,YAAA;;;;;EAMnB,KAAA,GAAQ,QAAA;;;;;;;EAQR,cAAA;;;;;;EAOA,SAAA;AAAA;AAAA,cACD,QAAA"}
|
package/dist/nuxt/module.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as createStripPlugin, t as createSourceLocationPlugin } from "../source-location-Dco0cRTz.mjs";
|
|
2
|
-
import { n as version, t as name } from "../package-
|
|
2
|
+
import { n as version, t as name } from "../package-B23bR3tK.mjs";
|
|
3
3
|
import { addImports, addPlugin, addServerHandler, addServerImports, addServerPlugin, addVitePlugin, createResolver, defineNuxtModule } from "@nuxt/kit";
|
|
4
4
|
//#region src/nuxt/module.ts
|
|
5
5
|
var module_default = defineNuxtModule({
|
package/dist/nuxt/module.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, LogLevel, RedactConfig, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport { createStripPlugin } from '../vite/strip'\nimport { createSourceLocationPlugin } from '../vite/source-location'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token */\n token: string\n /** Organization ID (required for Personal Access Tokens) */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * Suppress built-in console output.\n * When true, events are still built, sampled, and passed to drains,\n * but nothing is written to console. Use when drains own the output\n * channel (e.g., stdout-based platforms like GCP Cloud Run, AWS Lambda).\n * @default false\n */\n silent?: boolean\n\n /**\n * Route patterns to include in logging.\n * Supports glob patterns like '/api/**'.\n * If not set, all routes are logged.\n * @example ['/api/**', '/auth/**']\n */\n include?: string[]\n\n /**\n * Route patterns to exclude from logging.\n * Supports glob patterns like '/api/_nuxt_icon/**'.\n * Exclusions take precedence over inclusions.\n * @example ['/api/_nuxt_icon/**', '/health']\n */\n exclude?: string[]\n\n /**\n * Route-specific service configuration.\n * Allows setting different service names for different routes.\n * Patterns are matched using glob syntax.\n *\n * @example\n * ```ts\n * routes: {\n * '/api/foo/**': { service: 'service1' },\n * '/api/bar/**': { service: 'service2' }\n * }\n * ```\n */\n routes?: Record<string, RouteConfig>\n\n /**\n * Sampling configuration for filtering logs.\n * Allows configuring what percentage of logs to keep per level.\n *\n * @example\n * ```ts\n * sampling: {\n * rates: {\n * info: 10, // Keep 10% of info logs\n * warn: 50, // Keep 50% of warning logs\n * debug: 5, // Keep 5% of debug logs\n * error: 100, // Always keep errors (default)\n * }\n * }\n * ```\n */\n sampling?: SamplingConfig\n\n /**\n * Minimum severity for the global `log` API on server and client (not request wide events).\n * Order: debug < info < warn < error.\n * @default 'debug'\n */\n minLevel?: LogLevel\n\n /**\n * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // send client logs to server via API endpoint\n * endpoint: '/api/_evlog/ingest', // default endpoint (or custom endpoint)\n * credentials: 'include', // optional: cross-origin ingest\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Live stream of wide events, exposed by a small local HTTP server on\n * an ephemeral port. Any consumer (browser tab, CLI, devtool) can\n * subscribe via Server-Sent Events. The URL is printed at startup and\n * written to `.evlog/stream.url`.\n *\n * Strict opt-in — nothing starts unless this is set.\n *\n * - `true` — enable with defaults\n * - `false` — off (same as omitting)\n * - `StreamServerOptions` — full config (port, host, token, ...)\n * - `undefined` (default) — off\n *\n * Local-only: binds to `127.0.0.1` and does not work on serverless\n * platforms (each invocation is isolated).\n *\n * @example\n * ```ts\n * // Enable with defaults\n * evlog: { stream: true }\n *\n * // Custom port + auth token\n * evlog: { stream: { port: 4317, token: process.env.EVLOG_STREAM_TOKEN } }\n * ```\n */\n stream?: boolean | import('../stream').StreamServerOptions\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * token: process.env.AXIOM_TOKEN,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Auto-redaction configuration for PII protection.\n * `true` enables all built-in PII patterns (email, credit card, IPv4, phone, SSN).\n * Pass an object for fine-grained control.\n *\n * @example\n * ```ts\n * // Enable all built-in PII patterns\n * evlog: { redact: true }\n *\n * // Add custom paths on top of built-ins\n * evlog: {\n * redact: {\n * paths: ['user.password', 'headers.authorization'],\n * }\n * }\n * ```\n */\n redact?: boolean | RedactConfig\n\n /**\n * Log levels to strip from production builds. Set to [] to disable.\n * @default ['debug']\n */\n strip?: LogLevel[]\n\n /**\n * Inject source file:line into log calls.\n * When true, active in both dev and prod.\n * When 'dev', active only in development.\n * @default 'dev'\n */\n sourceLocation?: boolean | 'dev'\n\n /**\n * How long to retain events before cleanup (used by @evlog/nuxthub).\n * Supports \"30d\" (days), \"24h\" (hours), \"60m\" (minutes).\n * @default '30d'\n */\n retention?: string\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name,\n version,\n configKey: name,\n docs: 'https://evlog.dev',\n },\n defaults: {},\n setup(options, nuxt) {\n const resolver = createResolver(import.meta.url)\n\n const transportEnabled = options.transport?.enabled ?? false\n const transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n const transportCredentials = options.transport?.credentials ?? 'same-origin'\n\n // Normalize `evlog.stream` into a single canonical shape so the Nitro\n // plugin (which reads runtimeConfig.evlog at server boot) sees a\n // consistent value.\n //\n // The stream is exposed by a separate mini HTTP server on its own\n // ephemeral port (see `evlog/stream` → `startStreamServer`). It does\n // NOT register a route in the user's app.\n //\n // Strict opt-in: nothing starts unless the user explicitly asks for it.\n // - `stream === true` → enabled with defaults\n // - `stream === false` → off (alias for undefined)\n // - `stream: { ... }` → enabled with user options\n // - `stream === undefined` → off\n const streamRaw = options.stream\n const normalizedStream\n = streamRaw === true\n ? true\n : streamRaw && typeof streamRaw === 'object'\n ? streamRaw\n : false\n const streamEnabled = normalizedStream !== false\n options.stream = normalizedStream\n\n nuxt.options.runtimeConfig.evlog = options\n\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // Mirror standalone Nitro modules: serialize evlog options into __EVLOG_CONFIG so\n // resolveEvlogConfigForNitroPlugin() picks them up in dev (Nitro worker threads\n // often cannot resolve useRuntimeConfig().evlog via dynamic import reliably).\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n nitroConfig.errorHandler = nitroConfig.errorHandler || resolver.resolve('../nitro/errorHandler')\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n process.env.__EVLOG_CONFIG = JSON.stringify(evlogForNitro)\n }\n })\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n minLevel: options.minLevel,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\n credentials: transportCredentials,\n },\n }\n\n if (transportEnabled) {\n addServerHandler({\n route: transportEndpoint,\n method: 'post',\n handler: resolver.resolve('../runtime/server/routes/_evlog/ingest.post'),\n })\n }\n\n if (streamEnabled) {\n // The stream itself is served by an out-of-band HTTP mini-server\n // started in the Nitro plugin — see startStreamServer() in\n // packages/evlog/src/stream.ts. Here we only register a discovery\n // route so a browser tab on the user's app can find the mini-server\n // URL without having to read `.evlog/stream.url` directly.\n addServerHandler({\n route: '/api/_evlog/stream-info',\n method: 'get',\n handler: resolver.resolve('../runtime/server/routes/_evlog/stream-info.get'),\n })\n }\n\n addServerPlugin(resolver.resolve('../nitro/plugin'))\n\n addPlugin({\n src: resolver.resolve('../runtime/client/plugin'),\n mode: 'client',\n })\n\n addImports([\n {\n name: 'log',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'clearIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setMinLevel',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n {\n name: 'parseError',\n from: resolver.resolve('../runtime/utils/parseError'),\n },\n ])\n\n addServerImports([\n {\n name: 'useLogger',\n from: resolver.resolve('../runtime/server/useLogger'),\n },\n {\n name: 'log',\n from: resolver.resolve('../logger'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n ])\n\n const stripLevels = options.strip ?? ['debug']\n if (stripLevels.length > 0) {\n addVitePlugin(createStripPlugin(stripLevels))\n }\n\n const srcLoc = options.sourceLocation ?? 'dev'\n if (srcLoc === true || (srcLoc === 'dev' && nuxt.options.dev)) {\n addVitePlugin(createSourceLocationPlugin(true))\n }\n },\n})\n"],"mappings":";;;;AAoTA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EACJ;EACA;EACA,WAAW;EACX,MAAM;EACP;CACD,UAAU,EAAE;CACZ,MAAM,SAAS,MAAM;EACnB,MAAM,WAAW,eAAe,OAAO,KAAK,IAAI;EAEhD,MAAM,mBAAmB,QAAQ,WAAW,WAAW;EACvD,MAAM,oBAAoB,QAAQ,WAAW,YAAY;EACzD,MAAM,uBAAuB,QAAQ,WAAW,eAAe;EAe/D,MAAM,YAAY,QAAQ;EAC1B,MAAM,mBACF,cAAc,OACZ,OACA,aAAa,OAAO,cAAc,WAChC,YACA;EACR,MAAM,gBAAgB,qBAAqB;AAC3C,UAAQ,SAAS;AAEjB,OAAK,QAAQ,cAAc,QAAQ;AAQnC,OAAK,KAAK,iBAAiB,gBAA6B;AACtD,eAAY,eAAe,YAAY,gBAAgB,SAAS,QAAQ,wBAAwB;GAEhG,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,SAC1D,SAAQ,IAAI,iBAAiB,KAAK,UAAU,cAAc;IAE5D;AACF,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,WAAW;IACT,SAAS;IACT,UAAU;IACV,aAAa;IACd;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,CAAC;AAGJ,MAAI,cAMF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,kDAAkD;GAC7E,CAAC;AAGJ,kBAAgB,SAAS,QAAQ,kBAAkB,CAAC;AAEpD,YAAU;GACR,KAAK,SAAS,QAAQ,2BAA2B;GACjD,MAAM;GACP,CAAC;AAEF,aAAW;GACT;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACF,CAAC;AAEF,mBAAiB;GACf;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,YAAY;IACpC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACF,CAAC;EAEF,MAAM,cAAc,QAAQ,SAAS,CAAC,QAAQ;AAC9C,MAAI,YAAY,SAAS,EACvB,eAAc,kBAAkB,YAAY,CAAC;EAG/C,MAAM,SAAS,QAAQ,kBAAkB;AACzC,MAAI,WAAW,QAAS,WAAW,SAAS,KAAK,QAAQ,IACvD,eAAc,2BAA2B,KAAK,CAAC;;CAGpD,CAAC"}
|
|
1
|
+
{"version":3,"file":"module.mjs","names":[],"sources":["../../src/nuxt/module.ts"],"sourcesContent":["import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n addVitePlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, LogLevel, RedactConfig, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport { createStripPlugin } from '../vite/strip'\nimport { createSourceLocationPlugin } from '../vite/source-location'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token (evlog field `apiKey`) */\n apiKey?: string\n /**\n * @deprecated Renamed to `apiKey`. Will be removed in the next major version.\n */\n token?: string\n /** Organization ID (required for Personal Access Tokens) */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * Suppress built-in console output.\n * When true, events are still built, sampled, and passed to drains,\n * but nothing is written to console. Use when drains own the output\n * channel (e.g., stdout-based platforms like GCP Cloud Run, AWS Lambda).\n * @default false\n */\n silent?: boolean\n\n /**\n * Route patterns to include in logging.\n * Supports glob patterns like '/api/**'.\n * If not set, all routes are logged.\n * @example ['/api/**', '/auth/**']\n */\n include?: string[]\n\n /**\n * Route patterns to exclude from logging.\n * Supports glob patterns like '/api/_nuxt_icon/**'.\n * Exclusions take precedence over inclusions.\n * @example ['/api/_nuxt_icon/**', '/health']\n */\n exclude?: string[]\n\n /**\n * Route-specific service configuration.\n * Allows setting different service names for different routes.\n * Patterns are matched using glob syntax.\n *\n * @example\n * ```ts\n * routes: {\n * '/api/foo/**': { service: 'service1' },\n * '/api/bar/**': { service: 'service2' }\n * }\n * ```\n */\n routes?: Record<string, RouteConfig>\n\n /**\n * Sampling configuration for filtering logs.\n * Allows configuring what percentage of logs to keep per level.\n *\n * @example\n * ```ts\n * sampling: {\n * rates: {\n * info: 10, // Keep 10% of info logs\n * warn: 50, // Keep 50% of warning logs\n * debug: 5, // Keep 5% of debug logs\n * error: 100, // Always keep errors (default)\n * }\n * }\n * ```\n */\n sampling?: SamplingConfig\n\n /**\n * Minimum severity for the global `log` API on server and client (not request wide events).\n * Order: debug < info < warn < error.\n * @default 'debug'\n */\n minLevel?: LogLevel\n\n /**\n * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // send client logs to server via API endpoint\n * endpoint: '/api/_evlog/ingest', // default endpoint (or custom endpoint)\n * credentials: 'include', // optional: cross-origin ingest\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Live stream of wide events, exposed by a small local HTTP server on\n * an ephemeral port. Any consumer (browser tab, CLI, devtool) can\n * subscribe via Server-Sent Events. The URL is printed at startup and\n * written to `.evlog/stream.url`.\n *\n * Strict opt-in — nothing starts unless this is set.\n *\n * - `true` — enable with defaults\n * - `false` — off (same as omitting)\n * - `StreamServerOptions` — full config (port, host, token, ...)\n * - `undefined` (default) — off\n *\n * Local-only: binds to `127.0.0.1` and does not work on serverless\n * platforms (each invocation is isolated).\n *\n * @example\n * ```ts\n * // Enable with defaults\n * evlog: { stream: true }\n *\n * // Custom port + auth token\n * evlog: { stream: { port: 4317, token: process.env.EVLOG_STREAM_TOKEN } }\n * ```\n */\n stream?: boolean | import('../stream').StreamServerOptions\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * apiKey: process.env.AXIOM_API_KEY,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Auto-redaction configuration for PII protection.\n * `true` enables all built-in PII patterns (email, credit card, IPv4, phone, SSN).\n * Pass an object for fine-grained control.\n *\n * @example\n * ```ts\n * // Enable all built-in PII patterns\n * evlog: { redact: true }\n *\n * // Add custom paths on top of built-ins\n * evlog: {\n * redact: {\n * paths: ['user.password', 'headers.authorization'],\n * }\n * }\n * ```\n */\n redact?: boolean | RedactConfig\n\n /**\n * Log levels to strip from production builds. Set to [] to disable.\n * @default ['debug']\n */\n strip?: LogLevel[]\n\n /**\n * Inject source file:line into log calls.\n * When true, active in both dev and prod.\n * When 'dev', active only in development.\n * @default 'dev'\n */\n sourceLocation?: boolean | 'dev'\n\n /**\n * How long to retain events before cleanup (used by @evlog/nuxthub).\n * Supports \"30d\" (days), \"24h\" (hours), \"60m\" (minutes).\n * @default '30d'\n */\n retention?: string\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name,\n version,\n configKey: name,\n docs: 'https://evlog.dev',\n },\n defaults: {},\n setup(options, nuxt) {\n const resolver = createResolver(import.meta.url)\n\n const transportEnabled = options.transport?.enabled ?? false\n const transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n const transportCredentials = options.transport?.credentials ?? 'same-origin'\n\n // Normalize `evlog.stream` into a single canonical shape so the Nitro\n // plugin (which reads runtimeConfig.evlog at server boot) sees a\n // consistent value.\n //\n // The stream is exposed by a separate mini HTTP server on its own\n // ephemeral port (see `evlog/stream` → `startStreamServer`). It does\n // NOT register a route in the user's app.\n //\n // Strict opt-in: nothing starts unless the user explicitly asks for it.\n // - `stream === true` → enabled with defaults\n // - `stream === false` → off (alias for undefined)\n // - `stream: { ... }` → enabled with user options\n // - `stream === undefined` → off\n const streamRaw = options.stream\n const normalizedStream\n = streamRaw === true\n ? true\n : streamRaw && typeof streamRaw === 'object'\n ? streamRaw\n : false\n const streamEnabled = normalizedStream !== false\n options.stream = normalizedStream\n\n nuxt.options.runtimeConfig.evlog = options\n\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // Mirror standalone Nitro modules: serialize evlog options into __EVLOG_CONFIG so\n // resolveEvlogConfigForNitroPlugin() picks them up in dev (Nitro worker threads\n // often cannot resolve useRuntimeConfig().evlog via dynamic import reliably).\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n nitroConfig.errorHandler = nitroConfig.errorHandler || resolver.resolve('../nitro/errorHandler')\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n process.env.__EVLOG_CONFIG = JSON.stringify(evlogForNitro)\n }\n })\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n minLevel: options.minLevel,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\n credentials: transportCredentials,\n },\n }\n\n if (transportEnabled) {\n addServerHandler({\n route: transportEndpoint,\n method: 'post',\n handler: resolver.resolve('../runtime/server/routes/_evlog/ingest.post'),\n })\n }\n\n if (streamEnabled) {\n // The stream itself is served by an out-of-band HTTP mini-server\n // started in the Nitro plugin — see startStreamServer() in\n // packages/evlog/src/stream.ts. Here we only register a discovery\n // route so a browser tab on the user's app can find the mini-server\n // URL without having to read `.evlog/stream.url` directly.\n addServerHandler({\n route: '/api/_evlog/stream-info',\n method: 'get',\n handler: resolver.resolve('../runtime/server/routes/_evlog/stream-info.get'),\n })\n }\n\n addServerPlugin(resolver.resolve('../nitro/plugin'))\n\n addPlugin({\n src: resolver.resolve('../runtime/client/plugin'),\n mode: 'client',\n })\n\n addImports([\n {\n name: 'log',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'clearIdentity',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'setMinLevel',\n from: resolver.resolve('../runtime/client/log'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n {\n name: 'parseError',\n from: resolver.resolve('../runtime/utils/parseError'),\n },\n ])\n\n addServerImports([\n {\n name: 'useLogger',\n from: resolver.resolve('../runtime/server/useLogger'),\n },\n {\n name: 'log',\n from: resolver.resolve('../logger'),\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n },\n ])\n\n const stripLevels = options.strip ?? ['debug']\n if (stripLevels.length > 0) {\n addVitePlugin(createStripPlugin(stripLevels))\n }\n\n const srcLoc = options.sourceLocation ?? 'dev'\n if (srcLoc === true || (srcLoc === 'dev' && nuxt.options.dev)) {\n addVitePlugin(createSourceLocationPlugin(true))\n }\n },\n})\n"],"mappings":";;;;AAwTA,IAAA,iBAAe,iBAAgC;CAC7C,MAAM;EACJ;EACA;EACA,WAAW;EACX,MAAM;EACP;CACD,UAAU,EAAE;CACZ,MAAM,SAAS,MAAM;EACnB,MAAM,WAAW,eAAe,OAAO,KAAK,IAAI;EAEhD,MAAM,mBAAmB,QAAQ,WAAW,WAAW;EACvD,MAAM,oBAAoB,QAAQ,WAAW,YAAY;EACzD,MAAM,uBAAuB,QAAQ,WAAW,eAAe;EAe/D,MAAM,YAAY,QAAQ;EAC1B,MAAM,mBACF,cAAc,OACZ,OACA,aAAa,OAAO,cAAc,WAChC,YACA;EACR,MAAM,gBAAgB,qBAAqB;AAC3C,UAAQ,SAAS;AAEjB,OAAK,QAAQ,cAAc,QAAQ;AAQnC,OAAK,KAAK,iBAAiB,gBAA6B;AACtD,eAAY,eAAe,YAAY,gBAAgB,SAAS,QAAQ,wBAAwB;GAEhG,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,SAC1D,SAAQ,IAAI,iBAAiB,KAAK,UAAU,cAAc;IAE5D;AACF,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,WAAW;IACT,SAAS;IACT,UAAU;IACV,aAAa;IACd;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,CAAC;AAGJ,MAAI,cAMF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,kDAAkD;GAC7E,CAAC;AAGJ,kBAAgB,SAAS,QAAQ,kBAAkB,CAAC;AAEpD,YAAU;GACR,KAAK,SAAS,QAAQ,2BAA2B;GACjD,MAAM;GACP,CAAC;AAEF,aAAW;GACT;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAChD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACF,CAAC;AAEF,mBAAiB;GACf;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACtD;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,YAAY;IACpC;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IACnC;GACF,CAAC;EAEF,MAAM,cAAc,QAAQ,SAAS,CAAC,QAAQ;AAC9C,MAAI,YAAY,SAAS,EACvB,eAAc,kBAAkB,YAAY,CAAC;EAG/C,MAAM,SAAS,QAAQ,kBAAkB;AACzC,MAAI,WAAW,QAAS,WAAW,SAAS,KAAK,QAAQ,IACvD,eAAc,2BAA2B,KAAK,CAAC;;CAGpD,CAAC"}
|