evlog 2.4.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +2 -1
  2. package/dist/{_http-DVDwNag0.mjs → _http-DHpGetLZ.mjs} +2 -6
  3. package/dist/{_http-DVDwNag0.mjs.map → _http-DHpGetLZ.mjs.map} +1 -1
  4. package/dist/{_severity-78FkT5MD.mjs → _severity-Q1BuITU_.mjs} +2 -2
  5. package/dist/{_severity-78FkT5MD.mjs.map → _severity-Q1BuITU_.mjs.map} +1 -1
  6. package/dist/adapters/axiom.d.mts +1 -1
  7. package/dist/adapters/axiom.d.mts.map +1 -1
  8. package/dist/adapters/axiom.mjs +2 -3
  9. package/dist/adapters/axiom.mjs.map +1 -1
  10. package/dist/adapters/better-stack.d.mts +1 -1
  11. package/dist/adapters/better-stack.d.mts.map +1 -1
  12. package/dist/adapters/better-stack.mjs +2 -3
  13. package/dist/adapters/better-stack.mjs.map +1 -1
  14. package/dist/adapters/otlp.d.mts +1 -1
  15. package/dist/adapters/otlp.d.mts.map +1 -1
  16. package/dist/adapters/otlp.mjs +14 -11
  17. package/dist/adapters/otlp.mjs.map +1 -1
  18. package/dist/adapters/posthog.d.mts +1 -1
  19. package/dist/adapters/posthog.d.mts.map +1 -1
  20. package/dist/adapters/posthog.mjs +2 -3
  21. package/dist/adapters/posthog.mjs.map +1 -1
  22. package/dist/adapters/sentry.d.mts +1 -1
  23. package/dist/adapters/sentry.d.mts.map +1 -1
  24. package/dist/adapters/sentry.mjs +3 -4
  25. package/dist/adapters/sentry.mjs.map +1 -1
  26. package/dist/browser.d.mts +1 -1
  27. package/dist/browser.mjs +1 -2
  28. package/dist/browser.mjs.map +1 -1
  29. package/dist/{dist-By0jiJRA.mjs → dist-BsWcv7B8.mjs} +3 -4
  30. package/dist/{dist-By0jiJRA.mjs.map → dist-BsWcv7B8.mjs.map} +1 -1
  31. package/dist/elysia/index.d.mts +2 -2
  32. package/dist/elysia/index.mjs +2 -3
  33. package/dist/elysia/index.mjs.map +1 -1
  34. package/dist/enrichers.d.mts +1 -1
  35. package/dist/enrichers.mjs +1 -1
  36. package/dist/enrichers.mjs.map +1 -1
  37. package/dist/error-iV3zJCY3.d.mts +65 -0
  38. package/dist/error-iV3zJCY3.d.mts.map +1 -0
  39. package/dist/error.d.mts +2 -65
  40. package/dist/error.mjs +1 -2
  41. package/dist/error.mjs.map +1 -1
  42. package/dist/errors-BJRXUfMg.mjs +18 -0
  43. package/dist/errors-BJRXUfMg.mjs.map +1 -0
  44. package/dist/errors-CKSfdvLa.d.mts +39 -0
  45. package/dist/errors-CKSfdvLa.d.mts.map +1 -0
  46. package/dist/express/index.d.mts +2 -2
  47. package/dist/express/index.mjs +3 -4
  48. package/dist/express/index.mjs.map +1 -1
  49. package/dist/fastify/index.d.mts +2 -2
  50. package/dist/fastify/index.d.mts.map +1 -1
  51. package/dist/fastify/index.mjs +3 -4
  52. package/dist/fastify/index.mjs.map +1 -1
  53. package/dist/{headers-CXOd5EyZ.mjs → headers-Ba1eKT3i.mjs} +6 -6
  54. package/dist/headers-Ba1eKT3i.mjs.map +1 -0
  55. package/dist/hono/index.d.mts +2 -2
  56. package/dist/hono/index.mjs +2 -3
  57. package/dist/hono/index.mjs.map +1 -1
  58. package/dist/index.d.mts +5 -5
  59. package/dist/index.mjs +1 -2
  60. package/dist/logger-CvDYZUze.d.mts +59 -0
  61. package/dist/logger-CvDYZUze.d.mts.map +1 -0
  62. package/dist/logger.d.mts +2 -59
  63. package/dist/logger.mjs +45 -3
  64. package/dist/logger.mjs.map +1 -1
  65. package/dist/middleware-hZqyXoSk.d.mts +75 -0
  66. package/dist/middleware-hZqyXoSk.d.mts.map +1 -0
  67. package/dist/nestjs/index.d.mts +2 -2
  68. package/dist/nestjs/index.mjs +3 -4
  69. package/dist/nestjs/index.mjs.map +1 -1
  70. package/dist/next/client.d.mts +1 -1
  71. package/dist/next/client.mjs +2 -4
  72. package/dist/next/client.mjs.map +1 -1
  73. package/dist/next/index.d.mts +4 -4
  74. package/dist/next/index.d.mts.map +1 -1
  75. package/dist/next/index.mjs +2 -6
  76. package/dist/next/index.mjs.map +1 -1
  77. package/dist/nitro/errorHandler.mjs +3 -3
  78. package/dist/nitro/errorHandler.mjs.map +1 -1
  79. package/dist/nitro/module.d.mts +2 -2
  80. package/dist/nitro/module.mjs +1 -2
  81. package/dist/nitro/module.mjs.map +1 -1
  82. package/dist/nitro/plugin.mjs +3 -4
  83. package/dist/nitro/plugin.mjs.map +1 -1
  84. package/dist/nitro/v3/errorHandler.mjs +4 -4
  85. package/dist/nitro/v3/errorHandler.mjs.map +1 -1
  86. package/dist/nitro/v3/index.mjs +1 -2
  87. package/dist/nitro/v3/middleware.mjs +1 -2
  88. package/dist/nitro/v3/middleware.mjs.map +1 -1
  89. package/dist/nitro/v3/module.d.mts +1 -1
  90. package/dist/nitro/v3/module.mjs +4 -3
  91. package/dist/nitro/v3/module.mjs.map +1 -1
  92. package/dist/nitro/v3/plugin.d.mts +3 -1
  93. package/dist/nitro/v3/plugin.mjs +4 -5
  94. package/dist/nitro/v3/plugin.mjs.map +1 -1
  95. package/dist/nitro/v3/useLogger.d.mts +1 -1
  96. package/dist/nitro/v3/useLogger.mjs +1 -1
  97. package/dist/nitro/v3/useLogger.mjs.map +1 -1
  98. package/dist/{nitro-BRisWfGy.d.mts → nitro-CGGTUned.d.mts} +2 -2
  99. package/dist/nitro-CGGTUned.d.mts.map +1 -0
  100. package/dist/{nitro-Da8tEfJ3.mjs → nitro-D1pPm37T.mjs} +4 -9
  101. package/dist/nitro-D1pPm37T.mjs.map +1 -0
  102. package/dist/nuxt/module.d.mts +1 -1
  103. package/dist/nuxt/module.mjs +2 -5
  104. package/dist/nuxt/module.mjs.map +1 -1
  105. package/dist/parseError-BztqcPwZ.d.mts +7 -0
  106. package/dist/parseError-BztqcPwZ.d.mts.map +1 -0
  107. package/dist/pipeline.mjs +1 -1
  108. package/dist/{routes-BNbrnm14.mjs → routes-CE3_c-iZ.mjs} +2 -3
  109. package/dist/{routes-BNbrnm14.mjs.map → routes-CE3_c-iZ.mjs.map} +1 -1
  110. package/dist/runtime/client/log.d.mts +1 -1
  111. package/dist/runtime/client/log.d.mts.map +1 -1
  112. package/dist/runtime/client/log.mjs +4 -11
  113. package/dist/runtime/client/log.mjs.map +1 -1
  114. package/dist/runtime/client/plugin.mjs +1 -2
  115. package/dist/runtime/client/plugin.mjs.map +1 -1
  116. package/dist/runtime/server/routes/_evlog/ingest.post.mjs +1 -2
  117. package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -1
  118. package/dist/runtime/server/useLogger.d.mts +2 -39
  119. package/dist/runtime/server/useLogger.mjs +1 -1
  120. package/dist/runtime/server/useLogger.mjs.map +1 -1
  121. package/dist/runtime/utils/parseError.d.mts +3 -7
  122. package/dist/runtime/utils/parseError.mjs +1 -1
  123. package/dist/{storage-CejtuV76.mjs → storage-CJBW5Vos.mjs} +4 -3
  124. package/dist/storage-CJBW5Vos.mjs.map +1 -0
  125. package/dist/sveltekit/index.d.mts +2 -2
  126. package/dist/sveltekit/index.mjs +5 -5
  127. package/dist/toolkit.d.mts +38 -0
  128. package/dist/toolkit.d.mts.map +1 -0
  129. package/dist/toolkit.mjs +5 -0
  130. package/dist/types-B8-kC2ME.d.mts +496 -0
  131. package/dist/types-B8-kC2ME.d.mts.map +1 -0
  132. package/dist/types.d.mts +2 -496
  133. package/dist/types.mjs +1 -1
  134. package/dist/useLogger-_Ec6mXoR.d.mts +39 -0
  135. package/dist/useLogger-_Ec6mXoR.d.mts.map +1 -0
  136. package/dist/utils.d.mts +18 -2
  137. package/dist/utils.d.mts.map +1 -1
  138. package/dist/utils.mjs +28 -2
  139. package/dist/utils.mjs.map +1 -1
  140. package/dist/workers.d.mts +1 -1
  141. package/dist/workers.mjs +1 -2
  142. package/dist/workers.mjs.map +1 -1
  143. package/package.json +68 -39
  144. package/dist/error.d.mts.map +0 -1
  145. package/dist/headers-CXOd5EyZ.mjs.map +0 -1
  146. package/dist/logger.d.mts.map +0 -1
  147. package/dist/middleware-BoVCgsfQ.d.mts +0 -36
  148. package/dist/middleware-BoVCgsfQ.d.mts.map +0 -1
  149. package/dist/nitro-BRisWfGy.d.mts.map +0 -1
  150. package/dist/nitro-Da8tEfJ3.mjs.map +0 -1
  151. package/dist/runtime/server/useLogger.d.mts.map +0 -1
  152. package/dist/runtime/utils/parseError.d.mts.map +0 -1
  153. package/dist/storage-CejtuV76.mjs.map +0 -1
  154. package/dist/types.d.mts.map +0 -1
