evlog 2.7.0 → 2.8.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 (117) hide show
  1. package/README.md +26 -0
  2. package/dist/{_drain-FZVTbHn9.mjs → _drain-C9Nr-6Wc.mjs} +1 -1
  3. package/dist/{_drain-FZVTbHn9.mjs.map → _drain-C9Nr-6Wc.mjs.map} +1 -1
  4. package/dist/_http-C2UoHWgm.mjs +82 -0
  5. package/dist/_http-C2UoHWgm.mjs.map +1 -0
  6. package/dist/{_severity-fhhv2Nq0.mjs → _severity-BLiOKoxh.mjs} +1 -1
  7. package/dist/{_severity-fhhv2Nq0.mjs.map → _severity-BLiOKoxh.mjs.map} +1 -1
  8. package/dist/adapters/axiom.d.mts +3 -1
  9. package/dist/adapters/axiom.d.mts.map +1 -1
  10. package/dist/adapters/axiom.mjs +5 -3
  11. package/dist/adapters/axiom.mjs.map +1 -1
  12. package/dist/adapters/better-stack.d.mts +3 -1
  13. package/dist/adapters/better-stack.d.mts.map +1 -1
  14. package/dist/adapters/better-stack.mjs +5 -3
  15. package/dist/adapters/better-stack.mjs.map +1 -1
  16. package/dist/adapters/fs.d.mts +1 -1
  17. package/dist/adapters/fs.mjs +1 -1
  18. package/dist/adapters/otlp.d.mts +3 -1
  19. package/dist/adapters/otlp.d.mts.map +1 -1
  20. package/dist/adapters/otlp.mjs +6 -4
  21. package/dist/adapters/otlp.mjs.map +1 -1
  22. package/dist/adapters/posthog.d.mts +3 -1
  23. package/dist/adapters/posthog.d.mts.map +1 -1
  24. package/dist/adapters/posthog.mjs +7 -4
  25. package/dist/adapters/posthog.mjs.map +1 -1
  26. package/dist/adapters/sentry.d.mts +3 -1
  27. package/dist/adapters/sentry.d.mts.map +1 -1
  28. package/dist/adapters/sentry.mjs +6 -4
  29. package/dist/adapters/sentry.mjs.map +1 -1
  30. package/dist/ai/index.d.mts +88 -0
  31. package/dist/ai/index.d.mts.map +1 -0
  32. package/dist/ai/index.mjs +199 -0
  33. package/dist/ai/index.mjs.map +1 -0
  34. package/dist/browser.d.mts +1 -1
  35. package/dist/client.d.mts +2 -0
  36. package/dist/client.mjs +2 -0
  37. package/dist/{dist-BsWcv7B8.mjs → dist-BFn8qsRC.mjs} +1 -1
  38. package/dist/{dist-BsWcv7B8.mjs.map → dist-BFn8qsRC.mjs.map} +1 -1
  39. package/dist/elysia/index.d.mts +2 -2
  40. package/dist/elysia/index.mjs +1 -1
  41. package/dist/enrichers.d.mts +1 -1
  42. package/dist/{error-BuPbEDGO.d.mts → error-BheHTFFB.d.mts} +2 -2
  43. package/dist/{error-BuPbEDGO.d.mts.map → error-BheHTFFB.d.mts.map} +1 -1
  44. package/dist/error.d.mts +1 -1
  45. package/dist/{errors-BJRXUfMg.mjs → errors-BQgyQ9xe.mjs} +1 -1
  46. package/dist/{errors-BJRXUfMg.mjs.map → errors-BQgyQ9xe.mjs.map} +1 -1
  47. package/dist/{errors-nScQVwHW.d.mts → errors-D8WVZclz.d.mts} +2 -2
  48. package/dist/{errors-nScQVwHW.d.mts.map → errors-D8WVZclz.d.mts.map} +1 -1
  49. package/dist/express/index.d.mts +2 -2
  50. package/dist/express/index.mjs +2 -2
  51. package/dist/fastify/index.d.mts +2 -2
  52. package/dist/fastify/index.mjs +2 -2
  53. package/dist/{headers-BSgpnR0c.mjs → headers-DJ_YZbxT.mjs} +3 -3
  54. package/dist/{headers-BSgpnR0c.mjs.map → headers-DJ_YZbxT.mjs.map} +1 -1
  55. package/dist/hono/index.d.mts +2 -2
  56. package/dist/hono/index.mjs +1 -1
  57. package/dist/index.d.mts +5 -5
  58. package/dist/{logger-BH1gOdNP.d.mts → logger-BkXYNnHP.d.mts} +2 -2
  59. package/dist/{logger-BH1gOdNP.d.mts.map → logger-BkXYNnHP.d.mts.map} +1 -1
  60. package/dist/logger.d.mts +1 -1
  61. package/dist/logger.mjs +89 -99
  62. package/dist/logger.mjs.map +1 -1
  63. package/dist/{middleware-CDLTVOBs.d.mts → middleware-B-4hPOVG.d.mts} +2 -2
  64. package/dist/{middleware-CDLTVOBs.d.mts.map → middleware-B-4hPOVG.d.mts.map} +1 -1
  65. package/dist/nestjs/index.d.mts +2 -2
  66. package/dist/nestjs/index.mjs +2 -2
  67. package/dist/next/client.d.mts +1 -1
  68. package/dist/next/index.d.mts +4 -4
  69. package/dist/next/index.mjs +1 -1
  70. package/dist/nitro/errorHandler.mjs +2 -2
  71. package/dist/nitro/module.d.mts +2 -2
  72. package/dist/nitro/plugin.mjs +2 -2
  73. package/dist/nitro/v3/errorHandler.mjs +3 -3
  74. package/dist/nitro/v3/module.d.mts +1 -1
  75. package/dist/nitro/v3/plugin.mjs +3 -3
  76. package/dist/nitro/v3/useLogger.d.mts +1 -1
  77. package/dist/{nitro-D1pPm37T.mjs → nitro-CzyGROOC.mjs} +2 -2
  78. package/dist/{nitro-D1pPm37T.mjs.map → nitro-CzyGROOC.mjs.map} +1 -1
  79. package/dist/{nitro-CaIIZfdG.d.mts → nitro-DCNNxY_7.d.mts} +2 -2
  80. package/dist/{nitro-CaIIZfdG.d.mts.map → nitro-DCNNxY_7.d.mts.map} +1 -1
  81. package/dist/nuxt/module.d.mts +13 -1
  82. package/dist/nuxt/module.d.mts.map +1 -1
  83. package/dist/nuxt/module.mjs +7 -2
  84. package/dist/nuxt/module.mjs.map +1 -1
  85. package/dist/{parseError-DYrhDD1r.d.mts → parseError-B08FS7EQ.d.mts} +2 -2
  86. package/dist/parseError-B08FS7EQ.d.mts.map +1 -0
  87. package/dist/{routes-CE3_c-iZ.mjs → routes-CGPmbzCZ.mjs} +1 -1
  88. package/dist/{routes-CE3_c-iZ.mjs.map → routes-CGPmbzCZ.mjs.map} +1 -1
  89. package/dist/runtime/client/log.d.mts +1 -1
  90. package/dist/runtime/server/useLogger.d.mts +1 -1
  91. package/dist/runtime/utils/parseError.d.mts +2 -2
  92. package/dist/source-location-B1VVgXkh.mjs +1165 -0
  93. package/dist/source-location-B1VVgXkh.mjs.map +1 -0
  94. package/dist/{storage-DHU1gGqV.mjs → storage-DsueXspk.mjs} +1 -1
  95. package/dist/{storage-DHU1gGqV.mjs.map → storage-DsueXspk.mjs.map} +1 -1
  96. package/dist/sveltekit/index.d.mts +2 -2
  97. package/dist/sveltekit/index.mjs +4 -4
  98. package/dist/toolkit.d.mts +3 -3
  99. package/dist/toolkit.mjs +4 -4
  100. package/dist/{types-US-1hJZl.d.mts → types-CBpJBj_7.d.mts} +1 -1
  101. package/dist/{types-US-1hJZl.d.mts.map → types-CBpJBj_7.d.mts.map} +1 -1
  102. package/dist/types.d.mts +1 -1
  103. package/dist/{useLogger-DBHI03WK.d.mts → useLogger-DBPGEDf_.d.mts} +2 -2
  104. package/dist/{useLogger-DBHI03WK.d.mts.map → useLogger-DBPGEDf_.d.mts.map} +1 -1
  105. package/dist/utils.d.mts +1 -1
  106. package/dist/utils.d.mts.map +1 -1
  107. package/dist/utils.mjs +22 -16
  108. package/dist/utils.mjs.map +1 -1
  109. package/dist/vite/index.d.mts +80 -0
  110. package/dist/vite/index.d.mts.map +1 -0
  111. package/dist/vite/index.mjs +213 -0
  112. package/dist/vite/index.mjs.map +1 -0
  113. package/dist/workers.d.mts +1 -1
  114. package/package.json +39 -2
  115. package/dist/_http-DpL_o_Wk.mjs +0 -57
  116. package/dist/_http-DpL_o_Wk.mjs.map +0 -1
  117. package/dist/parseError-DYrhDD1r.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sentry.mjs","names":[],"sources":["../../src/adapters/sentry.ts"],"sourcesContent":["import type { WideEvent } from '../types'\nimport type { ConfigField } from './_config'\nimport { resolveAdapterConfig } from './_config'\nimport { defineDrain } from './_drain'\nimport { httpPost } from './_http'\nimport { OTEL_SEVERITY_NUMBER } from './_severity'\n\nexport interface SentryConfig {\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/** Sentry Log attribute value with type annotation */\nexport interface SentryAttributeValue {\n value: string | number | boolean\n type: 'string' | 'integer' | 'double' | 'boolean'\n}\n\n/** Sentry Structured Log payload */\nexport interface SentryLog {\n timestamp: number\n trace_id: string\n level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'\n body: string\n severity_number: number\n attributes?: Record<string, SentryAttributeValue>\n}\n\ninterface SentryDsnParts {\n publicKey: string\n secretKey?: string\n projectId: string\n origin: string\n basePath: string\n}\n\nconst SENTRY_FIELDS: ConfigField<SentryConfig>[] = [\n { key: 'dsn', env: ['NUXT_SENTRY_DSN', 'SENTRY_DSN'] },\n { key: 'environment', env: ['NUXT_SENTRY_ENVIRONMENT', 'SENTRY_ENVIRONMENT'] },\n { key: 'release', env: ['NUXT_SENTRY_RELEASE', 'SENTRY_RELEASE'] },\n { key: 'tags' },\n { key: 'timeout' },\n]\n\nfunction parseSentryDsn(dsn: string): SentryDsnParts {\n const url = new URL(dsn)\n const publicKey = url.username\n if (!publicKey) {\n throw new Error('Invalid Sentry DSN: missing public key')\n }\n\n const secretKey = url.password || undefined\n\n const pathParts = url.pathname.split('/').filter(Boolean)\n const projectId = pathParts.pop()\n if (!projectId) {\n throw new Error('Invalid Sentry DSN: missing project ID')\n }\n\n const basePath = pathParts.length > 0 ? `/${pathParts.join('/')}` : ''\n\n return {\n publicKey,\n secretKey,\n projectId,\n origin: `${url.protocol}//${url.host}`,\n basePath,\n }\n}\n\nfunction getSentryEnvelopeUrl(dsn: string): { url: string, authHeader: string } {\n const { publicKey, secretKey, projectId, origin, basePath } = parseSentryDsn(dsn)\n const url = `${origin}${basePath}/api/${projectId}/envelope/`\n let authHeader = `Sentry sentry_version=7, sentry_key=${publicKey}, sentry_client=evlog`\n if (secretKey) {\n authHeader += `, sentry_secret=${secretKey}`\n }\n return { url, authHeader }\n}\n\nfunction createTraceId(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return globalThis.crypto.randomUUID().replace(/-/g, '')\n }\n\n return Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join('')\n}\n\nfunction getFirstStringValue(event: WideEvent, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = event[key]\n if (typeof value === 'string' && value.length > 0) return value\n }\n return undefined\n}\n\nfunction toAttributeValue(value: unknown): SentryAttributeValue | undefined {\n if (value === null || value === undefined) {\n return undefined\n }\n if (typeof value === 'string') {\n return { value, type: 'string' }\n }\n if (typeof value === 'boolean') {\n return { value, type: 'boolean' }\n }\n if (typeof value === 'number') {\n if (Number.isInteger(value)) {\n return { value, type: 'integer' }\n }\n return { value, type: 'double' }\n }\n return { value: JSON.stringify(value), type: 'string' }\n}\n\nexport function toSentryLog(event: WideEvent, config: SentryConfig): SentryLog {\n const { timestamp, level, service, environment, version, ...rest } = event\n\n const body = getFirstStringValue(event, ['message', 'action', 'path'])\n ?? 'evlog wide event'\n\n const traceId = (typeof event.traceId === 'string' && event.traceId.length > 0)\n ? event.traceId\n : createTraceId()\n\n const attributes: Record<string, SentryAttributeValue> = {}\n\n const env = config.environment ?? environment\n if (env) {\n attributes['sentry.environment'] = { value: env, type: 'string' }\n }\n\n const rel = config.release ?? version\n if (typeof rel === 'string' && rel.length > 0) {\n attributes['sentry.release'] = { value: rel, type: 'string' }\n }\n\n attributes['service'] = { value: service, type: 'string' }\n\n if (config.tags) {\n for (const [key, value] of Object.entries(config.tags)) {\n attributes[key] = { value, type: 'string' }\n }\n }\n\n for (const [key, value] of Object.entries(rest)) {\n if (key === 'traceId' || key === 'spanId') continue\n if (value === undefined || value === null) continue\n const attr = toAttributeValue(value)\n if (attr) {\n attributes[key] = attr\n }\n }\n\n return {\n timestamp: new Date(timestamp).getTime() / 1000,\n trace_id: traceId,\n level: level as SentryLog['level'],\n body,\n severity_number: OTEL_SEVERITY_NUMBER[level] ?? 9,\n attributes,\n }\n}\n\n/**\n * Build the Sentry Envelope body for a list of logs.\n *\n * Envelope format (line-delimited):\n * - Line 1: Envelope headers (dsn, sent_at)\n * - Line 2: Item header (type: log, item_count, content_type)\n * - Line 3: Item payload ({\"items\": [...]})\n */\nfunction buildEnvelopeBody(logs: SentryLog[], dsn: string): string {\n const envelopeHeader = JSON.stringify({\n dsn,\n sent_at: new Date().toISOString(),\n })\n\n const itemHeader = JSON.stringify({\n type: 'log',\n item_count: logs.length,\n content_type: 'application/vnd.sentry.items.log+json',\n })\n\n const itemPayload = JSON.stringify({ items: logs })\n\n return `${envelopeHeader}\\n${itemHeader}\\n${itemPayload}\\n`\n}\n\n/**\n * Create a drain function for sending logs to Sentry.\n *\n * Sends wide events as Sentry Structured Logs, visible in Explore > Logs\n * in the Sentry dashboard.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createSentryDrain()\n * 2. runtimeConfig.evlog.sentry\n * 3. runtimeConfig.sentry\n * 4. Environment variables: NUXT_SENTRY_*, SENTRY_*\n *\n * @example\n * ```ts\n * // Zero config - just set NUXT_SENTRY_DSN env var\n * nitroApp.hooks.hook('evlog:drain', createSentryDrain())\n *\n * // With overrides\n * nitroApp.hooks.hook('evlog:drain', createSentryDrain({\n * dsn: 'https://public@o0.ingest.sentry.io/123',\n * }))\n * ```\n */\nexport function createSentryDrain(overrides?: Partial<SentryConfig>) {\n return defineDrain<SentryConfig>({\n name: 'sentry',\n resolve: () => {\n const config = resolveAdapterConfig<SentryConfig>('sentry', SENTRY_FIELDS, overrides)\n if (!config.dsn) {\n console.error('[evlog/sentry] Missing DSN. Set NUXT_SENTRY_DSN/SENTRY_DSN env var or pass to createSentryDrain()')\n return null\n }\n return config as SentryConfig\n },\n send: sendBatchToSentry,\n })\n}\n\n/**\n * Send a single event to Sentry as a structured log.\n *\n * @example\n * ```ts\n * await sendToSentry(event, {\n * dsn: process.env.SENTRY_DSN!,\n * })\n * ```\n */\nexport async function sendToSentry(event: WideEvent, config: SentryConfig): Promise<void> {\n await sendBatchToSentry([event], config)\n}\n\n/**\n * Send a batch of events to Sentry as structured logs via the Envelope endpoint.\n *\n * @example\n * ```ts\n * await sendBatchToSentry(events, {\n * dsn: process.env.SENTRY_DSN!,\n * })\n * ```\n */\nexport async function sendBatchToSentry(events: WideEvent[], config: SentryConfig): Promise<void> {\n if (events.length === 0) return\n\n const { url, authHeader } = getSentryEnvelopeUrl(config.dsn)\n\n const logs = events.map(event => toSentryLog(event, config))\n const body = buildEnvelopeBody(logs, config.dsn)\n\n await httpPost({\n url,\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n 'X-Sentry-Auth': authHeader,\n },\n body,\n timeout: config.timeout ?? 5000,\n label: 'Sentry',\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sentry.mjs","names":[],"sources":["../../src/adapters/sentry.ts"],"sourcesContent":["import type { WideEvent } from '../types'\nimport type { ConfigField } from './_config'\nimport { resolveAdapterConfig } from './_config'\nimport { defineDrain } from './_drain'\nimport { httpPost } from './_http'\nimport { OTEL_SEVERITY_NUMBER } from './_severity'\n\nexport interface SentryConfig {\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 /** Number of retry attempts on transient failures. Default: 2 */\n retries?: number\n}\n\n/** Sentry Log attribute value with type annotation */\nexport interface SentryAttributeValue {\n value: string | number | boolean\n type: 'string' | 'integer' | 'double' | 'boolean'\n}\n\n/** Sentry Structured Log payload */\nexport interface SentryLog {\n timestamp: number\n trace_id: string\n level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'\n body: string\n severity_number: number\n attributes?: Record<string, SentryAttributeValue>\n}\n\ninterface SentryDsnParts {\n publicKey: string\n secretKey?: string\n projectId: string\n origin: string\n basePath: string\n}\n\nconst SENTRY_FIELDS: ConfigField<SentryConfig>[] = [\n { key: 'dsn', env: ['NUXT_SENTRY_DSN', 'SENTRY_DSN'] },\n { key: 'environment', env: ['NUXT_SENTRY_ENVIRONMENT', 'SENTRY_ENVIRONMENT'] },\n { key: 'release', env: ['NUXT_SENTRY_RELEASE', 'SENTRY_RELEASE'] },\n { key: 'tags' },\n { key: 'timeout' },\n { key: 'retries' },\n]\n\nfunction parseSentryDsn(dsn: string): SentryDsnParts {\n const url = new URL(dsn)\n const publicKey = url.username\n if (!publicKey) {\n throw new Error('Invalid Sentry DSN: missing public key')\n }\n\n const secretKey = url.password || undefined\n\n const pathParts = url.pathname.split('/').filter(Boolean)\n const projectId = pathParts.pop()\n if (!projectId) {\n throw new Error('Invalid Sentry DSN: missing project ID')\n }\n\n const basePath = pathParts.length > 0 ? `/${pathParts.join('/')}` : ''\n\n return {\n publicKey,\n secretKey,\n projectId,\n origin: `${url.protocol}//${url.host}`,\n basePath,\n }\n}\n\nfunction getSentryEnvelopeUrl(dsn: string): { url: string, authHeader: string } {\n const { publicKey, secretKey, projectId, origin, basePath } = parseSentryDsn(dsn)\n const url = `${origin}${basePath}/api/${projectId}/envelope/`\n let authHeader = `Sentry sentry_version=7, sentry_key=${publicKey}, sentry_client=evlog`\n if (secretKey) {\n authHeader += `, sentry_secret=${secretKey}`\n }\n return { url, authHeader }\n}\n\nfunction createTraceId(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return globalThis.crypto.randomUUID().replace(/-/g, '')\n }\n\n return Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join('')\n}\n\nfunction getFirstStringValue(event: WideEvent, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = event[key]\n if (typeof value === 'string' && value.length > 0) return value\n }\n return undefined\n}\n\nfunction toAttributeValue(value: unknown): SentryAttributeValue | undefined {\n if (value === null || value === undefined) {\n return undefined\n }\n if (typeof value === 'string') {\n return { value, type: 'string' }\n }\n if (typeof value === 'boolean') {\n return { value, type: 'boolean' }\n }\n if (typeof value === 'number') {\n if (Number.isInteger(value)) {\n return { value, type: 'integer' }\n }\n return { value, type: 'double' }\n }\n return { value: JSON.stringify(value), type: 'string' }\n}\n\nexport function toSentryLog(event: WideEvent, config: SentryConfig): SentryLog {\n const { timestamp, level, service, environment, version, ...rest } = event\n\n const body = getFirstStringValue(event, ['message', 'action', 'path'])\n ?? 'evlog wide event'\n\n const traceId = (typeof event.traceId === 'string' && event.traceId.length > 0)\n ? event.traceId\n : createTraceId()\n\n const attributes: Record<string, SentryAttributeValue> = {}\n\n const env = config.environment ?? environment\n if (env) {\n attributes['sentry.environment'] = { value: env, type: 'string' }\n }\n\n const rel = config.release ?? version\n if (typeof rel === 'string' && rel.length > 0) {\n attributes['sentry.release'] = { value: rel, type: 'string' }\n }\n\n attributes['service'] = { value: service, type: 'string' }\n\n if (config.tags) {\n for (const [key, value] of Object.entries(config.tags)) {\n attributes[key] = { value, type: 'string' }\n }\n }\n\n for (const [key, value] of Object.entries(rest)) {\n if (key === 'traceId' || key === 'spanId') continue\n if (value === undefined || value === null) continue\n const attr = toAttributeValue(value)\n if (attr) {\n attributes[key] = attr\n }\n }\n\n return {\n timestamp: new Date(timestamp).getTime() / 1000,\n trace_id: traceId,\n level: level as SentryLog['level'],\n body,\n severity_number: OTEL_SEVERITY_NUMBER[level] ?? 9,\n attributes,\n }\n}\n\n/**\n * Build the Sentry Envelope body for a list of logs.\n *\n * Envelope format (line-delimited):\n * - Line 1: Envelope headers (dsn, sent_at)\n * - Line 2: Item header (type: log, item_count, content_type)\n * - Line 3: Item payload ({\"items\": [...]})\n */\nfunction buildEnvelopeBody(logs: SentryLog[], dsn: string): string {\n const envelopeHeader = JSON.stringify({\n dsn,\n sent_at: new Date().toISOString(),\n })\n\n const itemHeader = JSON.stringify({\n type: 'log',\n item_count: logs.length,\n content_type: 'application/vnd.sentry.items.log+json',\n })\n\n const itemPayload = JSON.stringify({ items: logs })\n\n return `${envelopeHeader}\\n${itemHeader}\\n${itemPayload}\\n`\n}\n\n/**\n * Create a drain function for sending logs to Sentry.\n *\n * Sends wide events as Sentry Structured Logs, visible in Explore > Logs\n * in the Sentry dashboard.\n *\n * Configuration priority (highest to lowest):\n * 1. Overrides passed to createSentryDrain()\n * 2. runtimeConfig.evlog.sentry\n * 3. runtimeConfig.sentry\n * 4. Environment variables: NUXT_SENTRY_*, SENTRY_*\n *\n * @example\n * ```ts\n * // Zero config - just set NUXT_SENTRY_DSN env var\n * nitroApp.hooks.hook('evlog:drain', createSentryDrain())\n *\n * // With overrides\n * nitroApp.hooks.hook('evlog:drain', createSentryDrain({\n * dsn: 'https://public@o0.ingest.sentry.io/123',\n * }))\n * ```\n */\nexport function createSentryDrain(overrides?: Partial<SentryConfig>) {\n return defineDrain<SentryConfig>({\n name: 'sentry',\n resolve: () => {\n const config = resolveAdapterConfig<SentryConfig>('sentry', SENTRY_FIELDS, overrides)\n if (!config.dsn) {\n console.error('[evlog/sentry] Missing DSN. Set NUXT_SENTRY_DSN/SENTRY_DSN env var or pass to createSentryDrain()')\n return null\n }\n return config as SentryConfig\n },\n send: sendBatchToSentry,\n })\n}\n\n/**\n * Send a single event to Sentry as a structured log.\n *\n * @example\n * ```ts\n * await sendToSentry(event, {\n * dsn: process.env.SENTRY_DSN!,\n * })\n * ```\n */\nexport async function sendToSentry(event: WideEvent, config: SentryConfig): Promise<void> {\n await sendBatchToSentry([event], config)\n}\n\n/**\n * Send a batch of events to Sentry as structured logs via the Envelope endpoint.\n *\n * @example\n * ```ts\n * await sendBatchToSentry(events, {\n * dsn: process.env.SENTRY_DSN!,\n * })\n * ```\n */\nexport async function sendBatchToSentry(events: WideEvent[], config: SentryConfig): Promise<void> {\n if (events.length === 0) return\n\n const { url, authHeader } = getSentryEnvelopeUrl(config.dsn)\n\n const logs = events.map(event => toSentryLog(event, config))\n const body = buildEnvelopeBody(logs, config.dsn)\n\n await httpPost({\n url,\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n 'X-Sentry-Auth': authHeader,\n },\n body,\n timeout: config.timeout ?? 5000,\n retries: config.retries,\n label: 'Sentry',\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { g as RequestLogger } from "../types-CBpJBj_7.mjs";
2
+ import { GatewayModelId } from "ai";
3
+ import { LanguageModelV3 } from "@ai-sdk/provider";
4
+
5
+ //#region src/ai/index.d.ts
6
+ /**
7
+ * Shape of the `ai` field written to the wide event.
8
+ */
9
+ interface AIEventData {
10
+ calls: number;
11
+ model: string;
12
+ models?: string[];
13
+ provider: string;
14
+ inputTokens: number;
15
+ outputTokens: number;
16
+ totalTokens: number;
17
+ cacheReadTokens?: number;
18
+ cacheWriteTokens?: number;
19
+ reasoningTokens?: number;
20
+ finishReason?: string;
21
+ toolCalls?: string[];
22
+ steps?: number;
23
+ msToFirstChunk?: number;
24
+ msToFinish?: number;
25
+ tokensPerSecond?: number;
26
+ error?: string;
27
+ }
28
+ interface AILogger {
29
+ /**
30
+ * Wrap a language model with evlog middleware.
31
+ * All `generateText`, `streamText`, `generateObject`, and `streamObject` calls
32
+ * using the wrapped model are captured automatically into the wide event.
33
+ *
34
+ * Accepts a `LanguageModelV3` object or a model string (e.g. `'anthropic/claude-sonnet-4.6'`).
35
+ * Strings are resolved via the AI SDK gateway.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const ai = createAILogger(log)
40
+ * const model = ai.wrap('anthropic/claude-sonnet-4.6')
41
+ *
42
+ * // Also accepts a model object
43
+ * const model = ai.wrap(anthropic('claude-sonnet-4.6'))
44
+ * ```
45
+ */
46
+ wrap: (model: LanguageModelV3 | GatewayModelId) => LanguageModelV3;
47
+ /**
48
+ * Manually capture token usage from an `embed()` or `embedMany()` result.
49
+ * Embedding models use a different type than language models, so they
50
+ * cannot be wrapped with middleware.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const { embedding, usage } = await embed({ model: embeddingModel, value: query })
55
+ * ai.captureEmbed({ usage })
56
+ * ```
57
+ */
58
+ captureEmbed: (result: {
59
+ usage: {
60
+ tokens: number;
61
+ };
62
+ }) => void;
63
+ }
64
+ /**
65
+ * Create an AI logger that captures AI SDK data into the wide event.
66
+ *
67
+ * Uses model middleware (`wrapLanguageModel`) to transparently intercept
68
+ * all LLM calls. `onFinish` and `onStepFinish` remain free for user code.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * import { createAILogger } from 'evlog/ai'
73
+ *
74
+ * const log = useLogger(event)
75
+ * const ai = createAILogger(log)
76
+ * const model = ai.wrap('anthropic/claude-sonnet-4.6')
77
+ *
78
+ * const result = streamText({
79
+ * model,
80
+ * messages,
81
+ * onFinish: ({ text }) => saveConversation(text),
82
+ * })
83
+ * ```
84
+ */
85
+ declare function createAILogger(log: RequestLogger): AILogger;
86
+ //#endregion
87
+ export { AIEventData, AILogger, createAILogger };
88
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/ai/index.ts"],"mappings":";;;;;;;AAQA;UAAiB,WAAA;EACf,KAAA;EACA,KAAA;EACA,MAAA;EACA,QAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;EACA,eAAA;EACA,gBAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,KAAA;EACA,cAAA;EACA,UAAA;EACA,eAAA;EACA,KAAA;AAAA;AAAA,UAGe,QAAA;EAHV;;AAGP;;;;;;;;;;;;;;;EAkBE,IAAA,GAAO,KAAA,EAAO,eAAA,GAAkB,cAAA,KAAmB,eAAA;EAapC;;;AA8DjB;;;;;;;;EA9DE,YAAA,GAAe,MAAA;IAAU,KAAA;MAAS,MAAA;IAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;iBA8DpB,cAAA,CAAe,GAAA,EAAK,aAAA,GAAgB,QAAA"}
@@ -0,0 +1,199 @@
1
+ import { gateway, wrapLanguageModel } from "ai";
2
+ //#region src/ai/index.ts
3
+ function addUsage(acc, usage) {
4
+ acc.inputTokens += usage.inputTokens.total ?? 0;
5
+ acc.outputTokens += usage.outputTokens.total ?? 0;
6
+ acc.cacheReadTokens += usage.inputTokens.cacheRead ?? 0;
7
+ acc.cacheWriteTokens += usage.inputTokens.cacheWrite ?? 0;
8
+ acc.reasoningTokens += usage.outputTokens.reasoning ?? 0;
9
+ }
10
+ /**
11
+ * When using `gateway('google/gemini-3-flash')`, the model object has
12
+ * `provider: 'gateway'` and `modelId: 'google/gemini-3-flash'`.
13
+ * This extracts the real provider and model name from the modelId.
14
+ */
15
+ function resolveProviderAndModel(provider, modelId) {
16
+ if (provider !== "gateway" || !modelId.includes("/")) return {
17
+ provider,
18
+ model: modelId
19
+ };
20
+ const slashIndex = modelId.indexOf("/");
21
+ return {
22
+ provider: modelId.slice(0, slashIndex),
23
+ model: modelId.slice(slashIndex + 1)
24
+ };
25
+ }
26
+ /**
27
+ * Create an AI logger that captures AI SDK data into the wide event.
28
+ *
29
+ * Uses model middleware (`wrapLanguageModel`) to transparently intercept
30
+ * all LLM calls. `onFinish` and `onStepFinish` remain free for user code.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { createAILogger } from 'evlog/ai'
35
+ *
36
+ * const log = useLogger(event)
37
+ * const ai = createAILogger(log)
38
+ * const model = ai.wrap('anthropic/claude-sonnet-4.6')
39
+ *
40
+ * const result = streamText({
41
+ * model,
42
+ * messages,
43
+ * onFinish: ({ text }) => saveConversation(text),
44
+ * })
45
+ * ```
46
+ */
47
+ function createAILogger(log) {
48
+ let calls = 0;
49
+ let steps = 0;
50
+ const usage = {
51
+ inputTokens: 0,
52
+ outputTokens: 0,
53
+ cacheReadTokens: 0,
54
+ cacheWriteTokens: 0,
55
+ reasoningTokens: 0
56
+ };
57
+ const models = [];
58
+ const providers = [];
59
+ const allToolCalls = [];
60
+ let lastFinishReason;
61
+ let lastMsToFirstChunk;
62
+ let lastMsToFinish;
63
+ let lastError;
64
+ function flush() {
65
+ const uniqueModels = [...new Set(models)];
66
+ const lastModel = models[models.length - 1];
67
+ const lastProvider = providers[providers.length - 1];
68
+ const data = {
69
+ calls,
70
+ inputTokens: usage.inputTokens,
71
+ outputTokens: usage.outputTokens,
72
+ totalTokens: usage.inputTokens + usage.outputTokens
73
+ };
74
+ if (lastModel) data.model = lastModel;
75
+ if (lastProvider) data.provider = lastProvider;
76
+ if (uniqueModels.length > 1) data.models = uniqueModels;
77
+ if (usage.cacheReadTokens > 0) data.cacheReadTokens = usage.cacheReadTokens;
78
+ if (usage.cacheWriteTokens > 0) data.cacheWriteTokens = usage.cacheWriteTokens;
79
+ if (usage.reasoningTokens > 0) data.reasoningTokens = usage.reasoningTokens;
80
+ if (lastFinishReason) data.finishReason = lastFinishReason;
81
+ if (allToolCalls.length > 0) data.toolCalls = [...allToolCalls];
82
+ if (steps > 1) data.steps = steps;
83
+ if (lastMsToFirstChunk !== void 0) data.msToFirstChunk = lastMsToFirstChunk;
84
+ if (lastMsToFinish !== void 0) {
85
+ data.msToFinish = lastMsToFinish;
86
+ if (usage.outputTokens > 0 && lastMsToFinish > 0) data.tokensPerSecond = Math.round(usage.outputTokens / lastMsToFinish * 1e3);
87
+ }
88
+ if (lastError) data.error = lastError;
89
+ log.set({ ai: data });
90
+ }
91
+ function recordModel(provider, modelId, responseModelId) {
92
+ const resolved = resolveProviderAndModel(provider, responseModelId ?? modelId);
93
+ models.push(resolved.model);
94
+ providers.push(resolved.provider);
95
+ }
96
+ const middleware = {
97
+ wrapGenerate: async ({ doGenerate, model }) => {
98
+ try {
99
+ const result = await doGenerate();
100
+ calls++;
101
+ steps++;
102
+ addUsage(usage, result.usage);
103
+ recordModel(model.provider, model.modelId, result.response?.modelId);
104
+ lastFinishReason = result.finishReason.unified;
105
+ for (const item of result.content) if (item.type === "tool-call") allToolCalls.push(item.toolName);
106
+ flush();
107
+ return result;
108
+ } catch (error) {
109
+ calls++;
110
+ steps++;
111
+ recordModel(model.provider, model.modelId);
112
+ lastFinishReason = "error";
113
+ lastError = error instanceof Error ? error.message : String(error);
114
+ flush();
115
+ throw error;
116
+ }
117
+ },
118
+ wrapStream: async ({ doStream, model }) => {
119
+ const streamStart = Date.now();
120
+ let firstChunkTime;
121
+ let streamUsage;
122
+ let streamFinishReason;
123
+ let streamModelId;
124
+ const streamToolCalls = [];
125
+ let streamError;
126
+ let doStreamResult;
127
+ try {
128
+ doStreamResult = await doStream();
129
+ } catch (error) {
130
+ calls++;
131
+ steps++;
132
+ recordModel(model.provider, model.modelId);
133
+ lastFinishReason = "error";
134
+ lastError = error instanceof Error ? error.message : String(error);
135
+ flush();
136
+ throw error;
137
+ }
138
+ const { stream, ...rest } = doStreamResult;
139
+ const transformStream = new TransformStream({
140
+ transform(chunk, controller) {
141
+ if (!firstChunkTime && chunk.type === "text-delta") firstChunkTime = Date.now();
142
+ if (chunk.type === "tool-input-start") streamToolCalls.push(chunk.toolName);
143
+ if (chunk.type === "finish") {
144
+ streamUsage = {
145
+ inputTokens: chunk.usage.inputTokens.total ?? 0,
146
+ outputTokens: chunk.usage.outputTokens.total ?? 0,
147
+ cacheReadTokens: chunk.usage.inputTokens.cacheRead ?? 0,
148
+ cacheWriteTokens: chunk.usage.inputTokens.cacheWrite ?? 0,
149
+ reasoningTokens: chunk.usage.outputTokens.reasoning ?? 0
150
+ };
151
+ streamFinishReason = chunk.finishReason.unified;
152
+ }
153
+ if (chunk.type === "response-metadata" && "modelId" in chunk && chunk.modelId) streamModelId = chunk.modelId;
154
+ if (chunk.type === "error") streamError = chunk.error instanceof Error ? chunk.error.message : String(chunk.error);
155
+ controller.enqueue(chunk);
156
+ },
157
+ flush() {
158
+ calls++;
159
+ steps++;
160
+ if (streamUsage) {
161
+ usage.inputTokens += streamUsage.inputTokens;
162
+ usage.outputTokens += streamUsage.outputTokens;
163
+ usage.cacheReadTokens += streamUsage.cacheReadTokens;
164
+ usage.cacheWriteTokens += streamUsage.cacheWriteTokens;
165
+ usage.reasoningTokens += streamUsage.reasoningTokens;
166
+ }
167
+ recordModel(model.provider, model.modelId, streamModelId);
168
+ lastFinishReason = streamFinishReason;
169
+ for (const name of streamToolCalls) allToolCalls.push(name);
170
+ if (firstChunkTime) lastMsToFirstChunk = firstChunkTime - streamStart;
171
+ lastMsToFinish = Date.now() - streamStart;
172
+ if (streamError) lastError = streamError;
173
+ flush();
174
+ }
175
+ });
176
+ return {
177
+ stream: stream.pipeThrough(transformStream),
178
+ ...rest
179
+ };
180
+ }
181
+ };
182
+ return {
183
+ wrap: (model) => {
184
+ return wrapLanguageModel({
185
+ model: typeof model === "string" ? gateway(model) : model,
186
+ middleware
187
+ });
188
+ },
189
+ captureEmbed: (result) => {
190
+ calls++;
191
+ usage.inputTokens += result.usage.tokens;
192
+ flush();
193
+ }
194
+ };
195
+ }
196
+ //#endregion
197
+ export { createAILogger };
198
+
199
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/ai/index.ts"],"sourcesContent":["import { gateway, wrapLanguageModel } from 'ai'\nimport type { GatewayModelId } from 'ai'\nimport type { LanguageModelV3, LanguageModelV3Middleware, LanguageModelV3StreamPart } from '@ai-sdk/provider'\nimport type { RequestLogger } from '../types'\n\n/**\n * Shape of the `ai` field written to the wide event.\n */\nexport interface AIEventData {\n calls: number\n model: string\n models?: string[]\n provider: string\n inputTokens: number\n outputTokens: number\n totalTokens: number\n cacheReadTokens?: number\n cacheWriteTokens?: number\n reasoningTokens?: number\n finishReason?: string\n toolCalls?: string[]\n steps?: number\n msToFirstChunk?: number\n msToFinish?: number\n tokensPerSecond?: number\n error?: string\n}\n\nexport interface AILogger {\n /**\n * Wrap a language model with evlog middleware.\n * All `generateText`, `streamText`, `generateObject`, and `streamObject` calls\n * using the wrapped model are captured automatically into the wide event.\n *\n * Accepts a `LanguageModelV3` object or a model string (e.g. `'anthropic/claude-sonnet-4.6'`).\n * Strings are resolved via the AI SDK gateway.\n *\n * @example\n * ```ts\n * const ai = createAILogger(log)\n * const model = ai.wrap('anthropic/claude-sonnet-4.6')\n *\n * // Also accepts a model object\n * const model = ai.wrap(anthropic('claude-sonnet-4.6'))\n * ```\n */\n wrap: (model: LanguageModelV3 | GatewayModelId) => LanguageModelV3\n\n /**\n * Manually capture token usage from an `embed()` or `embedMany()` result.\n * Embedding models use a different type than language models, so they\n * cannot be wrapped with middleware.\n *\n * @example\n * ```ts\n * const { embedding, usage } = await embed({ model: embeddingModel, value: query })\n * ai.captureEmbed({ usage })\n * ```\n */\n captureEmbed: (result: { usage: { tokens: number } }) => void\n}\n\ninterface UsageAccumulator {\n inputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n}\n\nfunction addUsage(\n acc: UsageAccumulator,\n usage: {\n inputTokens: { total: number | undefined, cacheRead?: number | undefined, cacheWrite?: number | undefined }\n outputTokens: { total: number | undefined, reasoning?: number | undefined }\n },\n): void {\n acc.inputTokens += usage.inputTokens.total ?? 0\n acc.outputTokens += usage.outputTokens.total ?? 0\n acc.cacheReadTokens += usage.inputTokens.cacheRead ?? 0\n acc.cacheWriteTokens += usage.inputTokens.cacheWrite ?? 0\n acc.reasoningTokens += usage.outputTokens.reasoning ?? 0\n}\n\n/**\n * When using `gateway('google/gemini-3-flash')`, the model object has\n * `provider: 'gateway'` and `modelId: 'google/gemini-3-flash'`.\n * This extracts the real provider and model name from the modelId.\n */\nfunction resolveProviderAndModel(provider: string, modelId: string): { provider: string, model: string } {\n if (provider !== 'gateway' || !modelId.includes('/')) {\n return { provider, model: modelId }\n }\n const slashIndex = modelId.indexOf('/')\n return {\n provider: modelId.slice(0, slashIndex),\n model: modelId.slice(slashIndex + 1),\n }\n}\n\n/**\n * Create an AI logger that captures AI SDK data into the wide event.\n *\n * Uses model middleware (`wrapLanguageModel`) to transparently intercept\n * all LLM calls. `onFinish` and `onStepFinish` remain free for user code.\n *\n * @example\n * ```ts\n * import { createAILogger } from 'evlog/ai'\n *\n * const log = useLogger(event)\n * const ai = createAILogger(log)\n * const model = ai.wrap('anthropic/claude-sonnet-4.6')\n *\n * const result = streamText({\n * model,\n * messages,\n * onFinish: ({ text }) => saveConversation(text),\n * })\n * ```\n */\nexport function createAILogger(log: RequestLogger): AILogger {\n let calls = 0\n let steps = 0\n const usage: UsageAccumulator = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n reasoningTokens: 0,\n }\n const models: string[] = []\n const providers: string[] = []\n const allToolCalls: string[] = []\n let lastFinishReason: string | undefined\n let lastMsToFirstChunk: number | undefined\n let lastMsToFinish: number | undefined\n let lastError: string | undefined\n\n function flush(): void {\n const uniqueModels = [...new Set(models)]\n const lastModel = models[models.length - 1]\n const lastProvider = providers[providers.length - 1]\n\n const data: Partial<AIEventData> & { calls: number, inputTokens: number, outputTokens: number, totalTokens: number } = {\n calls,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalTokens: usage.inputTokens + usage.outputTokens,\n }\n\n if (lastModel) data.model = lastModel\n if (lastProvider) data.provider = lastProvider\n if (uniqueModels.length > 1) data.models = uniqueModels\n if (usage.cacheReadTokens > 0) data.cacheReadTokens = usage.cacheReadTokens\n if (usage.cacheWriteTokens > 0) data.cacheWriteTokens = usage.cacheWriteTokens\n if (usage.reasoningTokens > 0) data.reasoningTokens = usage.reasoningTokens\n if (lastFinishReason) data.finishReason = lastFinishReason\n if (allToolCalls.length > 0) data.toolCalls = [...allToolCalls]\n if (steps > 1) data.steps = steps\n if (lastMsToFirstChunk !== undefined) data.msToFirstChunk = lastMsToFirstChunk\n if (lastMsToFinish !== undefined) {\n data.msToFinish = lastMsToFinish\n if (usage.outputTokens > 0 && lastMsToFinish > 0) {\n data.tokensPerSecond = Math.round((usage.outputTokens / lastMsToFinish) * 1000)\n }\n }\n if (lastError) data.error = lastError\n\n log.set({ ai: data } as Record<string, unknown>)\n }\n\n function recordModel(provider: string, modelId: string, responseModelId?: string): void {\n const resolved = resolveProviderAndModel(provider, responseModelId ?? modelId)\n models.push(resolved.model)\n providers.push(resolved.provider)\n }\n\n const middleware: LanguageModelV3Middleware = {\n wrapGenerate: async ({ doGenerate, model }) => {\n try {\n const result = await doGenerate()\n\n calls++\n steps++\n addUsage(usage, result.usage)\n recordModel(model.provider, model.modelId, result.response?.modelId)\n lastFinishReason = result.finishReason.unified\n\n for (const item of result.content) {\n if (item.type === 'tool-call') {\n allToolCalls.push(item.toolName)\n }\n }\n\n flush()\n return result\n } catch (error) {\n calls++\n steps++\n recordModel(model.provider, model.modelId)\n lastFinishReason = 'error'\n lastError = error instanceof Error ? error.message : String(error)\n flush()\n throw error\n }\n },\n\n wrapStream: async ({ doStream, model }) => {\n const streamStart = Date.now()\n let firstChunkTime: number | undefined\n\n let streamUsage: UsageAccumulator | undefined\n let streamFinishReason: string | undefined\n let streamModelId: string | undefined\n const streamToolCalls: string[] = []\n let streamError: string | undefined\n\n let doStreamResult: Awaited<ReturnType<typeof doStream>>\n try {\n doStreamResult = await doStream()\n } catch (error) {\n calls++\n steps++\n recordModel(model.provider, model.modelId)\n lastFinishReason = 'error'\n lastError = error instanceof Error ? error.message : String(error)\n flush()\n throw error\n }\n\n const { stream, ...rest } = doStreamResult\n\n const transformStream = new TransformStream<\n LanguageModelV3StreamPart,\n LanguageModelV3StreamPart\n >({\n transform(chunk, controller) {\n if (!firstChunkTime && chunk.type === 'text-delta') {\n firstChunkTime = Date.now()\n }\n\n if (chunk.type === 'tool-input-start') {\n streamToolCalls.push(chunk.toolName)\n }\n\n if (chunk.type === 'finish') {\n streamUsage = {\n inputTokens: chunk.usage.inputTokens.total ?? 0,\n outputTokens: chunk.usage.outputTokens.total ?? 0,\n cacheReadTokens: chunk.usage.inputTokens.cacheRead ?? 0,\n cacheWriteTokens: chunk.usage.inputTokens.cacheWrite ?? 0,\n reasoningTokens: chunk.usage.outputTokens.reasoning ?? 0,\n }\n streamFinishReason = chunk.finishReason.unified\n }\n\n if (chunk.type === 'response-metadata' && 'modelId' in chunk && chunk.modelId) {\n streamModelId = chunk.modelId as string\n }\n\n if (chunk.type === 'error') {\n streamError = chunk.error instanceof Error ? chunk.error.message : String(chunk.error)\n }\n\n controller.enqueue(chunk)\n },\n\n flush() {\n calls++\n steps++\n\n if (streamUsage) {\n usage.inputTokens += streamUsage.inputTokens\n usage.outputTokens += streamUsage.outputTokens\n usage.cacheReadTokens += streamUsage.cacheReadTokens\n usage.cacheWriteTokens += streamUsage.cacheWriteTokens\n usage.reasoningTokens += streamUsage.reasoningTokens\n }\n\n recordModel(model.provider, model.modelId, streamModelId)\n lastFinishReason = streamFinishReason\n\n for (const name of streamToolCalls) {\n allToolCalls.push(name)\n }\n\n if (firstChunkTime) {\n lastMsToFirstChunk = firstChunkTime - streamStart\n }\n lastMsToFinish = Date.now() - streamStart\n\n if (streamError) lastError = streamError\n\n flush()\n },\n })\n\n return {\n stream: stream.pipeThrough(transformStream),\n ...rest,\n }\n },\n }\n\n return {\n wrap: (model: LanguageModelV3 | GatewayModelId) => {\n const resolved = typeof model === 'string' ? gateway(model) : model\n return wrapLanguageModel({ model: resolved, middleware })\n },\n\n captureEmbed: (result: { usage: { tokens: number } }) => {\n calls++\n usage.inputTokens += result.usage.tokens\n flush()\n },\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { r as DrainContext } from "./types-US-1hJZl.mjs";
1
+ import { r as DrainContext } from "./types-CBpJBj_7.mjs";
2
2
  import { DrainPipelineOptions, PipelineDrainFn } from "./pipeline.mjs";
3
3
 
4
4
  //#region src/browser.d.ts
@@ -0,0 +1,2 @@
1
+ import { clearIdentity, initLog, log as _clientLog, setIdentity } from "./runtime/client/log.mjs";
2
+ export { clearIdentity, initLog, _clientLog as log, setIdentity };
@@ -0,0 +1,2 @@
1
+ import { clearIdentity, initLog, log as _clientLog, setIdentity } from "./runtime/client/log.mjs";
2
+ export { clearIdentity, initLog, _clientLog as log, setIdentity };
@@ -48,4 +48,4 @@ function parsePath(input = "") {
48
48
  //#endregion
49
49
  export { parseURL as t };
50
50
 
51
- //# sourceMappingURL=dist-BsWcv7B8.mjs.map
51
+ //# sourceMappingURL=dist-BFn8qsRC.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dist-BsWcv7B8.mjs","names":[],"sources":["../../../node_modules/ufo/dist/index.mjs"],"sourcesContent":["const n = /[^\\0-\\x7E]/;\nconst t = /[\\x2E\\u3002\\uFF0E\\uFF61]/g;\nconst o = {\n overflow: \"Overflow Error\",\n \"not-basic\": \"Illegal Input\",\n \"invalid-input\": \"Invalid Input\"\n};\nconst e = Math.floor;\nconst r = String.fromCharCode;\nfunction s(n2) {\n throw new RangeError(o[n2]);\n}\nconst c = function(n2, t2) {\n return n2 + 22 + 75 * (n2 < 26) - ((t2 != 0) << 5);\n};\nconst u = function(n2, t2, o2) {\n let r2 = 0;\n for (n2 = o2 ? e(n2 / 700) : n2 >> 1, n2 += e(n2 / t2); n2 > 455; r2 += 36) {\n n2 = e(n2 / 35);\n }\n return e(r2 + 36 * n2 / (n2 + 38));\n};\nfunction toASCII(o2) {\n return (function(n2, o3) {\n const e2 = n2.split(\"@\");\n let r2 = \"\";\n e2.length > 1 && (r2 = e2[0] + \"@\", n2 = e2[1]);\n const s2 = (function(n3, t2) {\n const o4 = [];\n let e3 = n3.length;\n for (; e3--; ) {\n o4[e3] = t2(n3[e3]);\n }\n return o4;\n })((n2 = n2.replace(t, \".\")).split(\".\"), o3).join(\".\");\n return r2 + s2;\n })(o2, function(t2) {\n return n.test(t2) ? \"xn--\" + (function(n2) {\n const t3 = [];\n const o3 = (n2 = (function(n3) {\n const t4 = [];\n let o4 = 0;\n const e2 = n3.length;\n for (; o4 < e2; ) {\n const r2 = n3.charCodeAt(o4++);\n if (r2 >= 55296 && r2 <= 56319 && o4 < e2) {\n const e3 = n3.charCodeAt(o4++);\n (64512 & e3) == 56320 ? t4.push(((1023 & r2) << 10) + (1023 & e3) + 65536) : (t4.push(r2), o4--);\n } else {\n t4.push(r2);\n }\n }\n return t4;\n })(n2)).length;\n let f = 128;\n let i = 0;\n let l = 72;\n for (const o4 of n2) {\n o4 < 128 && t3.push(r(o4));\n }\n const h = t3.length;\n let p = h;\n for (h && t3.push(\"-\"); p < o3; ) {\n let o4 = 2147483647;\n for (const t4 of n2) {\n t4 >= f && t4 < o4 && (o4 = t4);\n }\n const a = p + 1;\n o4 - f > e((2147483647 - i) / a) && s(\"overflow\"), i += (o4 - f) * a, f = o4;\n for (const o5 of n2) {\n if (o5 < f && ++i > 2147483647 && s(\"overflow\"), o5 == f) {\n let n3 = i;\n for (let o6 = 36; ; o6 += 36) {\n const s2 = o6 <= l ? 1 : o6 >= l + 26 ? 26 : o6 - l;\n if (n3 < s2) {\n break;\n }\n const u2 = n3 - s2;\n const f2 = 36 - s2;\n t3.push(r(c(s2 + u2 % f2, 0))), n3 = e(u2 / f2);\n }\n t3.push(r(c(n3, 0))), l = u(i, a, p == h), i = 0, ++p;\n }\n }\n ++i, ++f;\n }\n return t3.join(\"\");\n })(t2) : t2;\n });\n}\n\nconst HASH_RE = /#/g;\nconst AMPERSAND_RE = /&/g;\nconst SLASH_RE = /\\//g;\nconst EQUAL_RE = /=/g;\nconst IM_RE = /\\?/g;\nconst PLUS_RE = /\\+/g;\nconst ENC_CARET_RE = /%5e/gi;\nconst ENC_BACKTICK_RE = /%60/gi;\nconst ENC_CURLY_OPEN_RE = /%7b/gi;\nconst ENC_PIPE_RE = /%7c/gi;\nconst ENC_CURLY_CLOSE_RE = /%7d/gi;\nconst ENC_SPACE_RE = /%20/gi;\nconst ENC_SLASH_RE = /%2f/gi;\nconst ENC_ENC_SLASH_RE = /%252f/gi;\nfunction encode(text) {\n return encodeURI(\"\" + text).replace(ENC_PIPE_RE, \"|\");\n}\nfunction encodeHash(text) {\n return encode(text).replace(ENC_CURLY_OPEN_RE, \"{\").replace(ENC_CURLY_CLOSE_RE, \"}\").replace(ENC_CARET_RE, \"^\");\n}\nfunction encodeQueryValue(input) {\n return encode(typeof input === \"string\" ? input : JSON.stringify(input)).replace(PLUS_RE, \"%2B\").replace(ENC_SPACE_RE, \"+\").replace(HASH_RE, \"%23\").replace(AMPERSAND_RE, \"%26\").replace(ENC_BACKTICK_RE, \"`\").replace(ENC_CARET_RE, \"^\").replace(SLASH_RE, \"%2F\");\n}\nfunction encodeQueryKey(text) {\n return encodeQueryValue(text).replace(EQUAL_RE, \"%3D\");\n}\nfunction encodePath(text) {\n return encode(text).replace(HASH_RE, \"%23\").replace(IM_RE, \"%3F\").replace(ENC_ENC_SLASH_RE, \"%2F\").replace(AMPERSAND_RE, \"%26\").replace(PLUS_RE, \"%2B\");\n}\nfunction encodeParam(text) {\n return encodePath(text).replace(SLASH_RE, \"%2F\");\n}\nfunction decode(text = \"\") {\n try {\n return decodeURIComponent(\"\" + text);\n } catch {\n return \"\" + text;\n }\n}\nfunction decodePath(text) {\n return decode(text.replace(ENC_SLASH_RE, \"%252F\"));\n}\nfunction decodeQueryKey(text) {\n return decode(text.replace(PLUS_RE, \" \"));\n}\nfunction decodeQueryValue(text) {\n return decode(text.replace(PLUS_RE, \" \"));\n}\nfunction encodeHost(name = \"\") {\n return toASCII(name);\n}\n\nfunction parseQuery(parametersString = \"\") {\n const object = /* @__PURE__ */ Object.create(null);\n if (parametersString[0] === \"?\") {\n parametersString = parametersString.slice(1);\n }\n for (const parameter of parametersString.split(\"&\")) {\n const s = parameter.match(/([^=]+)=?(.*)/) || [];\n if (s.length < 2) {\n continue;\n }\n const key = decodeQueryKey(s[1]);\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = decodeQueryValue(s[2] || \"\");\n if (object[key] === void 0) {\n object[key] = value;\n } else if (Array.isArray(object[key])) {\n object[key].push(value);\n } else {\n object[key] = [object[key], value];\n }\n }\n return object;\n}\nfunction encodeQueryItem(key, value) {\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n value = String(value);\n }\n if (!value) {\n return encodeQueryKey(key);\n }\n if (Array.isArray(value)) {\n return value.map(\n (_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`\n ).join(\"&\");\n }\n return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;\n}\nfunction stringifyQuery(query) {\n return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join(\"&\");\n}\n\nconst PROTOCOL_STRICT_REGEX = /^[\\s\\w\\0+.-]{2,}:([/\\\\]{1,2})/;\nconst PROTOCOL_REGEX = /^[\\s\\w\\0+.-]{2,}:([/\\\\]{2})?/;\nconst PROTOCOL_RELATIVE_REGEX = /^([/\\\\]\\s*){2,}[^/\\\\]/;\nconst PROTOCOL_SCRIPT_RE = /^[\\s\\0]*(blob|data|javascript|vbscript):$/i;\nconst TRAILING_SLASH_RE = /\\/$|\\/\\?|\\/#/;\nconst JOIN_LEADING_SLASH_RE = /^\\.?\\//;\nfunction isRelative(inputString) {\n return [\"./\", \"../\"].some((string_) => inputString.startsWith(string_));\n}\nfunction hasProtocol(inputString, opts = {}) {\n if (typeof opts === \"boolean\") {\n opts = { acceptRelative: opts };\n }\n if (opts.strict) {\n return PROTOCOL_STRICT_REGEX.test(inputString);\n }\n return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);\n}\nfunction isScriptProtocol(protocol) {\n return !!protocol && PROTOCOL_SCRIPT_RE.test(protocol);\n}\nfunction hasTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return input.endsWith(\"/\");\n }\n return TRAILING_SLASH_RE.test(input);\n}\nfunction withoutTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || \"/\";\n }\n if (!hasTrailingSlash(input, true)) {\n return input || \"/\";\n }\n let path = input;\n let fragment = \"\";\n const fragmentIndex = input.indexOf(\"#\");\n if (fragmentIndex !== -1) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n }\n const [s0, ...s] = path.split(\"?\");\n const cleanPath = s0.endsWith(\"/\") ? s0.slice(0, -1) : s0;\n return (cleanPath || \"/\") + (s.length > 0 ? `?${s.join(\"?\")}` : \"\") + fragment;\n}\nfunction withTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return input.endsWith(\"/\") ? input : input + \"/\";\n }\n if (hasTrailingSlash(input, true)) {\n return input || \"/\";\n }\n let path = input;\n let fragment = \"\";\n const fragmentIndex = input.indexOf(\"#\");\n if (fragmentIndex !== -1) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n if (!path) {\n return fragment;\n }\n }\n const [s0, ...s] = path.split(\"?\");\n return s0 + \"/\" + (s.length > 0 ? `?${s.join(\"?\")}` : \"\") + fragment;\n}\nfunction hasLeadingSlash(input = \"\") {\n return input.startsWith(\"/\");\n}\nfunction withoutLeadingSlash(input = \"\") {\n return (hasLeadingSlash(input) ? input.slice(1) : input) || \"/\";\n}\nfunction withLeadingSlash(input = \"\") {\n return hasLeadingSlash(input) ? input : \"/\" + input;\n}\nfunction cleanDoubleSlashes(input = \"\") {\n return input.split(\"://\").map((string_) => string_.replace(/\\/{2,}/g, \"/\")).join(\"://\");\n}\nfunction withBase(input, base) {\n if (isEmptyURL(base) || hasProtocol(input)) {\n return input;\n }\n const _base = withoutTrailingSlash(base);\n if (input.startsWith(_base)) {\n const nextChar = input[_base.length];\n if (!nextChar || nextChar === \"/\" || nextChar === \"?\") {\n return input;\n }\n }\n return joinURL(_base, input);\n}\nfunction withoutBase(input, base) {\n if (isEmptyURL(base)) {\n return input;\n }\n const _base = withoutTrailingSlash(base);\n if (!input.startsWith(_base)) {\n return input;\n }\n const nextChar = input[_base.length];\n if (nextChar && nextChar !== \"/\" && nextChar !== \"?\") {\n return input;\n }\n const trimmed = input.slice(_base.length);\n return trimmed[0] === \"/\" ? trimmed : \"/\" + trimmed;\n}\nfunction withQuery(input, query) {\n const parsed = parseURL(input);\n const mergedQuery = { ...parseQuery(parsed.search), ...query };\n parsed.search = stringifyQuery(mergedQuery);\n return stringifyParsedURL(parsed);\n}\nfunction filterQuery(input, predicate) {\n if (!input.includes(\"?\")) {\n return input;\n }\n const parsed = parseURL(input);\n const query = parseQuery(parsed.search);\n const filteredQuery = Object.fromEntries(\n Object.entries(query).filter(([key, value]) => predicate(key, value))\n );\n parsed.search = stringifyQuery(filteredQuery);\n return stringifyParsedURL(parsed);\n}\nfunction getQuery(input) {\n return parseQuery(parseURL(input).search);\n}\nfunction isEmptyURL(url) {\n return !url || url === \"/\";\n}\nfunction isNonEmptyURL(url) {\n return url && url !== \"/\";\n}\nfunction joinURL(base, ...input) {\n let url = base || \"\";\n for (const segment of input.filter((url2) => isNonEmptyURL(url2))) {\n if (url) {\n const _segment = segment.replace(JOIN_LEADING_SLASH_RE, \"\");\n url = withTrailingSlash(url) + _segment;\n } else {\n url = segment;\n }\n }\n return url;\n}\nfunction joinRelativeURL(..._input) {\n const JOIN_SEGMENT_SPLIT_RE = /\\/(?!\\/)/;\n const input = _input.filter(Boolean);\n const segments = [];\n let segmentsDepth = 0;\n for (const i of input) {\n if (!i || i === \"/\") {\n continue;\n }\n for (const [sindex, s] of i.split(JOIN_SEGMENT_SPLIT_RE).entries()) {\n if (!s || s === \".\") {\n continue;\n }\n if (s === \"..\") {\n if (segments.length === 1 && hasProtocol(segments[0])) {\n continue;\n }\n segments.pop();\n segmentsDepth--;\n continue;\n }\n if (sindex === 1 && segments[segments.length - 1]?.endsWith(\":/\")) {\n segments[segments.length - 1] += \"/\" + s;\n continue;\n }\n segments.push(s);\n segmentsDepth++;\n }\n }\n let url = segments.join(\"/\");\n if (segmentsDepth >= 0) {\n if (input[0]?.startsWith(\"/\") && !url.startsWith(\"/\")) {\n url = \"/\" + url;\n } else if (input[0]?.startsWith(\"./\") && !url.startsWith(\"./\")) {\n url = \"./\" + url;\n }\n } else {\n url = \"../\".repeat(-1 * segmentsDepth) + url;\n }\n if (input[input.length - 1]?.endsWith(\"/\") && !url.endsWith(\"/\")) {\n url += \"/\";\n }\n return url;\n}\nfunction withHttp(input) {\n return withProtocol(input, \"http://\");\n}\nfunction withHttps(input) {\n return withProtocol(input, \"https://\");\n}\nfunction withoutProtocol(input) {\n return withProtocol(input, \"\");\n}\nfunction withProtocol(input, protocol) {\n let match = input.match(PROTOCOL_REGEX);\n if (!match) {\n match = input.match(/^\\/{2,}/);\n }\n if (!match) {\n return protocol + input;\n }\n return protocol + input.slice(match[0].length);\n}\nfunction normalizeURL(input) {\n const parsed = parseURL(input);\n parsed.pathname = encodePath(decodePath(parsed.pathname));\n parsed.hash = encodeHash(decode(parsed.hash));\n parsed.host = encodeHost(decode(parsed.host));\n parsed.search = stringifyQuery(parseQuery(parsed.search));\n return stringifyParsedURL(parsed);\n}\nfunction resolveURL(base = \"\", ...inputs) {\n if (typeof base !== \"string\") {\n throw new TypeError(\n `URL input should be string received ${typeof base} (${base})`\n );\n }\n const filteredInputs = inputs.filter((input) => isNonEmptyURL(input));\n if (filteredInputs.length === 0) {\n return base;\n }\n const url = parseURL(base);\n for (const inputSegment of filteredInputs) {\n const urlSegment = parseURL(inputSegment);\n if (urlSegment.pathname) {\n url.pathname = withTrailingSlash(url.pathname) + withoutLeadingSlash(urlSegment.pathname);\n }\n if (urlSegment.hash && urlSegment.hash !== \"#\") {\n url.hash = urlSegment.hash;\n }\n if (urlSegment.search && urlSegment.search !== \"?\") {\n if (url.search && url.search !== \"?\") {\n const queryString = stringifyQuery({\n ...parseQuery(url.search),\n ...parseQuery(urlSegment.search)\n });\n url.search = queryString.length > 0 ? \"?\" + queryString : \"\";\n } else {\n url.search = urlSegment.search;\n }\n }\n }\n return stringifyParsedURL(url);\n}\nfunction isSamePath(p1, p2) {\n return decode(withoutTrailingSlash(p1)) === decode(withoutTrailingSlash(p2));\n}\nfunction isEqual(a, b, options = {}) {\n if (!options.trailingSlash) {\n a = withTrailingSlash(a);\n b = withTrailingSlash(b);\n }\n if (!options.leadingSlash) {\n a = withLeadingSlash(a);\n b = withLeadingSlash(b);\n }\n if (!options.encoding) {\n a = decode(a);\n b = decode(b);\n }\n return a === b;\n}\nfunction withFragment(input, hash) {\n if (!hash || hash === \"#\") {\n return input;\n }\n const parsed = parseURL(input);\n parsed.hash = hash === \"\" ? \"\" : \"#\" + encodeHash(hash);\n return stringifyParsedURL(parsed);\n}\nfunction withoutFragment(input) {\n return stringifyParsedURL({ ...parseURL(input), hash: \"\" });\n}\nfunction withoutHost(input) {\n const parsed = parseURL(input);\n return (parsed.pathname || \"/\") + parsed.search + parsed.hash;\n}\n\nconst protocolRelative = Symbol.for(\"ufo:protocolRelative\");\nfunction parseURL(input = \"\", defaultProto) {\n const _specialProtoMatch = input.match(\n /^[\\s\\0]*(blob:|data:|javascript:|vbscript:)(.*)/i\n );\n if (_specialProtoMatch) {\n const [, _proto, _pathname = \"\"] = _specialProtoMatch;\n return {\n protocol: _proto.toLowerCase(),\n pathname: _pathname,\n href: _proto + _pathname,\n auth: \"\",\n host: \"\",\n search: \"\",\n hash: \"\"\n };\n }\n if (!hasProtocol(input, { acceptRelative: true })) {\n return defaultProto ? parseURL(defaultProto + input) : parsePath(input);\n }\n const [, protocol = \"\", auth, hostAndPath = \"\"] = input.replace(/\\\\/g, \"/\").match(/^[\\s\\0]*([\\w+.-]{2,}:)?\\/\\/([^/@]+@)?(.*)/) || [];\n let [, host = \"\", path = \"\"] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];\n if (protocol === \"file:\") {\n path = path.replace(/\\/(?=[A-Za-z]:)/, \"\");\n }\n const { pathname, search, hash } = parsePath(path);\n return {\n protocol: protocol.toLowerCase(),\n auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : \"\",\n host,\n pathname,\n search,\n hash,\n [protocolRelative]: !protocol\n };\n}\nfunction parsePath(input = \"\") {\n const [pathname = \"\", search = \"\", hash = \"\"] = (input.match(/([^#?]*)(\\?[^#]*)?(#.*)?/) || []).splice(1);\n return {\n pathname,\n search,\n hash\n };\n}\nfunction parseAuth(input = \"\") {\n const [username, password] = input.split(\":\");\n return {\n username: decode(username),\n password: decode(password)\n };\n}\nfunction parseHost(input = \"\") {\n const [hostname, port] = (input.match(/([^/:]*):?(\\d+)?/) || []).splice(1);\n return {\n hostname: decode(hostname),\n port\n };\n}\nfunction stringifyParsedURL(parsed) {\n const pathname = parsed.pathname || \"\";\n const search = parsed.search ? (parsed.search.startsWith(\"?\") ? \"\" : \"?\") + parsed.search : \"\";\n const hash = parsed.hash || \"\";\n const auth = parsed.auth ? parsed.auth + \"@\" : \"\";\n const host = parsed.host || \"\";\n const proto = parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || \"\") + \"//\" : \"\";\n return proto + auth + host + pathname + search + hash;\n}\nconst FILENAME_STRICT_REGEX = /\\/([^/]+\\.[^/]+)$/;\nconst FILENAME_REGEX = /\\/([^/]+)$/;\nfunction parseFilename(input = \"\", opts) {\n const { pathname } = parseURL(input);\n const matches = opts?.strict ? pathname.match(FILENAME_STRICT_REGEX) : pathname.match(FILENAME_REGEX);\n return matches ? matches[1] : void 0;\n}\n\nclass $URL {\n protocol;\n host;\n auth;\n pathname;\n query = {};\n hash;\n constructor(input = \"\") {\n if (typeof input !== \"string\") {\n throw new TypeError(\n `URL input should be string received ${typeof input} (${input})`\n );\n }\n const parsed = parseURL(input);\n this.protocol = decode(parsed.protocol);\n this.host = decode(parsed.host);\n this.auth = decode(parsed.auth);\n this.pathname = decodePath(parsed.pathname);\n this.query = parseQuery(parsed.search);\n this.hash = decode(parsed.hash);\n }\n get hostname() {\n return parseHost(this.host).hostname;\n }\n get port() {\n return parseHost(this.host).port || \"\";\n }\n get username() {\n return parseAuth(this.auth).username;\n }\n get password() {\n return parseAuth(this.auth).password || \"\";\n }\n get hasProtocol() {\n return this.protocol.length;\n }\n get isAbsolute() {\n return this.hasProtocol || this.pathname[0] === \"/\";\n }\n get search() {\n const q = stringifyQuery(this.query);\n return q.length > 0 ? \"?\" + q : \"\";\n }\n get searchParams() {\n const p = new URLSearchParams();\n for (const name in this.query) {\n const value = this.query[name];\n if (Array.isArray(value)) {\n for (const v of value) {\n p.append(name, v);\n }\n } else {\n p.append(\n name,\n typeof value === \"string\" ? value : JSON.stringify(value)\n );\n }\n }\n return p;\n }\n get origin() {\n return (this.protocol ? this.protocol + \"//\" : \"\") + encodeHost(this.host);\n }\n get fullpath() {\n return encodePath(this.pathname) + this.search + encodeHash(this.hash);\n }\n get encodedAuth() {\n if (!this.auth) {\n return \"\";\n }\n const { username, password } = parseAuth(this.auth);\n return encodeURIComponent(username) + (password ? \":\" + encodeURIComponent(password) : \"\");\n }\n get href() {\n const auth = this.encodedAuth;\n const originWithAuth = (this.protocol ? this.protocol + \"//\" : \"\") + (auth ? auth + \"@\" : \"\") + encodeHost(this.host);\n return this.hasProtocol && this.isAbsolute ? originWithAuth + this.fullpath : this.fullpath;\n }\n append(url) {\n if (url.hasProtocol) {\n throw new Error(\"Cannot append a URL with protocol\");\n }\n Object.assign(this.query, url.query);\n if (url.pathname) {\n this.pathname = withTrailingSlash(this.pathname) + withoutLeadingSlash(url.pathname);\n }\n if (url.hash) {\n this.hash = url.hash;\n }\n }\n toJSON() {\n return this.href;\n }\n toString() {\n return this.href;\n }\n}\nfunction createURL(input) {\n return new $URL(input);\n}\n\nexport { $URL, cleanDoubleSlashes, createURL, decode, decodePath, decodeQueryKey, decodeQueryValue, encode, encodeHash, encodeHost, encodeParam, encodePath, encodeQueryItem, encodeQueryKey, encodeQueryValue, filterQuery, getQuery, hasLeadingSlash, hasProtocol, hasTrailingSlash, isEmptyURL, isEqual, isNonEmptyURL, isRelative, isSamePath, isScriptProtocol, joinRelativeURL, joinURL, normalizeURL, parseAuth, parseFilename, parseHost, parsePath, parseQuery, parseURL, resolveURL, stringifyParsedURL, stringifyQuery, withBase, withFragment, withHttp, withHttps, withLeadingSlash, withProtocol, withQuery, withTrailingSlash, withoutBase, withoutFragment, withoutHost, withoutLeadingSlash, withoutProtocol, withoutTrailingSlash };\n"],"x_google_ignoreList":[0],"mappings":"AAQU,OAAO;AAkLjB,MAAM,wBAAwB;AAC9B,MAAM,iBAAiB;AACvB,MAAM,0BAA0B;AAOhC,SAAS,YAAY,aAAa,OAAO,EAAE,EAAE;AAC3C,KAAI,OAAO,SAAS,UAClB,QAAO,EAAE,gBAAgB,MAAM;AAEjC,KAAI,KAAK,OACP,QAAO,sBAAsB,KAAK,YAAY;AAEhD,QAAO,eAAe,KAAK,YAAY,KAAK,KAAK,iBAAiB,wBAAwB,KAAK,YAAY,GAAG;;AA0QhH,MAAM,mBAAmB,OAAO,IAAI,uBAAuB;AAC3D,SAAS,SAAS,QAAQ,IAAI,cAAc;CAC1C,MAAM,qBAAqB,MAAM,MAC/B,mDACD;AACD,KAAI,oBAAoB;EACtB,MAAM,GAAG,QAAQ,YAAY,MAAM;AACnC,SAAO;GACL,UAAU,OAAO,aAAa;GAC9B,UAAU;GACV,MAAM,SAAS;GACf,MAAM;GACN,MAAM;GACN,QAAQ;GACR,MAAM;GACP;;AAEH,KAAI,CAAC,YAAY,OAAO,EAAE,gBAAgB,MAAM,CAAC,CAC/C,QAAO,eAAe,SAAS,eAAe,MAAM,GAAG,UAAU,MAAM;CAEzE,MAAM,GAAG,WAAW,IAAI,MAAM,cAAc,MAAM,MAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,4CAA4C,IAAI,EAAE;CACpI,IAAI,GAAG,OAAO,IAAI,OAAO,MAAM,YAAY,MAAM,iBAAiB,IAAI,EAAE;AACxE,KAAI,aAAa,QACf,QAAO,KAAK,QAAQ,mBAAmB,GAAG;CAE5C,MAAM,EAAE,UAAU,QAAQ,SAAS,UAAU,KAAK;AAClD,QAAO;EACL,UAAU,SAAS,aAAa;EAChC,MAAM,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC,GAAG;EAC3D;EACA;EACA;EACA;GACC,mBAAmB,CAAC;EACtB;;AAEH,SAAS,UAAU,QAAQ,IAAI;CAC7B,MAAM,CAAC,WAAW,IAAI,SAAS,IAAI,OAAO,OAAO,MAAM,MAAM,2BAA2B,IAAI,EAAE,EAAE,OAAO,EAAE;AACzG,QAAO;EACL;EACA;EACA;EACD"}
1
+ {"version":3,"file":"dist-BFn8qsRC.mjs","names":[],"sources":["../../../node_modules/ufo/dist/index.mjs"],"sourcesContent":["const n = /[^\\0-\\x7E]/;\nconst t = /[\\x2E\\u3002\\uFF0E\\uFF61]/g;\nconst o = {\n overflow: \"Overflow Error\",\n \"not-basic\": \"Illegal Input\",\n \"invalid-input\": \"Invalid Input\"\n};\nconst e = Math.floor;\nconst r = String.fromCharCode;\nfunction s(n2) {\n throw new RangeError(o[n2]);\n}\nconst c = function(n2, t2) {\n return n2 + 22 + 75 * (n2 < 26) - ((t2 != 0) << 5);\n};\nconst u = function(n2, t2, o2) {\n let r2 = 0;\n for (n2 = o2 ? e(n2 / 700) : n2 >> 1, n2 += e(n2 / t2); n2 > 455; r2 += 36) {\n n2 = e(n2 / 35);\n }\n return e(r2 + 36 * n2 / (n2 + 38));\n};\nfunction toASCII(o2) {\n return (function(n2, o3) {\n const e2 = n2.split(\"@\");\n let r2 = \"\";\n e2.length > 1 && (r2 = e2[0] + \"@\", n2 = e2[1]);\n const s2 = (function(n3, t2) {\n const o4 = [];\n let e3 = n3.length;\n for (; e3--; ) {\n o4[e3] = t2(n3[e3]);\n }\n return o4;\n })((n2 = n2.replace(t, \".\")).split(\".\"), o3).join(\".\");\n return r2 + s2;\n })(o2, function(t2) {\n return n.test(t2) ? \"xn--\" + (function(n2) {\n const t3 = [];\n const o3 = (n2 = (function(n3) {\n const t4 = [];\n let o4 = 0;\n const e2 = n3.length;\n for (; o4 < e2; ) {\n const r2 = n3.charCodeAt(o4++);\n if (r2 >= 55296 && r2 <= 56319 && o4 < e2) {\n const e3 = n3.charCodeAt(o4++);\n (64512 & e3) == 56320 ? t4.push(((1023 & r2) << 10) + (1023 & e3) + 65536) : (t4.push(r2), o4--);\n } else {\n t4.push(r2);\n }\n }\n return t4;\n })(n2)).length;\n let f = 128;\n let i = 0;\n let l = 72;\n for (const o4 of n2) {\n o4 < 128 && t3.push(r(o4));\n }\n const h = t3.length;\n let p = h;\n for (h && t3.push(\"-\"); p < o3; ) {\n let o4 = 2147483647;\n for (const t4 of n2) {\n t4 >= f && t4 < o4 && (o4 = t4);\n }\n const a = p + 1;\n o4 - f > e((2147483647 - i) / a) && s(\"overflow\"), i += (o4 - f) * a, f = o4;\n for (const o5 of n2) {\n if (o5 < f && ++i > 2147483647 && s(\"overflow\"), o5 == f) {\n let n3 = i;\n for (let o6 = 36; ; o6 += 36) {\n const s2 = o6 <= l ? 1 : o6 >= l + 26 ? 26 : o6 - l;\n if (n3 < s2) {\n break;\n }\n const u2 = n3 - s2;\n const f2 = 36 - s2;\n t3.push(r(c(s2 + u2 % f2, 0))), n3 = e(u2 / f2);\n }\n t3.push(r(c(n3, 0))), l = u(i, a, p == h), i = 0, ++p;\n }\n }\n ++i, ++f;\n }\n return t3.join(\"\");\n })(t2) : t2;\n });\n}\n\nconst HASH_RE = /#/g;\nconst AMPERSAND_RE = /&/g;\nconst SLASH_RE = /\\//g;\nconst EQUAL_RE = /=/g;\nconst IM_RE = /\\?/g;\nconst PLUS_RE = /\\+/g;\nconst ENC_CARET_RE = /%5e/gi;\nconst ENC_BACKTICK_RE = /%60/gi;\nconst ENC_CURLY_OPEN_RE = /%7b/gi;\nconst ENC_PIPE_RE = /%7c/gi;\nconst ENC_CURLY_CLOSE_RE = /%7d/gi;\nconst ENC_SPACE_RE = /%20/gi;\nconst ENC_SLASH_RE = /%2f/gi;\nconst ENC_ENC_SLASH_RE = /%252f/gi;\nfunction encode(text) {\n return encodeURI(\"\" + text).replace(ENC_PIPE_RE, \"|\");\n}\nfunction encodeHash(text) {\n return encode(text).replace(ENC_CURLY_OPEN_RE, \"{\").replace(ENC_CURLY_CLOSE_RE, \"}\").replace(ENC_CARET_RE, \"^\");\n}\nfunction encodeQueryValue(input) {\n return encode(typeof input === \"string\" ? input : JSON.stringify(input)).replace(PLUS_RE, \"%2B\").replace(ENC_SPACE_RE, \"+\").replace(HASH_RE, \"%23\").replace(AMPERSAND_RE, \"%26\").replace(ENC_BACKTICK_RE, \"`\").replace(ENC_CARET_RE, \"^\").replace(SLASH_RE, \"%2F\");\n}\nfunction encodeQueryKey(text) {\n return encodeQueryValue(text).replace(EQUAL_RE, \"%3D\");\n}\nfunction encodePath(text) {\n return encode(text).replace(HASH_RE, \"%23\").replace(IM_RE, \"%3F\").replace(ENC_ENC_SLASH_RE, \"%2F\").replace(AMPERSAND_RE, \"%26\").replace(PLUS_RE, \"%2B\");\n}\nfunction encodeParam(text) {\n return encodePath(text).replace(SLASH_RE, \"%2F\");\n}\nfunction decode(text = \"\") {\n try {\n return decodeURIComponent(\"\" + text);\n } catch {\n return \"\" + text;\n }\n}\nfunction decodePath(text) {\n return decode(text.replace(ENC_SLASH_RE, \"%252F\"));\n}\nfunction decodeQueryKey(text) {\n return decode(text.replace(PLUS_RE, \" \"));\n}\nfunction decodeQueryValue(text) {\n return decode(text.replace(PLUS_RE, \" \"));\n}\nfunction encodeHost(name = \"\") {\n return toASCII(name);\n}\n\nfunction parseQuery(parametersString = \"\") {\n const object = /* @__PURE__ */ Object.create(null);\n if (parametersString[0] === \"?\") {\n parametersString = parametersString.slice(1);\n }\n for (const parameter of parametersString.split(\"&\")) {\n const s = parameter.match(/([^=]+)=?(.*)/) || [];\n if (s.length < 2) {\n continue;\n }\n const key = decodeQueryKey(s[1]);\n if (key === \"__proto__\" || key === \"constructor\") {\n continue;\n }\n const value = decodeQueryValue(s[2] || \"\");\n if (object[key] === void 0) {\n object[key] = value;\n } else if (Array.isArray(object[key])) {\n object[key].push(value);\n } else {\n object[key] = [object[key], value];\n }\n }\n return object;\n}\nfunction encodeQueryItem(key, value) {\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n value = String(value);\n }\n if (!value) {\n return encodeQueryKey(key);\n }\n if (Array.isArray(value)) {\n return value.map(\n (_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`\n ).join(\"&\");\n }\n return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;\n}\nfunction stringifyQuery(query) {\n return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join(\"&\");\n}\n\nconst PROTOCOL_STRICT_REGEX = /^[\\s\\w\\0+.-]{2,}:([/\\\\]{1,2})/;\nconst PROTOCOL_REGEX = /^[\\s\\w\\0+.-]{2,}:([/\\\\]{2})?/;\nconst PROTOCOL_RELATIVE_REGEX = /^([/\\\\]\\s*){2,}[^/\\\\]/;\nconst PROTOCOL_SCRIPT_RE = /^[\\s\\0]*(blob|data|javascript|vbscript):$/i;\nconst TRAILING_SLASH_RE = /\\/$|\\/\\?|\\/#/;\nconst JOIN_LEADING_SLASH_RE = /^\\.?\\//;\nfunction isRelative(inputString) {\n return [\"./\", \"../\"].some((string_) => inputString.startsWith(string_));\n}\nfunction hasProtocol(inputString, opts = {}) {\n if (typeof opts === \"boolean\") {\n opts = { acceptRelative: opts };\n }\n if (opts.strict) {\n return PROTOCOL_STRICT_REGEX.test(inputString);\n }\n return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);\n}\nfunction isScriptProtocol(protocol) {\n return !!protocol && PROTOCOL_SCRIPT_RE.test(protocol);\n}\nfunction hasTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return input.endsWith(\"/\");\n }\n return TRAILING_SLASH_RE.test(input);\n}\nfunction withoutTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || \"/\";\n }\n if (!hasTrailingSlash(input, true)) {\n return input || \"/\";\n }\n let path = input;\n let fragment = \"\";\n const fragmentIndex = input.indexOf(\"#\");\n if (fragmentIndex !== -1) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n }\n const [s0, ...s] = path.split(\"?\");\n const cleanPath = s0.endsWith(\"/\") ? s0.slice(0, -1) : s0;\n return (cleanPath || \"/\") + (s.length > 0 ? `?${s.join(\"?\")}` : \"\") + fragment;\n}\nfunction withTrailingSlash(input = \"\", respectQueryAndFragment) {\n if (!respectQueryAndFragment) {\n return input.endsWith(\"/\") ? input : input + \"/\";\n }\n if (hasTrailingSlash(input, true)) {\n return input || \"/\";\n }\n let path = input;\n let fragment = \"\";\n const fragmentIndex = input.indexOf(\"#\");\n if (fragmentIndex !== -1) {\n path = input.slice(0, fragmentIndex);\n fragment = input.slice(fragmentIndex);\n if (!path) {\n return fragment;\n }\n }\n const [s0, ...s] = path.split(\"?\");\n return s0 + \"/\" + (s.length > 0 ? `?${s.join(\"?\")}` : \"\") + fragment;\n}\nfunction hasLeadingSlash(input = \"\") {\n return input.startsWith(\"/\");\n}\nfunction withoutLeadingSlash(input = \"\") {\n return (hasLeadingSlash(input) ? input.slice(1) : input) || \"/\";\n}\nfunction withLeadingSlash(input = \"\") {\n return hasLeadingSlash(input) ? input : \"/\" + input;\n}\nfunction cleanDoubleSlashes(input = \"\") {\n return input.split(\"://\").map((string_) => string_.replace(/\\/{2,}/g, \"/\")).join(\"://\");\n}\nfunction withBase(input, base) {\n if (isEmptyURL(base) || hasProtocol(input)) {\n return input;\n }\n const _base = withoutTrailingSlash(base);\n if (input.startsWith(_base)) {\n const nextChar = input[_base.length];\n if (!nextChar || nextChar === \"/\" || nextChar === \"?\") {\n return input;\n }\n }\n return joinURL(_base, input);\n}\nfunction withoutBase(input, base) {\n if (isEmptyURL(base)) {\n return input;\n }\n const _base = withoutTrailingSlash(base);\n if (!input.startsWith(_base)) {\n return input;\n }\n const nextChar = input[_base.length];\n if (nextChar && nextChar !== \"/\" && nextChar !== \"?\") {\n return input;\n }\n const trimmed = input.slice(_base.length);\n return trimmed[0] === \"/\" ? trimmed : \"/\" + trimmed;\n}\nfunction withQuery(input, query) {\n const parsed = parseURL(input);\n const mergedQuery = { ...parseQuery(parsed.search), ...query };\n parsed.search = stringifyQuery(mergedQuery);\n return stringifyParsedURL(parsed);\n}\nfunction filterQuery(input, predicate) {\n if (!input.includes(\"?\")) {\n return input;\n }\n const parsed = parseURL(input);\n const query = parseQuery(parsed.search);\n const filteredQuery = Object.fromEntries(\n Object.entries(query).filter(([key, value]) => predicate(key, value))\n );\n parsed.search = stringifyQuery(filteredQuery);\n return stringifyParsedURL(parsed);\n}\nfunction getQuery(input) {\n return parseQuery(parseURL(input).search);\n}\nfunction isEmptyURL(url) {\n return !url || url === \"/\";\n}\nfunction isNonEmptyURL(url) {\n return url && url !== \"/\";\n}\nfunction joinURL(base, ...input) {\n let url = base || \"\";\n for (const segment of input.filter((url2) => isNonEmptyURL(url2))) {\n if (url) {\n const _segment = segment.replace(JOIN_LEADING_SLASH_RE, \"\");\n url = withTrailingSlash(url) + _segment;\n } else {\n url = segment;\n }\n }\n return url;\n}\nfunction joinRelativeURL(..._input) {\n const JOIN_SEGMENT_SPLIT_RE = /\\/(?!\\/)/;\n const input = _input.filter(Boolean);\n const segments = [];\n let segmentsDepth = 0;\n for (const i of input) {\n if (!i || i === \"/\") {\n continue;\n }\n for (const [sindex, s] of i.split(JOIN_SEGMENT_SPLIT_RE).entries()) {\n if (!s || s === \".\") {\n continue;\n }\n if (s === \"..\") {\n if (segments.length === 1 && hasProtocol(segments[0])) {\n continue;\n }\n segments.pop();\n segmentsDepth--;\n continue;\n }\n if (sindex === 1 && segments[segments.length - 1]?.endsWith(\":/\")) {\n segments[segments.length - 1] += \"/\" + s;\n continue;\n }\n segments.push(s);\n segmentsDepth++;\n }\n }\n let url = segments.join(\"/\");\n if (segmentsDepth >= 0) {\n if (input[0]?.startsWith(\"/\") && !url.startsWith(\"/\")) {\n url = \"/\" + url;\n } else if (input[0]?.startsWith(\"./\") && !url.startsWith(\"./\")) {\n url = \"./\" + url;\n }\n } else {\n url = \"../\".repeat(-1 * segmentsDepth) + url;\n }\n if (input[input.length - 1]?.endsWith(\"/\") && !url.endsWith(\"/\")) {\n url += \"/\";\n }\n return url;\n}\nfunction withHttp(input) {\n return withProtocol(input, \"http://\");\n}\nfunction withHttps(input) {\n return withProtocol(input, \"https://\");\n}\nfunction withoutProtocol(input) {\n return withProtocol(input, \"\");\n}\nfunction withProtocol(input, protocol) {\n let match = input.match(PROTOCOL_REGEX);\n if (!match) {\n match = input.match(/^\\/{2,}/);\n }\n if (!match) {\n return protocol + input;\n }\n return protocol + input.slice(match[0].length);\n}\nfunction normalizeURL(input) {\n const parsed = parseURL(input);\n parsed.pathname = encodePath(decodePath(parsed.pathname));\n parsed.hash = encodeHash(decode(parsed.hash));\n parsed.host = encodeHost(decode(parsed.host));\n parsed.search = stringifyQuery(parseQuery(parsed.search));\n return stringifyParsedURL(parsed);\n}\nfunction resolveURL(base = \"\", ...inputs) {\n if (typeof base !== \"string\") {\n throw new TypeError(\n `URL input should be string received ${typeof base} (${base})`\n );\n }\n const filteredInputs = inputs.filter((input) => isNonEmptyURL(input));\n if (filteredInputs.length === 0) {\n return base;\n }\n const url = parseURL(base);\n for (const inputSegment of filteredInputs) {\n const urlSegment = parseURL(inputSegment);\n if (urlSegment.pathname) {\n url.pathname = withTrailingSlash(url.pathname) + withoutLeadingSlash(urlSegment.pathname);\n }\n if (urlSegment.hash && urlSegment.hash !== \"#\") {\n url.hash = urlSegment.hash;\n }\n if (urlSegment.search && urlSegment.search !== \"?\") {\n if (url.search && url.search !== \"?\") {\n const queryString = stringifyQuery({\n ...parseQuery(url.search),\n ...parseQuery(urlSegment.search)\n });\n url.search = queryString.length > 0 ? \"?\" + queryString : \"\";\n } else {\n url.search = urlSegment.search;\n }\n }\n }\n return stringifyParsedURL(url);\n}\nfunction isSamePath(p1, p2) {\n return decode(withoutTrailingSlash(p1)) === decode(withoutTrailingSlash(p2));\n}\nfunction isEqual(a, b, options = {}) {\n if (!options.trailingSlash) {\n a = withTrailingSlash(a);\n b = withTrailingSlash(b);\n }\n if (!options.leadingSlash) {\n a = withLeadingSlash(a);\n b = withLeadingSlash(b);\n }\n if (!options.encoding) {\n a = decode(a);\n b = decode(b);\n }\n return a === b;\n}\nfunction withFragment(input, hash) {\n if (!hash || hash === \"#\") {\n return input;\n }\n const parsed = parseURL(input);\n parsed.hash = hash === \"\" ? \"\" : \"#\" + encodeHash(hash);\n return stringifyParsedURL(parsed);\n}\nfunction withoutFragment(input) {\n return stringifyParsedURL({ ...parseURL(input), hash: \"\" });\n}\nfunction withoutHost(input) {\n const parsed = parseURL(input);\n return (parsed.pathname || \"/\") + parsed.search + parsed.hash;\n}\n\nconst protocolRelative = Symbol.for(\"ufo:protocolRelative\");\nfunction parseURL(input = \"\", defaultProto) {\n const _specialProtoMatch = input.match(\n /^[\\s\\0]*(blob:|data:|javascript:|vbscript:)(.*)/i\n );\n if (_specialProtoMatch) {\n const [, _proto, _pathname = \"\"] = _specialProtoMatch;\n return {\n protocol: _proto.toLowerCase(),\n pathname: _pathname,\n href: _proto + _pathname,\n auth: \"\",\n host: \"\",\n search: \"\",\n hash: \"\"\n };\n }\n if (!hasProtocol(input, { acceptRelative: true })) {\n return defaultProto ? parseURL(defaultProto + input) : parsePath(input);\n }\n const [, protocol = \"\", auth, hostAndPath = \"\"] = input.replace(/\\\\/g, \"/\").match(/^[\\s\\0]*([\\w+.-]{2,}:)?\\/\\/([^/@]+@)?(.*)/) || [];\n let [, host = \"\", path = \"\"] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];\n if (protocol === \"file:\") {\n path = path.replace(/\\/(?=[A-Za-z]:)/, \"\");\n }\n const { pathname, search, hash } = parsePath(path);\n return {\n protocol: protocol.toLowerCase(),\n auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : \"\",\n host,\n pathname,\n search,\n hash,\n [protocolRelative]: !protocol\n };\n}\nfunction parsePath(input = \"\") {\n const [pathname = \"\", search = \"\", hash = \"\"] = (input.match(/([^#?]*)(\\?[^#]*)?(#.*)?/) || []).splice(1);\n return {\n pathname,\n search,\n hash\n };\n}\nfunction parseAuth(input = \"\") {\n const [username, password] = input.split(\":\");\n return {\n username: decode(username),\n password: decode(password)\n };\n}\nfunction parseHost(input = \"\") {\n const [hostname, port] = (input.match(/([^/:]*):?(\\d+)?/) || []).splice(1);\n return {\n hostname: decode(hostname),\n port\n };\n}\nfunction stringifyParsedURL(parsed) {\n const pathname = parsed.pathname || \"\";\n const search = parsed.search ? (parsed.search.startsWith(\"?\") ? \"\" : \"?\") + parsed.search : \"\";\n const hash = parsed.hash || \"\";\n const auth = parsed.auth ? parsed.auth + \"@\" : \"\";\n const host = parsed.host || \"\";\n const proto = parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || \"\") + \"//\" : \"\";\n return proto + auth + host + pathname + search + hash;\n}\nconst FILENAME_STRICT_REGEX = /\\/([^/]+\\.[^/]+)$/;\nconst FILENAME_REGEX = /\\/([^/]+)$/;\nfunction parseFilename(input = \"\", opts) {\n const { pathname } = parseURL(input);\n const matches = opts?.strict ? pathname.match(FILENAME_STRICT_REGEX) : pathname.match(FILENAME_REGEX);\n return matches ? matches[1] : void 0;\n}\n\nclass $URL {\n protocol;\n host;\n auth;\n pathname;\n query = {};\n hash;\n constructor(input = \"\") {\n if (typeof input !== \"string\") {\n throw new TypeError(\n `URL input should be string received ${typeof input} (${input})`\n );\n }\n const parsed = parseURL(input);\n this.protocol = decode(parsed.protocol);\n this.host = decode(parsed.host);\n this.auth = decode(parsed.auth);\n this.pathname = decodePath(parsed.pathname);\n this.query = parseQuery(parsed.search);\n this.hash = decode(parsed.hash);\n }\n get hostname() {\n return parseHost(this.host).hostname;\n }\n get port() {\n return parseHost(this.host).port || \"\";\n }\n get username() {\n return parseAuth(this.auth).username;\n }\n get password() {\n return parseAuth(this.auth).password || \"\";\n }\n get hasProtocol() {\n return this.protocol.length;\n }\n get isAbsolute() {\n return this.hasProtocol || this.pathname[0] === \"/\";\n }\n get search() {\n const q = stringifyQuery(this.query);\n return q.length > 0 ? \"?\" + q : \"\";\n }\n get searchParams() {\n const p = new URLSearchParams();\n for (const name in this.query) {\n const value = this.query[name];\n if (Array.isArray(value)) {\n for (const v of value) {\n p.append(name, v);\n }\n } else {\n p.append(\n name,\n typeof value === \"string\" ? value : JSON.stringify(value)\n );\n }\n }\n return p;\n }\n get origin() {\n return (this.protocol ? this.protocol + \"//\" : \"\") + encodeHost(this.host);\n }\n get fullpath() {\n return encodePath(this.pathname) + this.search + encodeHash(this.hash);\n }\n get encodedAuth() {\n if (!this.auth) {\n return \"\";\n }\n const { username, password } = parseAuth(this.auth);\n return encodeURIComponent(username) + (password ? \":\" + encodeURIComponent(password) : \"\");\n }\n get href() {\n const auth = this.encodedAuth;\n const originWithAuth = (this.protocol ? this.protocol + \"//\" : \"\") + (auth ? auth + \"@\" : \"\") + encodeHost(this.host);\n return this.hasProtocol && this.isAbsolute ? originWithAuth + this.fullpath : this.fullpath;\n }\n append(url) {\n if (url.hasProtocol) {\n throw new Error(\"Cannot append a URL with protocol\");\n }\n Object.assign(this.query, url.query);\n if (url.pathname) {\n this.pathname = withTrailingSlash(this.pathname) + withoutLeadingSlash(url.pathname);\n }\n if (url.hash) {\n this.hash = url.hash;\n }\n }\n toJSON() {\n return this.href;\n }\n toString() {\n return this.href;\n }\n}\nfunction createURL(input) {\n return new $URL(input);\n}\n\nexport { $URL, cleanDoubleSlashes, createURL, decode, decodePath, decodeQueryKey, decodeQueryValue, encode, encodeHash, encodeHost, encodeParam, encodePath, encodeQueryItem, encodeQueryKey, encodeQueryValue, filterQuery, getQuery, hasLeadingSlash, hasProtocol, hasTrailingSlash, isEmptyURL, isEqual, isNonEmptyURL, isRelative, isSamePath, isScriptProtocol, joinRelativeURL, joinURL, normalizeURL, parseAuth, parseFilename, parseHost, parsePath, parseQuery, parseURL, resolveURL, stringifyParsedURL, stringifyQuery, withBase, withFragment, withHttp, withHttps, withLeadingSlash, withProtocol, withQuery, withTrailingSlash, withoutBase, withoutFragment, withoutHost, withoutLeadingSlash, withoutProtocol, withoutTrailingSlash };\n"],"x_google_ignoreList":[0],"mappings":"AAQU,OAAO;AAkLjB,MAAM,wBAAwB;AAC9B,MAAM,iBAAiB;AACvB,MAAM,0BAA0B;AAOhC,SAAS,YAAY,aAAa,OAAO,EAAE,EAAE;AAC3C,KAAI,OAAO,SAAS,UAClB,QAAO,EAAE,gBAAgB,MAAM;AAEjC,KAAI,KAAK,OACP,QAAO,sBAAsB,KAAK,YAAY;AAEhD,QAAO,eAAe,KAAK,YAAY,KAAK,KAAK,iBAAiB,wBAAwB,KAAK,YAAY,GAAG;;AA0QhH,MAAM,mBAAmB,OAAO,IAAI,uBAAuB;AAC3D,SAAS,SAAS,QAAQ,IAAI,cAAc;CAC1C,MAAM,qBAAqB,MAAM,MAC/B,mDACD;AACD,KAAI,oBAAoB;EACtB,MAAM,GAAG,QAAQ,YAAY,MAAM;AACnC,SAAO;GACL,UAAU,OAAO,aAAa;GAC9B,UAAU;GACV,MAAM,SAAS;GACf,MAAM;GACN,MAAM;GACN,QAAQ;GACR,MAAM;GACP;;AAEH,KAAI,CAAC,YAAY,OAAO,EAAE,gBAAgB,MAAM,CAAC,CAC/C,QAAO,eAAe,SAAS,eAAe,MAAM,GAAG,UAAU,MAAM;CAEzE,MAAM,GAAG,WAAW,IAAI,MAAM,cAAc,MAAM,MAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,4CAA4C,IAAI,EAAE;CACpI,IAAI,GAAG,OAAO,IAAI,OAAO,MAAM,YAAY,MAAM,iBAAiB,IAAI,EAAE;AACxE,KAAI,aAAa,QACf,QAAO,KAAK,QAAQ,mBAAmB,GAAG;CAE5C,MAAM,EAAE,UAAU,QAAQ,SAAS,UAAU,KAAK;AAClD,QAAO;EACL,UAAU,SAAS,aAAa;EAChC,MAAM,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC,GAAG;EAC3D;EACA;EACA;EACA;GACC,mBAAmB,CAAC;EACtB;;AAEH,SAAS,UAAU,QAAQ,IAAI;CAC7B,MAAM,CAAC,WAAW,IAAI,SAAS,IAAI,OAAO,OAAO,MAAM,MAAM,2BAA2B,IAAI,EAAE,EAAE,OAAO,EAAE;AACzG,QAAO;EACL;EACA;EACA;EACD"}
@@ -1,5 +1,5 @@
1
- import { g as RequestLogger } from "../types-US-1hJZl.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-CDLTVOBs.mjs";
1
+ import { g as RequestLogger } from "../types-CBpJBj_7.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-B-4hPOVG.mjs";
3
3
  import { Elysia } from "elysia";
4
4
 
5
5
  //#region src/elysia/index.d.ts
@@ -1,4 +1,4 @@
1
- import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-BSgpnR0c.mjs";
1
+ import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-DJ_YZbxT.mjs";
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  import { Elysia } from "elysia";
4
4
  //#region src/elysia/index.ts
@@ -1,4 +1,4 @@
1
- import { i as EnrichContext } from "./types-US-1hJZl.mjs";
1
+ import { i as EnrichContext } from "./types-CBpJBj_7.mjs";
2
2
 
3
3
  //#region src/enrichers/index.d.ts
4
4
  interface EnricherOptions {
@@ -1,4 +1,4 @@
1
- import { o as ErrorOptions } from "./types-US-1hJZl.mjs";
1
+ import { o as ErrorOptions } from "./types-CBpJBj_7.mjs";
2
2
 
3
3
  //#region src/error.d.ts
4
4
  /**
@@ -62,4 +62,4 @@ declare class EvlogError extends Error {
62
62
  declare function createError(options: ErrorOptions | string): EvlogError;
63
63
  //#endregion
64
64
  export { createError as n, EvlogError as t };
65
- //# sourceMappingURL=error-BuPbEDGO.d.mts.map
65
+ //# sourceMappingURL=error-BheHTFFB.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-BuPbEDGO.d.mts","names":[],"sources":["../src/error.ts"],"mappings":";;;;;AAkBA;;;;;;;;;;;;;cAAa,UAAA,SAAmB,KAAA;EAQT;EAAA,SALZ,MAAA;EAAA,SACA,GAAA;EAAA,SACA,GAAA;EAAA,SACA,IAAA;cAEG,OAAA,EAAS,YAAA;EAiCP;EAAA,IAfV,UAAA,CAAA;EAesC;EAAA,IAVtC,UAAA,CAAA;EAkDJ;EAAA,IA7CI,aAAA,CAAA;EA6CY;EAAA,IAxCZ,IAAA,CAAA;IAAU,GAAA;IAAc,GAAA;IAAc,IAAA;EAAA;EAOjC,QAAA,CAAA;EAiCT,MAAA,CAAA,GAAU,MAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;iBAoCI,WAAA,CAAY,OAAA,EAAS,YAAA,YAAwB,UAAA"}
1
+ {"version":3,"file":"error-BheHTFFB.d.mts","names":[],"sources":["../src/error.ts"],"mappings":";;;;;AAkBA;;;;;;;;;;;;;cAAa,UAAA,SAAmB,KAAA;EAQT;EAAA,SALZ,MAAA;EAAA,SACA,GAAA;EAAA,SACA,GAAA;EAAA,SACA,IAAA;cAEG,OAAA,EAAS,YAAA;EAiCP;EAAA,IAfV,UAAA,CAAA;EAesC;EAAA,IAVtC,UAAA,CAAA;EAkDJ;EAAA,IA7CI,aAAA,CAAA;EA6CY;EAAA,IAxCZ,IAAA,CAAA;IAAU,GAAA;IAAc,GAAA;IAAc,IAAA;EAAA;EAOjC,QAAA,CAAA;EAiCT,MAAA,CAAA,GAAU,MAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;iBAoCI,WAAA,CAAY,OAAA,EAAS,YAAA,YAAwB,UAAA"}
package/dist/error.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as createError, t as EvlogError } from "./error-BuPbEDGO.mjs";
1
+ import { n as createError, t as EvlogError } from "./error-BheHTFFB.mjs";
2
2
  export { EvlogError, createError, createError as createEvlogError };
@@ -15,4 +15,4 @@ function extractErrorStatus(error) {
15
15
  //#endregion
16
16
  export { extractErrorStatus as t };
17
17
 
18
- //# sourceMappingURL=errors-BJRXUfMg.mjs.map
18
+ //# sourceMappingURL=errors-BQgyQ9xe.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors-BJRXUfMg.mjs","names":[],"sources":["../src/shared/errors.ts"],"sourcesContent":["/**\n * Extract HTTP status from an error, checking both `status` and `statusCode`.\n *\n * Works with any error shape (H3, Nitro, EvlogError, plain objects).\n *\n * @beta This function is part of the evlog toolkit API for building custom framework integrations.\n */\nexport function extractErrorStatus(error: unknown): number {\n if (error === null || typeof error !== 'object') return 500\n const raw = (error as { status?: unknown }).status\n ?? (error as { statusCode?: unknown }).statusCode\n const status = Number(raw)\n return Number.isFinite(status) ? status : 500\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,mBAAmB,OAAwB;AACzD,KAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;CACxD,MAAM,MAAO,MAA+B,UACtC,MAAmC;CACzC,MAAM,SAAS,OAAO,IAAI;AAC1B,QAAO,OAAO,SAAS,OAAO,GAAG,SAAS"}
1
+ {"version":3,"file":"errors-BQgyQ9xe.mjs","names":[],"sources":["../src/shared/errors.ts"],"sourcesContent":["/**\n * Extract HTTP status from an error, checking both `status` and `statusCode`.\n *\n * Works with any error shape (H3, Nitro, EvlogError, plain objects).\n *\n * @beta This function is part of the evlog toolkit API for building custom framework integrations.\n */\nexport function extractErrorStatus(error: unknown): number {\n if (error === null || typeof error !== 'object') return 500\n const raw = (error as { status?: unknown }).status\n ?? (error as { statusCode?: unknown }).statusCode\n const status = Number(raw)\n return Number.isFinite(status) ? status : 500\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,mBAAmB,OAAwB;AACzD,KAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;CACxD,MAAM,MAAO,MAA+B,UACtC,MAAmC;CACzC,MAAM,SAAS,OAAO,IAAI;AAC1B,QAAO,OAAO,SAAS,OAAO,GAAG,SAAS"}
@@ -1,4 +1,4 @@
1
- import { v as RouteConfig } from "./types-US-1hJZl.mjs";
1
+ import { v as RouteConfig } from "./types-CBpJBj_7.mjs";
2
2
 
3
3
  //#region src/shared/routes.d.ts
4
4
  declare function shouldLog(path: string, include?: string[], exclude?: string[]): boolean;
@@ -36,4 +36,4 @@ declare function getServiceForPath(path: string, routes?: Record<string, RouteCo
36
36
  declare function extractErrorStatus(error: unknown): number;
37
37
  //#endregion
38
38
  export { getServiceForPath as n, shouldLog as r, extractErrorStatus as t };
39
- //# sourceMappingURL=errors-nScQVwHW.d.mts.map
39
+ //# sourceMappingURL=errors-D8WVZclz.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors-nScQVwHW.d.mts","names":[],"sources":["../src/shared/routes.ts","../src/shared/errors.ts"],"mappings":";;;iBAGgB,SAAA,CAAU,IAAA,UAAc,OAAA,aAAoB,OAAA;;AAA5D;;;;;;;;;AAsCA;;;;;;;;;;;iBAAgB,iBAAA,CAAkB,IAAA,UAAc,MAAA,GAAS,MAAA,SAAe,WAAA;;;;;;AAtCxE;;;;iBCIgB,kBAAA,CAAmB,KAAA"}
1
+ {"version":3,"file":"errors-D8WVZclz.d.mts","names":[],"sources":["../src/shared/routes.ts","../src/shared/errors.ts"],"mappings":";;;iBAGgB,SAAA,CAAU,IAAA,UAAc,OAAA,aAAoB,OAAA;;AAA5D;;;;;;;;;AAsCA;;;;;;;;;;;iBAAgB,iBAAA,CAAkB,IAAA,UAAc,MAAA,GAAS,MAAA,SAAe,WAAA;;;;;;AAtCxE;;;;iBCIgB,kBAAA,CAAmB,KAAA"}
@@ -1,5 +1,5 @@
1
- import { g as RequestLogger } from "../types-US-1hJZl.mjs";
2
- import { t as BaseEvlogOptions } from "../middleware-CDLTVOBs.mjs";
1
+ import { g as RequestLogger } from "../types-CBpJBj_7.mjs";
2
+ import { t as BaseEvlogOptions } from "../middleware-B-4hPOVG.mjs";
3
3
  import { RequestHandler } from "express";
4
4
 
5
5
  //#region src/express/index.d.ts
@@ -1,5 +1,5 @@
1
- import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-BSgpnR0c.mjs";
2
- import { t as createLoggerStorage } from "../storage-DHU1gGqV.mjs";
1
+ import { n as extractSafeNodeHeaders, r as createMiddlewareLogger } from "../headers-DJ_YZbxT.mjs";
2
+ import { t as createLoggerStorage } from "../storage-DsueXspk.mjs";
3
3
  //#region src/express/index.ts
4
4
  const { storage, useLogger } = createLoggerStorage("middleware context. Make sure app.use(evlog()) is registered before your routes.");
5
5
  /**