evlog 2.19.2 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -1
- package/dist/adapters/axiom.d.mts +1 -1
- package/dist/adapters/axiom.mjs +2 -2
- 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 +1 -1
- package/dist/adapters/memory.mjs +1 -1
- 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 +39 -16
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +81 -16
- package/dist/ai/index.mjs.map +1 -1
- package/dist/asyncStorageScope-DnF7Xk8l.mjs +81 -0
- package/dist/asyncStorageScope-DnF7Xk8l.mjs.map +1 -0
- package/dist/{audit-CL0q7GJU.mjs → audit-BXCYMjcC.mjs} +21 -6
- package/dist/audit-BXCYMjcC.mjs.map +1 -0
- package/dist/{audit-CBfv3rl1.d.mts → audit-BZrUvjfW.d.mts} +2 -1
- package/dist/{audit-CBfv3rl1.d.mts.map → audit-BZrUvjfW.d.mts.map} +1 -1
- package/dist/audit-action.d.mts +1 -1
- package/dist/audit.d.mts +1 -1
- package/dist/audit.mjs +1 -1
- package/dist/better-auth/index.d.mts +1 -1
- package/dist/browser.d.mts +1 -1
- package/dist/{catalog-CyemiLYG.d.mts → catalog-1cQnNxR2.d.mts} +3 -3
- package/dist/{catalog-CyemiLYG.d.mts.map → catalog-1cQnNxR2.d.mts.map} +1 -1
- package/dist/catalog.d.mts +1 -1
- package/dist/{define-BuDJpV2b.d.mts → define-Ct2QyrE9.d.mts} +3 -3
- package/dist/{define-BuDJpV2b.d.mts.map → define-Ct2QyrE9.d.mts.map} +1 -1
- package/dist/{drain-6lV-g7JB.mjs → drain-AD7Mn_5_.mjs} +3 -3
- package/dist/{drain-6lV-g7JB.mjs.map → drain-AD7Mn_5_.mjs.map} +1 -1
- package/dist/elysia/index.d.mts +6 -5
- package/dist/elysia/index.d.mts.map +1 -1
- package/dist/elysia/index.mjs +11 -8
- package/dist/elysia/index.mjs.map +1 -1
- package/dist/{enrich-error-stack-next.node-BecxSKUc.mjs → enrich-error-stack-next.node-KB0Oap7R.mjs} +1 -1
- package/dist/{enrich-error-stack-next.node-BecxSKUc.mjs.map → enrich-error-stack-next.node-KB0Oap7R.mjs.map} +1 -1
- package/dist/{enricher-VdBVX4oT.d.mts → enricher-BOzt2FCi.d.mts} +2 -2
- package/dist/{enricher-VdBVX4oT.d.mts.map → enricher-BOzt2FCi.d.mts.map} +1 -1
- package/dist/enrichers.d.mts +2 -2
- package/dist/{error-CPCM5a1D.d.mts → error-BRymuv8U.d.mts} +2 -2
- package/dist/{error-CPCM5a1D.d.mts.map → error-BRymuv8U.d.mts.map} +1 -1
- package/dist/error.d.mts +1 -1
- package/dist/{errors-ZdY6Ohi6.d.mts → errors-C7qA6CAi.d.mts} +2 -2
- package/dist/{errors-ZdY6Ohi6.d.mts.map → errors-C7qA6CAi.d.mts.map} +1 -1
- package/dist/eve/index.d.mts +72 -0
- package/dist/eve/index.d.mts.map +1 -0
- package/dist/eve/index.mjs +593 -0
- package/dist/eve/index.mjs.map +1 -0
- package/dist/express/index.d.mts +2 -2
- package/dist/express/index.mjs +3 -3
- package/dist/fastify/index.d.mts +2 -2
- package/dist/fastify/index.mjs +3 -3
- package/dist/fork-S9gpZmF8.mjs +72 -0
- package/dist/fork-S9gpZmF8.mjs.map +1 -0
- package/dist/hono/index.d.mts +2 -2
- package/dist/hono/index.mjs +1 -1
- package/dist/{http-DA3RWQrm.mjs → http-CuZ6Cm2M.mjs} +2 -2
- package/dist/{http-DA3RWQrm.mjs.map → http-CuZ6Cm2M.mjs.map} +1 -1
- package/dist/http.d.mts +1 -1
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{instrumentation-create-STGmQGQt.d.mts → instrumentation-create-gSDk0leX.d.mts} +2 -2
- package/dist/{instrumentation-create-STGmQGQt.d.mts.map → instrumentation-create-gSDk0leX.d.mts.map} +1 -1
- package/dist/{integration-2PpI-bCm.mjs → integration-CeL90DtN.mjs} +3 -2
- package/dist/{integration-2PpI-bCm.mjs.map → integration-CeL90DtN.mjs.map} +1 -1
- package/dist/{logger-DWTPZ0c1.d.mts → logger-CxWz7QJ3.d.mts} +7 -3
- package/dist/logger-CxWz7QJ3.d.mts.map +1 -0
- package/dist/logger.d.mts +2 -2
- package/dist/logger.mjs +2 -2
- package/dist/{fork-Di44utlp.mjs → middleware-Cdebyfdt.mjs} +3 -69
- package/dist/middleware-Cdebyfdt.mjs.map +1 -0
- package/dist/{middleware-CjVyGyrG.d.mts → middleware-fbtEs6bq.d.mts} +2 -2
- package/dist/{middleware-CjVyGyrG.d.mts.map → middleware-fbtEs6bq.d.mts.map} +1 -1
- package/dist/nestjs/index.d.mts +2 -2
- package/dist/nestjs/index.mjs +4 -3
- package/dist/nestjs/index.mjs.map +1 -1
- package/dist/next/client.d.mts +1 -1
- package/dist/next/index.d.mts +4 -4
- package/dist/next/index.d.mts.map +1 -1
- package/dist/next/index.mjs +4 -3
- package/dist/next/index.mjs.map +1 -1
- package/dist/next/instrumentation/create.d.mts +1 -1
- package/dist/next/instrumentation/create.mjs +1 -1
- package/dist/next/instrumentation.d.mts +1 -1
- package/dist/next/stream.d.mts +1 -1
- package/dist/nitro/errorHandler.mjs +1 -1
- package/dist/nitro/module.d.mts +2 -2
- package/dist/nitro/module.mjs +1 -1
- package/dist/nitro/plugin.mjs +2 -2
- package/dist/nitro/v3/errorHandler.mjs +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.mjs +1 -1
- package/dist/nitro/v3/plugin.mjs +2 -2
- package/dist/nitro/v3/useLogger.d.mts +1 -1
- package/dist/{nitro--E4op34w.d.mts → nitro-CcN7HDnr.d.mts} +2 -2
- package/dist/{nitro--E4op34w.d.mts.map → nitro-CcN7HDnr.d.mts.map} +1 -1
- package/dist/{nitro-ClHmVj1H.mjs → nitro-DYFCSlho.mjs} +2 -2
- package/dist/{nitro-ClHmVj1H.mjs.map → nitro-DYFCSlho.mjs.map} +1 -1
- package/dist/{nitroConfigBridge-BkVWnSV3.mjs → nitroConfigBridge-lHPsE5zG.mjs} +8 -6
- package/dist/nitroConfigBridge-lHPsE5zG.mjs.map +1 -0
- package/dist/{nodeResponse-DKrYWrxk.mjs → nodeResponse-Dsl7gZUf.mjs} +1 -1
- package/dist/{nodeResponse-DKrYWrxk.mjs.map → nodeResponse-Dsl7gZUf.mjs.map} +1 -1
- package/dist/nuxt/module.d.mts +1 -1
- package/dist/nuxt/module.d.mts.map +1 -1
- package/dist/nuxt/module.mjs +44 -12
- package/dist/nuxt/module.mjs.map +1 -1
- package/dist/orpc/index.d.mts +2 -2
- package/dist/orpc/index.mjs +2 -2
- package/dist/{package-Bgs0VSDF.mjs → package-DtGhNwVN.mjs} +2 -2
- package/dist/package-DtGhNwVN.mjs.map +1 -0
- package/dist/{parseError-BwBg-iW4.d.mts → parseError-BmoJ7XeF.d.mts} +2 -2
- package/dist/parseError-BmoJ7XeF.d.mts.map +1 -0
- package/dist/react-router/index.d.mts +2 -2
- package/dist/react-router/index.mjs +3 -2
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs → register-disk-snippet-B5svlT8-.mjs} +1 -1
- package/dist/{register-disk-snippet-B_JyhodL.mjs.map → register-disk-snippet-B5svlT8-.mjs.map} +1 -1
- package/dist/runtime/client/log.d.mts +1 -1
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -1
- package/dist/runtime/server/useLogger.d.mts +1 -1
- package/dist/runtime/utils/parseError.d.mts +2 -2
- package/dist/{storage-D4sBVffQ.mjs → storage-BeFdoGTI.mjs} +1 -1
- package/dist/{storage-D4sBVffQ.mjs.map → storage-BeFdoGTI.mjs.map} +1 -1
- package/dist/stream.d.mts +1 -1
- package/dist/stream.d.mts.map +1 -1
- package/dist/stream.mjs +7 -1
- package/dist/stream.mjs.map +1 -1
- package/dist/sveltekit/index.d.mts +2 -2
- package/dist/sveltekit/index.mjs +5 -4
- package/dist/sveltekit/index.mjs.map +1 -1
- package/dist/toolkit.d.mts +5 -5
- package/dist/toolkit.mjs +7 -6
- package/dist/types.d.mts +1 -1
- package/dist/{useLogger-DiRWGD33.d.mts → useLogger-BupVLO9_.d.mts} +2 -2
- package/dist/{useLogger-DiRWGD33.d.mts.map → useLogger-BupVLO9_.d.mts.map} +1 -1
- package/dist/{utils-XPMPENUK.d.mts → utils-D_LY-J1k.d.mts} +2 -2
- package/dist/{utils-XPMPENUK.d.mts.map → utils-D_LY-J1k.d.mts.map} +1 -1
- package/dist/utils.d.mts +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 +17 -2
- package/dist/audit-CL0q7GJU.mjs.map +0 -1
- package/dist/fork-Di44utlp.mjs.map +0 -1
- package/dist/logger-DWTPZ0c1.d.mts.map +0 -1
- package/dist/nitroConfigBridge-BkVWnSV3.mjs.map +0 -1
- package/dist/package-Bgs0VSDF.mjs.map +0 -1
- package/dist/parseError-BwBg-iW4.d.mts.map +0 -1
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 type { DevTerminalInput } from '../shared/dev-terminal'\nimport { prependNitroErrorHandler } from '../nitro'\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 * Dev terminal output: preset or explicit overlay + pretty-error settings.\n * @default 'evlog' when pretty in development\n */\n dev?: DevTerminalInput\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 const evlogHandler = resolver.resolve('../nitro/errorHandler').replace(/\\\\/g, '/')\n nitroConfig.errorHandler = prependNitroErrorHandler(nitroConfig.errorHandler, evlogHandler)\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n const serialized = JSON.stringify(evlogForNitro)\n nitroConfig.replace = nitroConfig.replace || {}\n nitroConfig.replace.__EVLOG_CONFIG__ = serialized\n process.env.__EVLOG_CONFIG = serialized\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":";;;;;AAgUA,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;GACtD,MAAM,eAAe,SAAS,QAAQ,wBAAwB,CAAC,QAAQ,OAAO,IAAI;AAClF,eAAY,eAAe,yBAAyB,YAAY,cAAc,aAAa;GAE3F,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,UAAU;IACpE,MAAM,aAAa,KAAK,UAAU,cAAc;AAChD,gBAAY,UAAU,YAAY,WAAW,EAAE;AAC/C,gBAAY,QAAQ,mBAAmB;AACvC,YAAQ,IAAI,iBAAiB;;IAE/B;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 addTypeTemplate,\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 type { DevTerminalInput } from '../shared/dev-terminal'\nimport { prependNitroErrorHandler } from '../nitro'\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 * Dev terminal output: preset or explicit overlay + pretty-error settings.\n * @default 'evlog' when pretty in development\n */\n dev?: DevTerminalInput\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 const evlogHandler = resolver.resolve('../nitro/errorHandler').replace(/\\\\/g, '/')\n nitroConfig.errorHandler = prependNitroErrorHandler(nitroConfig.errorHandler, evlogHandler)\n\n const evlogForNitro = nuxt.options.runtimeConfig.evlog ?? options\n if (evlogForNitro !== undefined && typeof evlogForNitro === 'object') {\n const serialized = JSON.stringify(evlogForNitro)\n nitroConfig.replace = nitroConfig.replace || {}\n nitroConfig.replace.__EVLOG_CONFIG__ = serialized\n process.env.__EVLOG_CONFIG = serialized\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 dtsDisabled: true,\n },\n {\n name: 'setIdentity',\n from: resolver.resolve('../runtime/client/log'),\n dtsDisabled: true,\n },\n {\n name: 'clearIdentity',\n from: resolver.resolve('../runtime/client/log'),\n dtsDisabled: true,\n },\n {\n name: 'setMinLevel',\n from: resolver.resolve('../runtime/client/log'),\n dtsDisabled: true,\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n dtsDisabled: true,\n },\n {\n name: 'parseError',\n from: resolver.resolve('../runtime/utils/parseError'),\n dtsDisabled: true,\n },\n ])\n\n addTypeTemplate({\n filename: 'types/evlog-client.d.ts',\n getContents: () => `declare global {\n const log: typeof import('evlog/client').log\n const setIdentity: typeof import('evlog/client').setIdentity\n const clearIdentity: typeof import('evlog/client').clearIdentity\n const setMinLevel: typeof import('evlog/client').setMinLevel\n const createEvlogError: typeof import('evlog').createEvlogError\n const parseError: typeof import('evlog').parseError\n}\nexport {}\n`,\n })\n\n addServerImports([\n {\n name: 'useLogger',\n from: resolver.resolve('../runtime/server/useLogger'),\n dtsDisabled: true,\n },\n {\n name: 'log',\n from: resolver.resolve('../logger'),\n dtsDisabled: true,\n },\n {\n name: 'createEvlogError',\n from: resolver.resolve('../error'),\n dtsDisabled: true,\n },\n ])\n\n addTypeTemplate({\n filename: 'types/evlog-server.d.ts',\n getContents: () => `declare global {\n const useLogger: typeof import('evlog').useLogger\n const log: typeof import('evlog').log\n const createEvlogError: typeof import('evlog').createEvlogError\n}\nexport {}\n`,\n }, { nitro: true })\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":";;;;;AAiUA,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;GACtD,MAAM,eAAe,SAAS,QAAQ,wBAAwB,CAAC,QAAQ,OAAO,IAAI;AAClF,eAAY,eAAe,yBAAyB,YAAY,cAAc,aAAa;GAE3F,MAAM,gBAAgB,KAAK,QAAQ,cAAc,SAAS;AAC1D,OAAI,kBAAkB,KAAA,KAAa,OAAO,kBAAkB,UAAU;IACpE,MAAM,aAAa,KAAK,UAAU,cAAc;AAChD,gBAAY,UAAU,YAAY,WAAW,EAAE;AAC/C,gBAAY,QAAQ,mBAAmB;AACvC,YAAQ,IAAI,iBAAiB;;IAE/B;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;IAC/C,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAC/C,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAC/C,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,wBAAwB;IAC/C,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IAClC,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACrD,aAAa;IACd;GACF,CAAC;AAEF,kBAAgB;GACd,UAAU;GACV,mBAAmB;;;;;;;;;;GAUpB,CAAC;AAEF,mBAAiB;GACf;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,8BAA8B;IACrD,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,YAAY;IACnC,aAAa;IACd;GACD;IACE,MAAM;IACN,MAAM,SAAS,QAAQ,WAAW;IAClC,aAAa;IACd;GACF,CAAC;AAEF,kBAAgB;GACd,UAAU;GACV,mBAAmB;;;;;;;GAOpB,EAAE,EAAE,OAAO,MAAM,CAAC;EAEnB,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"}
|
package/dist/orpc/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as AuditableLogger } from "../audit-
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
3
3
|
import { Context, MiddlewareOptions, MiddlewareResult } from "@orpc/server";
|
|
4
4
|
|
|
5
5
|
//#region src/orpc/index.d.ts
|
package/dist/orpc/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EvlogError } from "../error.mjs";
|
|
2
2
|
import { parseError } from "../runtime/utils/parseError.mjs";
|
|
3
|
-
import { t as defineFrameworkIntegration } from "../integration-
|
|
4
|
-
import { t as createLoggerStorage } from "../storage-
|
|
3
|
+
import { t as defineFrameworkIntegration } from "../integration-CeL90DtN.mjs";
|
|
4
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
5
5
|
import { ORPCError } from "@orpc/server";
|
|
6
6
|
//#region src/orpc/index.ts
|
|
7
7
|
const { storage, useLogger } = createLoggerStorage("oRPC handler. Wrap your handler with `withEvlog()` from evlog/orpc.");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-DtGhNwVN.mjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { tt as ParsedError } from "./audit-
|
|
1
|
+
import { tt as ParsedError } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/utils/parseError.d.ts
|
|
4
4
|
declare function parseError(error: unknown): ParsedError;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { parseError as t };
|
|
7
|
-
//# sourceMappingURL=parseError-
|
|
7
|
+
//# sourceMappingURL=parseError-BmoJ7XeF.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseError-BmoJ7XeF.d.mts","names":[],"sources":["../src/runtime/utils/parseError.ts"],"mappings":";;;iBAcgB,UAAA,CAAW,KAAA,YAAiB,WAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as AuditableLogger } from "../audit-
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
3
3
|
import * as _$react_router0 from "react-router";
|
|
4
4
|
|
|
5
5
|
//#region src/react-router/index.d.ts
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as extractSafeHeaders } from "../headers-VtmnWcfn.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
2
|
+
import { t as createMiddlewareLogger } from "../middleware-Cdebyfdt.mjs";
|
|
3
|
+
import { t as attachForkToLogger } from "../fork-S9gpZmF8.mjs";
|
|
4
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
4
5
|
import { createContext } from "react-router";
|
|
5
6
|
//#region src/react-router/index.ts
|
|
6
7
|
const { storage, useLogger } = createLoggerStorage("middleware context. Make sure the evlog middleware is added to your route.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type { AuditableLogger } from '../audit'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure the evlog middleware is added to your route.',\n)\n\n/**\n * Typed context key for accessing the evlog logger in loaders and actions.\n *\n * @example\n * ```ts\n * import { loggerContext } from 'evlog/react-router'\n *\n * export async function loader({ context }: Route.LoaderArgs) {\n * const log = context.get(loggerContext)\n * log.set({ user: { id: 'u-1' } })\n * return { ok: true }\n * }\n * ```\n */\nexport const loggerContext = createContext<AuditableLogger>()\n\nexport type EvlogReactRouterOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * Create an evlog middleware for React Router.\n *\n * @example\n * ```ts\n * // app/root.tsx\n * import { evlog } from 'evlog/react-router'\n *\n * export const middleware: Route.MiddlewareFunction[] = [\n * evlog({ drain: createAxiomDrain() }),\n * ]\n * ```\n */\nexport function evlog(options: EvlogReactRouterOptions = {}) {\n return async (\n { request, context }: { request: Request; context: { set(ctx: unknown, value: unknown): void } },\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const url = new URL(request.url)\n const middlewareOpts = {\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return next()\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n context.set(loggerContext, logger)\n\n try {\n const response = await storage.run(logger, () => next())\n return finishResponse(response, { status: response.status })\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/react-router/index.ts"],"sourcesContent":["import { createContext } from 'react-router'\nimport type { AuditableLogger } from '../audit'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'middleware context. Make sure the evlog middleware is added to your route.',\n)\n\n/**\n * Typed context key for accessing the evlog logger in loaders and actions.\n *\n * @example\n * ```ts\n * import { loggerContext } from 'evlog/react-router'\n *\n * export async function loader({ context }: Route.LoaderArgs) {\n * const log = context.get(loggerContext)\n * log.set({ user: { id: 'u-1' } })\n * return { ok: true }\n * }\n * ```\n */\nexport const loggerContext = createContext<AuditableLogger>()\n\nexport type EvlogReactRouterOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * Create an evlog middleware for React Router.\n *\n * @example\n * ```ts\n * // app/root.tsx\n * import { evlog } from 'evlog/react-router'\n *\n * export const middleware: Route.MiddlewareFunction[] = [\n * evlog({ drain: createAxiomDrain() }),\n * ]\n * ```\n */\nexport function evlog(options: EvlogReactRouterOptions = {}) {\n return async (\n { request, context }: { request: Request; context: { set(ctx: unknown, value: unknown): void } },\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const url = new URL(request.url)\n const middlewareOpts = {\n method: request.method,\n path: url.pathname,\n requestId: request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return next()\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n context.set(loggerContext, logger)\n\n try {\n const response = await storage.run(logger, () => next())\n return finishResponse(response, { status: response.status })\n } catch (error) {\n await finish({ error: error as Error })\n throw error\n }\n }\n}\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,6EACD;;;;;;;;;;;;;;;AAgBD,MAAa,gBAAgB,eAAgC;;;;;;;;;;;;;;AAmB7D,SAAgB,MAAM,UAAmC,EAAE,EAAE;AAC3D,QAAO,OACL,EAAE,SAAS,WACX,SACsB;EACtB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAChC,MAAM,iBAAiB;GACrB,QAAQ,QAAQ;GAChB,MAAM,IAAI;GACV,WAAW,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GACrE,SAAS,mBAAmB,QAAQ,QAAQ;GAC5C,GAAG;GACJ;EACD,MAAM,EAAE,QAAQ,QAAQ,gBAAgB,YAAY,uBAAuB,eAAe;AAE1F,MAAI,QACF,QAAO,MAAM;AAGf,qBAAmB,SAAS,QAAQ,eAAe;AACnD,UAAQ,IAAI,eAAe,OAAO;AAElC,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,IAAI,cAAc,MAAM,CAAC;AACxD,UAAO,eAAe,UAAU,EAAE,QAAQ,SAAS,QAAQ,CAAC;WACrD,OAAO;AACd,SAAM,OAAO,EAAS,OAAgB,CAAC;AACvC,SAAM"}
|
package/dist/{register-disk-snippet-B_JyhodL.mjs.map → register-disk-snippet-B5svlT8-.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-disk-snippet-
|
|
1
|
+
{"version":3,"file":"register-disk-snippet-B5svlT8-.mjs","names":[],"sources":["../src/shared/register-disk-snippet.ts"],"sourcesContent":["import { registerPrettyErrorSnippetReader } from './pretty-error'\n\n/**\n * Register the disk-backed pretty-error snippet reader when Node built-ins are available.\n *\n * Uses a dynamic import so Edge and non-Node bundles never parse `pretty-error-snippet.node`.\n *\n * @internal\n */\nexport async function registerDiskPrettyErrorSnippetReader(): Promise<void> {\n try {\n const { readCodeSnippetFromDisk } = await import('./pretty-error-snippet.node.js')\n registerPrettyErrorSnippetReader(readCodeSnippetFromDisk)\n } catch {\n registerPrettyErrorSnippetReader(null)\n }\n}\n"],"mappings":";;;;;;;;;AASA,eAAsB,uCAAsD;AAC1E,KAAI;EACF,MAAM,EAAE,4BAA4B,MAAM,OAAO,4CAAA,MAAA,MAAA,EAAA,EAAA;AACjD,mCAAiC,wBAAwB;SACnD;AACN,mCAAiC,KAAK"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as LogLevel, Q as Log, mt as TransportConfig } from "../../audit-
|
|
1
|
+
import { $ as LogLevel, Q as Log, mt as TransportConfig } from "../../audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/client/log.d.ts
|
|
4
4
|
declare function setIdentity(identity: Record<string, unknown>): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { filterSafeHeaders } from "../../../../utils.mjs";
|
|
2
|
-
import { b as getGlobalPluginRunner, v as getEnvironment } from "../../../../audit-
|
|
2
|
+
import { b as getGlobalPluginRunner, v as getEnvironment } from "../../../../audit-BXCYMjcC.mjs";
|
|
3
3
|
import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readRawBody, setResponseStatus } from "h3";
|
|
4
4
|
import { useNitroApp } from "nitropack/runtime";
|
|
5
5
|
//#region src/runtime/server/routes/_evlog/ingest.post.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as useLogger } from "../../useLogger-
|
|
1
|
+
import { t as useLogger } from "../../useLogger-BupVLO9_.mjs";
|
|
2
2
|
export { useLogger };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { tt as ParsedError } from "../../audit-
|
|
2
|
-
import { t as parseError } from "../../parseError-
|
|
1
|
+
import { tt as ParsedError } from "../../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as parseError } from "../../parseError-BmoJ7XeF.mjs";
|
|
3
3
|
export { ParsedError, parseError };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-
|
|
1
|
+
{"version":3,"file":"storage-BeFdoGTI.mjs","names":[],"sources":["../src/shared/storage.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { AuditableLogger } from '../audit'\n\n/**\n * Create a request-scoped `AsyncLocalStorage` and matching `useLogger`\n * accessor. Every framework that exposes `useLogger()` (Express, Fastify,\n * NestJS, SvelteKit) calls this once at module level.\n *\n * @param contextHint - Appended to the error message when `useLogger()` is\n * called outside of a request, e.g. `\"middleware context. Make sure\n * app.use(evlog()) is registered before your routes.\"`.\n */\nexport function createLoggerStorage(contextHint: string) {\n const storage = new AsyncLocalStorage<AuditableLogger>()\n\n function useLogger<T extends object = Record<string, unknown>>(): AuditableLogger<T> {\n const logger = storage.getStore()\n if (!logger) {\n throw new Error(\n `[evlog] useLogger() was called outside of an evlog ${contextHint}`,\n )\n }\n /** @internal ALS store is untyped; cast satisfies the caller's generic `T`. */\n return logger as AuditableLogger<T>\n }\n\n return { storage, useLogger }\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,oBAAoB,aAAqB;CACvD,MAAM,UAAU,IAAI,mBAAoC;CAExD,SAAS,YAA4E;EACnF,MAAM,SAAS,QAAQ,UAAU;AACjC,MAAI,CAAC,OACH,OAAM,IAAI,MACR,sDAAsD,cACvD;;AAGH,SAAO;;AAGT,QAAO;EAAE;EAAS;EAAW"}
|
package/dist/stream.d.mts
CHANGED
package/dist/stream.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.mts","names":[],"sources":["../src/stream.ts"],"mappings":";;;;UA0BiB,kBAAA;EA+CiB;;;;;;EAxChC,MAAA;EA2BA;;;;EAtBA,MAAA,IAAU,KAAA,EAAO,SAAA;EA8BH;;;;;;EAvBd,kBAAA;AAAA;;UAIe,WAAA;EAgDgB;;;;EA3C/B,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;EA2CoB;;;AAsJrE;;EA3LE,SAAA,GAAY,QAAA,GAAW,KAAA,EAAO,SAAA;EA2L2C;;;;;;AAS3E;EA5LE,MAAA,QAAc,qBAAA,CAAsB,SAAA;;;;AAkMtC;EA7LE,MAAA,iBAAuB,SAAA;;WAEd,eAAA;EAkMT;EAAA,SAhMS,YAAA;EA8MT;;;;EAzMA,KAAA;AAAA;;AAoOF;;;iBArNgB,iBAAA,CAAkB,OAAA,GAAS,kBAAA,GAA0B,WAAA;;;;;;;;;;;;;;;;iBAsJrD,gBAAA,CAAiB,OAAA,GAAU,kBAAA,GAAqB,WAAA;;;;AA6HhE;iBApHgB,gBAAA,CAAiB,MAAA,EAAQ,WAAA;;UAMxB,mBAAA;EA8GmE;;;;;;EAvGlF,IAAA;EAuGkF;;;
|
|
1
|
+
{"version":3,"file":"stream.d.mts","names":[],"sources":["../src/stream.ts"],"mappings":";;;;UA0BiB,kBAAA;EA+CiB;;;;;;EAxChC,MAAA;EA2BA;;;;EAtBA,MAAA,IAAU,KAAA,EAAO,SAAA;EA8BH;;;;;;EAvBd,kBAAA;AAAA;;UAIe,WAAA;EAgDgB;;;;EA3C/B,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;EA2CoB;;;AAsJrE;;EA3LE,SAAA,GAAY,QAAA,GAAW,KAAA,EAAO,SAAA;EA2L2C;;;;;;AAS3E;EA5LE,MAAA,QAAc,qBAAA,CAAsB,SAAA;;;;AAkMtC;EA7LE,MAAA,iBAAuB,SAAA;;WAEd,eAAA;EAkMT;EAAA,SAhMS,YAAA;EA8MT;;;;EAzMA,KAAA;AAAA;;AAoOF;;;iBArNgB,iBAAA,CAAkB,OAAA,GAAS,kBAAA,GAA0B,WAAA;;;;;;;;;;;;;;;;iBAsJrD,gBAAA,CAAiB,OAAA,GAAU,kBAAA,GAAqB,WAAA;;;;AA6HhE;iBApHgB,gBAAA,CAAiB,MAAA,EAAQ,WAAA;;UAMxB,mBAAA;EA8GmE;;;;;;EAvGlF,IAAA;EAuGkF;;;AAmNpF;;;EAnTE,IAAA;EAmTuC;;;;;;EA5SvC,KAAA;;;;;;EAMA,WAAA;;;;;;EAMA,MAAA;;;;;EAKA,MAAA;;;;;;EAMA,UAAA;AAAA;;UAIe,YAAA;;WAEN,GAAA;;WAEA,IAAA;;;;;;;;WAQA,KAAA,GAAQ,GAAA,EAAK,YAAA,GAAe,YAAA,OAAmB,OAAA;;WAE/C,MAAA,EAAQ,WAAA;;EAEjB,KAAA,QAAa,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8CO,iBAAA,CAAkB,OAAA,GAAS,mBAAA,GAA2B,OAAA,CAAQ,YAAA;;iBAmNpE,yBAAA,CAAA"}
|
package/dist/stream.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as EVLOG_VERSION } from "./http-
|
|
1
|
+
import { n as EVLOG_VERSION } from "./http-CuZ6Cm2M.mjs";
|
|
2
2
|
//#region src/stream.ts
|
|
3
3
|
const DEFAULT_BUFFER = 500;
|
|
4
4
|
const DEFAULT_QUEUE = 1e3;
|
|
@@ -269,6 +269,12 @@ async function startStreamServer(options = {}) {
|
|
|
269
269
|
}));
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
|
+
if (url.pathname !== "/" && url.pathname !== "") {
|
|
273
|
+
writeCors(res);
|
|
274
|
+
res.writeHead(404);
|
|
275
|
+
res.end("not found");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
272
278
|
writeCors(res);
|
|
273
279
|
res.writeHead(200, {
|
|
274
280
|
"Content-Type": "text/event-stream; charset=utf-8",
|
package/dist/stream.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.mjs","names":[],"sources":["../src/stream.ts"],"sourcesContent":["/**\n * In-process event stream — the foundation for any local consumer (devtools,\n * dashboards, CLIs, SSE/WebSocket bridges) to observe events flowing through\n * the drain pipeline without re-implementing one.\n *\n * @example\n * ```ts\n * import { createStreamDrain } from 'evlog/stream'\n *\n * const stream = createStreamDrain({ buffer: 200 })\n * nitroApp.hooks.hook('evlog:drain', stream.drain)\n *\n * stream.subscribe((event) => {\n * if (event.level === 'error') notifyOps(event)\n * })\n *\n * for await (const event of stream.events()) {\n * console.log(event.timestamp, event.action ?? event.message)\n * }\n * ```\n */\n\nimport type { DrainContext, WideEvent } from './types'\nimport { EVLOG_VERSION } from './shared/http'\n\n/** Configuration accepted by {@link createStreamDrain}. */\nexport interface StreamDrainOptions {\n /**\n * Number of recent events kept in the ring buffer and replayed to new\n * subscribers via {@link StreamDrain.recent}. Set to `0` to disable\n * replay.\n * @default 500\n */\n buffer?: number\n /**\n * Optional predicate run on each drained event — return `false` to skip\n * the event entirely (it is neither buffered nor delivered).\n */\n filter?: (event: WideEvent) => boolean\n /**\n * Per-subscriber queue size for the {@link StreamDrain.events} async\n * iterator. When the consumer falls behind by more than this many events,\n * the oldest queued events are dropped — the drain is never blocked.\n * @default 1000\n */\n perSubscriberQueue?: number\n}\n\n/** Live drain that exposes its events to in-process subscribers. */\nexport interface StreamDrain {\n /**\n * Drain callback. Pass to `nitroApp.hooks.hook('evlog:drain', stream.drain)`\n * or to a plugin via `drainPlugin('stream', stream.drain)`.\n */\n drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /**\n * Register a synchronous listener. Errors thrown by the listener are\n * caught and logged — they never affect other subscribers or the drain.\n * @returns Unsubscribe function.\n */\n subscribe: (listener: (event: WideEvent) => void) => () => void\n /**\n * Async iterator over live events. Each call returns a fresh iterator —\n * past events from the ring buffer are NOT replayed. Combine with\n * {@link StreamDrain.recent} to seed history.\n *\n * Calling `return()` (e.g. via `break`) cleanly unsubscribes.\n */\n events: () => AsyncIterableIterator<WideEvent>\n /**\n * Snapshot of buffered events (oldest first, most recent last). Useful\n * to seed a new connection / UI panel before switching to live updates.\n */\n recent: () => readonly WideEvent[]\n /** Number of currently active subscribers (sync + async iterators). */\n readonly subscriberCount: number\n /** Number of events dropped because the buffer was disabled or wrapped. */\n readonly droppedCount: number\n /**\n * Disconnect all subscribers and end any pending async iterators. The\n * stream itself remains usable — new subscriptions still work.\n */\n close: () => void\n}\n\nconst DEFAULT_BUFFER = 500\nconst DEFAULT_QUEUE = 1000\n\ninterface AsyncSubscriber {\n push: (event: WideEvent) => void\n end: () => void\n}\n\n/**\n * Create an in-process {@link StreamDrain}. Multiple stream drains can\n * coexist in the same process — they are fully independent.\n */\nexport function createStreamDrain(options: StreamDrainOptions = {}): StreamDrain {\n const bufferSize = Math.max(0, Math.floor(options.buffer ?? DEFAULT_BUFFER))\n const queueLimit = Math.max(1, Math.floor(options.perSubscriberQueue ?? DEFAULT_QUEUE))\n const { filter } = options\n\n const buffer: WideEvent[] = []\n const syncListeners = new Set<(event: WideEvent) => void>()\n const asyncSubscribers = new Set<AsyncSubscriber>()\n let dropped = 0\n\n function publish(event: WideEvent): void {\n if (filter && !filter(event)) return\n\n if (bufferSize > 0) {\n buffer.push(event)\n while (buffer.length > bufferSize) {\n buffer.shift()\n dropped++\n }\n }\n\n for (const listener of syncListeners) {\n try {\n listener(event)\n } catch (err) {\n console.error('[evlog/stream] subscriber threw:', err)\n }\n }\n\n for (const sub of asyncSubscribers) {\n sub.push(event)\n }\n }\n\n const drain: StreamDrain['drain'] = (ctx) => {\n const contexts = Array.isArray(ctx) ? ctx : [ctx]\n for (const c of contexts) {\n if (c?.event) publish(c.event)\n }\n return Promise.resolve()\n }\n\n const subscribe: StreamDrain['subscribe'] = (listener) => {\n syncListeners.add(listener)\n return () => {\n syncListeners.delete(listener)\n }\n }\n\n function createAsyncIterator(): AsyncIterableIterator<WideEvent> {\n const queue: WideEvent[] = []\n let pendingResolve: ((result: IteratorResult<WideEvent>) => void) | null = null\n let closed = false\n\n const subscriber: AsyncSubscriber = {\n push(event) {\n if (closed) return\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: event, done: false })\n return\n }\n queue.push(event)\n while (queue.length > queueLimit) {\n queue.shift()\n dropped++\n }\n },\n end() {\n if (closed) return\n closed = true\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n },\n }\n\n asyncSubscribers.add(subscriber)\n\n const iterator: AsyncIterableIterator<WideEvent> = {\n [Symbol.asyncIterator]() {\n return iterator\n },\n next(): Promise<IteratorResult<WideEvent>> {\n if (queue.length > 0) {\n return Promise.resolve({ value: queue.shift()!, done: false })\n }\n if (closed) {\n return Promise.resolve({ value: undefined, done: true })\n }\n return new Promise((resolve) => {\n pendingResolve = resolve\n })\n },\n return(): Promise<IteratorResult<WideEvent>> {\n closed = true\n asyncSubscribers.delete(subscriber)\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n return Promise.resolve({ value: undefined, done: true })\n },\n }\n\n return iterator\n }\n\n return {\n drain,\n subscribe,\n events: createAsyncIterator,\n recent: () => buffer.slice(),\n get subscriberCount() {\n return syncListeners.size + asyncSubscribers.size\n },\n get droppedCount() {\n return dropped\n },\n close() {\n syncListeners.clear()\n for (const sub of asyncSubscribers) {\n sub.end()\n }\n asyncSubscribers.clear()\n },\n }\n}\n\nlet defaultStream: StreamDrain | null = null\n\n/**\n * Lazily create / return the process-wide default {@link StreamDrain}.\n *\n * Used by built-in framework integrations (Nuxt SSE bridge, devtools panel)\n * so they share a single buffer. Custom code can subscribe to this stream\n * to observe everything draining through evlog without registering a new\n * drain.\n *\n * @example\n * ```ts\n * import { getDefaultStream } from 'evlog/stream'\n *\n * getDefaultStream().subscribe((event) => console.log(event.action))\n * ```\n */\nexport function getDefaultStream(options?: StreamDrainOptions): StreamDrain {\n if (!defaultStream) defaultStream = createStreamDrain(options)\n return defaultStream\n}\n\n/**\n * Replace or clear the default stream. Pass `null` to reset (mostly useful\n * in tests).\n */\nexport function setDefaultStream(stream: StreamDrain | null): void {\n defaultStream?.close()\n defaultStream = stream\n}\n\n/** Configuration accepted by {@link startStreamServer}. */\nexport interface StreamServerOptions {\n /**\n * TCP port to listen on. `0` (default) lets the OS pick an ephemeral port —\n * the actual port is exposed on the returned `port` / `url` and printed in\n * the startup banner.\n * @default 0\n */\n port?: number\n /**\n * Listen address. Default `127.0.0.1` — local-only, never exposed to the\n * LAN. Override to `0.0.0.0` only if you understand the security\n * implications.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Bearer token. When set, the server requires `Authorization: Bearer\n * <token>` on every request and 401s otherwise. When unset, only\n * connections from `127.0.0.1` (and equivalent local hosts) are\n * accepted — same-origin policy applies on non-local hosts.\n */\n token?: string\n /**\n * Heartbeat interval (ms) sent as `event: ping` to keep the connection\n * alive through proxies and detect disconnects.\n * @default 15000\n */\n heartbeatMs?: number\n /**\n * Ring buffer size kept on the underlying default stream — replayed for\n * late-joining clients via `?since=<iso>`.\n * @default 500\n */\n buffer?: number\n /**\n * Print `[evlog] Stream → http://...` at startup.\n * @default true\n */\n banner?: boolean\n /**\n * Directory where `stream.url` is written so external tools can discover\n * the server. Set to `false` to disable.\n * @default '.evlog'\n */\n urlFileDir?: string | false\n}\n\n/** Return value of {@link startStreamServer}. */\nexport interface StreamServer {\n /** Listening URL, e.g. `http://127.0.0.1:51203`. */\n readonly url: string\n /** Resolved TCP port (useful when `port: 0`). */\n readonly port: number\n /**\n * Drain function — register on `evlog:drain` (Nitro / Nuxt), pass to\n * `initLogger({ drain })` (Next / standalone), or call directly.\n *\n * Equivalent to the underlying default stream's drain — events flow\n * through and reach every connected SSE client.\n */\n readonly drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /** The underlying in-process {@link StreamDrain}. */\n readonly stream: StreamDrain\n /** Stop the server, remove the URL file, and unsubscribe all clients. */\n close: () => Promise<void>\n}\n\nconst STREAM_DEFAULTS = {\n port: 0,\n host: '127.0.0.1',\n heartbeatMs: 15_000,\n buffer: 500,\n banner: true,\n urlFileDir: '.evlog' as string | false,\n}\n\nlet activeStreamServer: StreamServer | null = null\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (!host) return false\n const lower = host.toLowerCase()\n return lower.startsWith('localhost') || lower.startsWith('127.0.0.1') || lower.startsWith('[::1]')\n}\n\n/**\n * Start a local HTTP server that exposes the default in-process stream over\n * Server-Sent Events. Framework-agnostic: works in any Node / Bun process\n * (Nuxt, Next.js, Hono, Express, Fastify, raw scripts).\n *\n * The server binds to `127.0.0.1` on an ephemeral port by default — local\n * tools and browser tabs from the same machine can connect, but the LAN\n * cannot reach it.\n *\n * Idempotent: subsequent calls return the same instance until `close()` is\n * called.\n *\n * @example\n * ```ts\n * import { startStreamServer } from 'evlog/stream'\n *\n * const server = await startStreamServer()\n * console.log(server.url) // → http://127.0.0.1:51203\n *\n * // Hook into your drain pipeline (Nitro example):\n * nitroApp.hooks.hook('evlog:drain', server.drain)\n *\n * // Or for a standalone script with initLogger:\n * initLogger({ drain: server.drain })\n * ```\n */\nexport async function startStreamServer(options: StreamServerOptions = {}): Promise<StreamServer> {\n if (activeStreamServer) return activeStreamServer\n\n const opts = { ...STREAM_DEFAULTS, ...options }\n const stream = getDefaultStream({ buffer: opts.buffer })\n\n const { createServer } = await import('node:http')\n const { writeFile, unlink, mkdir } = await import('node:fs/promises')\n const { unlinkSync } = await import('node:fs')\n const { join } = await import('node:path')\n\n function envelopeFrame(type: 'event' | 'replay' | 'hello', data: unknown): string {\n return `data: ${JSON.stringify({ evlog: '1', type, data })}\\n\\n`\n }\n\n function writeCors(res: import('node:http').ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Authorization, Accept')\n }\n\n const server = createServer((req, res) => {\n if (req.method === 'OPTIONS') {\n writeCors(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'GET') {\n res.writeHead(405)\n res.end('method not allowed')\n return\n }\n\n if (opts.token) {\n if (req.headers.authorization !== `Bearer ${opts.token}`) {\n writeCors(res)\n res.writeHead(401)\n res.end('unauthorized')\n return\n }\n } else {\n const origin = typeof req.headers.origin === 'string' ? req.headers.origin : null\n if (origin) {\n let originHost: string | null = null\n try {\n originHost = new URL(origin).host\n } catch {\n originHost = null\n }\n if (!isLocalHost(originHost ?? undefined)) {\n writeCors(res)\n res.writeHead(403)\n res.end('forbidden')\n return\n }\n }\n }\n\n const url = new URL(req.url ?? '/', 'http://localhost')\n\n if (url.pathname === '/info') {\n writeCors(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n return\n }\n\n writeCors(res)\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Evlog-Version': EVLOG_VERSION,\n })\n\n res.write(envelopeFrame('hello', {\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n\n const since = url.searchParams.get('since')\n const sinceMs = since ? Date.parse(since) : Number.NaN\n if (Number.isFinite(sinceMs)) {\n for (const past of stream.recent()) {\n const ts = typeof past.timestamp === 'string' ? Date.parse(past.timestamp) : Number.NaN\n if (Number.isFinite(ts) && ts >= sinceMs) {\n res.write(envelopeFrame('replay', past))\n }\n }\n }\n\n let closed = false\n const unsubscribe = stream.subscribe((event) => {\n if (closed) return\n res.write(envelopeFrame('event', event))\n })\n\n const heartbeat = setInterval(() => {\n if (closed) return\n res.write(`event: ping\\ndata: ${JSON.stringify({ evlog: '1', type: 'ping', data: { t: Date.now() } })}\\n\\n`)\n }, opts.heartbeatMs)\n\n const cleanup = () => {\n if (closed) return\n closed = true\n clearInterval(heartbeat)\n unsubscribe()\n try {\n res.end()\n } catch {\n // noop\n }\n }\n\n req.on('close', cleanup)\n req.on('error', cleanup)\n res.on('close', cleanup)\n res.on('error', cleanup)\n })\n\n const port: number = await new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(opts.port, opts.host, () => {\n const addr = server.address()\n if (addr && typeof addr === 'object') {\n resolve(addr.port)\n } else {\n reject(new Error('[evlog/stream] failed to determine listening port'))\n }\n })\n })\n\n const url = `http://${opts.host}:${port}`\n\n let urlFile: string | undefined\n if (opts.urlFileDir !== false) {\n try {\n await mkdir(opts.urlFileDir, { recursive: true })\n urlFile = join(opts.urlFileDir, 'stream.url')\n await writeFile(urlFile, url, 'utf-8')\n } catch (err) {\n console.warn('[evlog/stream] failed to write stream.url:', err)\n }\n }\n\n if (opts.banner) {\n console.info(`\\n [evlog] Stream → ${url}\\n`)\n }\n\n const exitHandler = () => {\n if (urlFile) {\n try {\n unlinkSync(urlFile)\n } catch {\n // noop\n }\n }\n server.close()\n }\n process.once('SIGINT', exitHandler)\n process.once('SIGTERM', exitHandler)\n process.once('exit', exitHandler)\n\n const close = async (): Promise<void> => {\n process.off('SIGINT', exitHandler)\n process.off('SIGTERM', exitHandler)\n process.off('exit', exitHandler)\n if (urlFile) {\n try {\n await unlink(urlFile)\n } catch {\n // noop\n }\n }\n await new Promise<void>((resolve, reject) => {\n server.close(err => err ? reject(err) : resolve())\n })\n if (activeStreamServer === result) activeStreamServer = null\n }\n\n const result: StreamServer = {\n url,\n port,\n drain: ctx => stream.drain(ctx),\n stream,\n close,\n }\n\n activeStreamServer = result\n return result\n}\n\n/** @internal Used by tests to reset state between specs. */\nexport function resetStreamServerForTests(): void {\n activeStreamServer = null\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.mjs","names":[],"sources":["../src/stream.ts"],"sourcesContent":["/**\n * In-process event stream — the foundation for any local consumer (devtools,\n * dashboards, CLIs, SSE/WebSocket bridges) to observe events flowing through\n * the drain pipeline without re-implementing one.\n *\n * @example\n * ```ts\n * import { createStreamDrain } from 'evlog/stream'\n *\n * const stream = createStreamDrain({ buffer: 200 })\n * nitroApp.hooks.hook('evlog:drain', stream.drain)\n *\n * stream.subscribe((event) => {\n * if (event.level === 'error') notifyOps(event)\n * })\n *\n * for await (const event of stream.events()) {\n * console.log(event.timestamp, event.action ?? event.message)\n * }\n * ```\n */\n\nimport type { DrainContext, WideEvent } from './types'\nimport { EVLOG_VERSION } from './shared/http'\n\n/** Configuration accepted by {@link createStreamDrain}. */\nexport interface StreamDrainOptions {\n /**\n * Number of recent events kept in the ring buffer and replayed to new\n * subscribers via {@link StreamDrain.recent}. Set to `0` to disable\n * replay.\n * @default 500\n */\n buffer?: number\n /**\n * Optional predicate run on each drained event — return `false` to skip\n * the event entirely (it is neither buffered nor delivered).\n */\n filter?: (event: WideEvent) => boolean\n /**\n * Per-subscriber queue size for the {@link StreamDrain.events} async\n * iterator. When the consumer falls behind by more than this many events,\n * the oldest queued events are dropped — the drain is never blocked.\n * @default 1000\n */\n perSubscriberQueue?: number\n}\n\n/** Live drain that exposes its events to in-process subscribers. */\nexport interface StreamDrain {\n /**\n * Drain callback. Pass to `nitroApp.hooks.hook('evlog:drain', stream.drain)`\n * or to a plugin via `drainPlugin('stream', stream.drain)`.\n */\n drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /**\n * Register a synchronous listener. Errors thrown by the listener are\n * caught and logged — they never affect other subscribers or the drain.\n * @returns Unsubscribe function.\n */\n subscribe: (listener: (event: WideEvent) => void) => () => void\n /**\n * Async iterator over live events. Each call returns a fresh iterator —\n * past events from the ring buffer are NOT replayed. Combine with\n * {@link StreamDrain.recent} to seed history.\n *\n * Calling `return()` (e.g. via `break`) cleanly unsubscribes.\n */\n events: () => AsyncIterableIterator<WideEvent>\n /**\n * Snapshot of buffered events (oldest first, most recent last). Useful\n * to seed a new connection / UI panel before switching to live updates.\n */\n recent: () => readonly WideEvent[]\n /** Number of currently active subscribers (sync + async iterators). */\n readonly subscriberCount: number\n /** Number of events dropped because the buffer was disabled or wrapped. */\n readonly droppedCount: number\n /**\n * Disconnect all subscribers and end any pending async iterators. The\n * stream itself remains usable — new subscriptions still work.\n */\n close: () => void\n}\n\nconst DEFAULT_BUFFER = 500\nconst DEFAULT_QUEUE = 1000\n\ninterface AsyncSubscriber {\n push: (event: WideEvent) => void\n end: () => void\n}\n\n/**\n * Create an in-process {@link StreamDrain}. Multiple stream drains can\n * coexist in the same process — they are fully independent.\n */\nexport function createStreamDrain(options: StreamDrainOptions = {}): StreamDrain {\n const bufferSize = Math.max(0, Math.floor(options.buffer ?? DEFAULT_BUFFER))\n const queueLimit = Math.max(1, Math.floor(options.perSubscriberQueue ?? DEFAULT_QUEUE))\n const { filter } = options\n\n const buffer: WideEvent[] = []\n const syncListeners = new Set<(event: WideEvent) => void>()\n const asyncSubscribers = new Set<AsyncSubscriber>()\n let dropped = 0\n\n function publish(event: WideEvent): void {\n if (filter && !filter(event)) return\n\n if (bufferSize > 0) {\n buffer.push(event)\n while (buffer.length > bufferSize) {\n buffer.shift()\n dropped++\n }\n }\n\n for (const listener of syncListeners) {\n try {\n listener(event)\n } catch (err) {\n console.error('[evlog/stream] subscriber threw:', err)\n }\n }\n\n for (const sub of asyncSubscribers) {\n sub.push(event)\n }\n }\n\n const drain: StreamDrain['drain'] = (ctx) => {\n const contexts = Array.isArray(ctx) ? ctx : [ctx]\n for (const c of contexts) {\n if (c?.event) publish(c.event)\n }\n return Promise.resolve()\n }\n\n const subscribe: StreamDrain['subscribe'] = (listener) => {\n syncListeners.add(listener)\n return () => {\n syncListeners.delete(listener)\n }\n }\n\n function createAsyncIterator(): AsyncIterableIterator<WideEvent> {\n const queue: WideEvent[] = []\n let pendingResolve: ((result: IteratorResult<WideEvent>) => void) | null = null\n let closed = false\n\n const subscriber: AsyncSubscriber = {\n push(event) {\n if (closed) return\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: event, done: false })\n return\n }\n queue.push(event)\n while (queue.length > queueLimit) {\n queue.shift()\n dropped++\n }\n },\n end() {\n if (closed) return\n closed = true\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n },\n }\n\n asyncSubscribers.add(subscriber)\n\n const iterator: AsyncIterableIterator<WideEvent> = {\n [Symbol.asyncIterator]() {\n return iterator\n },\n next(): Promise<IteratorResult<WideEvent>> {\n if (queue.length > 0) {\n return Promise.resolve({ value: queue.shift()!, done: false })\n }\n if (closed) {\n return Promise.resolve({ value: undefined, done: true })\n }\n return new Promise((resolve) => {\n pendingResolve = resolve\n })\n },\n return(): Promise<IteratorResult<WideEvent>> {\n closed = true\n asyncSubscribers.delete(subscriber)\n if (pendingResolve) {\n const resolve = pendingResolve\n pendingResolve = null\n resolve({ value: undefined, done: true })\n }\n return Promise.resolve({ value: undefined, done: true })\n },\n }\n\n return iterator\n }\n\n return {\n drain,\n subscribe,\n events: createAsyncIterator,\n recent: () => buffer.slice(),\n get subscriberCount() {\n return syncListeners.size + asyncSubscribers.size\n },\n get droppedCount() {\n return dropped\n },\n close() {\n syncListeners.clear()\n for (const sub of asyncSubscribers) {\n sub.end()\n }\n asyncSubscribers.clear()\n },\n }\n}\n\nlet defaultStream: StreamDrain | null = null\n\n/**\n * Lazily create / return the process-wide default {@link StreamDrain}.\n *\n * Used by built-in framework integrations (Nuxt SSE bridge, devtools panel)\n * so they share a single buffer. Custom code can subscribe to this stream\n * to observe everything draining through evlog without registering a new\n * drain.\n *\n * @example\n * ```ts\n * import { getDefaultStream } from 'evlog/stream'\n *\n * getDefaultStream().subscribe((event) => console.log(event.action))\n * ```\n */\nexport function getDefaultStream(options?: StreamDrainOptions): StreamDrain {\n if (!defaultStream) defaultStream = createStreamDrain(options)\n return defaultStream\n}\n\n/**\n * Replace or clear the default stream. Pass `null` to reset (mostly useful\n * in tests).\n */\nexport function setDefaultStream(stream: StreamDrain | null): void {\n defaultStream?.close()\n defaultStream = stream\n}\n\n/** Configuration accepted by {@link startStreamServer}. */\nexport interface StreamServerOptions {\n /**\n * TCP port to listen on. `0` (default) lets the OS pick an ephemeral port —\n * the actual port is exposed on the returned `port` / `url` and printed in\n * the startup banner.\n * @default 0\n */\n port?: number\n /**\n * Listen address. Default `127.0.0.1` — local-only, never exposed to the\n * LAN. Override to `0.0.0.0` only if you understand the security\n * implications.\n * @default '127.0.0.1'\n */\n host?: string\n /**\n * Bearer token. When set, the server requires `Authorization: Bearer\n * <token>` on every request and 401s otherwise. When unset, only\n * connections from `127.0.0.1` (and equivalent local hosts) are\n * accepted — same-origin policy applies on non-local hosts.\n */\n token?: string\n /**\n * Heartbeat interval (ms) sent as `event: ping` to keep the connection\n * alive through proxies and detect disconnects.\n * @default 15000\n */\n heartbeatMs?: number\n /**\n * Ring buffer size kept on the underlying default stream — replayed for\n * late-joining clients via `?since=<iso>`.\n * @default 500\n */\n buffer?: number\n /**\n * Print `[evlog] Stream → http://...` at startup.\n * @default true\n */\n banner?: boolean\n /**\n * Directory where `stream.url` is written so external tools can discover\n * the server. Set to `false` to disable.\n * @default '.evlog'\n */\n urlFileDir?: string | false\n}\n\n/** Return value of {@link startStreamServer}. */\nexport interface StreamServer {\n /** Listening URL, e.g. `http://127.0.0.1:51203`. */\n readonly url: string\n /** Resolved TCP port (useful when `port: 0`). */\n readonly port: number\n /**\n * Drain function — register on `evlog:drain` (Nitro / Nuxt), pass to\n * `initLogger({ drain })` (Next / standalone), or call directly.\n *\n * Equivalent to the underlying default stream's drain — events flow\n * through and reach every connected SSE client.\n */\n readonly drain: (ctx: DrainContext | DrainContext[]) => Promise<void>\n /** The underlying in-process {@link StreamDrain}. */\n readonly stream: StreamDrain\n /** Stop the server, remove the URL file, and unsubscribe all clients. */\n close: () => Promise<void>\n}\n\nconst STREAM_DEFAULTS = {\n port: 0,\n host: '127.0.0.1',\n heartbeatMs: 15_000,\n buffer: 500,\n banner: true,\n urlFileDir: '.evlog' as string | false,\n}\n\nlet activeStreamServer: StreamServer | null = null\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (!host) return false\n const lower = host.toLowerCase()\n return lower.startsWith('localhost') || lower.startsWith('127.0.0.1') || lower.startsWith('[::1]')\n}\n\n/**\n * Start a local HTTP server that exposes the default in-process stream over\n * Server-Sent Events. Framework-agnostic: works in any Node / Bun process\n * (Nuxt, Next.js, Hono, Express, Fastify, raw scripts).\n *\n * The server binds to `127.0.0.1` on an ephemeral port by default — local\n * tools and browser tabs from the same machine can connect, but the LAN\n * cannot reach it.\n *\n * Idempotent: subsequent calls return the same instance until `close()` is\n * called.\n *\n * @example\n * ```ts\n * import { startStreamServer } from 'evlog/stream'\n *\n * const server = await startStreamServer()\n * console.log(server.url) // → http://127.0.0.1:51203\n *\n * // Hook into your drain pipeline (Nitro example):\n * nitroApp.hooks.hook('evlog:drain', server.drain)\n *\n * // Or for a standalone script with initLogger:\n * initLogger({ drain: server.drain })\n * ```\n */\nexport async function startStreamServer(options: StreamServerOptions = {}): Promise<StreamServer> {\n if (activeStreamServer) return activeStreamServer\n\n const opts = { ...STREAM_DEFAULTS, ...options }\n const stream = getDefaultStream({ buffer: opts.buffer })\n\n const { createServer } = await import('node:http')\n const { writeFile, unlink, mkdir } = await import('node:fs/promises')\n const { unlinkSync } = await import('node:fs')\n const { join } = await import('node:path')\n\n function envelopeFrame(type: 'event' | 'replay' | 'hello', data: unknown): string {\n return `data: ${JSON.stringify({ evlog: '1', type, data })}\\n\\n`\n }\n\n function writeCors(res: import('node:http').ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Authorization, Accept')\n }\n\n const server = createServer((req, res) => {\n if (req.method === 'OPTIONS') {\n writeCors(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'GET') {\n res.writeHead(405)\n res.end('method not allowed')\n return\n }\n\n if (opts.token) {\n if (req.headers.authorization !== `Bearer ${opts.token}`) {\n writeCors(res)\n res.writeHead(401)\n res.end('unauthorized')\n return\n }\n } else {\n const origin = typeof req.headers.origin === 'string' ? req.headers.origin : null\n if (origin) {\n let originHost: string | null = null\n try {\n originHost = new URL(origin).host\n } catch {\n originHost = null\n }\n if (!isLocalHost(originHost ?? undefined)) {\n writeCors(res)\n res.writeHead(403)\n res.end('forbidden')\n return\n }\n }\n }\n\n const url = new URL(req.url ?? '/', 'http://localhost')\n\n if (url.pathname === '/info') {\n writeCors(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n return\n }\n\n // Only the root path is SSE — stray GETs (e.g. health probes) must not\n // return 200 or tooling that scans stdout for loopback URLs can mis-detect\n // this server as something else (eve/next dev proxy is one real case).\n if (url.pathname !== '/' && url.pathname !== '') {\n writeCors(res)\n res.writeHead(404)\n res.end('not found')\n return\n }\n\n writeCors(res)\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n 'Connection': 'keep-alive',\n 'X-Accel-Buffering': 'no',\n 'X-Evlog-Version': EVLOG_VERSION,\n })\n\n res.write(envelopeFrame('hello', {\n evlogVersion: EVLOG_VERSION,\n bufferSize: opts.buffer,\n heartbeatMs: opts.heartbeatMs,\n }))\n\n const since = url.searchParams.get('since')\n const sinceMs = since ? Date.parse(since) : Number.NaN\n if (Number.isFinite(sinceMs)) {\n for (const past of stream.recent()) {\n const ts = typeof past.timestamp === 'string' ? Date.parse(past.timestamp) : Number.NaN\n if (Number.isFinite(ts) && ts >= sinceMs) {\n res.write(envelopeFrame('replay', past))\n }\n }\n }\n\n let closed = false\n const unsubscribe = stream.subscribe((event) => {\n if (closed) return\n res.write(envelopeFrame('event', event))\n })\n\n const heartbeat = setInterval(() => {\n if (closed) return\n res.write(`event: ping\\ndata: ${JSON.stringify({ evlog: '1', type: 'ping', data: { t: Date.now() } })}\\n\\n`)\n }, opts.heartbeatMs)\n\n const cleanup = () => {\n if (closed) return\n closed = true\n clearInterval(heartbeat)\n unsubscribe()\n try {\n res.end()\n } catch {\n // noop\n }\n }\n\n req.on('close', cleanup)\n req.on('error', cleanup)\n res.on('close', cleanup)\n res.on('error', cleanup)\n })\n\n const port: number = await new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(opts.port, opts.host, () => {\n const addr = server.address()\n if (addr && typeof addr === 'object') {\n resolve(addr.port)\n } else {\n reject(new Error('[evlog/stream] failed to determine listening port'))\n }\n })\n })\n\n const url = `http://${opts.host}:${port}`\n\n let urlFile: string | undefined\n if (opts.urlFileDir !== false) {\n try {\n await mkdir(opts.urlFileDir, { recursive: true })\n urlFile = join(opts.urlFileDir, 'stream.url')\n await writeFile(urlFile, url, 'utf-8')\n } catch (err) {\n console.warn('[evlog/stream] failed to write stream.url:', err)\n }\n }\n\n if (opts.banner) {\n console.info(`\\n [evlog] Stream → ${url}\\n`)\n }\n\n const exitHandler = () => {\n if (urlFile) {\n try {\n unlinkSync(urlFile)\n } catch {\n // noop\n }\n }\n server.close()\n }\n process.once('SIGINT', exitHandler)\n process.once('SIGTERM', exitHandler)\n process.once('exit', exitHandler)\n\n const close = async (): Promise<void> => {\n process.off('SIGINT', exitHandler)\n process.off('SIGTERM', exitHandler)\n process.off('exit', exitHandler)\n if (urlFile) {\n try {\n await unlink(urlFile)\n } catch {\n // noop\n }\n }\n await new Promise<void>((resolve, reject) => {\n server.close(err => err ? reject(err) : resolve())\n })\n if (activeStreamServer === result) activeStreamServer = null\n }\n\n const result: StreamServer = {\n url,\n port,\n drain: ctx => stream.drain(ctx),\n stream,\n close,\n }\n\n activeStreamServer = result\n return result\n}\n\n/** @internal Used by tests to reset state between specs. */\nexport function resetStreamServerForTests(): void {\n activeStreamServer = null\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as AuditableLogger } from "../audit-
|
|
2
|
-
import { t as BaseEvlogOptions } from "../middleware-
|
|
1
|
+
import { l as AuditableLogger } from "../audit-BZrUvjfW.mjs";
|
|
2
|
+
import { t as BaseEvlogOptions } from "../middleware-fbtEs6bq.mjs";
|
|
3
3
|
//#region src/sveltekit/index.d.ts
|
|
4
4
|
declare const useLogger: <T extends object = Record<string, unknown>>() => AuditableLogger<T>;
|
|
5
5
|
type EvlogSvelteKitOptions = BaseEvlogOptions;
|
package/dist/sveltekit/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { EvlogError } from "../error.mjs";
|
|
2
2
|
import { t as extractSafeHeaders } from "../headers-VtmnWcfn.mjs";
|
|
3
3
|
import { t as extractErrorStatus } from "../errors-DA0cyr8q.mjs";
|
|
4
|
-
import { a as serializeEvlogErrorResponse, i as resolveEvlogError } from "../nitro-
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
7
|
-
import { t as
|
|
4
|
+
import { a as serializeEvlogErrorResponse, i as resolveEvlogError } from "../nitro-DYFCSlho.mjs";
|
|
5
|
+
import { t as createMiddlewareLogger } from "../middleware-Cdebyfdt.mjs";
|
|
6
|
+
import { t as attachForkToLogger } from "../fork-S9gpZmF8.mjs";
|
|
7
|
+
import { t as registerDiskPrettyErrorSnippetReader } from "../register-disk-snippet-B5svlT8-.mjs";
|
|
8
|
+
import { t as createLoggerStorage } from "../storage-BeFdoGTI.mjs";
|
|
8
9
|
//#region src/sveltekit/index.ts
|
|
9
10
|
const { storage, useLogger } = createLoggerStorage("handle context. Make sure evlog() handle is added to your hooks.server.ts.");
|
|
10
11
|
registerDiskPrettyErrorSnippetReader();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/sveltekit/index.ts"],"sourcesContent":["import type { RequestLogger } from '../types'\nimport { registerDiskPrettyErrorSnippetReader } from '../shared/register-disk-snippet'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\nimport { EvlogError } from '../error'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'handle context. Make sure evlog() handle is added to your hooks.server.ts.',\n)\n\nvoid registerDiskPrettyErrorSnippetReader()\n\nexport type EvlogSvelteKitOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandle = (input: {\n event: { request: Request; url: URL; locals: Record<string, any> }\n resolve: (...args: any[]) => Response | Promise<Response>\n}) => Promise<Response>\n\n/**\n * SvelteKit `HandleServerError` signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandleServerError = (input: {\n error: unknown\n event: { request: Request; url: URL; locals: Record<string, any> }\n status: number\n message: string\n}) => MaybePromise<void | AppError>\n\ntype MaybePromise<T> = T | Promise<T>\n\n/** Minimal SvelteKit `App.Error` shape */\ninterface AppError {\n message: string\n [key: string]: unknown\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isRequestLogger(value: unknown): value is RequestLogger {\n return isPlainObject(value)\n && typeof value.error === 'function'\n && typeof value.emit === 'function'\n}\n\ninterface ContextEvlogError {\n name: 'EvlogError'\n status: number\n message: string\n why?: string\n fix?: string\n link?: string\n code?: string\n}\n\nfunction isContextEvlogError(value: unknown): value is Record<string, unknown> & ContextEvlogError {\n return isPlainObject(value)\n && value.name === 'EvlogError'\n && typeof value.status === 'number'\n && typeof value.message === 'string'\n}\n\nfunction evlogErrorFromContext(errorData: Record<string, unknown>): EvlogError {\n const nested = isPlainObject(errorData.data) ? errorData.data : undefined\n const readString = (key: string): string | undefined => {\n const direct = errorData[key]\n if (typeof direct === 'string') return direct\n const fromNested = nested?.[key]\n return typeof fromNested === 'string' ? fromNested : undefined\n }\n return new EvlogError({\n message: String(errorData.message),\n status: errorData.status as number,\n code: readString('code'),\n why: readString('why'),\n fix: readString('fix'),\n link: readString('link'),\n })\n}\n\nfunction readEvlogResponseData(response: Record<string, unknown>): { why?: string, fix?: string, link?: string } {\n const { data } = response\n if (!isPlainObject(data)) return {}\n return {\n why: typeof data.why === 'string' ? data.why : undefined,\n fix: typeof data.fix === 'string' ? data.fix : undefined,\n link: typeof data.link === 'string' ? data.link : undefined,\n }\n}\n\n/**\n * Create an evlog handle hook for SvelteKit.\n *\n * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper\n * or as the sole handle export.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-sveltekit-app' } })\n *\n * export const handle = evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { evlog } from 'evlog/sveltekit'\n *\n * export const handle = sequence(evlog(), yourOtherHook)\n * ```\n */\nexport function evlog(options: EvlogSvelteKitOptions = {}): SvelteKitHandle {\n return async ({ event, resolve }) => {\n const middlewareOpts = {\n method: event.request.method,\n path: event.url.pathname,\n requestId: event.request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(event.request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return await resolve(event)\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n event.locals.log = logger\n\n return storage.run(logger, async () => {\n try {\n const response = await resolve(event)\n\n // SvelteKit catches route errors internally and returns 500.\n // If handleError already logged an EvlogError with a specific status,\n // return a structured JSON response instead of SvelteKit's generic 500.\n const ctx = logger.getContext()\n const errorData = ctx.error\n if (response.status >= 500 && isContextEvlogError(errorData)) {\n const { status } = errorData\n await finish({ status })\n const body = serializeEvlogErrorResponse(evlogErrorFromContext(errorData), event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n return finishResponse(response)\n } catch (error) {\n await finish({ error: error instanceof Error ? error : new Error(String(error)) })\n\n // Return structured JSON for EvlogError (like NextJS withEvlog / Nuxt errorHandler)\n if (error instanceof EvlogError) {\n const status = error.status ?? 500\n const body = serializeEvlogErrorResponse(error, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n throw error\n }\n })\n }\n}\n\n/**\n * Create an evlog error handler for SvelteKit.\n *\n * Logs unhandled errors via `event.locals.log` (if available) and returns\n * structured error responses for `EvlogError` instances. For non-evlog errors,\n * returns a generic error response with sanitized messages in production.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { evlog, evlogHandleError } from 'evlog/sveltekit'\n *\n * export const handle = evlog()\n * export const handleError = evlogHandleError()\n * ```\n */\nexport function evlogHandleError(): SvelteKitHandleServerError {\n return ({ error, event, status, message }) => {\n const logger = isRequestLogger(event.locals.log) ? event.locals.log : undefined\n\n if (logger && error instanceof Error) {\n logger.error(error)\n }\n\n const evlogError = error instanceof Error ? resolveEvlogError(error) : null\n\n if (evlogError) {\n const errorStatus = extractErrorStatus(evlogError)\n const response = serializeEvlogErrorResponse(evlogError, event.url.pathname)\n return {\n message: typeof response.message === 'string' ? response.message : message,\n status: errorStatus,\n ...readEvlogResponseData(response),\n }\n }\n\n return { message, status }\n }\n}\n\n/**\n * Create both `handle` and `handleError` hooks in a single call.\n *\n * This is the recommended setup for SvelteKit — it returns both hooks\n * pre-configured and ready to export from `hooks.server.ts`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-app' } })\n *\n * export const { handle, handleError } = createEvlogHooks({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n *\n * const evlogHooks = createEvlogHooks()\n *\n * export const handle = sequence(evlogHooks.handle, yourOtherHook)\n * export const handleError = evlogHooks.handleError\n * ```\n */\nexport function createEvlogHooks(options: EvlogSvelteKitOptions = {}) {\n return {\n handle: evlog(options),\n handleError: evlogHandleError(),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/sveltekit/index.ts"],"sourcesContent":["import type { RequestLogger } from '../types'\nimport { registerDiskPrettyErrorSnippetReader } from '../shared/register-disk-snippet'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { attachForkToLogger } from '../shared/fork'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\nimport { EvlogError } from '../error'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'handle context. Make sure evlog() handle is added to your hooks.server.ts.',\n)\n\nvoid registerDiskPrettyErrorSnippetReader()\n\nexport type EvlogSvelteKitOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandle = (input: {\n event: { request: Request; url: URL; locals: Record<string, any> }\n resolve: (...args: any[]) => Response | Promise<Response>\n}) => Promise<Response>\n\n/**\n * SvelteKit `HandleServerError` signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandleServerError = (input: {\n error: unknown\n event: { request: Request; url: URL; locals: Record<string, any> }\n status: number\n message: string\n}) => MaybePromise<void | AppError>\n\ntype MaybePromise<T> = T | Promise<T>\n\n/** Minimal SvelteKit `App.Error` shape */\ninterface AppError {\n message: string\n [key: string]: unknown\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isRequestLogger(value: unknown): value is RequestLogger {\n return isPlainObject(value)\n && typeof value.error === 'function'\n && typeof value.emit === 'function'\n}\n\ninterface ContextEvlogError {\n name: 'EvlogError'\n status: number\n message: string\n why?: string\n fix?: string\n link?: string\n code?: string\n}\n\nfunction isContextEvlogError(value: unknown): value is Record<string, unknown> & ContextEvlogError {\n return isPlainObject(value)\n && value.name === 'EvlogError'\n && typeof value.status === 'number'\n && typeof value.message === 'string'\n}\n\nfunction evlogErrorFromContext(errorData: Record<string, unknown>): EvlogError {\n const nested = isPlainObject(errorData.data) ? errorData.data : undefined\n const readString = (key: string): string | undefined => {\n const direct = errorData[key]\n if (typeof direct === 'string') return direct\n const fromNested = nested?.[key]\n return typeof fromNested === 'string' ? fromNested : undefined\n }\n return new EvlogError({\n message: String(errorData.message),\n status: errorData.status as number,\n code: readString('code'),\n why: readString('why'),\n fix: readString('fix'),\n link: readString('link'),\n })\n}\n\nfunction readEvlogResponseData(response: Record<string, unknown>): { why?: string, fix?: string, link?: string } {\n const { data } = response\n if (!isPlainObject(data)) return {}\n return {\n why: typeof data.why === 'string' ? data.why : undefined,\n fix: typeof data.fix === 'string' ? data.fix : undefined,\n link: typeof data.link === 'string' ? data.link : undefined,\n }\n}\n\n/**\n * Create an evlog handle hook for SvelteKit.\n *\n * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper\n * or as the sole handle export.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-sveltekit-app' } })\n *\n * export const handle = evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { evlog } from 'evlog/sveltekit'\n *\n * export const handle = sequence(evlog(), yourOtherHook)\n * ```\n */\nexport function evlog(options: EvlogSvelteKitOptions = {}): SvelteKitHandle {\n return async ({ event, resolve }) => {\n const middlewareOpts = {\n method: event.request.method,\n path: event.url.pathname,\n requestId: event.request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(event.request.headers),\n ...options,\n }\n const { logger, finish, finishResponse, skipped } = createMiddlewareLogger(middlewareOpts)\n\n if (skipped) {\n return await resolve(event)\n }\n\n attachForkToLogger(storage, logger, middlewareOpts)\n event.locals.log = logger\n\n return storage.run(logger, async () => {\n try {\n const response = await resolve(event)\n\n // SvelteKit catches route errors internally and returns 500.\n // If handleError already logged an EvlogError with a specific status,\n // return a structured JSON response instead of SvelteKit's generic 500.\n const ctx = logger.getContext()\n const errorData = ctx.error\n if (response.status >= 500 && isContextEvlogError(errorData)) {\n const { status } = errorData\n await finish({ status })\n const body = serializeEvlogErrorResponse(evlogErrorFromContext(errorData), event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n return finishResponse(response)\n } catch (error) {\n await finish({ error: error instanceof Error ? error : new Error(String(error)) })\n\n // Return structured JSON for EvlogError (like NextJS withEvlog / Nuxt errorHandler)\n if (error instanceof EvlogError) {\n const status = error.status ?? 500\n const body = serializeEvlogErrorResponse(error, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n throw error\n }\n })\n }\n}\n\n/**\n * Create an evlog error handler for SvelteKit.\n *\n * Logs unhandled errors via `event.locals.log` (if available) and returns\n * structured error responses for `EvlogError` instances. For non-evlog errors,\n * returns a generic error response with sanitized messages in production.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { evlog, evlogHandleError } from 'evlog/sveltekit'\n *\n * export const handle = evlog()\n * export const handleError = evlogHandleError()\n * ```\n */\nexport function evlogHandleError(): SvelteKitHandleServerError {\n return ({ error, event, status, message }) => {\n const logger = isRequestLogger(event.locals.log) ? event.locals.log : undefined\n\n if (logger && error instanceof Error) {\n logger.error(error)\n }\n\n const evlogError = error instanceof Error ? resolveEvlogError(error) : null\n\n if (evlogError) {\n const errorStatus = extractErrorStatus(evlogError)\n const response = serializeEvlogErrorResponse(evlogError, event.url.pathname)\n return {\n message: typeof response.message === 'string' ? response.message : message,\n status: errorStatus,\n ...readEvlogResponseData(response),\n }\n }\n\n return { message, status }\n }\n}\n\n/**\n * Create both `handle` and `handleError` hooks in a single call.\n *\n * This is the recommended setup for SvelteKit — it returns both hooks\n * pre-configured and ready to export from `hooks.server.ts`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-app' } })\n *\n * export const { handle, handleError } = createEvlogHooks({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n *\n * const evlogHooks = createEvlogHooks()\n *\n * export const handle = sequence(evlogHooks.handle, yourOtherHook)\n * export const handleError = evlogHooks.handleError\n * ```\n */\nexport function createEvlogHooks(options: EvlogSvelteKitOptions = {}) {\n return {\n handle: evlog(options),\n handleError: evlogHandleError(),\n }\n}\n"],"mappings":"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"}
|
package/dist/toolkit.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as LogLevel, Ct as createPluginRunner, Dt as getEmptyPluginRunner, Et as enricherPlugin, St as RequestLifecycleContext, Tt as drainPlugin, U as DrainContext, W as EnrichContext, _t as ClientLogContext, bt as PluginSetupContext, ht as WideEvent, l as AuditableLogger, ot as RequestLogger, pt as TailSamplingContext, vt as EvlogPlugin, wt as definePlugin, xt as RequestFinishContext, yt as PluginRunner } from "./audit-
|
|
2
|
-
import { a as resolveMiddlewarePluginRunner, i as createMiddlewareLogger, n as MiddlewareLoggerOptions, o as runEnrichAndDrain, r as MiddlewareLoggerResult, t as BaseEvlogOptions } from "./middleware-
|
|
3
|
-
import { i as toMiddlewareOptions, n as defineEvlog, r as toLoggerConfig, t as EvlogConfig } from "./define-
|
|
4
|
-
import { n as EnricherOptions, r as defineEnricher, t as EnricherDefinition } from "./enricher-
|
|
5
|
-
import { n as getServiceForPath, r as shouldLog, t as extractErrorStatus } from "./errors-
|
|
1
|
+
import { $ as LogLevel, Ct as createPluginRunner, Dt as getEmptyPluginRunner, Et as enricherPlugin, St as RequestLifecycleContext, Tt as drainPlugin, U as DrainContext, W as EnrichContext, _t as ClientLogContext, bt as PluginSetupContext, ht as WideEvent, l as AuditableLogger, ot as RequestLogger, pt as TailSamplingContext, vt as EvlogPlugin, wt as definePlugin, xt as RequestFinishContext, yt as PluginRunner } from "./audit-BZrUvjfW.mjs";
|
|
2
|
+
import { a as resolveMiddlewarePluginRunner, i as createMiddlewareLogger, n as MiddlewareLoggerOptions, o as runEnrichAndDrain, r as MiddlewareLoggerResult, t as BaseEvlogOptions } from "./middleware-fbtEs6bq.mjs";
|
|
3
|
+
import { i as toMiddlewareOptions, n as defineEvlog, r as toLoggerConfig, t as EvlogConfig } from "./define-Ct2QyrE9.mjs";
|
|
4
|
+
import { n as EnricherOptions, r as defineEnricher, t as EnricherDefinition } from "./enricher-BOzt2FCi.mjs";
|
|
5
|
+
import { n as getServiceForPath, r as shouldLog, t as extractErrorStatus } from "./errors-C7qA6CAi.mjs";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
|
|
8
8
|
//#region src/shared/streamResponse.d.ts
|
package/dist/toolkit.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as definePlugin, M as enricherPlugin, N as getEmptyPluginRunner, j as drainPlugin, k as createPluginRunner } from "./audit-BXCYMjcC.mjs";
|
|
2
2
|
import { i as normalizeNumber, n as extractSafeNodeHeaders, r as getHeader, t as extractSafeHeaders } from "./headers-VtmnWcfn.mjs";
|
|
3
3
|
import { t as extractErrorStatus } from "./errors-DA0cyr8q.mjs";
|
|
4
4
|
import { n as toLoggerConfig, r as toMiddlewareOptions, t as defineEvlog } from "./define-Bpaymi-h.mjs";
|
|
5
5
|
import { n as shouldLog, t as getServiceForPath } from "./routes-4rMzRyTk.mjs";
|
|
6
6
|
import { n as isStreamingResponse, r as shouldDeferEmitForResponse, t as bindStreamingResponseLifecycle } from "./streamResponse-CmQ3qUbF.mjs";
|
|
7
|
-
import { i as withEvlogIdentityHeaders, n as EVLOG_VERSION, r as httpPost, t as EVLOG_USER_AGENT } from "./http-
|
|
8
|
-
import { a as getRuntimeConfig, i as formatPublicEnvKeys, n as defineHttpDrain, o as resolveAdapterConfig, r as applyDeprecatedAlias, t as defineDrain } from "./drain-
|
|
7
|
+
import { i as withEvlogIdentityHeaders, n as EVLOG_VERSION, r as httpPost, t as EVLOG_USER_AGENT } from "./http-CuZ6Cm2M.mjs";
|
|
8
|
+
import { a as getRuntimeConfig, i as formatPublicEnvKeys, n as defineHttpDrain, o as resolveAdapterConfig, r as applyDeprecatedAlias, t as defineDrain } from "./drain-AD7Mn_5_.mjs";
|
|
9
9
|
import { n as toOtlpAttributeValue, r as toTypedAttributeValue, t as mergeEventField } from "./event-qwAv-7AZ.mjs";
|
|
10
10
|
import { n as OTEL_SEVERITY_TEXT, t as OTEL_SEVERITY_NUMBER } from "./severity-CwXUSHt3.mjs";
|
|
11
11
|
import { a as composePlugins, i as composeKeep, n as composeDrains, r as composeEnrichers, t as defineEnricher } from "./enricher-DAWf2-Fx.mjs";
|
|
12
|
-
import {
|
|
13
|
-
import { t as
|
|
14
|
-
import { t as
|
|
12
|
+
import { n as resolveMiddlewarePluginRunner, r as runEnrichAndDrain, t as createMiddlewareLogger } from "./middleware-Cdebyfdt.mjs";
|
|
13
|
+
import { n as forkBackgroundLogger, t as attachForkToLogger } from "./fork-S9gpZmF8.mjs";
|
|
14
|
+
import { t as defineFrameworkIntegration } from "./integration-CeL90DtN.mjs";
|
|
15
|
+
import { t as createLoggerStorage } from "./storage-BeFdoGTI.mjs";
|
|
15
16
|
export { EVLOG_USER_AGENT, EVLOG_VERSION, OTEL_SEVERITY_NUMBER, OTEL_SEVERITY_TEXT, applyDeprecatedAlias, attachForkToLogger, bindStreamingResponseLifecycle, composeDrains, composeEnrichers, composeKeep, composePlugins, createLoggerStorage, createMiddlewareLogger, createPluginRunner, defineDrain, defineEnricher, defineEvlog, defineFrameworkIntegration, defineHttpDrain, definePlugin, drainPlugin, enricherPlugin, extractErrorStatus, extractSafeHeaders, extractSafeNodeHeaders, forkBackgroundLogger, formatPublicEnvKeys, getEmptyPluginRunner, getHeader, getRuntimeConfig, getServiceForPath, httpPost, isStreamingResponse, mergeEventField, normalizeNumber, resolveAdapterConfig, resolveMiddlewarePluginRunner, runEnrichAndDrain, shouldDeferEmitForResponse, shouldLog, toLoggerConfig, toMiddlewareOptions, toOtlpAttributeValue, toTypedAttributeValue, withEvlogIdentityHeaders };
|
package/dist/types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as LogLevel, B as AuditTarget, F as AuditChanges, G as EnvironmentContext, H as DeepPartial, I as AuditFields, J as FieldContext, K as ErrorCode, L as AuditLoggerMethod, M as AuditAction, N as AuditActionDefinition, P as AuditActor, Q as Log, R as AuditPatchOp, U as DrainContext, V as BaseWideEvent, W as EnrichContext, X as IngestPayload, Y as H3EventContext, Z as InternalFields, at as RequestLogEntry, ct as RouteConfig, dt as ServerEvent, et as LoggerConfig, ft as TailSamplingCondition, ht as WideEvent, it as RegisteredErrorCatalogs, lt as SamplingConfig, mt as TransportConfig, nt as RedactConfig, ot as RequestLogger, pt as TailSamplingContext, q as ErrorOptions, rt as RegisteredAuditCatalogs, st as RequestLoggerOptions, tt as ParsedError, ut as SamplingRates, z as AuditSeverity } from "./audit-
|
|
1
|
+
import { $ as LogLevel, B as AuditTarget, F as AuditChanges, G as EnvironmentContext, H as DeepPartial, I as AuditFields, J as FieldContext, K as ErrorCode, L as AuditLoggerMethod, M as AuditAction, N as AuditActionDefinition, P as AuditActor, Q as Log, R as AuditPatchOp, U as DrainContext, V as BaseWideEvent, W as EnrichContext, X as IngestPayload, Y as H3EventContext, Z as InternalFields, at as RequestLogEntry, ct as RouteConfig, dt as ServerEvent, et as LoggerConfig, ft as TailSamplingCondition, ht as WideEvent, it as RegisteredErrorCatalogs, lt as SamplingConfig, mt as TransportConfig, nt as RedactConfig, ot as RequestLogger, pt as TailSamplingContext, q as ErrorOptions, rt as RegisteredAuditCatalogs, st as RequestLoggerOptions, tt as ParsedError, ut as SamplingRates, z as AuditSeverity } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
export { AuditAction, AuditActionDefinition, AuditActor, AuditChanges, AuditFields, AuditLoggerMethod, AuditPatchOp, AuditSeverity, AuditTarget, BaseWideEvent, DeepPartial, DrainContext, EnrichContext, EnvironmentContext, ErrorCode, ErrorOptions, FieldContext, H3EventContext, IngestPayload, InternalFields, Log, LogLevel, LoggerConfig, ParsedError, RedactConfig, RegisteredAuditCatalogs, RegisteredErrorCatalogs, RequestLogEntry, RequestLogger, RequestLoggerOptions, RouteConfig, SamplingConfig, SamplingRates, ServerEvent, TailSamplingCondition, TailSamplingContext, TransportConfig, WideEvent };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dt as ServerEvent, l as AuditableLogger } from "./audit-
|
|
1
|
+
import { dt as ServerEvent, l as AuditableLogger } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/useLogger.d.ts
|
|
4
4
|
/**
|
|
@@ -36,4 +36,4 @@ import { dt as ServerEvent, l as AuditableLogger } from "./audit-CBfv3rl1.mjs";
|
|
|
36
36
|
declare function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): AuditableLogger<T>;
|
|
37
37
|
//#endregion
|
|
38
38
|
export { useLogger as t };
|
|
39
|
-
//# sourceMappingURL=useLogger-
|
|
39
|
+
//# sourceMappingURL=useLogger-BupVLO9_.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogger-
|
|
1
|
+
{"version":3,"file":"useLogger-BupVLO9_.d.mts","names":[],"sources":["../src/runtime/server/useLogger.ts"],"mappings":";;;;AAmCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,SAAA,oBAA6B,MAAA,kBAAA,CAAyB,KAAA,EAAO,WAAA,EAAa,OAAA,YAAmB,eAAA,CAAgB,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as LogLevel, G as EnvironmentContext } from "./audit-
|
|
1
|
+
import { $ as LogLevel, G as EnvironmentContext } from "./audit-BZrUvjfW.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils.d.ts
|
|
4
4
|
declare function formatDuration(ms: number): string;
|
|
@@ -69,4 +69,4 @@ declare function globToRegExp(pattern: string, separator?: '/' | '.'): RegExp;
|
|
|
69
69
|
declare function matchesPattern(path: string, pattern: string): boolean;
|
|
70
70
|
//#endregion
|
|
71
71
|
export { matchesPattern as _, escapeFormatString as a, getConsoleMethod as c, globToRegExp as d, isBrowser as f, isServer as g, isLevelEnabled as h, detectEnvironment as i, getCssLevelColor as l, isDev as m, colors as n, filterSafeHeaders as o, isClient as p, cssColors as r, formatDuration as s, SENSITIVE_HEADERS as t, getLevelColor as u };
|
|
72
|
-
//# sourceMappingURL=utils-
|
|
72
|
+
//# sourceMappingURL=utils-D_LY-J1k.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils-
|
|
1
|
+
{"version":3,"file":"utils-D_LY-J1k.d.mts","names":[],"sources":["../src/utils.ts"],"mappings":";;;iBAEgB,cAAA,CAAe,EAAA;AAAA,iBAOf,QAAA,CAAA;AAAA,iBAIA,QAAA,CAAA;AAAA,iBAIA,SAAA,CAAA;AAAA,iBAOA,KAAA,CAAA;AAAA,iBAUA,iBAAA,CAAA,GAAqB,OAAA,CAAQ,kBAAA;;AAzB7C;;iBAsDgB,cAAA,CAAe,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA;AAAA,iBAI1C,gBAAA,CAAiB,KAAA,EAAO,QAAA,GAAW,QAAA;AAAA,cAItC,MAAA;EAAA;;;;;;;;;;;;iBAgBG,aAAA,CAAc,KAAA;AAAA,cAIjB,SAAA;EAAA;;;;;;;;iBAYG,gBAAA,CAAiB,KAAA;;;;;;iBASjB,kBAAA,CAAmB,GAAA;;cAKtB,iBAAA;;;;;;;;;AA9Cb;iBAkEgB,iBAAA,CAAkB,OAAA,EAAS,OAAA,CAAQ,MAAA,gCAAsC,MAAA;;;;;;;;iBAqBzE,YAAA,CAAa,OAAA,UAAiB,SAAA,eAA6B,MAAA;;;;;iBAsB3D,cAAA,CAAe,IAAA,UAAc,OAAA"}
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as matchesPattern, a as escapeFormatString, c as getConsoleMethod, d as globToRegExp, f as isBrowser, g as isServer, h as isLevelEnabled, i as detectEnvironment, l as getCssLevelColor, m as isDev, n as colors, o as filterSafeHeaders, p as isClient, r as cssColors, s as formatDuration, t as SENSITIVE_HEADERS, u as getLevelColor } from "./utils-
|
|
1
|
+
import { _ as matchesPattern, a as escapeFormatString, c as getConsoleMethod, d as globToRegExp, f as isBrowser, g as isServer, h as isLevelEnabled, i as detectEnvironment, l as getCssLevelColor, m as isDev, n as colors, o as filterSafeHeaders, p as isClient, r as cssColors, s as formatDuration, t as SENSITIVE_HEADERS, u as getLevelColor } from "./utils-D_LY-J1k.mjs";
|
|
2
2
|
export { SENSITIVE_HEADERS, colors, cssColors, detectEnvironment, escapeFormatString, filterSafeHeaders, formatDuration, getConsoleMethod, getCssLevelColor, getLevelColor, globToRegExp, isBrowser, isClient, isDev, isLevelEnabled, isServer, matchesPattern };
|