@@ -1,15 +1,12 @@
1
1
  import { addImports, addPlugin, addServerHandler, addServerImports, addServerPlugin, createResolver, defineNuxtModule } from "@nuxt/kit";
2
-
3
2
  //#region package.json
4
3
  var name = "evlog";
5
- var version = "2.4.1";
6
-
7
4
  //#endregion
8
5
  //#region src/nuxt/module.ts
9
6
  var module_default = defineNuxtModule({
10
7
  meta: {
11
8
  name,
12
- version,
9
+ version: "2.6.0",
13
10
  configKey: name,
14
11
  docs: "https://evlog.dev"
15
12
  },
@@ -79,7 +76,7 @@ var module_default = defineNuxtModule({
79
76
  ]);
80
77
  }
81
78
  });
82
-
83
79
  //#endregion
84
80
  export { module_default as default };
81
+
85
82
  //# sourceMappingURL=module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.mjs","names":[],"sources":["../../package.json","../../src/nuxt/module.ts"],"sourcesContent":["","import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token */\n token: string\n /** Organization ID (required for Personal Access Tokens) */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * 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 * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // Send logs to server API\n * endpoint: '/api/_evlog/ingest' // Custom endpoint\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * token: process.env.AXIOM_TOKEN,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * 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\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n nitroConfig.errorHandler = nitroConfig.errorHandler || resolver.resolve('../nitro/errorHandler')\n })\n\n nuxt.options.runtimeConfig.evlog = options\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\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 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: '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})\n"],"mappings":";;;;;;;;ACmOA,qBAAe,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;AAKzD,OAAK,KAAK,iBAAiB,gBAA6B;AACtD,eAAY,eAAe,YAAY,gBAAgB,SAAS,QAAQ,wBAAwB;IAChG;AAEF,OAAK,QAAQ,cAAc,QAAQ;AACnC,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,WAAW;IACT,SAAS;IACT,UAAU;IACX;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,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,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;;CAEL,CAAC"}
1
+ {"version":3,"file":"module.mjs","names":[],"sources":["../../package.json","../../src/nuxt/module.ts"],"sourcesContent":["","import {\n addImports,\n addPlugin,\n addServerHandler,\n addServerImports,\n addServerPlugin,\n createResolver,\n defineNuxtModule,\n} from '@nuxt/kit'\nimport type { NitroConfig } from 'nitropack'\nimport type { EnvironmentContext, RouteConfig, SamplingConfig, TransportConfig } from '../types'\nimport { name, version } from '../../package.json'\n\ninterface ModuleAxiomBaseConfig {\n /** Axiom dataset name */\n dataset: string\n /** Axiom API token */\n token: string\n /** Organization ID (required for Personal Access Tokens) */\n orgId?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n}\n\ninterface ModuleAxiomEdgeConfig {\n /**\n * Edge URL for Axiom ingest/query endpoints.\n * If no path is provided, uses /v1/ingest/{dataset}.\n * If a custom path is provided, it is used as-is (trailing slash trimmed).\n */\n edgeUrl: string\n /** Mutually exclusive with edgeUrl. */\n baseUrl?: never\n}\n\ninterface ModuleAxiomEndpointConfig {\n /** Base URL for Axiom API. Uses /v1/datasets/{dataset}/ingest. */\n baseUrl?: string\n /** Mutually exclusive with baseUrl. */\n edgeUrl?: never\n}\n\ntype ModuleAxiomConfig = ModuleAxiomBaseConfig & (ModuleAxiomEdgeConfig | ModuleAxiomEndpointConfig)\n\nexport interface ModuleOptions {\n /**\n * Enable or disable all logging globally.\n * When false, all emits, tagged logs, and request logger operations become no-ops.\n * @default true\n */\n enabled?: boolean\n\n /**\n * Environment context overrides.\n */\n env?: Partial<EnvironmentContext>\n\n /**\n * Enable or disable browser console output.\n * When false, client-side logs are suppressed in the browser DevTools console\n * but still sent to the server via transport (if enabled).\n * @default true\n */\n console?: boolean\n\n /**\n * Enable pretty printing.\n * @default true in development, false in production\n */\n pretty?: boolean\n\n /**\n * 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 * Transport configuration for sending client logs to the server.\n *\n * @example\n * ```ts\n * transport: {\n * enabled: true, // Send logs to server API\n * endpoint: '/api/_evlog/ingest' // Custom endpoint\n * }\n * ```\n */\n transport?: TransportConfig\n\n /**\n * Axiom adapter configuration.\n * When configured, use `createAxiomDrain()` from `evlog/axiom` to send logs.\n *\n * @example\n * ```ts\n * axiom: {\n * dataset: 'my-app-logs',\n * token: process.env.AXIOM_TOKEN,\n * }\n * ```\n */\n axiom?: ModuleAxiomConfig\n\n /**\n * OTLP adapter configuration.\n * When configured, use `createOTLPDrain()` from `evlog/otlp` to send logs.\n *\n * @example\n * ```ts\n * otlp: {\n * endpoint: 'http://localhost:4318',\n * headers: {\n * 'Authorization': `Basic ${process.env.GRAFANA_TOKEN}`,\n * },\n * }\n * ```\n */\n otlp?: {\n /** OTLP HTTP endpoint (e.g., http://localhost:4318) */\n endpoint: string\n /** Override service name (defaults to event.service) */\n serviceName?: string\n /** Additional resource attributes */\n resourceAttributes?: Record<string, string | number | boolean>\n /** Custom headers (e.g., for authentication) */\n headers?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * PostHog adapter configuration.\n * When configured, use `createPostHogDrain()` from `evlog/posthog` to send logs\n * via PostHog Logs (OTLP).\n *\n * @example\n * ```ts\n * posthog: {\n * apiKey: process.env.POSTHOG_API_KEY,\n * }\n * ```\n */\n posthog?: {\n /** PostHog project API key */\n apiKey: string\n /** PostHog host URL. Default: https://us.i.posthog.com */\n host?: string\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * Sentry adapter configuration.\n * When configured, use `createSentryDrain()` from `evlog/sentry` to send logs.\n *\n * @example\n * ```ts\n * sentry: {\n * dsn: process.env.SENTRY_DSN,\n * }\n * ```\n */\n sentry?: {\n /** Sentry DSN */\n dsn: string\n /** Environment override (defaults to event.environment) */\n environment?: string\n /** Release version override (defaults to event.version) */\n release?: string\n /** Additional tags to attach as attributes */\n tags?: Record<string, string>\n /** Request timeout in milliseconds. Default: 5000 */\n timeout?: number\n }\n\n /**\n * 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\n // Register custom error handler for proper EvlogError serialization\n // Only set if not already configured to avoid overwriting user's custom handler\n // @ts-expect-error nitro:config hook exists but is not in NuxtHooks type\n nuxt.hook('nitro:config', (nitroConfig: NitroConfig) => {\n nitroConfig.errorHandler = nitroConfig.errorHandler || resolver.resolve('../nitro/errorHandler')\n })\n\n nuxt.options.runtimeConfig.evlog = options\n nuxt.options.runtimeConfig.public.evlog = {\n enabled: options.enabled ?? true,\n console: options.console,\n pretty: options.pretty,\n transport: {\n enabled: transportEnabled,\n endpoint: transportEndpoint,\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 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: '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})\n"],"mappings":";;;;;ACmOA,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;AAKzD,OAAK,KAAK,iBAAiB,gBAA6B;AACtD,eAAY,eAAe,YAAY,gBAAgB,SAAS,QAAQ,wBAAwB;IAChG;AAEF,OAAK,QAAQ,cAAc,QAAQ;AACnC,OAAK,QAAQ,cAAc,OAAO,QAAQ;GACxC,SAAS,QAAQ,WAAW;GAC5B,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,WAAW;IACT,SAAS;IACT,UAAU;IACX;GACF;AAED,MAAI,iBACF,kBAAiB;GACf,OAAO;GACP,QAAQ;GACR,SAAS,SAAS,QAAQ,8CAA8C;GACzE,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,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;;CAEL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { m as ParsedError } from "./types-B8-kC2ME.mjs";
2
+
3
+ //#region src/runtime/utils/parseError.d.ts
4
+ declare function parseError(error: unknown): ParsedError;
5
+ //#endregion
6
+ export { parseError as t };
7
+ //# sourceMappingURL=parseError-BztqcPwZ.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseError-BztqcPwZ.d.mts","names":[],"sources":["../src/runtime/utils/parseError.ts"],"mappings":";;;iBAKgB,UAAA,CAAW,KAAA,YAAiB,WAAA"}
package/dist/pipeline.mjs CHANGED
@@ -116,7 +116,7 @@ function createDrainPipeline(options) {
116
116
  return hookFn;
117
117
  };
118
118
  }
119
-
120
119
  //#endregion
121
120
  export { createDrainPipeline };
121
+
122
122
  //# sourceMappingURL=pipeline.mjs.map
@@ -1,5 +1,4 @@
1
1
  import { matchesPattern } from "./utils.mjs";
2
-
3
2
  //#region src/shared/routes.ts
4
3
  function shouldLog(path, include, exclude) {
5
4
  if (exclude && exclude.length > 0) {
@@ -33,7 +32,7 @@ function getServiceForPath(path, routes) {
33
32
  if (!routes) return void 0;
34
33
  for (const [pattern, config] of Object.entries(routes)) if (matchesPattern(path, pattern)) return config.service;
35
34
  }
36
-
37
35
  //#endregion
38
36
  export { shouldLog as n, getServiceForPath as t };
39
- //# sourceMappingURL=routes-BNbrnm14.mjs.map
37
+
38
+ //# sourceMappingURL=routes-CE3_c-iZ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes-BNbrnm14.mjs","names":[],"sources":["../src/shared/routes.ts"],"sourcesContent":["import type { RouteConfig } from '../types'\nimport { matchesPattern } from '../utils'\n\nexport function shouldLog(path: string, include?: string[], exclude?: string[]): boolean {\n // Check exclusions first (they take precedence)\n if (exclude && exclude.length > 0) {\n if (exclude.some(pattern => matchesPattern(path, pattern))) {\n return false\n }\n }\n\n // If no include patterns, log everything (that wasn't excluded)\n if (!include || include.length === 0) {\n return true\n }\n\n // Log only if path matches at least one include pattern\n return include.some(pattern => matchesPattern(path, pattern))\n}\n\n/**\n * Find the service name for a given path based on route patterns.\n *\n * When multiple patterns match the same path, the first matching pattern wins\n * based on object iteration order. To ensure predictable behavior, order your\n * route patterns from most specific to most general.\n *\n * @param path - The request path to match\n * @param routes - Route configuration mapping patterns to service names\n * @returns The service name for the matching route, or undefined if no match\n *\n * @example\n * ```ts\n * // Good: specific patterns first, general patterns last\n * routes: {\n * '/api/auth/admin/**': { service: 'admin-service' },\n * '/api/auth/**': { service: 'auth-service' },\n * '/api/**': { service: 'api-service' },\n * }\n * ```\n */\nexport function getServiceForPath(path: string, routes?: Record<string, RouteConfig>): string | undefined {\n if (!routes) return undefined\n\n for (const [pattern, config] of Object.entries(routes)) {\n if (matchesPattern(path, pattern)) {\n return config.service\n }\n }\n\n return undefined\n}\n"],"mappings":";;;AAGA,SAAgB,UAAU,MAAc,SAAoB,SAA6B;AAEvF,KAAI,WAAW,QAAQ,SAAS,GAC9B;MAAI,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC,CACxD,QAAO;;AAKX,KAAI,CAAC,WAAW,QAAQ,WAAW,EACjC,QAAO;AAIT,QAAO,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;AAwB/D,SAAgB,kBAAkB,MAAc,QAA0D;AACxG,KAAI,CAAC,OAAQ,QAAO;AAEpB,MAAK,MAAM,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,CACpD,KAAI,eAAe,MAAM,QAAQ,CAC/B,QAAO,OAAO"}
1
+ {"version":3,"file":"routes-CE3_c-iZ.mjs","names":[],"sources":["../src/shared/routes.ts"],"sourcesContent":["import type { RouteConfig } from '../types'\nimport { matchesPattern } from '../utils'\n\nexport function shouldLog(path: string, include?: string[], exclude?: string[]): boolean {\n // Check exclusions first (they take precedence)\n if (exclude && exclude.length > 0) {\n if (exclude.some(pattern => matchesPattern(path, pattern))) {\n return false\n }\n }\n\n // If no include patterns, log everything (that wasn't excluded)\n if (!include || include.length === 0) {\n return true\n }\n\n // Log only if path matches at least one include pattern\n return include.some(pattern => matchesPattern(path, pattern))\n}\n\n/**\n * Find the service name for a given path based on route patterns.\n *\n * When multiple patterns match the same path, the first matching pattern wins\n * based on object iteration order. To ensure predictable behavior, order your\n * route patterns from most specific to most general.\n *\n * @param path - The request path to match\n * @param routes - Route configuration mapping patterns to service names\n * @returns The service name for the matching route, or undefined if no match\n *\n * @example\n * ```ts\n * // Good: specific patterns first, general patterns last\n * routes: {\n * '/api/auth/admin/**': { service: 'admin-service' },\n * '/api/auth/**': { service: 'auth-service' },\n * '/api/**': { service: 'api-service' },\n * }\n * ```\n */\nexport function getServiceForPath(path: string, routes?: Record<string, RouteConfig>): string | undefined {\n if (!routes) return undefined\n\n for (const [pattern, config] of Object.entries(routes)) {\n if (matchesPattern(path, pattern)) {\n return config.service\n }\n }\n\n return undefined\n}\n"],"mappings":";;AAGA,SAAgB,UAAU,MAAc,SAAoB,SAA6B;AAEvF,KAAI,WAAW,QAAQ,SAAS;MAC1B,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC,CACxD,QAAO;;AAKX,KAAI,CAAC,WAAW,QAAQ,WAAW,EACjC,QAAO;AAIT,QAAO,QAAQ,MAAK,YAAW,eAAe,MAAM,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;AAwB/D,SAAgB,kBAAkB,MAAc,QAA0D;AACxG,KAAI,CAAC,OAAQ,QAAO,KAAA;AAEpB,MAAK,MAAM,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,CACpD,KAAI,eAAe,MAAM,QAAQ,CAC/B,QAAO,OAAO"}
@@ -1,4 +1,4 @@
1
- import { Log, TransportConfig } from "../../types.mjs";
1
+ import { d as Log, w as TransportConfig } from "../../types-B8-kC2ME.mjs";
2
2
 
3
3
  //#region src/runtime/client/log.d.ts
4
4
  declare function setIdentity(identity: Record<string, unknown>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.mts","names":[],"sources":["../../../src/runtime/client/log.ts"],"mappings":";;;iBAagB,WAAA,CAAY,QAAA,EAAU,MAAA;AAAA,iBAItB,aAAA,CAAA;AAAA,iBAWA,OAAA,CAAQ,OAAA;EAAW,OAAA;EAAmB,OAAA;EAAmB,MAAA;EAAkB,OAAA;EAAkB,SAAA,GAAY,eAAA;AAAA;AAAA,cAoFnH,UAAA,EAAY,GAAA"}
1
+ {"version":3,"file":"log.d.mts","names":[],"sources":["../../../src/runtime/client/log.ts"],"mappings":";;;iBAagB,WAAA,CAAY,QAAA,EAAU,MAAA;AAAA,iBAItB,aAAA,CAAA;AAAA,iBAKA,OAAA,CAAQ,OAAA;EAAW,OAAA;EAAmB,OAAA;EAAmB,MAAA;EAAkB,OAAA;EAAkB,SAAA,GAAY,eAAA;AAAA;AAAA,cAoFnH,UAAA,EAAY,GAAA"}
@@ -1,5 +1,4 @@
1
- import { getConsoleMethod } from "../../utils.mjs";
2
-
1
+ import { cssColors, escapeFormatString, getConsoleMethod, getCssLevelColor } from "../../utils.mjs";
3
2
  //#region src/runtime/client/log.ts
4
3
  const isClient = typeof window !== "undefined";
5
4
  let clientEnabled = true;
@@ -15,12 +14,6 @@ function setIdentity(identity) {
15
14
  function clearIdentity() {
16
15
  identityContext = {};
17
16
  }
18
- const LEVEL_COLORS = {
19
- error: "color: #ef4444; font-weight: bold",
20
- warn: "color: #f59e0b; font-weight: bold",
21
- info: "color: #06b6d4; font-weight: bold",
22
- debug: "color: #6b7280; font-weight: bold"
23
- };
24
17
  function initLog(options = {}) {
25
18
  clientEnabled = typeof options.enabled === "boolean" ? options.enabled : true;
26
19
  clientConsole = typeof options.console === "boolean" ? options.console : true;
@@ -54,7 +47,7 @@ function emitLog(level, event) {
54
47
  const method = getConsoleMethod(level);
55
48
  if (clientPretty) {
56
49
  const { level: lvl, service, ...rest } = formatted;
57
- console[method](`%c[${service}]%c ${lvl}`, LEVEL_COLORS[lvl] || "", "color: inherit", rest);
50
+ console[method](`%c[${escapeFormatString(String(service))}]%c ${lvl}`, getCssLevelColor(lvl), cssColors.reset, rest);
58
51
  } else console[method](JSON.stringify(formatted));
59
52
  }
60
53
  sendToServer(formatted);
@@ -62,7 +55,7 @@ function emitLog(level, event) {
62
55
  function emitTaggedLog(level, tag, message) {
63
56
  if (!clientEnabled) return;
64
57
  if (clientPretty) {
65
- if (clientConsole) console[getConsoleMethod(level)](`%c[${tag}]%c ${message}`, LEVEL_COLORS[level] || "", "color: inherit");
58
+ if (clientConsole) console[getConsoleMethod(level)](`%c[${escapeFormatString(tag)}]%c ${escapeFormatString(message)}`, getCssLevelColor(level), cssColors.reset);
66
59
  sendToServer({
67
60
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
68
61
  level,
@@ -90,7 +83,7 @@ const _clientLog = {
90
83
  warn: createLogMethod("warn"),
91
84
  debug: createLogMethod("debug")
92
85
  };
93
-
94
86
  //#endregion
95
87
  export { clearIdentity, initLog, _clientLog as log, setIdentity };
88
+
96
89
  //# sourceMappingURL=log.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"log.mjs","names":[],"sources":["../../../src/runtime/client/log.ts"],"sourcesContent":["import type { Log, LogLevel, TransportConfig } from '../../types'\nimport { getConsoleMethod } from '../../utils'\n\nconst isClient = typeof window !== 'undefined'\n\nlet clientEnabled = true\nlet clientConsole = true\nlet clientPretty = true\nlet clientService = 'client'\nlet transportEnabled = false\nlet transportEndpoint = '/api/_evlog/ingest'\nlet identityContext: Record<string, unknown> = {}\n\nexport function setIdentity(identity: Record<string, unknown>): void {\n identityContext = { ...identity }\n}\n\nexport function clearIdentity(): void {\n identityContext = {}\n}\n\nconst LEVEL_COLORS: Record<string, string> = {\n error: 'color: #ef4444; font-weight: bold',\n warn: 'color: #f59e0b; font-weight: bold',\n info: 'color: #06b6d4; font-weight: bold',\n debug: 'color: #6b7280; font-weight: bold',\n}\n\nexport function initLog(options: { enabled?: boolean, console?: boolean, pretty?: boolean, service?: string, transport?: TransportConfig } = {}): void {\n clientEnabled = typeof options.enabled === 'boolean' ? options.enabled : true\n clientConsole = typeof options.console === 'boolean' ? options.console : true\n clientPretty = typeof options.pretty === 'boolean' ? options.pretty : true\n clientService = options.service ?? 'client'\n transportEnabled = options.transport?.enabled ?? false\n transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n}\n\nasync function sendToServer(event: Record<string, unknown>): Promise<void> {\n if (!transportEnabled) return\n\n try {\n await fetch(transportEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(event),\n keepalive: true,\n credentials: 'same-origin',\n })\n } catch {\n // Silently fail - don't break the app\n }\n}\n\nfunction emitLog(level: LogLevel, event: Record<string, unknown>): void {\n if (!clientEnabled) return\n\n const formatted = {\n timestamp: new Date().toISOString(),\n level,\n service: clientService,\n ...identityContext,\n ...event,\n }\n\n if (clientConsole) {\n const method = getConsoleMethod(level)\n if (clientPretty) {\n const { level: lvl, service, ...rest } = formatted\n console[method](`%c[${service}]%c ${lvl}`, LEVEL_COLORS[lvl] || '', 'color: inherit', rest)\n } else {\n console[method](JSON.stringify(formatted))\n }\n }\n\n sendToServer(formatted)\n}\n\nfunction emitTaggedLog(level: LogLevel, tag: string, message: string): void {\n if (!clientEnabled) return\n if (clientPretty) {\n if (clientConsole) {\n console[getConsoleMethod(level)](`%c[${tag}]%c ${message}`, LEVEL_COLORS[level] || '', 'color: inherit')\n }\n sendToServer({\n timestamp: new Date().toISOString(),\n level,\n service: clientService,\n ...identityContext,\n tag,\n message,\n })\n } else {\n emitLog(level, { tag, message })\n }\n}\n\nfunction createLogMethod(level: LogLevel) {\n return function logMethod(tagOrEvent: string | Record<string, unknown>, message?: string): void {\n if (!(import.meta.client ?? isClient)) {\n return\n }\n\n if (typeof tagOrEvent === 'string' && message !== undefined) {\n emitTaggedLog(level, tagOrEvent, message)\n } else if (typeof tagOrEvent === 'object') {\n emitLog(level, tagOrEvent)\n } else {\n emitTaggedLog(level, 'log', String(tagOrEvent))\n }\n }\n}\n\nconst _clientLog: Log = {\n info: createLogMethod('info'),\n error: createLogMethod('error'),\n warn: createLogMethod('warn'),\n debug: createLogMethod('debug'),\n}\n\nexport { _clientLog as log }\n"],"mappings":";;;AAGA,MAAM,WAAW,OAAO,WAAW;AAEnC,IAAI,gBAAgB;AACpB,IAAI,gBAAgB;AACpB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,mBAAmB;AACvB,IAAI,oBAAoB;AACxB,IAAI,kBAA2C,EAAE;AAEjD,SAAgB,YAAY,UAAyC;AACnE,mBAAkB,EAAE,GAAG,UAAU;;AAGnC,SAAgB,gBAAsB;AACpC,mBAAkB,EAAE;;AAGtB,MAAM,eAAuC;CAC3C,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,SAAgB,QAAQ,UAAqH,EAAE,EAAQ;AACrJ,iBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,UAAU;AACzE,iBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,UAAU;AACzE,gBAAe,OAAO,QAAQ,WAAW,YAAY,QAAQ,SAAS;AACtE,iBAAgB,QAAQ,WAAW;AACnC,oBAAmB,QAAQ,WAAW,WAAW;AACjD,qBAAoB,QAAQ,WAAW,YAAY;;AAGrD,eAAe,aAAa,OAA+C;AACzE,KAAI,CAAC,iBAAkB;AAEvB,KAAI;AACF,QAAM,MAAM,mBAAmB;GAC7B,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU,MAAM;GAC3B,WAAW;GACX,aAAa;GACd,CAAC;SACI;;AAKV,SAAS,QAAQ,OAAiB,OAAsC;AACtE,KAAI,CAAC,cAAe;CAEpB,MAAM,YAAY;EAChB,4BAAW,IAAI,MAAM,EAAC,aAAa;EACnC;EACA,SAAS;EACT,GAAG;EACH,GAAG;EACJ;AAED,KAAI,eAAe;EACjB,MAAM,SAAS,iBAAiB,MAAM;AACtC,MAAI,cAAc;GAChB,MAAM,EAAE,OAAO,KAAK,SAAS,GAAG,SAAS;AACzC,WAAQ,QAAQ,MAAM,QAAQ,MAAM,OAAO,aAAa,QAAQ,IAAI,kBAAkB,KAAK;QAE3F,SAAQ,QAAQ,KAAK,UAAU,UAAU,CAAC;;AAI9C,cAAa,UAAU;;AAGzB,SAAS,cAAc,OAAiB,KAAa,SAAuB;AAC1E,KAAI,CAAC,cAAe;AACpB,KAAI,cAAc;AAChB,MAAI,cACF,SAAQ,iBAAiB,MAAM,EAAE,MAAM,IAAI,MAAM,WAAW,aAAa,UAAU,IAAI,iBAAiB;AAE1G,eAAa;GACX,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACA,SAAS;GACT,GAAG;GACH;GACA;GACD,CAAC;OAEF,SAAQ,OAAO;EAAE;EAAK;EAAS,CAAC;;AAIpC,SAAS,gBAAgB,OAAiB;AACxC,QAAO,SAAS,UAAU,YAA8C,SAAwB;AAC9F,MAAI,EAAE,OAAO,KAAK,UAAU,UAC1B;AAGF,MAAI,OAAO,eAAe,YAAY,YAAY,OAChD,eAAc,OAAO,YAAY,QAAQ;WAChC,OAAO,eAAe,SAC/B,SAAQ,OAAO,WAAW;MAE1B,eAAc,OAAO,OAAO,OAAO,WAAW,CAAC;;;AAKrD,MAAM,aAAkB;CACtB,MAAM,gBAAgB,OAAO;CAC7B,OAAO,gBAAgB,QAAQ;CAC/B,MAAM,gBAAgB,OAAO;CAC7B,OAAO,gBAAgB,QAAQ;CAChC"}
1
+ {"version":3,"file":"log.mjs","names":[],"sources":["../../../src/runtime/client/log.ts"],"sourcesContent":["import type { Log, LogLevel, TransportConfig } from '../../types'\nimport { cssColors, escapeFormatString, getConsoleMethod, getCssLevelColor } from '../../utils'\n\nconst isClient = typeof window !== 'undefined'\n\nlet clientEnabled = true\nlet clientConsole = true\nlet clientPretty = true\nlet clientService = 'client'\nlet transportEnabled = false\nlet transportEndpoint = '/api/_evlog/ingest'\nlet identityContext: Record<string, unknown> = {}\n\nexport function setIdentity(identity: Record<string, unknown>): void {\n identityContext = { ...identity }\n}\n\nexport function clearIdentity(): void {\n identityContext = {}\n}\n\n\nexport function initLog(options: { enabled?: boolean, console?: boolean, pretty?: boolean, service?: string, transport?: TransportConfig } = {}): void {\n clientEnabled = typeof options.enabled === 'boolean' ? options.enabled : true\n clientConsole = typeof options.console === 'boolean' ? options.console : true\n clientPretty = typeof options.pretty === 'boolean' ? options.pretty : true\n clientService = options.service ?? 'client'\n transportEnabled = options.transport?.enabled ?? false\n transportEndpoint = options.transport?.endpoint ?? '/api/_evlog/ingest'\n}\n\nasync function sendToServer(event: Record<string, unknown>): Promise<void> {\n if (!transportEnabled) return\n\n try {\n await fetch(transportEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(event),\n keepalive: true,\n credentials: 'same-origin',\n })\n } catch {\n // Silently fail - don't break the app\n }\n}\n\nfunction emitLog(level: LogLevel, event: Record<string, unknown>): void {\n if (!clientEnabled) return\n\n const formatted = {\n timestamp: new Date().toISOString(),\n level,\n service: clientService,\n ...identityContext,\n ...event,\n }\n\n if (clientConsole) {\n const method = getConsoleMethod(level)\n if (clientPretty) {\n const { level: lvl, service, ...rest } = formatted\n console[method](`%c[${escapeFormatString(String(service))}]%c ${lvl}`, getCssLevelColor(lvl), cssColors.reset, rest)\n } else {\n console[method](JSON.stringify(formatted))\n }\n }\n\n sendToServer(formatted)\n}\n\nfunction emitTaggedLog(level: LogLevel, tag: string, message: string): void {\n if (!clientEnabled) return\n if (clientPretty) {\n if (clientConsole) {\n console[getConsoleMethod(level)](`%c[${escapeFormatString(tag)}]%c ${escapeFormatString(message)}`, getCssLevelColor(level), cssColors.reset)\n }\n sendToServer({\n timestamp: new Date().toISOString(),\n level,\n service: clientService,\n ...identityContext,\n tag,\n message,\n })\n } else {\n emitLog(level, { tag, message })\n }\n}\n\nfunction createLogMethod(level: LogLevel) {\n return function logMethod(tagOrEvent: string | Record<string, unknown>, message?: string): void {\n if (!(import.meta.client ?? isClient)) {\n return\n }\n\n if (typeof tagOrEvent === 'string' && message !== undefined) {\n emitTaggedLog(level, tagOrEvent, message)\n } else if (typeof tagOrEvent === 'object') {\n emitLog(level, tagOrEvent)\n } else {\n emitTaggedLog(level, 'log', String(tagOrEvent))\n }\n }\n}\n\nconst _clientLog: Log = {\n info: createLogMethod('info'),\n error: createLogMethod('error'),\n warn: createLogMethod('warn'),\n debug: createLogMethod('debug'),\n}\n\nexport { _clientLog as log }\n"],"mappings":";;AAGA,MAAM,WAAW,OAAO,WAAW;AAEnC,IAAI,gBAAgB;AACpB,IAAI,gBAAgB;AACpB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,mBAAmB;AACvB,IAAI,oBAAoB;AACxB,IAAI,kBAA2C,EAAE;AAEjD,SAAgB,YAAY,UAAyC;AACnE,mBAAkB,EAAE,GAAG,UAAU;;AAGnC,SAAgB,gBAAsB;AACpC,mBAAkB,EAAE;;AAItB,SAAgB,QAAQ,UAAqH,EAAE,EAAQ;AACrJ,iBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,UAAU;AACzE,iBAAgB,OAAO,QAAQ,YAAY,YAAY,QAAQ,UAAU;AACzE,gBAAe,OAAO,QAAQ,WAAW,YAAY,QAAQ,SAAS;AACtE,iBAAgB,QAAQ,WAAW;AACnC,oBAAmB,QAAQ,WAAW,WAAW;AACjD,qBAAoB,QAAQ,WAAW,YAAY;;AAGrD,eAAe,aAAa,OAA+C;AACzE,KAAI,CAAC,iBAAkB;AAEvB,KAAI;AACF,QAAM,MAAM,mBAAmB;GAC7B,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU,MAAM;GAC3B,WAAW;GACX,aAAa;GACd,CAAC;SACI;;AAKV,SAAS,QAAQ,OAAiB,OAAsC;AACtE,KAAI,CAAC,cAAe;CAEpB,MAAM,YAAY;EAChB,4BAAW,IAAI,MAAM,EAAC,aAAa;EACnC;EACA,SAAS;EACT,GAAG;EACH,GAAG;EACJ;AAED,KAAI,eAAe;EACjB,MAAM,SAAS,iBAAiB,MAAM;AACtC,MAAI,cAAc;GAChB,MAAM,EAAE,OAAO,KAAK,SAAS,GAAG,SAAS;AACzC,WAAQ,QAAQ,MAAM,mBAAmB,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,iBAAiB,IAAI,EAAE,UAAU,OAAO,KAAK;QAEpH,SAAQ,QAAQ,KAAK,UAAU,UAAU,CAAC;;AAI9C,cAAa,UAAU;;AAGzB,SAAS,cAAc,OAAiB,KAAa,SAAuB;AAC1E,KAAI,CAAC,cAAe;AACpB,KAAI,cAAc;AAChB,MAAI,cACF,SAAQ,iBAAiB,MAAM,EAAE,MAAM,mBAAmB,IAAI,CAAC,MAAM,mBAAmB,QAAQ,IAAI,iBAAiB,MAAM,EAAE,UAAU,MAAM;AAE/I,eAAa;GACX,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACA,SAAS;GACT,GAAG;GACH;GACA;GACD,CAAC;OAEF,SAAQ,OAAO;EAAE;EAAK;EAAS,CAAC;;AAIpC,SAAS,gBAAgB,OAAiB;AACxC,QAAO,SAAS,UAAU,YAA8C,SAAwB;AAC9F,MAAI,EAAE,OAAO,KAAK,UAAU,UAC1B;AAGF,MAAI,OAAO,eAAe,YAAY,YAAY,KAAA,EAChD,eAAc,OAAO,YAAY,QAAQ;WAChC,OAAO,eAAe,SAC/B,SAAQ,OAAO,WAAW;MAE1B,eAAc,OAAO,OAAO,OAAO,WAAW,CAAC;;;AAKrD,MAAM,aAAkB;CACtB,MAAM,gBAAgB,OAAO;CAC7B,OAAO,gBAAgB,QAAQ;CAC/B,MAAM,gBAAgB,OAAO;CAC7B,OAAO,gBAAgB,QAAQ;CAChC"}
@@ -1,6 +1,5 @@
1
1
  import { initLog } from "./log.mjs";
2
2
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
3
-
4
3
  //#region src/runtime/client/plugin.ts
5
4
  var plugin_default = defineNuxtPlugin(() => {
6
5
  const evlogConfig = useRuntimeConfig().public?.evlog;
@@ -12,7 +11,7 @@ var plugin_default = defineNuxtPlugin(() => {
12
11
  transport: evlogConfig?.transport
13
12
  });
14
13
  });
15
-
16
14
  //#endregion
17
15
  export { plugin_default as default };
16
+
18
17
  //# sourceMappingURL=plugin.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/runtime/client/plugin.ts"],"sourcesContent":["import type { TransportConfig } from '../../types'\nimport { initLog } from './log'\nimport { defineNuxtPlugin, useRuntimeConfig } from '#app'\n\ninterface EvlogPublicConfig {\n enabled?: boolean\n console?: boolean\n pretty?: boolean\n transport?: TransportConfig\n}\n\nexport default defineNuxtPlugin(() => {\n const config = useRuntimeConfig()\n const evlogConfig = config.public?.evlog as EvlogPublicConfig | undefined\n\n initLog({\n enabled: evlogConfig?.enabled,\n console: evlogConfig?.console,\n pretty: evlogConfig?.pretty ?? import.meta.dev,\n service: 'client',\n transport: evlogConfig?.transport,\n })\n})\n"],"mappings":";;;;AAWA,qBAAe,uBAAuB;CAEpC,MAAM,cADS,kBAAkB,CACN,QAAQ;AAEnC,SAAQ;EACN,SAAS,aAAa;EACtB,SAAS,aAAa;EACtB,QAAQ,aAAa,UAAU,OAAO,KAAK;EAC3C,SAAS;EACT,WAAW,aAAa;EACzB,CAAC;EACF"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../../src/runtime/client/plugin.ts"],"sourcesContent":["import type { TransportConfig } from '../../types'\nimport { initLog } from './log'\nimport { defineNuxtPlugin, useRuntimeConfig } from '#app'\n\ninterface EvlogPublicConfig {\n enabled?: boolean\n console?: boolean\n pretty?: boolean\n transport?: TransportConfig\n}\n\nexport default defineNuxtPlugin(() => {\n const config = useRuntimeConfig()\n const evlogConfig = config.public?.evlog as EvlogPublicConfig | undefined\n\n initLog({\n enabled: evlogConfig?.enabled,\n console: evlogConfig?.console,\n pretty: evlogConfig?.pretty ?? import.meta.dev,\n service: 'client',\n transport: evlogConfig?.transport,\n })\n})\n"],"mappings":";;;AAWA,IAAA,iBAAe,uBAAuB;CAEpC,MAAM,cADS,kBAAkB,CACN,QAAQ;AAEnC,SAAQ;EACN,SAAS,aAAa;EACtB,SAAS,aAAa;EACtB,QAAQ,aAAa,UAAU,OAAO,KAAK;EAC3C,SAAS;EACT,WAAW,aAAa;EACzB,CAAC;EACF"}
@@ -2,7 +2,6 @@ import { filterSafeHeaders } from "../../../../utils.mjs";
2
2
  import { getEnvironment } from "../../../../logger.mjs";
3
3
  import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readBody, setResponseStatus } from "h3";
4
4
  import { useNitroApp } from "nitropack/runtime";
5
-
6
5
  //#region src/runtime/server/routes/_evlog/ingest.post.ts
7
6
  const VALID_LEVELS = [
8
7
  "info",
@@ -117,7 +116,7 @@ var ingest_post_default = defineEventHandler(async (event) => {
117
116
  setResponseStatus(event, 204);
118
117
  return null;
119
118
  });
120
-
121
119
  //#endregion
122
120
  export { ingest_post_default as default };
121
+
123
122
  //# sourceMappingURL=ingest.post.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ingest.post.mjs","names":[],"sources":["../../../../../src/runtime/server/routes/_evlog/ingest.post.ts"],"sourcesContent":["import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readBody, setResponseStatus } from 'h3'\nimport { useNitroApp } from 'nitropack/runtime'\nimport type { IngestPayload, WideEvent } from '../../../../types'\nimport { getEnvironment } from '../../../../logger'\nimport { filterSafeHeaders } from '../../../../utils'\n\nconst VALID_LEVELS = ['info', 'error', 'warn', 'debug'] as const\n\nfunction validateOrigin(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): void {\n const origin = getHeader(event, 'origin')\n const referer = getHeader(event, 'referer')\n const host = getRequestHost(event)\n\n const requestOrigin = origin || (referer ? new URL(referer).origin : null)\n\n if (!requestOrigin) {\n throw createError({ statusCode: 403, message: 'Missing origin header' })\n }\n\n const originHost = new URL(requestOrigin).host\n\n if (originHost !== host) {\n throw createError({ statusCode: 403, message: 'Invalid origin' })\n }\n}\n\n// ISO 8601 datetime pattern (e.g., 2024-01-31T14:00:00.000Z)\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/\n\nfunction isValidISOTimestamp(value: string): boolean {\n if (!ISO_8601_REGEX.test(value)) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nfunction validatePayload(body: unknown): IngestPayload {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n\n const payload = body as Record<string, unknown>\n\n if (payload.timestamp === undefined || payload.timestamp === null) {\n throw createError({ statusCode: 400, message: 'Missing required field: timestamp' })\n }\n\n const { timestamp: rawTimestamp } = payload\n let timestamp: string\n if (typeof rawTimestamp === 'number') {\n const minTimestamp = new Date('2000-01-01').getTime()\n const maxTimestamp = Date.now() + 24 * 60 * 60 * 1000 // 1 day in the future\n if (rawTimestamp < minTimestamp || rawTimestamp > maxTimestamp) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: value out of reasonable range' })\n }\n timestamp = new Date(rawTimestamp).toISOString()\n } else if (typeof rawTimestamp === 'string') {\n if (!isValidISOTimestamp(rawTimestamp)) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be a valid ISO 8601 datetime string' })\n }\n timestamp = rawTimestamp\n } else {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be string or number' })\n }\n\n if (!payload.level || typeof payload.level !== 'string') {\n throw createError({ statusCode: 400, message: 'Missing required field: level' })\n }\n\n if (!VALID_LEVELS.includes(payload.level as typeof VALID_LEVELS[number])) {\n throw createError({ statusCode: 400, message: `Invalid level: must be one of ${VALID_LEVELS.join(', ')}` })\n }\n\n return {\n ...payload,\n timestamp,\n level: payload.level as IngestPayload['level'],\n }\n}\n\nfunction getSafeHeaders(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\nexport default defineEventHandler(async (event) => {\n validateOrigin(event)\n\n const body = await readBody(event)\n const payload = validatePayload(body)\n const nitroApp = useNitroApp()\n const env = getEnvironment()\n\n const { service: _clientService, ...sanitizedPayload } = payload as IngestPayload & { service?: unknown }\n\n const wideEvent: WideEvent = {\n ...sanitizedPayload,\n ...env,\n source: 'client',\n }\n\n const headers = getSafeHeaders(event)\n const request = { method: 'POST' as const, path: event.path }\n\n try {\n await nitroApp.hooks.callHook('evlog:enrich', {\n event: wideEvent,\n request,\n headers,\n response: { status: 204 },\n })\n } catch (err) {\n console.error('[evlog] enrich failed:', err)\n }\n\n const drainPromise = nitroApp.hooks.callHook('evlog:drain', {\n event: wideEvent,\n request,\n headers,\n }).catch((err) => {\n console.error('[evlog] drain failed:', err)\n })\n\n // Use waitUntil if available (Cloudflare Workers, Vercel Edge)\n // Otherwise, await the drain to prevent lost logs in serverless environments\n const waitUntilCtx = (event as unknown as { context: Record<string, unknown> }).context\n const cfCtx = (waitUntilCtx as { cloudflare?: { context?: { waitUntil?: (p: Promise<unknown>) => void } } }).cloudflare?.context ?? waitUntilCtx\n if (typeof (cfCtx as { waitUntil?: unknown }).waitUntil === 'function') {\n (cfCtx as { waitUntil: (p: Promise<unknown>) => void }).waitUntil(drainPromise)\n } else {\n await drainPromise\n }\n\n setResponseStatus(event, 204)\n return null\n})\n"],"mappings":";;;;;;AAMA,MAAM,eAAe;CAAC;CAAQ;CAAS;CAAQ;CAAQ;AAEvD,SAAS,eAAe,OAAmG;CACzH,MAAM,SAAS,UAAU,OAAO,SAAS;CACzC,MAAM,UAAU,UAAU,OAAO,UAAU;CAC3C,MAAM,OAAO,eAAe,MAAM;CAElC,MAAM,gBAAgB,WAAW,UAAU,IAAI,IAAI,QAAQ,CAAC,SAAS;AAErE,KAAI,CAAC,cACH,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAAyB,CAAC;AAK1E,KAFmB,IAAI,IAAI,cAAc,CAAC,SAEvB,KACjB,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAAkB,CAAC;;AAKrE,MAAM,iBAAiB;AAEvB,SAAS,oBAAoB,OAAwB;AACnD,KAAI,CAAC,eAAe,KAAK,MAAM,CAAE,QAAO;CACxC,MAAM,OAAO,IAAI,KAAK,MAAM;AAC5B,QAAO,CAAC,OAAO,MAAM,KAAK,SAAS,CAAC;;AAGtC,SAAS,gBAAgB,MAA8B;AACrD,KAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAC1D,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAAwB,CAAC;CAGzE,MAAM,UAAU;AAEhB,KAAI,QAAQ,cAAc,UAAa,QAAQ,cAAc,KAC3D,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAAqC,CAAC;CAGtF,MAAM,EAAE,WAAW,iBAAiB;CACpC,IAAI;AACJ,KAAI,OAAO,iBAAiB,UAAU;EACpC,MAAM,gCAAe,IAAI,KAAK,aAAa,EAAC,SAAS;EACrD,MAAM,eAAe,KAAK,KAAK,GAAG,OAAU,KAAK;AACjD,MAAI,eAAe,gBAAgB,eAAe,aAChD,OAAM,YAAY;GAAE,YAAY;GAAK,SAAS;GAAoD,CAAC;AAErG,cAAY,IAAI,KAAK,aAAa,CAAC,aAAa;YACvC,OAAO,iBAAiB,UAAU;AAC3C,MAAI,CAAC,oBAAoB,aAAa,CACpC,OAAM,YAAY;GAAE,YAAY;GAAK,SAAS;GAA+D,CAAC;AAEhH,cAAY;OAEZ,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAA+C,CAAC;AAGhG,KAAI,CAAC,QAAQ,SAAS,OAAO,QAAQ,UAAU,SAC7C,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS;EAAiC,CAAC;AAGlF,KAAI,CAAC,aAAa,SAAS,QAAQ,MAAqC,CACtE,OAAM,YAAY;EAAE,YAAY;EAAK,SAAS,iCAAiC,aAAa,KAAK,KAAK;EAAI,CAAC;AAG7G,QAAO;EACL,GAAG;EACH;EACA,OAAO,QAAQ;EAChB;;AAGH,SAAS,eAAe,OAAqH;AAE3I,QAAO,kBADY,WAAW,MAA0C,CACpC;;AAGtC,0BAAe,mBAAmB,OAAO,UAAU;AACjD,gBAAe,MAAM;CAGrB,MAAM,UAAU,gBADH,MAAM,SAAS,MAAM,CACG;CACrC,MAAM,WAAW,aAAa;CAC9B,MAAM,MAAM,gBAAgB;CAE5B,MAAM,EAAE,SAAS,gBAAgB,GAAG,qBAAqB;CAEzD,MAAM,YAAuB;EAC3B,GAAG;EACH,GAAG;EACH,QAAQ;EACT;CAED,MAAM,UAAU,eAAe,MAAM;CACrC,MAAM,UAAU;EAAE,QAAQ;EAAiB,MAAM,MAAM;EAAM;AAE7D,KAAI;AACF,QAAM,SAAS,MAAM,SAAS,gBAAgB;GAC5C,OAAO;GACP;GACA;GACA,UAAU,EAAE,QAAQ,KAAK;GAC1B,CAAC;UACK,KAAK;AACZ,UAAQ,MAAM,0BAA0B,IAAI;;CAG9C,MAAM,eAAe,SAAS,MAAM,SAAS,eAAe;EAC1D,OAAO;EACP;EACA;EACD,CAAC,CAAC,OAAO,QAAQ;AAChB,UAAQ,MAAM,yBAAyB,IAAI;GAC3C;CAIF,MAAM,eAAgB,MAA0D;CAChF,MAAM,QAAS,aAA8F,YAAY,WAAW;AACpI,KAAI,OAAQ,MAAkC,cAAc,WAC1D,CAAC,MAAuD,UAAU,aAAa;KAE/E,OAAM;AAGR,mBAAkB,OAAO,IAAI;AAC7B,QAAO;EACP"}
1
+ {"version":3,"file":"ingest.post.mjs","names":[],"sources":["../../../../../src/runtime/server/routes/_evlog/ingest.post.ts"],"sourcesContent":["import { createError, defineEventHandler, getHeader, getHeaders, getRequestHost, readBody, setResponseStatus } from 'h3'\nimport { useNitroApp } from 'nitropack/runtime'\nimport type { IngestPayload, WideEvent } from '../../../../types'\nimport { getEnvironment } from '../../../../logger'\nimport { filterSafeHeaders } from '../../../../utils'\n\nconst VALID_LEVELS = ['info', 'error', 'warn', 'debug'] as const\n\nfunction validateOrigin(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): void {\n const origin = getHeader(event, 'origin')\n const referer = getHeader(event, 'referer')\n const host = getRequestHost(event)\n\n const requestOrigin = origin || (referer ? new URL(referer).origin : null)\n\n if (!requestOrigin) {\n throw createError({ statusCode: 403, message: 'Missing origin header' })\n }\n\n const originHost = new URL(requestOrigin).host\n\n if (originHost !== host) {\n throw createError({ statusCode: 403, message: 'Invalid origin' })\n }\n}\n\n// ISO 8601 datetime pattern (e.g., 2024-01-31T14:00:00.000Z)\nconst ISO_8601_REGEX = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/\n\nfunction isValidISOTimestamp(value: string): boolean {\n if (!ISO_8601_REGEX.test(value)) return false\n const date = new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nfunction validatePayload(body: unknown): IngestPayload {\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n throw createError({ statusCode: 400, message: 'Invalid request body' })\n }\n\n const payload = body as Record<string, unknown>\n\n if (payload.timestamp === undefined || payload.timestamp === null) {\n throw createError({ statusCode: 400, message: 'Missing required field: timestamp' })\n }\n\n const { timestamp: rawTimestamp } = payload\n let timestamp: string\n if (typeof rawTimestamp === 'number') {\n const minTimestamp = new Date('2000-01-01').getTime()\n const maxTimestamp = Date.now() + 24 * 60 * 60 * 1000 // 1 day in the future\n if (rawTimestamp < minTimestamp || rawTimestamp > maxTimestamp) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: value out of reasonable range' })\n }\n timestamp = new Date(rawTimestamp).toISOString()\n } else if (typeof rawTimestamp === 'string') {\n if (!isValidISOTimestamp(rawTimestamp)) {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be a valid ISO 8601 datetime string' })\n }\n timestamp = rawTimestamp\n } else {\n throw createError({ statusCode: 400, message: 'Invalid timestamp: must be string or number' })\n }\n\n if (!payload.level || typeof payload.level !== 'string') {\n throw createError({ statusCode: 400, message: 'Missing required field: level' })\n }\n\n if (!VALID_LEVELS.includes(payload.level as typeof VALID_LEVELS[number])) {\n throw createError({ statusCode: 400, message: `Invalid level: must be one of ${VALID_LEVELS.join(', ')}` })\n }\n\n return {\n ...payload,\n timestamp,\n level: payload.level as IngestPayload['level'],\n }\n}\n\nfunction getSafeHeaders(event: Parameters<typeof defineEventHandler>[0] extends (e: infer E) => unknown ? E : never): Record<string, string> {\n const allHeaders = getHeaders(event as Parameters<typeof getHeaders>[0])\n return filterSafeHeaders(allHeaders)\n}\n\nexport default defineEventHandler(async (event) => {\n validateOrigin(event)\n\n const body = await readBody(event)\n const payload = validatePayload(body)\n const nitroApp = useNitroApp()\n const env = getEnvironment()\n\n const { service: _clientService, ...sanitizedPayload } = payload as IngestPayload & { service?: unknown }\n\n const wideEvent: WideEvent = {\n ...sanitizedPayload,\n ...env,\n source: 'client',\n }\n\n const headers = getSafeHeaders(event)\n const request = { method: 'POST' as const, path: event.path }\n\n try {\n await nitroApp.hooks.callHook('evlog:enrich', {\n event: wideEvent,\n request,\n headers,\n response: { status: 204 },\n })\n } catch (err) {\n console.error('[evlog] enrich failed:', err)\n }\n\n const drainPromise = nitroApp.hooks.callHook('evlog:drain', {\n event: wideEvent,\n request,\n headers,\n }).catch((err) => {\n console.error('[evlog] drain failed:', err)\n })\n\n // Use waitUntil if available (Cloudflare Workers, Vercel Edge)\n // Otherwise, await the drain to prevent lost logs in serverless environments\n const waitUntilCtx = (event as unknown as { context: Record<string, unknown> }).context\n const cfCtx = (waitUntilCtx as { cloudflare?: { context?: { waitUntil?: (p: Promise<unknown>) => void } } }).cloudflare?.context ?? waitUntilCtx\n if (typeof (cfCtx as { waitUntil?: unknown }).waitUntil === 'function') {\n (cfCtx as { waitUntil: (p: Promise<unknown>) => void }).waitUntil(drainPromise)\n } else {\n await drainPromise\n }\n\n setResponseStatus(event, 204)\n return null\n})\n"],"mappings":"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"}
@@ -1,39 +1,2 @@
1
- import { RequestLogger, ServerEvent } from "../../types.mjs";
2
-
3
- //#region src/runtime/server/useLogger.d.ts
4
- /**
5
- * Returns the request logger attached to the given server event.
6
- *
7
- * @param event - The current server event containing the context with the logger.
8
- * @param service - Optional service name to override the default service.
9
- * @returns The request-scoped logger.
10
- * @throws Error if the logger is not initialized on the event context.
11
- *
12
- * @example
13
- * export default defineEventHandler((event) => {
14
- * const log = useLogger(event)
15
- * log.set({ foo: 'bar' })
16
- * // ...
17
- * })
18
- *
19
- * @example
20
- * // Override service name for specific routes
21
- * export default defineEventHandler((event) => {
22
- * const log = useLogger(event, 'payment-service')
23
- * log.set({ foo: 'bar' })
24
- * // ...
25
- * })
26
- *
27
- * @example
28
- * // Typed fields — must use explicit import for type checking to work
29
- * import { useLogger } from 'evlog'
30
- *
31
- * interface MyFields { user: { id: string; plan: string } }
32
- * const log = useLogger<MyFields>(event)
33
- * log.set({ user: { id: '123', plan: 'pro' } }) // OK
34
- * log.set({ foo: 'bar' }) // TS error
35
- */
36
- declare function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): RequestLogger<T>;
37
- //#endregion
38
- export { useLogger };
39
- //# sourceMappingURL=useLogger.d.mts.map
1
+ import { t as useLogger } from "../../useLogger-_Ec6mXoR.mjs";
2
+ export { useLogger };
@@ -37,7 +37,7 @@ function useLogger(event, service) {
37
37
  if (service) log.set({ service });
38
38
  return log;
39
39
  }
40
-
41
40
  //#endregion
42
41
  export { useLogger };
42
+
43
43
  //# sourceMappingURL=useLogger.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useLogger.mjs","names":[],"sources":["../../../src/runtime/server/useLogger.ts"],"sourcesContent":["import type { RequestLogger, ServerEvent } from '../../types'\n\n/**\n * Returns the request logger attached to the given server event.\n *\n * @param event - The current server event containing the context with the logger.\n * @param service - Optional service name to override the default service.\n * @returns The request-scoped logger.\n * @throws Error if the logger is not initialized on the event context.\n *\n * @example\n * export default defineEventHandler((event) => {\n * const log = useLogger(event)\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Override service name for specific routes\n * export default defineEventHandler((event) => {\n * const log = useLogger(event, 'payment-service')\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Typed fields — must use explicit import for type checking to work\n * import { useLogger } from 'evlog'\n *\n * interface MyFields { user: { id: string; plan: string } }\n * const log = useLogger<MyFields>(event)\n * log.set({ user: { id: '123', plan: 'pro' } }) // OK\n * log.set({ foo: 'bar' }) // TS error\n */\nexport function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): RequestLogger<T> {\n const log = event.context.log as RequestLogger<T> | undefined\n\n if (!log) {\n throw new Error(\n '[evlog] Logger not initialized. Make sure the evlog Nitro plugin is registered. '\n + 'If using Nuxt, add \"evlog\" to your modules.',\n )\n }\n\n if (service) {\n const untyped = log as unknown as RequestLogger\n untyped.set({ service })\n }\n\n return log\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,UAAsD,OAAoB,SAAoC;CAC5H,MAAM,MAAM,MAAM,QAAQ;AAE1B,KAAI,CAAC,IACH,OAAM,IAAI,MACR,gIAED;AAGH,KAAI,QAEF,CADgB,IACR,IAAI,EAAE,SAAS,CAAC;AAG1B,QAAO"}
1
+ {"version":3,"file":"useLogger.mjs","names":[],"sources":["../../../src/runtime/server/useLogger.ts"],"sourcesContent":["import type { RequestLogger, ServerEvent } from '../../types'\n\n/**\n * Returns the request logger attached to the given server event.\n *\n * @param event - The current server event containing the context with the logger.\n * @param service - Optional service name to override the default service.\n * @returns The request-scoped logger.\n * @throws Error if the logger is not initialized on the event context.\n *\n * @example\n * export default defineEventHandler((event) => {\n * const log = useLogger(event)\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Override service name for specific routes\n * export default defineEventHandler((event) => {\n * const log = useLogger(event, 'payment-service')\n * log.set({ foo: 'bar' })\n * // ...\n * })\n *\n * @example\n * // Typed fields — must use explicit import for type checking to work\n * import { useLogger } from 'evlog'\n *\n * interface MyFields { user: { id: string; plan: string } }\n * const log = useLogger<MyFields>(event)\n * log.set({ user: { id: '123', plan: 'pro' } }) // OK\n * log.set({ foo: 'bar' }) // TS error\n */\nexport function useLogger<T extends object = Record<string, unknown>>(event: ServerEvent, service?: string): RequestLogger<T> {\n const log = event.context.log as RequestLogger<T> | undefined\n\n if (!log) {\n throw new Error(\n '[evlog] Logger not initialized. Make sure the evlog Nitro plugin is registered. '\n + 'If using Nuxt, add \"evlog\" to your modules.',\n )\n }\n\n if (service) {\n const untyped = log as unknown as RequestLogger\n untyped.set({ service })\n }\n\n return log\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,UAAsD,OAAoB,SAAoC;CAC5H,MAAM,MAAM,MAAM,QAAQ;AAE1B,KAAI,CAAC,IACH,OAAM,IAAI,MACR,gIAED;AAGH,KAAI,QACc,KACR,IAAI,EAAE,SAAS,CAAC;AAG1B,QAAO"}
@@ -1,7 +1,3 @@
1
- import { ParsedError } from "../../types.mjs";
2
-
3
- //#region src/runtime/utils/parseError.d.ts
4
- declare function parseError(error: unknown): ParsedError;
5
- //#endregion
6
- export { type ParsedError, parseError };
7
- //# sourceMappingURL=parseError.d.mts.map
1
+ import { m as ParsedError } from "../../types-B8-kC2ME.mjs";
2
+ import { t as parseError } from "../../parseError-BztqcPwZ.mjs";
3
+ export { ParsedError, parseError };
@@ -23,7 +23,7 @@ function parseError(error) {
23
23
  raw: error
24
24
  };
25
25
  }
26
-
27
26
  //#endregion
28
27
  export { parseError };
28
+
29
29
  //# sourceMappingURL=parseError.mjs.map
@@ -1,5 +1,4 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
-
3
2
  //#region src/shared/storage.ts
4
3
  /**
5
4
  * Create a request-scoped `AsyncLocalStorage` and a matching `useLogger` accessor.
@@ -10,6 +9,8 @@ import { AsyncLocalStorage } from "node:async_hooks";
10
9
  * @param contextHint - Human-readable hint appended to the error message when
11
10
  * `useLogger()` is called outside of a request (e.g.
12
11
  * `"middleware context. Make sure app.use(evlog()) is registered before your routes."`).
12
+ *
13
+ * @beta Part of `evlog/toolkit` — the public API for building custom integrations.
13
14
  */
14
15
  function createLoggerStorage(contextHint) {
15
16
  const storage = new AsyncLocalStorage();
@@ -39,7 +40,7 @@ function createLoggerStorage(contextHint) {
39
40
  useLogger
40
41
  };
41
42
  }
42
-
43
43
  //#endregion
44
44
  export { createLoggerStorage as t };
45
- //# sourceMappingURL=storage-CejtuV76.mjs.map
45
+
46
+ //# sourceMappingURL=storage-CJBW5Vos.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-CJBW5Vos.mjs","names":[],"sources":["../src/shared/storage.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { RequestLogger } from '../types'\n\n/**\n * Create a request-scoped `AsyncLocalStorage` and a matching `useLogger` accessor.\n *\n * Every framework that needs `useLogger()` (Express, Fastify, NestJS, SvelteKit)\n * calls this once at module level to get its own isolated storage + accessor pair.\n *\n * @param contextHint - Human-readable hint appended to the error message when\n * `useLogger()` is called outside of a request (e.g.\n * `\"middleware context. Make sure app.use(evlog()) is registered before your routes.\"`).\n *\n * @beta Part of `evlog/toolkit` — the public API for building custom integrations.\n */\nexport function createLoggerStorage(contextHint: string) {\n const storage = new AsyncLocalStorage<RequestLogger>()\n\n /**\n * Access the request-scoped logger created by the evlog middleware.\n *\n * Must be called inside a request that is handled by the evlog middleware.\n * Throws if called outside of a request context.\n *\n * @example\n * ```ts\n * import { useLogger } from 'evlog/express' // or /fastify, /nestjs, /sveltekit, /elysia\n *\n * function myService() {\n * const log = useLogger()\n * log.set({ users: { count: 42 } })\n * }\n * ```\n */\n function useLogger<T extends object = Record<string, unknown>>(): RequestLogger<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 return logger as RequestLogger<T>\n }\n\n return { storage, useLogger }\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,oBAAoB,aAAqB;CACvD,MAAM,UAAU,IAAI,mBAAkC;;;;;;;;;;;;;;;;;CAkBtD,SAAS,YAA0E;EACjF,MAAM,SAAS,QAAQ,UAAU;AACjC,MAAI,CAAC,OACH,OAAM,IAAI,MACR,sDAAsD,cACvD;AAEH,SAAO;;AAGT,QAAO;EAAE;EAAS;EAAW"}
@@ -1,5 +1,5 @@
1
- import { RequestLogger } from "../types.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-BoVCgsfQ.mjs";
1
+ import { g as RequestLogger } from "../types-B8-kC2ME.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-hZqyXoSk.mjs";
3
3
 
4
4
  //#region src/sveltekit/index.d.ts
5
5
  declare const useLogger: <T extends object = Record<string, unknown>>() => RequestLogger<T>;
@@ -1,8 +1,8 @@
1
1
  import { EvlogError } from "../error.mjs";
2
- import { n as resolveEvlogError, r as serializeEvlogErrorResponse, t as extractErrorStatus } from "../nitro-Da8tEfJ3.mjs";
3
- import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-CXOd5EyZ.mjs";
4
- import { t as createLoggerStorage } from "../storage-CejtuV76.mjs";
5
-
2
+ import { t as extractErrorStatus } from "../errors-BJRXUfMg.mjs";
3
+ import { n as serializeEvlogErrorResponse, t as resolveEvlogError } from "../nitro-D1pPm37T.mjs";
4
+ import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-Ba1eKT3i.mjs";
5
+ import { t as createLoggerStorage } from "../storage-CJBW5Vos.mjs";
6
6
  //#region src/sveltekit/index.ts
7
7
  const { storage, useLogger } = createLoggerStorage("handle context. Make sure evlog() handle is added to your hooks.server.ts.");
8
8
  /**
@@ -157,7 +157,7 @@ function createEvlogHooks(options = {}) {
157
157
  handleError: evlogHandleError()
158
158
  };
159
159
  }
160
-
161
160
  //#endregion
162
161
  export { createEvlogHooks, evlog, evlogHandleError, useLogger };
162
+
163
163
  //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,38 @@
1
+ import { g as RequestLogger } from "./types-B8-kC2ME.mjs";
2
+ import { i as createMiddlewareLogger, n as MiddlewareLoggerOptions, r as MiddlewareLoggerResult, t as BaseEvlogOptions } from "./middleware-hZqyXoSk.mjs";
3
+ import { n as getServiceForPath, r as shouldLog, t as extractErrorStatus } from "./errors-CKSfdvLa.mjs";
4
+ import { AsyncLocalStorage } from "node:async_hooks";
5
+
6
+ //#region src/shared/headers.d.ts
7
+ /**
8
+ * Extract headers from a Web API `Headers` object and filter out sensitive ones.
9
+ * Works with any runtime that supports the standard `Headers` API (Hono, Elysia,
10
+ * Nitro v3, Cloudflare Workers, Bun, Deno, etc.).
11
+ */
12
+ declare function extractSafeHeaders(headers: Headers): Record<string, string>;
13
+ /**
14
+ * Extract headers from Node.js `IncomingHttpHeaders` and filter out sensitive ones.
15
+ * Works with Express, Fastify, and any Node.js HTTP server using `req.headers`.
16
+ */
17
+ declare function extractSafeNodeHeaders(headers: Record<string, string | string[] | undefined>): Record<string, string>;
18
+ //#endregion
19
+ //#region src/shared/storage.d.ts
20
+ /**
21
+ * Create a request-scoped `AsyncLocalStorage` and a matching `useLogger` accessor.
22
+ *
23
+ * Every framework that needs `useLogger()` (Express, Fastify, NestJS, SvelteKit)
24
+ * calls this once at module level to get its own isolated storage + accessor pair.
25
+ *
26
+ * @param contextHint - Human-readable hint appended to the error message when
27
+ * `useLogger()` is called outside of a request (e.g.
28
+ * `"middleware context. Make sure app.use(evlog()) is registered before your routes."`).
29
+ *
30
+ * @beta Part of `evlog/toolkit` — the public API for building custom integrations.
31
+ */
32
+ declare function createLoggerStorage(contextHint: string): {
33
+ storage: AsyncLocalStorage<RequestLogger<Record<string, unknown>>>;
34
+ useLogger: <T extends object = Record<string, unknown>>() => RequestLogger<T>;
35
+ };
36
+ //#endregion
37
+ export { BaseEvlogOptions, MiddlewareLoggerOptions, MiddlewareLoggerResult, createLoggerStorage, createMiddlewareLogger, extractErrorStatus, extractSafeHeaders, extractSafeNodeHeaders, getServiceForPath, shouldLog };
38
+ //# sourceMappingURL=toolkit.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolkit.d.mts","names":[],"sources":["../src/shared/headers.ts","../src/shared/storage.ts"],"mappings":";;;;;;;;;;;iBAOgB,kBAAA,CAAmB,OAAA,EAAS,OAAA,GAAU,MAAA;AAAtD;;;;AAAA,iBAYgB,sBAAA,CAAuB,OAAA,EAAS,MAAA,0CAAgD,MAAA;;;;;;;AAZhG;;;;;;;;iBCQgB,mBAAA,CAAoB,WAAA;;iCAmBC,MAAA,wBAA+B,aAAA,CAAc,CAAA;AAAA"}
@@ -0,0 +1,5 @@
1
+ import { t as extractErrorStatus } from "./errors-BJRXUfMg.mjs";
2
+ import { n as shouldLog, t as getServiceForPath } from "./routes-CE3_c-iZ.mjs";
3
+ import { n as extractSafeNodeHeaders, r as createMiddlewareLogger, t as extractSafeHeaders } from "./headers-Ba1eKT3i.mjs";
4
+ import { t as createLoggerStorage } from "./storage-CJBW5Vos.mjs";
5
+ export { createLoggerStorage, createMiddlewareLogger, extractErrorStatus, extractSafeHeaders, extractSafeNodeHeaders, getServiceForPath, shouldLog };